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 0e2e32e8..4fdd4699 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 @@ -9,6 +9,7 @@ import android.os.Build import android.os.Bundle import android.os.Handler import android.provider.Settings +import android.util.Log import android.widget.Toast import androidx.core.app.ActivityCompat.startActivityForResult import com.ejada.hmg.MainActivity @@ -19,6 +20,7 @@ import io.flutter.plugin.common.EventChannel import android.util.SparseArray import androidx.annotation.RequiresApi import com.cloud.diplomaticquarterapp.ble.utils.EcgData +import com.cloud.diplomaticquarterapp.ble.utils.RTBP2Data import com.google.gson.Gson @@ -29,6 +31,10 @@ import com.lepu.blepro.event.EventMsgConst import com.lepu.blepro.event.EventMsgConst.Ble.* import com.lepu.blepro.event.InterfaceEvent import com.lepu.blepro.ext.BleServiceHelper +import com.lepu.blepro.ext.bp2.Bp2File +import com.lepu.blepro.ext.bp2.BpFile +import com.lepu.blepro.ext.bp2.EcgFile +import com.lepu.blepro.ext.bp2.RtBpIng import com.lepu.blepro.ext.er2.DeviceInfo import com.lepu.blepro.ext.er2.Er2EcgFile import com.lepu.blepro.ext.er2.Er2File @@ -51,8 +57,10 @@ class BleBridge( private var eventSink: EventChannel.EventSink? = null private var ecgFileNames = arrayListOf() + private var bpFileNames = arrayListOf() var ecgList: ArrayList = arrayListOf() + val gson = Gson() companion object { @@ -61,6 +69,7 @@ class BleBridge( private const val SCAN_DEVICE = "scan" private const val SCAN_DEVICE_EKG = "scan_ekg" private const val EKG_FILES_LIST = "ekg_files_list" + private const val BP2_FILES_LIST = "bp2_files_list" private const val EKG_FILE_DETAIL = "ekg_file_detail" private const val DISCONNECT_DEVICE = "disconnect_device" } @@ -137,7 +146,10 @@ class BleBridge( private var rtTask = RtTask() private var ecgRTHandler = Handler() - private var ecgRTTask = ECGRtTask() + + private var br2Handler = Handler() + private var bp2rtTask = Bp2RtTask() + inner class RtTask : Runnable { override fun run() { @@ -146,6 +158,13 @@ class BleBridge( } } + inner class Bp2RtTask : Runnable { + override fun run() { + br2Handler.postDelayed(bp2rtTask, 1000) + BleServiceHelper.BleServiceHelper.startRtTask(model) + } + } + inner class ECGRtTask : Runnable { override fun run() { ecgRTHandler.postDelayed(rtTask, 1000) @@ -153,6 +172,7 @@ class BleBridge( } } + @SuppressLint("NewApi") fun create() { channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) @@ -167,6 +187,8 @@ class BleBridge( // scanDeviceEKG(methodCall, result) } else if (methodCall.method == EKG_FILES_LIST) { getEKGFilesList() + } else if (methodCall.method == BP2_FILES_LIST) { + getBP2FilesList() } else if (methodCall.method == EKG_FILE_DETAIL) { val fileName = methodCall.arguments; getEKGFileDetail(fileName.toString()) @@ -192,148 +214,229 @@ class BleBridge( BleServiceHelper.BleServiceHelper.disconnect(false) } - fun scanDevice(methodCall: MethodCall, result: MethodChannel.Result) { + private fun scanDevice(methodCall: MethodCall, result: MethodChannel.Result) { println("This is Test of Scanning") - 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) { - var deviceName: String = "" - for (b in BluetoothController.getDevices()) { - // println(b.name) - if (b.name.contains("POD-1_SN8187", true) || b.name.contains( - "O2M 1670", - true - ) || b.name.contains("DuoEK", true) - ) { - model = b.model - deviceName = b.name - BleServiceHelper.BleServiceHelper.setInterfaces(b.model) - BleServiceHelper.BleServiceHelper.stopScan() - BleServiceHelper.BleServiceHelper.connect( - this.mainActivity.applicationContext, - b.model, - b.device - ) - } + 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) { + var deviceName: String = "" + for (b in BluetoothController.getDevices()) { + // println(b.name) +// if (b.name.contains("POD-1_SN8187", true) || b.name.contains( +// "O2M 1670", true +// ) || b.name.contains("DuoEK", true) || b.name.contains("BP2", true) +// + + if (b.name.contains("BP2", true)) { + println("connecting bp2") + + model = b.model + deviceName = b.name + BleServiceHelper.BleServiceHelper.setInterfaces(b.model) + BleServiceHelper.BleServiceHelper.stopScan() + BleServiceHelper.BleServiceHelper.connect( + this.mainActivity.applicationContext, b.model, b.device + ) } + } - println("EventDeviceFound") - println(deviceName) + println("EventDeviceFound") + println(deviceName) - if (deviceName == "POD-1_SN8187") { - LiveEventBus.get(InterfaceEvent.PC60Fw.EventPC60FwRtParam) - .observe(this.mainActivity) { - val data = it.data as RtParam - println("OXY DATA POD-1W: $data") - eventSink?.success(data.toString()) - } + if (deviceName == "POD-1_SN8187") { + LiveEventBus.get(InterfaceEvent.PC60Fw.EventPC60FwRtParam).observe(this.mainActivity) { + val data = it.data as RtParam + println("OXY DATA POD-1W: $data") + eventSink?.success(data.toString()) } + } - if (deviceName.contains("DuoEK", ignoreCase = true)) { - LiveEventBus.get(InterfaceEvent.ER2.EventEr2Info) - .observe(this.mainActivity) { - val data = it.data as DeviceInfo - println("DuoEK INFO DATA: $data") - val returnData = mapOf("type" to "infoData", "data" to data.toString()) - eventSink?.success(returnData) - } - LiveEventBus.get(InterfaceEvent.ER2.EventEr2FileList) - .observe(this.mainActivity) { - BleServiceHelper.BleServiceHelper.stopRtTask(model) - ecgFileNames = it.data as ArrayList - readFile() + if (deviceName.contains("DuoEK", ignoreCase = true)) { + LiveEventBus.get(InterfaceEvent.ER2.EventEr2Info).observe(this.mainActivity) { + val data = it.data as DeviceInfo + println("DuoEK INFO DATA: $data") + val returnData = mapOf("type" to "infoData", "data" to data.toString()) + eventSink?.success(returnData) + } + LiveEventBus.get(InterfaceEvent.ER2.EventEr2FileList).observe(this.mainActivity) { + BleServiceHelper.BleServiceHelper.stopRtTask(model) + ecgFileNames = it.data as ArrayList + readFile() // 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) + LiveEventBus.get(InterfaceEvent.ER2.EventEr2SetTime).observe(this.mainActivity) { + println("EventEr2SetTime") + // Get Device Info + BleServiceHelper.BleServiceHelper.er2GetInfo(model) // ecgRTTask.run() - } - LiveEventBus.get(InterfaceEvent.ER2.EventEr2ReadFileComplete) - .observe(this.mainActivity) { - println("EventEr2ReadFileComplete") - val data = it.data as Er2File - if (data.fileName.contains("R")) { - val file = Er2EcgFile(data.content) - 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) - print(ecgList) + } + LiveEventBus.get(InterfaceEvent.ER2.EventEr2ReadFileComplete).observe(this.mainActivity) { + println("EventEr2ReadFileComplete") + val data = it.data as Er2File + if (data.fileName.contains("R")) { + val file = Er2EcgFile(data.content) + 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) + print(ecgList) // val returnData = // mapOf("type" to "fileDetail", "data" to gson.toJson(ecgList)) // eventSink?.success(returnData) - } - ecgFileNames.removeAt(0) - readFile() - } - - 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) + } + ecgFileNames.removeAt(0) + readFile() + } + + 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}" - // 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) - // data.param.battery:0-100 - // data.param.recordTime:unit(s) - // data.param.curStatus:0(idle),1(preparing),2(measuring),3(saving file),4(saving succeed), - // 5(less than 30s, file not saved),6(6 retests),7(lead off) - } - + // 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) + // data.param.battery:0-100 + // data.param.recordTime:unit(s) + // data.param.curStatus:0(idle),1(preparing),2(measuring),3(saving file),4(saving succeed), + // 5(less than 30s, file not saved),6(6 retests),7(lead off) } - if (deviceName == "O2M 1670") { - rtHandler.removeCallbacks(rtTask) - rtHandler.post(rtTask) + } + + if (deviceName == "O2M 1670") { + rtHandler.removeCallbacks(rtTask) + rtHandler.post(rtTask) - LiveEventBus.get(InterfaceEvent.Oxy.EventOxyRtParamData) - .observe(this.mainActivity) { - val data = it.data as com.lepu.blepro.ext.oxy.RtParam - println("OXY DATA O2M: $data") - eventSink?.success(data.toString()) + LiveEventBus.get(InterfaceEvent.Oxy.EventOxyRtParamData).observe(this.mainActivity) { + val data = it.data as com.lepu.blepro.ext.oxy.RtParam + println("OXY DATA O2M: $data") + eventSink?.success(data.toString()) // tv_oxy.text = data.spo2.toString() // tv_pr.text = data.pr.toString() // tv_pi.text = data.pi.toString() // data_log.text = "$data" - // data.battery:0-100 - // data.batteryState:0(no charge),1(charging),2(charging complete) - // data.state:0(lead off),1(lead on),other(error) - } + // data.battery:0-100 + // data.batteryState:0(no charge),1(charging),2(charging complete) + // data.state:0(lead off),1(lead on),other(error) + } + } + + if (deviceName.contains("BP2", ignoreCase = true)) { + +// br2Handler.removeCallbacks(bp2rtTask) +// br2Handler.post(bp2rtTask) +// println("startRtTask") + + + 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") + val returnData = mapOf("type" to "infoData", "data" to data.toString()) + eventSink?.success(returnData) + BleServiceHelper.BleServiceHelper.startRtTask(model) + } + + + LiveEventBus.get(InterfaceEvent.BP2.EventBp2FileList).observe(this.mainActivity) { + bpFileNames = it.data as ArrayList + } + + + + LiveEventBus.get(InterfaceEvent.BP2.EventBp2ReadFileComplete).observe(this.mainActivity) { + val data = it.data as Bp2File + // data.type: 1(BP), 2(ECG) + println("LiveEventBus with BP2 : $data") + + if (data.type == 1) { + val file = BpFile(data.content) + // file.measureTime:unit(s) + println("BpFile : $file") + } else if (data.type == 2) { + + val file = EcgFile(data.content) + val ecgData = EcgData() + val startTime = DateUtil.getSecondTimestamp(data.fileName) + ecgData.fileName = data.fileName + ecgData.duration = file.recordingTime + ecgData.shortData = Er1Decompress.unCompressAlgECG(file.waveData) +// ecgData.shortData = FilterUtil.getEcgFileFilterData(it.model, data.content) + ecgData.startTime = startTime + ecgList.add(ecgData) + // sampling rate:125HZ + // mV = file.waveShortData * 0.003098 + // file.measureTime:unit(s) + // file.recordingTime:unit(s) + // file.connectCable: Whether the cable is connected + // file.diagnosis:EcgDiagnosis + // diagnosis.isRegular:Whether Regular ECG Rhythm + // diagnosis.isPoorSignal:Whether Unable to analyze + // diagnosis.isLeadOff:Whether Always lead off + // diagnosis.isFastHr:Whether Fast Heart Rate + // diagnosis.isSlowHr:Whether Slow Heart Rate + // diagnosis.isIrregular:Whether Irregular ECG Rhythm + // diagnosis.isPvcs:Whether Possible ventricular premature beats + // diagnosis.isHeartPause:Whether Possible heart pause + // diagnosis.isFibrillation:Whether Possible Atrial fibrillation + // diagnosis.isWideQrs:Whether Wide QRS duration + // diagnosis.isProlongedQtc:Whether QTc is prolonged + // diagnosis.isShortQtc:Whether QTc is short + println("EcgFile : $file") + } + bpFileNames.removeAt(0) + readFileForBp2() } + LiveEventBus.get(InterfaceEvent.BP2.EventBp2RtData).observe(this.mainActivity) { + val data = it.data as RTBP2Data + // data.status: RtStatus + // data.status.deviceStatus: 0(STATUS_SLEEP), 1(STATUS_MEMERY), 2(STATUS_CHARGE), 3(STATUS_READY), + // 4(STATUS_BP_MEASURING), 5(STATUS_BP_MEASURE_END), + // 6(STATUS_ECG_MEASURING), 7(STATUS_ECG_MEASURE_END), 20(STATUS_VEN) + // data.status.batteryStatus: 0(no charge), 1(charging), 2(charging complete), 3(low battery) + // data.status.percent: 0-100 + // data.param: RtParam + // data.param.paramDataType: 0(Bp measuring), 1(Bp end), 2(Ecg measuring), 3(Ecg end) + + println("EventBp2RtData FOR BP : $data") + val returnData = mapOf("type" to "RealTimeDataBP2", "data" to gson.toJson(data)) + println(returnData) + eventSink?.success(returnData) + } } + + + } val rawFolders = SparseArray() try { - BleServiceHelper.BleServiceHelper.initRawFolder(rawFolders) - .initService(this.mainActivity.application) + BleServiceHelper.BleServiceHelper.initRawFolder(rawFolders).initService(this.mainActivity.application) } catch (e: Exception) { println(e) @@ -342,19 +445,32 @@ class BleBridge( private fun readFile() { if (ecgFileNames.size == 0) { - val returnData = - mapOf("type" to "fileDetail", "data" to gson.toJson(ecgList)) + val returnData = mapOf("type" to "fileDetail", "data" to gson.toJson(ecgList)) eventSink?.success(returnData) } else { BleServiceHelper.BleServiceHelper.er2ReadFile(model, ecgFileNames[0]) } } + private fun readFileForBp2() { + if (ecgFileNames.size == 0) { + val returnData = mapOf("type" to "fileDetail", "data" to gson.toJson(ecgList)) + eventSink?.success(returnData) + } else { + BleServiceHelper.BleServiceHelper.bp2ReadFile(model, bpFileNames[0]) + } + } + private fun getEKGFilesList() { //Get EKG File List BleServiceHelper.BleServiceHelper.er2GetFileList(model) } + private fun getBP2FilesList() { + //Get EKG File List + BleServiceHelper.BleServiceHelper.bp2GetFileList(model) + } + private fun getEKGFileDetail(fileName: String) { // readFile() // BleServiceHelper.BleServiceHelper.er2ReadFile(model, fileName) diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/AlgorithmUtil.java b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/AlgorithmUtil.java new file mode 100644 index 00000000..1b1f8b9c --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/AlgorithmUtil.java @@ -0,0 +1,12 @@ +package com.cloud.diplomaticquarterapp.ble.utils; + +public class AlgorithmUtil { + public static native double[] filter(double var0, boolean var2); + + public static native short[] shortFilter(short[] var0); + + static { + System.loadLibrary("online-lib"); + System.loadLibrary("offline-lib"); + } +} 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 new file mode 100644 index 00000000..c5674818 --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/DecompressUtil.java @@ -0,0 +1,26 @@ +//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/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/FilterUtil.java b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/FilterUtil.java new file mode 100644 index 00000000..ef2d86ca --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/FilterUtil.java @@ -0,0 +1,49 @@ +//package com.cloud.diplomaticquarterapp.ble.utils; +// +//// +//// Source code recreated from a .class file by IntelliJ IDEA +//// (powered by FernFlower decompiler) +//// +// +// +//import doac.doba; +//import doac.dobn; +//import doac.docn; +// +//public class FilterUtil { +// public FilterUtil() { +// } +// +// public static short[] getEcgFileFilterData(int var0, byte[] var1) { +// if (var0 != 7 && var0 != 8) { +// if (var0 == 19) { +// return AlgorithmUtil.shortFilter((new doba(var1)).doan()); +// } +// +// if (var0 == 52) { +// return AlgorithmUtil.shortFilter((new docn("", var1, "")).doah()); +// } +// +// if (var0 != 77 && var0 != 127) { +// if (var0 == 32) { +// return AlgorithmUtil.shortFilter((new doba(var1)).doan()); +// } +// +// if (var0 != 33 && var0 != 74 && var0 != 75) { +// switch (var0) { +// case 145: +// case 146: +// case 147: +// case 148: +// case 149: +// break; +// default: +// return new short[0]; +// } +// } +// } +// } +// +// return AlgorithmUtil.shortFilter(DecompressUtil.er1Decompress((new dobn(var1)).doad())); +// } +//} diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/HexString.java b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/HexString.java new file mode 100644 index 00000000..91db13db --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/HexString.java @@ -0,0 +1,50 @@ +package com.cloud.diplomaticquarterapp.ble.utils; + +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +public class HexString { + private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); + + private HexString() { + } + + public static String bytesToHex(byte[] var0) { + char[] var1 = new char[var0.length * 2]; + + for(int var2 = 0; var2 < var0.length; ++var2) { + int var3 = var0[var2] & 255; + int var4 = var2 * 2; + char[] var5; + char[] var10001 = var5 = HEX_ARRAY; + int var10002 = var3; + var1[var4] = var5[var3 >>> 4]; + var3 = var4 + 1; + var1[var3] = var10001[var10002 & 15]; + } + + return new String(var1); + } + + public static byte[] hexToBytes(String var0) { + if (var0.length() % 2 == 1) { + throw new IllegalArgumentException("hexToBytes requires an even-length String parameter"); + } else { + int var1; + byte[] var2 = new byte[(var1 = var0.length()) / 2]; + + for(int var3 = 0; var3 < var1; var3 += 2) { + int var4 = var3 / 2; + var2[var4] = (byte)((Character.digit(var0.charAt(var3), 16) << 4) + Character.digit(var0.charAt(var3 + 1), 16)); + } + + return var2; + } + } + + public static String trimStr(String var0) { + return var0.trim(); + } +} diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/RTBP2Data.java b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/RTBP2Data.java new file mode 100644 index 00000000..36a61dba --- /dev/null +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/ble/utils/RTBP2Data.java @@ -0,0 +1,34 @@ +package com.cloud.diplomaticquarterapp.ble.utils; + +import com.lepu.blepro.ext.bp2.RtParam; +import com.lepu.blepro.ext.bp2.RtStatus; + +public class RTBP2Data { + + private RtStatus status; + private RtParam param; + + public RTBP2Data() { + } + + public RtStatus getStatus() { + return this.status; + } + + public void setStatus(RtStatus var1) { + this.status = var1; + } + + public RtParam getParam() { + return this.param; + } + + public void setParam(RtParam var1) { + this.param = var1; + } + + public String toString() { + return "RtData{status=" + this.status + ", param=" + this.param + '}'; + } + +} diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 0e107160..d93c2a0c 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -19,6 +19,7 @@ import 'package:diplomaticquarterapp/pages/landing/home_page_2.dart'; import 'package:diplomaticquarterapp/pages/medical/medical_profile_page_new.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/ecg_ble.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/spirometer.dart'; +import 'package:diplomaticquarterapp/pages/medical/my_trackers/viatom_devices/bp_tracker_ble.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/viatom_devices/ekg_tracker_ble.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/viatom_devices/oxymeter_ble.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/weight_scale_ble.dart'; @@ -572,7 +573,8 @@ class _LandingPageState extends State with WidgetsBindingObserver { }, onLoginClick: () { // login(); - Navigator.push(context, FadePage(page: EKG_BLE())); + Navigator.push(context, FadePage(page: BpTrackerBLE())); + // Navigator.push(context, FadePage(page: EKG_BLE())); }, onMedicalFileClick: () { changeCurrentTab(1); diff --git a/lib/pages/medical/my_trackers/viatom_devices/bp_tracker_ble.dart b/lib/pages/medical/my_trackers/viatom_devices/bp_tracker_ble.dart new file mode 100644 index 00000000..a179e2b1 --- /dev/null +++ b/lib/pages/medical/my_trackers/viatom_devices/bp_tracker_ble.dart @@ -0,0 +1,181 @@ +import 'dart:io'; + +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; +import 'package:diplomaticquarterapp/viatom_ble/ble_connect.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class BpTrackerBLE extends StatefulWidget { + @override + State createState() => _BpTrackerBLEState(); +} + +class _BpTrackerBLEState extends State { + EventChannel eventChannel = EventChannel('BLE-Platform-Bridge-Event'); + String receivedData = ''; + + final bpDataNotifier = ValueNotifier("start"); + + // String deviceName = "CheckMeO2"; + String deviceName = "BP2"; + + @override + void dispose() { + bpDataNotifier.dispose(); + super.dispose(); + BleChannel.disconnect(); + } + + @override + void initState() { + // TODO: implement initState + super.initState(); + } + + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: "BP Tracker", + showNewAppBar: true, + isShowDecPage: false, + showNewAppBarTitle: true, + backgroundColor: Color(0xffF8F8F8), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: DefaultButton( + "Get Info", + () async { + checkBLEPermissions(); + }, + textColor: Colors.white, + ), + ), + mWidth(16.0), + Expanded( + child: DefaultButton( + "Get Files List", + () async { + await BleChannel.getBP2FilesList(["bloodpressure", "BP2"]); + }, + textColor: Colors.white, + ), + ), + ], + ), + mHeight(20.0), + // _buildLiveLineChart() + ValueListenableBuilder( + valueListenable: bpDataNotifier, + builder: (context, value, _) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + value, + style: TextStyle(fontSize: 9.0), + ), + mHeight(24.0), + getFilesListWidget(), + mHeight(20.0), + ], + ); + }, + ), + ], + ), + ), + ), + ); + } + + Widget getFilesListWidget() { + return SizedBox(); + // return ListView.separated( + // shrinkWrap: true, + // physics: ScrollPhysics(), + // reverse: true, + // itemBuilder: (context, index) { + // return InkWell( + // onTap: () { + // showEKGFileDetails(ekgFileDetailResponseModelList[index]); + // }, + // child: getECGFileCard(ekgFileDetailResponseModelList[index])); + // // child: Text(ekgFileDetailResponseModelList[index].fileName)); + // }, + // itemCount: ekgFileDetailResponseModelList.length, + // separatorBuilder: (context, index) => SizedBox(height: 14), + // ); + } + + void checkBLEPermissions() async { + [Permission.location, Permission.storage, Permission.bluetooth, Permission.bluetoothConnect, Permission.bluetoothScan].request().then((status) async { + // startBLEConnection(); + + eventChannel.receiveBroadcastStream().listen((event) { + print('Received event---: $event'); + print(event['type']); + if (event['type'] == "infoData") { + bpDataNotifier.value = event['data']; + } + if (event['type'] == "fileList") { + // parseEKGFilesList(event['data']); + } + if (event['type'] == 'fileDetail') { + print("Received file data ---:"); + print(event['data']); + // parseEKGFileDetailObject(event['data']); + } + if (event['type'] == "RealTimeDataBP2") { + bpDataNotifier.value = event['data']; + // parseEKGRealTimeDataObject(event['data']); + } + }); + await BleChannel.getScanningResult(["bloodpressure", "BP2"]); + }); + } + + String getSPO2(String value) { + return "SpO2: " + value.split(",")[0].replaceAll("{spo2=", ""); + } + + String getPR(String value) { + return "Pulse Rate: " + value.split(",")[1].replaceAll("pr=", ""); + } + + String getPI(String value) { + return "Perfusion Index: " + value.split(",")[2].replaceAll("pi=", "") + "%"; + } + + String getSPO2iOS(String value) { + return "SpO2: " + value.split(",")[0]; + } + + String getPRiOS(String value) { + return "Pulse Rate: " + value.split(",")[1]; + } + +// List setResult(String value) { +// List values = value.split(","); +// +// print(values[0].replaceAll("{spo2=", "")); +// print(values[1].replaceAll("pr=", "")); +// print(values[2].replaceAll("pi=", "")); +// +// values.clear(); +// values.add(values[0].replaceAll("{spo2=", "")); +// values.add(values[1].replaceAll("pr=", "")); +// values.add(values[2].replaceAll("pi=", "")); +// +// return values; +// } +} diff --git a/lib/viatom_ble/ble_connect.dart b/lib/viatom_ble/ble_connect.dart index 35a264a1..fc8d8e44 100644 --- a/lib/viatom_ble/ble_connect.dart +++ b/lib/viatom_ble/ble_connect.dart @@ -3,7 +3,6 @@ import 'package:flutter/services.dart'; class BleChannel { static const platform = MethodChannel('BLE-Platform-Bridge'); - //BLE-Platform-Bridge static Future getScanningResult(List deviceType) async { try { @@ -29,6 +28,18 @@ class BleChannel { } } + static Future getBP2FilesList(List deviceType) async { + try { + print("----------Flutter Init -------"); + final String result = await platform.invokeMethod('bp2_files_list', deviceType); + print("----------Flutter Result -------"); + print(result); + return result; + } catch (e) { + return "Error: $e"; + } + } + static Future getEKGFileDetails(String fileName) async { try { print("----------Flutter Init -------"); @@ -52,5 +63,4 @@ class BleChannel { return "Error: $e"; } } - }