From 43f149d940f3512a4b7e7d9da3baad1756dad174 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Thu, 18 Jan 2024 10:07:28 +0300 Subject: [PATCH] Added ER1 Without fileList --- android/app/build.gradle | 7 +- .../diplomaticquarterapp/ble/BleBridge.kt | 116 +++++++++++++----- .../ble/utils/DecompressUtil.java | 26 ---- .../my_trackers_view_model.dart | 4 +- 4 files changed, 94 insertions(+), 59 deletions(-) delete mode 100644 android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/DecompressUtil.java diff --git a/android/app/build.gradle b/android/app/build.gradle index f8fb47f9..774ae2fb 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -51,7 +51,7 @@ android { disable 'MissingTranslation' checkReleaseBuilds false } - + defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). @@ -122,7 +122,7 @@ dependencies { // }) implementation 'pub.devrel:easypermissions:0.4.0' // implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0' - // implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0' + // implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0' implementation 'com.google.guava:guava:27.0.1-android' // Dependency on local binaries implementation fileTree(dir: 'libs', include: ['*.jar']) @@ -146,12 +146,13 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0' implementation 'androidx.work:work-runtime:2.7.0-alpha05' androidTestImplementation "androidx.test:core:1.4.0" - + // Lepu Libraries implementation 'no.nordicsemi.android:ble:2.2.4' implementation(name: 'lepu-blepro-1.0.1', ext: 'aar') implementation 'io.github.jeremyliao:live-event-bus-x:1.8.0' implementation 'com.guolindev.permissionx:permissionx:1.7.1' + implementation 'org.apache.commons:commons-io:1.3.2' // for FileUtills in ER1 device configuration } diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/BleBridge.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/BleBridge.kt index 681def83..4b6bbf8f 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/BleBridge.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/BleBridge.kt @@ -14,6 +14,7 @@ import com.cloud.diplomaticquarterapp.ble.BPModelMeasuring import com.cloud.diplomaticquarterapp.ble.BPModelResult import com.cloud.diplomaticquarterapp.ble.OxymeterModel import com.cloud.diplomaticquarterapp.ble.utils.EcgData +import com.cloud.diplomaticquarterapp.ble.utils.HexString import com.google.gson.Gson @@ -32,12 +33,18 @@ import com.lepu.blepro.ext.er2.Er2EcgFile import com.lepu.blepro.ext.er2.Er2File import com.lepu.blepro.ext.er2.RtData import com.lepu.blepro.ext.bp2.* +import com.lepu.blepro.ext.er1.Er1Config +import com.lepu.blepro.ext.er1.Er1EcgFile +import com.lepu.blepro.ext.er1.Er1File +import com.lepu.blepro.ext.er1.Er1HrFile import com.lepu.blepro.ext.pc60fw.RtParam import com.lepu.blepro.ext.sp20.RtWave import com.lepu.blepro.objs.Bluetooth import com.lepu.blepro.objs.BluetoothController import com.lepu.blepro.utils.DateUtil import com.lepu.blepro.utils.Er1Decompress +import org.apache.commons.io.FileUtils +import java.io.File class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivity: MainActivity) { @@ -210,14 +217,12 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi private fun scanDevice() { - LiveEventBus.get(EventMsgConst.Ble.EventServiceConnectedAndInterfaceInit).observe(this.mainActivity) { // BleService init success println("EventServiceConnectedAndInterfaceInit---------") BleServiceHelper.BleServiceHelper.startScan(models) println("EventServiceConnectedAndInterfaceInit") } - LiveEventBus.get(EventMsgConst.Discovery.EventDeviceFound).observe(this.mainActivity) { val deviceName: String = "" val returnData = mapOf("type" to "DevicesList", "data" to gson.toJson(BluetoothController.getDevices())) @@ -231,7 +236,6 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi val rawFolders = SparseArray() try { BleServiceHelper.BleServiceHelper.initRawFolder(rawFolders).initService(this.mainActivity.application) - } catch (e: Exception) { println(e) } @@ -251,20 +255,16 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi eventSink?.success(returnData) BleServiceHelper.BleServiceHelper.startRtTask(model) } + LiveEventBus.get(InterfaceEvent.ER2.EventEr2FactoryReset).observe(this.mainActivity) { + val data = it.data as Boolean // We will get a ping from here to confirm if reset success + } LiveEventBus.get(InterfaceEvent.ER2.EventEr2FileList).observe(this.mainActivity) { BleServiceHelper.BleServiceHelper.stopRtTask(model) ecgFileNames = it.data as ArrayList readFileForEr2() -// val fileNames = it.data as ArrayList -// println("DuoEK FileNames List: ${fileNames}") -// val returnData = -// mapOf("type" to "fileList", "data" to fileNames) -// eventSink?.success(returnData) } - LiveEventBus.get(InterfaceEvent.ER2.EventEr2SetTime).observe(this.mainActivity) { println("EventEr2SetTime") - // Get Device Info BleServiceHelper.BleServiceHelper.er2GetInfo(model) // ecgRTTask.run() } @@ -282,25 +282,69 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi ecgData.startTime = startTime ecgList.add(ecgData) print(ecgList) -// val returnData = -// mapOf("type" to "fileDetail", "data" to gson.toJson(ecgList)) -// eventSink?.success(returnData) } ecgFileNames.removeAt(0) readFileForEr2() } - LiveEventBus.get(InterfaceEvent.ER2.EventEr2RtData).observe(this.mainActivity) { val data = it.data as RtData println("EventEr2RtData") val returnData = mapOf("type" to "RealTimeDataECG", "data" to gson.toJson(data)) println(returnData) eventSink?.success(returnData) -// DataController.receive(data.wave.ecgFloats) -// hr.text = "${data.param.hr}" -// data_log.text = "${data.param}" + } + } + + if (deviceName.contains("ER1")) { + LiveEventBus.get(InterfaceEvent.ER1.EventEr1Info).observe(this.mainActivity) { + val data = it.data as com.lepu.blepro.ext.er1.DeviceInfo + println("ER1 INFO DATA: $data") + val returnData = mapOf("type" to "infoData", "data" to data.toString()) + eventSink?.success(returnData) + BleServiceHelper.BleServiceHelper.startRtTask(model) + } + LiveEventBus.get(InterfaceEvent.ER1.EventEr1ResetFactory).observe(this.mainActivity) { + val data = it.data as Boolean + } + LiveEventBus.get(InterfaceEvent.ER1.EventEr1FileList).observe(this.mainActivity) { + BleServiceHelper.BleServiceHelper.stopRtTask(model) + ecgFileNames = it.data as ArrayList + readFileForEr1() + } + LiveEventBus.get(InterfaceEvent.ER1.EventEr1SetTime).observe(this.mainActivity) { + println("EventEr1SetTime") + BleServiceHelper.BleServiceHelper.er1GetInfo(model) + } + LiveEventBus.get(InterfaceEvent.ER1.EventEr1ReadFileComplete).observe(this.mainActivity) { + println("EventEr1ReadFileComplete") + val rawFile = getOffset(it.model, ecgFileNames[0], "") + val data = it.data as Er1File + + val file = if (rawFile.isEmpty()) { + Er1EcgFile(data.content) + } else { + Er1EcgFile(rawFile) + } + val ecgShorts = Er1Decompress.unCompressAlgECG(file.waveData) + val ecgData = EcgData() + val startTime = DateUtil.getSecondTimestamp(data.fileName.replace("R", "")) + ecgData.fileName = data.fileName + ecgData.duration = file.recordingTime + ecgData.shortData = ecgShorts + ecgData.startTime = startTime + ecgList.add(ecgData) + + ecgFileNames.removeAt(0) + readFileForEr1() + } + LiveEventBus.get(InterfaceEvent.ER1.EventEr1RtData).observe(this.mainActivity) { + val data = it.data as com.lepu.blepro.ext.er1.RtData + println("EventEr2RtData") + val returnData = mapOf("type" to "RealTimeDataECG", "data" to gson.toJson(data)) + println(returnData) + eventSink?.success(returnData) // sampling rate:125HZ // mV = n * 0.002467(data.wave.ecgFloats = data.wave.ecgShorts * 0.002467) // data.param.batteryState:0(no charge),1(charging),2(charging complete),3(low battery) @@ -312,9 +356,7 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi } - // OXYMETER - if (deviceName == "POD-1_SN8187" || deviceName == "PC-60FW") { //DONE LiveEventBus.get(InterfaceEvent.PC60Fw.EventPC60FwRtParam).observe(this.mainActivity) { val data = it.data as RtParam @@ -326,6 +368,7 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi } } + if (deviceName == "O2M 1670" || deviceName == "O2Ring 4135") { // DONE rtHandler.removeCallbacks(rtTask) rtHandler.post(rtTask) @@ -339,13 +382,12 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi } } - if (deviceName.contains("SP-20", ignoreCase = true)) { //DONE + if (deviceName.contains("SP-20", ignoreCase = true)) { //DONE LiveEventBus.get(InterfaceEvent.SP20.EventSp20SetTime).observe(this.mainActivity) { println("EventSp20SetTime") BleServiceHelper.BleServiceHelper.bp2GetInfo(model) } - LiveEventBus.get(InterfaceEvent.SP20.EventSp20DeviceInfo).observe(this.mainActivity) { val data = it.data as com.lepu.blepro.ext.sp20.DeviceInfo println("EventSp20DeviceInfo: $data") @@ -353,7 +395,6 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi eventSink?.success(returnData) BleServiceHelper.BleServiceHelper.startRtTask(model) } - LiveEventBus.get(InterfaceEvent.SP20.EventSp20RtParam).observe(this.mainActivity) { val data = it.data as com.lepu.blepro.ext.sp20.RtParam println("OxyRtParam: $data") @@ -366,19 +407,16 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi println("OxyRtParam: $data") } - } //BLOOD PRESSURE if (deviceName.contains("BP2", ignoreCase = true)) { - LiveEventBus.get(InterfaceEvent.BP2.EventBp2SyncTime).observe(this.mainActivity) { println("EventBp2SyncTime") // Get Device Info BleServiceHelper.BleServiceHelper.bp2GetInfo(model) } - LiveEventBus.get(InterfaceEvent.BP2.EventBp2Info).observe(this.mainActivity) { val data = it.data as com.lepu.blepro.ext.bp2.DeviceInfo println("BP2 INFO DATA: $data") @@ -386,14 +424,12 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi eventSink?.success(returnData) BleServiceHelper.BleServiceHelper.startRtTask(model) } - LiveEventBus.get(InterfaceEvent.BP2.EventBp2FileList).observe(this.mainActivity) { BleServiceHelper.BleServiceHelper.stopRtTask(model) ecgFileNames = it.data as ArrayList println("EventBp2FileList: ${it.data}") readFileForBp2() } - LiveEventBus.get(InterfaceEvent.BP2.EventBp2ReadFileComplete).observe(this.mainActivity) { val data = it.data as Bp2File // data.type: 1(BP), 2(ECG) @@ -420,7 +456,6 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi ecgFileNames.removeAt(0) readFileForBp2() } - LiveEventBus.get(InterfaceEvent.BP2.EventBp2RtData).observe(this.mainActivity) { val data = it.data as com.lepu.blepro.ext.bp2.RtData // data.status: RtStatus @@ -541,6 +576,15 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi } } + private fun readFileForEr1() { + if (ecgFileNames.size == 0) { + val returnData = mapOf("type" to "FileDetail", "data" to gson.toJson(ecgList)) + eventSink?.success(returnData) + } else { + BleServiceHelper.BleServiceHelper.er1ReadFile(model, ecgFileNames[0]) + } + } + private fun readFileForBp2() { if (ecgFileNames.size == 0) { val returnData = mapOf("type" to "FileDetail", "data" to gson.toJson(ecgList)) @@ -550,6 +594,22 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi } } + // sdk save the original file name : userId + fileName + .dat + private fun getOffset(model: Int, fileName: String, userId: String): ByteArray { + val trimStr = HexString.trimStr(fileName) + BleServiceHelper.BleServiceHelper.rawFolder?.get(model)?.let { s -> + val mFile = File(s, "$userId$trimStr.dat") + if (mFile.exists()) { + FileUtils.readFileToByteArray(mFile)?.let { + return it + } + } else { + return ByteArray(0) + } + } + return ByteArray(0) + } + private fun getECGFilesList(device: List) { //Get ECG File List val deviceName = device[0] diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/DecompressUtil.java b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/DecompressUtil.java deleted file mode 100644 index c5674818..00000000 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/DecompressUtil.java +++ /dev/null @@ -1,26 +0,0 @@ -//package com.cloud.diplomaticquarterapp.ble.utils; -// -//// -//// Source code recreated from a .class file by IntelliJ IDEA -//// (powered by FernFlower decompiler) -//// -// -// -//import doac.docd; -//import doag.doad; -//import doag.doae; -// -//public class DecompressUtil { -// private static doad er1Decompress; -// private static doae er3Decompress; -// private static docd waveFile; -// private static int leadType; -// -// public DecompressUtil() { -// } -// -// public static short[] er1Decompress(byte[] var0) { -// return doad. do (var0); -// } -// -//} diff --git a/lib/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart b/lib/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart index af692392..f886c193 100644 --- a/lib/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart +++ b/lib/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart @@ -55,7 +55,7 @@ class MyTrackersViewModel extends ChangeNotifier { ], "ECGTracker": [ {"model": "DuoEK"}, - {"model": ""}, + {"model": "ER1"}, {"model": ""}, {"model": ""}, ], @@ -67,7 +67,7 @@ class MyTrackersViewModel extends ChangeNotifier { ], }; - List ecgEnabledDevices = ["BP2 0567", "DuoEK"]; + List ecgEnabledDevices = ["BP2 0567", "DuoEK", "ER1"]; //************************************* OXYMETER *************************************