Completed the available ECG devices

dev_3.3_BLE
Faiz Hashmi 2 years ago
parent 8611903db0
commit 1cc77e7d32

@ -0,0 +1,17 @@
package com.cloud.diplomaticquarterapp.ble;
public class BPModelMeasuring {
public int pressure;
public int pr;
public boolean deflate;
public boolean pulse;
public BPModelMeasuring(int pressure, int pr, boolean deflate, boolean pulse) {
this.pressure = pressure;
this.pr = pr;
this.deflate = deflate;
this.pulse = pulse;
}
}

@ -0,0 +1,23 @@
package com.cloud.diplomaticquarterapp.ble;
public class BPModelResult {
public boolean deflate;
public int dia;
public int mean;
public int pr;
public int pressure;
public int result;
public int sys;
public BPModelResult(boolean deflate, int dia, int mean, int pr, int pressure, int result, int sys) {
this.deflate = deflate;
this.dia = dia;
this.mean = mean;
this.pr = pr;
this.pressure = pressure;
this.result = result;
this.sys = sys;
}
}

@ -10,6 +10,8 @@ import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.EventChannel
import android.util.SparseArray
import androidx.annotation.RequiresApi
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.google.gson.Gson
@ -44,7 +46,6 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
private var eventSink: EventChannel.EventSink? = null
private var ecgFileNames = arrayListOf<String>()
private var bpFileNames = arrayListOf<String>()
var ecgList: ArrayList<EcgData> = arrayListOf()
@ -53,13 +54,13 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
companion object {
private const val CHANNEL = "BLE-Platform-Bridge"
private const val EVENTCHANNEL = "BLE-Platform-Bridge-Event"
private const val SCAN_DEVICE = "scan"
private const val SCAN_DEVICE = "scanDevices"
private const val CONNECT_DEVICE = "connectDevice"
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"
private const val EKG_FILES_LIST = "ecgFilesList"
private const val FACTORY_RESET_ECG = "factoryResetECG"
private const val BP2_FILES_LIST = "bp2FilesList"
private const val DISCONNECT_DEVICE = "disconnectDevice"
}
@ -176,12 +177,11 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
} else if (methodCall.method == SCAN_DEVICE_EKG) {
// scanDeviceEKG(methodCall, result)
} else if (methodCall.method == EKG_FILES_LIST) {
getEKGFilesList()
getECGFilesList(methodCall.arguments as List<String>)
} else if (methodCall.method == FACTORY_RESET_ECG) {
factoryResetECG(methodCall.arguments as List<String>)
} else if (methodCall.method == BP2_FILES_LIST) {
getBP2FilesList()
} else if (methodCall.method == EKG_FILE_DETAIL) {
val fileName = methodCall.arguments;
getEKGFileDetail(fileName.toString())
} else {
result.notImplemented()
}
@ -220,8 +220,8 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
LiveEventBus.get<Bluetooth>(EventMsgConst.Discovery.EventDeviceFound).observe(this.mainActivity) {
val deviceName: String = ""
val returnData = mapOf("type" to "devicesList", "data" to gson.toJson(BluetoothController.getDevices()))
println("devicesList: ${BluetoothController.getDevices()}");
val returnData = mapOf("type" to "DevicesList", "data" to gson.toJson(BluetoothController.getDevices()))
println("DevicesList: ${BluetoothController.getDevices()}");
eventSink?.success(returnData)
println("EventDeviceFound")
@ -248,13 +248,13 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
val data = it.data as DeviceInfo
println("DuoEK INFO DATA: $data")
val returnData = mapOf("type" to "infoData", "data" to data.toString())
eventSink?.success(returnData)
BleServiceHelper.BleServiceHelper.startRtTask(model)
}
LiveEventBus.get<InterfaceEvent>(InterfaceEvent.ER2.EventEr2FileList).observe(this.mainActivity) {
BleServiceHelper.BleServiceHelper.stopRtTask(model)
ecgFileNames = it.data as ArrayList<String>
readFile()
readFileForEr2()
// val fileNames = it.data as ArrayList<String>
// println("DuoEK FileNames List: ${fileNames}")
// val returnData =
@ -288,13 +288,13 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
}
ecgFileNames.removeAt(0)
readFile()
readFileForEr2()
}
LiveEventBus.get<InterfaceEvent>(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))
val returnData = mapOf("type" to "RealTimeDataECG", "data" to gson.toJson(data))
println(returnData)
eventSink?.success(returnData)
// DataController.receive(data.wave.ecgFloats)
@ -388,7 +388,10 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
}
LiveEventBus.get<InterfaceEvent>(InterfaceEvent.BP2.EventBp2FileList).observe(this.mainActivity) {
bpFileNames = it.data as ArrayList<String>
BleServiceHelper.BleServiceHelper.stopRtTask(model)
ecgFileNames = it.data as ArrayList<String>
println("EventBp2FileList: ${it.data}")
readFileForBp2()
}
LiveEventBus.get<InterfaceEvent>(InterfaceEvent.BP2.EventBp2ReadFileComplete).observe(this.mainActivity) {
@ -403,35 +406,18 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
} else if (data.type == 2) {
val file = EcgFile(data.content)
val ecgShorts = Er1Decompress.unCompressAlgECG(file.waveData)
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.shortData = ecgShorts
ecgData.startTime = startTime
ecgList.add(ecgData)
// sampling rate125HZ
// mV = file.waveShortData * 0.003098
// file.measureTimeunits
// file.recordingTimeunits
// file.connectCable: Whether the cable is connected
// file.diagnosisEcgDiagnosis
// diagnosis.isRegularWhether Regular ECG Rhythm
// diagnosis.isPoorSignalWhether Unable to analyze
// diagnosis.isLeadOffWhether Always lead off
// diagnosis.isFastHrWhether Fast Heart Rate
// diagnosis.isSlowHrWhether Slow Heart Rate
// diagnosis.isIrregularWhether Irregular ECG Rhythm
// diagnosis.isPvcsWhether Possible ventricular premature beats
// diagnosis.isHeartPauseWhether Possible heart pause
// diagnosis.isFibrillationWhether Possible Atrial fibrillation
// diagnosis.isWideQrsWhether Wide QRS duration
// diagnosis.isProlongedQtcWhether QTc is prolonged
// diagnosis.isShortQtcWhether QTc is short
println("EcgFile : $file")
print(ecgList)
}
bpFileNames.removeAt(0)
ecgFileNames.removeAt(0)
readFileForBp2()
}
@ -450,20 +436,68 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
0 -> {
val bpIng = RtBpIng(data.param.paramData)
val returnData = mapOf("type" to "RealTimeDataBP2Measuring", "data" to gson.toJson(bpIng))
//class BpRtMeasuringModel {
// bool deflate;
// int pr;
// int pressure;
// bool pulse;
val bpMeasuring = BPModelMeasuring(bpIng.pressure, bpIng.pr, bpIng.isDeflate, bpIng.isPulse);
val returnData = mapOf("type" to "RealTimeDataBPMeasuring", "data" to gson.toJson(bpMeasuring))
eventSink?.success(returnData)
}
1 -> {
val bpResult = RtBpResult(data.param.paramData)
val returnData = mapOf("type" to "RealTimeDataBP2Result", "data" to gson.toJson(bpResult))
println("RealTimeDataBP2Result FOR BP : $returnData")
val bpModel = BPModelResult(bpResult.isDeflate, bpResult.dia, bpResult.mean, bpResult.pr, bpResult.pressure, bpResult.result, bpResult.sys);
val returnData = mapOf("type" to "RealTimeDataBPResult", "data" to gson.toJson(bpModel))
eventSink?.success(returnData)
}
2 -> {
val ecgIng = RtEcgIng(data.param.paramData)
val returnData = mapOf("type" to "RealTimeDataECGMeasuring", "data" to gson.toJson(ecgIng))
println("RealTimeDataECGMeasuring: $returnData")
eventSink?.success(returnData)
// hr.text = "${ecgIng.hr}"
// data_log.text = "lead status${if (ecgIng.isLeadOff) "lead off" else "lead on"}\n" +
// "pool signal${if (ecgIng.isPoolSignal) "yes" else "no"}\n" +
// "duration: ${ecgIng.curDuration} s"
// DataController.receive(data.param.ecgFloatsFilter)
// sampling rate250HZ
// mV = n * 0.003098 (data.param.ecgFloats = data.param.ecgShorts * 0.003098)
}
3 -> {
val ecgResult = RtEcgResult(data.param.paramData)
val returnData = mapOf("type" to "RealTimeDataECGResult", "data" to gson.toJson(ecgResult))
println("RealTimeDataECGResult: $returnData")
eventSink?.success(returnData)
// hr.text = "${ecgResult.hr}"
// data_log.text = "result${ecgResult.diagnosis.resultMess}\n" +
// "hr${ecgResult.hr}\n" +
// "qrs${ecgResult.qrs}\n" +
// "pvcs${ecgResult.pvcs}\n" +
// "qtc${ecgResult.qtc}"
// ecgResult.diagnosisEcgDiagnosis
// diagnosis.isRegularWhether Regular ECG Rhythm
// diagnosis.isPoorSignalWhether Unable to analyze
// diagnosis.isLeadOffWhether Always lead off
// diagnosis.isFastHrWhether Fast Heart Rate
// diagnosis.isSlowHrWhether Slow Heart Rate
// diagnosis.isIrregularWhether Irregular ECG Rhythm
// diagnosis.isPvcsWhether Possible ventricular premature beats
// diagnosis.isHeartPauseWhether Possible heart pause
// diagnosis.isFibrillationWhether Possible Atrial fibrillation
// diagnosis.isWideQrsWhether Wide QRS duration
// diagnosis.isProlongedQtcWhether QTc is prolonged
// diagnosis.isShortQtcWhether QTc is short
}
}
@ -474,6 +508,7 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun connectDevice(device: List<String>) {
println("connectDevice: $device");
@ -497,9 +532,9 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
}
private fun readFile() {
private fun readFileForEr2() {
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])
@ -508,26 +543,41 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi
private fun readFileForBp2() {
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.bp2ReadFile(model, bpFileNames[0])
BleServiceHelper.BleServiceHelper.bp2ReadFile(model, ecgFileNames[0])
}
}
private fun getEKGFilesList() {
//Get EKG File List
BleServiceHelper.BleServiceHelper.er2GetFileList(model)
private fun getECGFilesList(device: List<String>) {
//Get ECG File List
val deviceName = device[0]
println("deviceName: $deviceName and model: $model")
if (deviceName.contains("DuoEK")) {
BleServiceHelper.BleServiceHelper.er2GetFileList(model);
} else if (deviceName.contains("BP2")) {
BleServiceHelper.BleServiceHelper.bp2GetFileList(model);
}
}
private fun factoryResetECG(device: List<String>) {
val deviceName = device[0]
println("deviceName: $deviceName and model: $model")
if (deviceName.contains("DuoEK")) {
BleServiceHelper.BleServiceHelper.er2FactoryResetAll(model);
} else if (deviceName.contains("BP2")) {
BleServiceHelper.BleServiceHelper.bp2FactoryResetAll(model);
}
}
private fun getBP2FilesList() {
//Get EKG File List
//Get BP2 File List
BleServiceHelper.BleServiceHelper.bp2GetFileList(model)
}
private fun getEKGFileDetail(fileName: String) {
// readFile()
// BleServiceHelper.BleServiceHelper.er2ReadFile(model, fileName)
}
}

@ -1,5 +1,7 @@
import 'dart:developer';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/device_types/bloodpressure_connect_screen.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/device_types/ecg_connect_screen.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/device_types/oxymeter_connect_screen.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/ble_devices_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
@ -30,6 +32,36 @@ class _BleDevicesScreenState extends State<BleDevicesScreen> {
super.initState();
}
bool getIfECGAvailableInBPDevice(String name) {
int index = myTrackersVm.ecgEnabledDevices.indexWhere((deviceName) => deviceName == name);
return index != -1;
}
void onDeviceTapped(BleDeviceModel device) {
switch (device.deviceType) {
case TrackerTypeEnum.OxymeterTracker:
myTrackersVm.oxyRtModel = null;
Navigator.pushReplacement(context, FadePage(page: OxymeterConnectScreen(deviceModel: device)));
break;
case TrackerTypeEnum.BloodPressureTracker:
myTrackersVm.bpRtResultModel = null;
myTrackersVm.bpRtMeasuringModel = null;
myTrackersVm.bpCurrentStatus = null;
Navigator.pushReplacement(context, FadePage(page: BloodPressureConnectScreen(deviceModel: device, isEcgAvailable: getIfECGAvailableInBPDevice(device.name))));
break;
case TrackerTypeEnum.BloodSugarTracker:
// TODO: Handle this case.
break;
case TrackerTypeEnum.ECGTracker:
myTrackersVm.ecgRtModel = null;
Navigator.pushReplacement(context, FadePage(page: ECGConnectScreen(deviceModel: device)));
break;
case TrackerTypeEnum.AllInOneTracker:
// TODO: Handle this case.
break;
}
}
@override
Widget build(BuildContext context) {
return AppScaffold(
@ -68,10 +100,7 @@ class _BleDevicesScreenState extends State<BleDevicesScreen> {
itemBuilder: (BuildContext context, int index) {
BleDeviceModel device = myTrackerVm.devicesList[index];
return InkWell(
onTap: () {
myTrackerVm.oxyRtModel = null;
Navigator.pushReplacement(context, FadePage(page: OxymeterConnectScreen(deviceModel: device)));
},
onTap: () => onDeviceTapped(device),
child: MedicalProfileItem(
title: "${device.name}",
imagePath: 'tracker.svg',

@ -1,15 +1,20 @@
import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/ble_devices_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_toggle_tab/flutter_toggle_tab.dart';
class BloodPressureConnectScreen extends StatefulWidget {
final BleDeviceModel deviceModel;
final bool isEcgAvailable;
const BloodPressureConnectScreen({this.deviceModel});
const BloodPressureConnectScreen({this.deviceModel, this.isEcgAvailable = false});
@override
State<BloodPressureConnectScreen> createState() => _BloodPressureConnectScreenState();
@ -27,10 +32,286 @@ class _BloodPressureConnectScreenState extends State<BloodPressureConnectScreen>
@override
void dispose() {
myTrackersVm.bpCurrentStatus = null;
myTrackersVm.bpRtMeasuringModel = null;
myTrackersVm.bpRtResultModel = null;
myTrackersVm.ecgCurrentStatus = null;
myTrackersVm.ecgRtMeasuringModelFromBP = null;
myTrackersVm.ecgRtResultModelFromBP = null;
myTrackersVm.disConnectDevice();
super.dispose();
}
Widget buildBloodPressureUI(MyTrackersViewModel myTrackersViewModel) {
return Expanded(
child: ListView(
children: [
if (myTrackersViewModel.bpCurrentStatus == kRealTimeDataBPMeasuring) ...[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
mHeight(24.0),
Column(
children: [
Text(myTrackersViewModel.bpRtMeasuringModel.pressure.toString(), style: TextStyle(fontSize: 100, fontWeight: FontWeight.bold)),
Text("Pressure", style: TextStyle(fontSize: 20)),
],
),
mHeight(24.0),
],
),
] else if (myTrackersViewModel.bpCurrentStatus == kRealTimeDataBPResult) ...[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
mHeight(24.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Text("Dia", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.bpRtResultModel.dia.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("mmHg", style: TextStyle(fontSize: 10)),
],
),
Column(
children: [
Text("Sys", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.bpRtResultModel.sys.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("mmHg", style: TextStyle(fontSize: 10)),
],
),
Column(
children: [
Text("♥︎", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.bpRtResultModel.pr.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("/min", style: TextStyle(fontSize: 10)),
],
),
],
),
mHeight(30.0),
buildStatusForBP(myTrackersViewModel.bpRtResultModel.result),
mHeight(24.0),
],
),
] else ...[
Padding(
padding: const EdgeInsets.all(24.0),
child: Center(
child: Text(
"Some animation with the instruction",
style: TextStyle(fontSize: 9.0),
),
),
)
],
],
),
);
}
Widget buildECGUI(MyTrackersViewModel myTrackersViewModel) {
return Expanded(
child: ListView(
children: [
if (myTrackersViewModel.ecgCurrentStatus == kRealTimeDataECGMeasuring) ...[
mHeight(24.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Text("Duration", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.ecgRtMeasuringModelFromBP.curDuration.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("seconds", style: TextStyle(fontSize: 10)),
],
),
Column(
children: [
Text("♥︎", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.ecgRtMeasuringModelFromBP.hr.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("/min", style: TextStyle(fontSize: 10)),
],
),
],
),
mHeight(30.0),
] else if (myTrackersViewModel.ecgCurrentStatus == kRealTimeDataECGResult) ...[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
mHeight(24.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Text("Regular", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.ecgRtResultModelFromBP.diagnosis.isRegular ? "YES" : "NO", style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("", style: TextStyle(fontSize: 10)),
],
),
Column(
children: [
Text("♥︎", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.ecgRtResultModelFromBP.hr.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("/min", style: TextStyle(fontSize: 10)),
],
),
// Column(
// children: [
// Text("Heart Pause", style: TextStyle(fontSize: 20)),
// Text(myTrackersViewModel.ecgRtResultModelFromBP.diagnosis.isHeartPause ? "YES" : "NO", style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
// Text("", style: TextStyle(fontSize: 10)),
// ],
// ),
],
),
mHeight(30.0),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// children: [
// Column(
// children: [
// Text("Lead Off", style: TextStyle(fontSize: 20)),
// Text(myTrackersViewModel.ecgRtResultModelFromBP.diagnosis.isLeadOff ? "YES" : "NO", style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
// Text("", style: TextStyle(fontSize: 10)),
// ],
// ),
// Column(
// children: [
// Text("Poor Signal", style: TextStyle(fontSize: 20)),
// Text(myTrackersViewModel.ecgRtResultModelFromBP.diagnosis.isPoorSignal ? "YES" : "NO", style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
// Text("", style: TextStyle(fontSize: 10)),
// ],
// ),
// Column(
// children: [
// Text("PVCs", style: TextStyle(fontSize: 20)),
// Text(myTrackersViewModel.ecgRtResultModelFromBP.diagnosis.isPvcs ? "YES" : "NO", style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold)),
// Text("", style: TextStyle(fontSize: 10)),
// ],
// ),
// ],
// ),
mHeight(30.0),
buildStatusForECG(myTrackersViewModel.ecgRtResultModelFromBP.result),
],
),
] else ...[
Padding(
padding: const EdgeInsets.all(24.0),
child: Center(
child: Text(
"Some animation with the instruction",
style: TextStyle(fontSize: 9.0),
),
),
)
],
],
),
);
}
Widget buildStatusForBP(int result) {
String resultStatus = "";
if (result == 0) {
resultStatus = "Normal";
} else if (result == 1) {
resultStatus = "Unable to analyze(cuff is too loose, inflation is slow, slow air leakage, large air volume)";
} else if (result == 2) {
resultStatus = "Waveform disorder(arm movement or other interference detected during pumping)";
} else if (result == 3) {
resultStatus = "Weak signal, unable to detect pulse wave(clothes with interference sleeves)";
} else {
resultStatus = "Equipment error(valve blocking, over-range blood pressure measurement, serious cuff leakage, software system abnormality, hardware system error, and other abnormalities)";
}
return Column(
children: [
Center(child: Text("$resultStatus", style: TextStyle(fontSize: 20))),
if (result != 0) ...[
mHeight(24.0),
Center(child: Text("Press START/STOP Button on the device to restart.", style: TextStyle(fontSize: 15))),
],
],
);
}
Widget buildStatusForECG(int result) {
String resultStatus = "";
if (result == 0) {
// resultStatus = "Normal";
resultStatus = ""; // NO NEED TO SHOW "NORMAL"
} else if (result == 1) {
resultStatus = "Unable to analyze(cuff is too loose, inflation is slow, slow air leakage, large air volume)";
} else if (result == 2) {
resultStatus = "Waveform disorder(arm movement or other interference detected during pumping)";
} else if (result == 3) {
resultStatus = "Weak signal, unable to detect pulse wave(clothes with interference sleeves)";
} else {
resultStatus = "Equipment error(valve blocking, over-range blood pressure measurement, serious cuff leakage, software system abnormality, hardware system error, and other abnormalities)";
}
return Column(
children: [
Center(child: Text("$resultStatus", style: TextStyle(fontSize: 20))),
if (result != 0) ...[
mHeight(24.0),
Center(child: Text("Press LIST Button on the device to restart.", style: TextStyle(fontSize: 15))),
],
],
);
}
showHistoryDialog(BuildContext context) {
return showDialog(
context: context,
builder: (context) => Container(
decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(15)), color: Colors.white),
padding: const EdgeInsets.all(20),
margin: const EdgeInsets.symmetric(vertical: 35, horizontal: 30),
child: SingleChildScrollView(
child: Consumer(builder: (BuildContext context, MyTrackersViewModel myTrackersVm, Widget child) {
return Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Material(child: Center(child: Text("Files History", style: TextStyle(fontSize: 20)))),
if (myTrackersVm.filesLoader) ...[
Center(child: CircularProgressIndicator())
] else if (myTrackersVm.ecgHistoryFiles.isNotEmpty) ...[
myTrackersVm.getFilesListWidget(myTrackersVm.ecgHistoryFiles, context),
mHeight(15),
Row(
children: [
Expanded(
child: DefaultButton(
"Reset History",
() async {
myTrackersVm.clearEcgHistoryFiles();
myTrackersVm.factoryResetECG(widget.deviceModel);
// Navigator.pop(context);
},
textColor: Colors.white,
),
),
],
),
] else ...[
Material(child: Center(child: Text("No History Files to show", style: TextStyle(fontSize: 20)))),
]
],
);
}),
),
),
);
}
@override
Widget build(BuildContext context) {
return AppScaffold(
@ -39,80 +320,67 @@ class _BloodPressureConnectScreenState extends State<BloodPressureConnectScreen>
isShowDecPage: false,
showNewAppBarTitle: true,
backgroundColor: Color(0xffF8F8F8),
appBarIcons: [
if (myTrackersVm.isECGSelected) ...[
IconButton(
onPressed: () async {
myTrackersVm.updateFilesLoader(true);
showHistoryDialog(context);
await myTrackersVm.getEcgFilesList(widget.deviceModel);
},
icon: Icon(Icons.format_list_numbered_rounded),
),
],
IconButton(
onPressed: () {
AppSharedPreferences().remove(IS_LIVECARE_APPOINTMENT);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => LandingPage()),
(Route<dynamic> route) => false,
);
},
icon: Icon(Icons.home),
),
],
body: Padding(
padding: const EdgeInsets.all(24.0),
child: Consumer(
builder: (BuildContext context, MyTrackersViewModel myTrackersViewModel, Widget child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: ListView(
children: [
if (myTrackersViewModel.bpCurrentStatus == "RealTimeDataBP2Measuring") ...[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
mHeight(24.0),
Column(
children: [
Text(myTrackersViewModel.bpRtMeasuringModel.pressure.toString(), style: TextStyle(fontSize: 100, fontWeight: FontWeight.bold)),
Text("Pressure", style: TextStyle(fontSize: 20)),
],
),
mHeight(24.0),
],
),
] else if (myTrackersViewModel.bpCurrentStatus == "RealTimeDataBP2Result") ...[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
mHeight(24.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Text("Dia", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.bpRtResultModel.dia.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("mmHg", style: TextStyle(fontSize: 10)),
],
),
Column(
children: [
Text("Sys", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.bpRtResultModel.sys.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("mmHg", style: TextStyle(fontSize: 10)),
],
),
Column(
children: [
Text("♥︎", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.bpRtResultModel.pr.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("/min", style: TextStyle(fontSize: 10)),
],
),
],
),
mHeight(24.0),
],
),
] else ...[
Padding(
padding: const EdgeInsets.all(24.0),
child: Center(
child: Text(
"Some animation with the instruction",
style: TextStyle(fontSize: 9.0),
),
),
)
],
],
if (widget.isEcgAvailable) ...[
FlutterToggleTab(
borderRadius: 30,
height: 40,
width: 80,
selectedIndex: myTrackersViewModel.isECGSelected ? 1 : 0,
selectedBackgroundColors: [Color(0xffD02127), Color(0xffD02127)],
selectedTextStyle: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.w700),
unSelectedTextStyle: TextStyle(color: Colors.black87, fontSize: 14, fontWeight: FontWeight.w500),
labels: ["BP", "ECG"],
selectedLabelIndex: (index) {
if (index == 1 && myTrackersViewModel.bpCurrentStatus == kRealTimeDataBPMeasuring) {
return;
}
if (index == 0 && myTrackersViewModel.ecgCurrentStatus == kRealTimeDataECGMeasuring) {
return;
}
if (index == 0) {
myTrackersViewModel.updateIsECGSelected(false);
} else {
myTrackersViewModel.updateIsECGSelected(true);
}
setState(() {});
},
isScroll: false,
),
),
if (myTrackersViewModel.bpCurrentStatus != null) ...[
],
myTrackersViewModel.isECGSelected ? buildECGUI(myTrackersViewModel) : buildBloodPressureUI(myTrackersViewModel),
if (myTrackersViewModel.bpCurrentStatus != null || myTrackersViewModel.ecgCurrentStatus != null) ...[
Row(
children: [
Expanded(
@ -122,6 +390,9 @@ class _BloodPressureConnectScreenState extends State<BloodPressureConnectScreen>
myTrackersVm.bpCurrentStatus = null;
myTrackersVm.bpRtMeasuringModel = null;
myTrackersVm.bpRtResultModel = null;
myTrackersVm.ecgCurrentStatus = null;
myTrackersVm.ecgRtMeasuringModelFromBP = null;
myTrackersVm.ecgRtResultModelFromBP = null;
Navigator.pop(context);
},
textColor: Colors.white,

@ -0,0 +1,227 @@
import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/ble_devices_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ecg_file_detail_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/viatom_devices/ekg_chart_view.dart';
import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ECGConnectScreen extends StatefulWidget {
final BleDeviceModel deviceModel;
const ECGConnectScreen({this.deviceModel});
@override
State<ECGConnectScreen> createState() => _ECGConnectScreenState();
}
class _ECGConnectScreenState extends State<ECGConnectScreen> {
MyTrackersViewModel myTrackersVm;
@override
void initState() {
myTrackersVm = context.read<MyTrackersViewModel>();
myTrackersVm.connectDevice(widget.deviceModel);
super.initState();
}
@override
void dispose() {
myTrackersVm.disConnectDevice();
super.dispose();
}
Widget buildStatus(int currentStatus) {
String resultStatus = "";
if (currentStatus == 0) {
resultStatus = "Idle";
} else if (currentStatus == 1) {
resultStatus = "Preparing";
} else if (currentStatus == 2) {
resultStatus = "Measuring";
} else if (currentStatus == 3) {
resultStatus = "Saving File";
} else if (currentStatus == 4) {
resultStatus = "File Successfully Saved";
} else if (currentStatus == 5) {
resultStatus = "Can't measure before 30s, file was not saved";
} else if (currentStatus == 6) {
resultStatus = "Retests";
} else if (currentStatus == 7) {
resultStatus = "Lead Off";
} else {
resultStatus = "";
}
return Column(
children: [
Center(child: Text("$resultStatus", style: TextStyle(fontSize: 20))),
if (currentStatus == 5) ...[
mHeight(24.0),
Center(child: Text("Press hold on the device to restart.", style: TextStyle(fontSize: 15))),
],
],
);
}
showHistoryDialog(BuildContext context) {
return showDialog(
context: context,
builder: (context) => Container(
decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(15)), color: Colors.white),
padding: const EdgeInsets.all(20),
margin: const EdgeInsets.symmetric(vertical: 35, horizontal: 30),
child: SingleChildScrollView(
child: Consumer(builder: (BuildContext context, MyTrackersViewModel myTrackersVm, Widget child) {
return Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Material(child: Center(child: Text("Files History", style: TextStyle(fontSize: 20)))),
if (myTrackersVm.filesLoader) ...[
Center(child: CircularProgressIndicator())
] else if (myTrackersVm.ecgHistoryFiles.isNotEmpty) ...[
myTrackersVm.getFilesListWidget(myTrackersVm.ecgHistoryFiles, context),
mHeight(15),
Row(
children: [
Expanded(
child: DefaultButton(
"Reset History",
() async {
myTrackersVm.clearEcgHistoryFiles();
myTrackersVm.factoryResetECG(widget.deviceModel);
// Navigator.pop(context);
},
textColor: Colors.white,
),
),
],
),
] else ...[
Material(child: Center(child: Text("No History Files to show", style: TextStyle(fontSize: 20)))),
]
],
);
}),
),
),
);
}
@override
Widget build(BuildContext context) {
MyTrackersViewModel myTrackersViewModel = context.watch<MyTrackersViewModel>();
return AppScaffold(
appBarTitle: "${widget.deviceModel.name}",
showNewAppBar: true,
isShowDecPage: false,
showNewAppBarTitle: true,
backgroundColor: Color(0xffF8F8F8),
appBarIcons: [
IconButton(
onPressed: () async {
myTrackersViewModel.updateFilesLoader(true);
showHistoryDialog(context);
await myTrackersViewModel.getEcgFilesList(widget.deviceModel);
},
icon: Icon(Icons.format_list_numbered_rounded),
),
IconButton(
onPressed: () {
AppSharedPreferences().remove(IS_LIVECARE_APPOINTMENT);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => LandingPage()),
(Route<dynamic> route) => false,
);
},
icon: Icon(Icons.home),
),
],
body: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: ListView(
children: [
if (myTrackersViewModel.ecgRtModel != null) ...[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
mHeight(24.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Text("Record Time", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.ecgRtModel.param.recordTime.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("seconds", style: TextStyle(fontSize: 10)),
],
),
Column(
children: [
Text("♥︎", style: TextStyle(fontSize: 20)),
Text(myTrackersViewModel.ecgRtModel.param.hr.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)),
Text("/min", style: TextStyle(fontSize: 10)),
],
),
],
),
mHeight(30.0),
buildStatus(myTrackersViewModel.ecgRtModel.param.curStatus),
],
)
],
if (myTrackersViewModel.ecgRtModel == null) ...[
Padding(
padding: const EdgeInsets.all(24.0),
child: Center(
child: Text(
"Some animation with the instruction",
style: TextStyle(fontSize: 9.0),
),
),
),
]
],
),
),
if (myTrackersViewModel.ecgRtModel != null) ...[
mHeight(10.0),
Row(
children: [
Expanded(
flex: 2,
child: DefaultButton(
"Disconnect ${widget.deviceModel.name}",
() async {
myTrackersViewModel.ecgRtModel = null;
Navigator.pop(context);
},
textColor: Colors.white,
),
),
],
),
]
],
),
),
);
}
}

@ -85,6 +85,10 @@ class SelectTrackerType extends StatelessWidget {
showNewAppBar: true,
isHelp: true,
showNewAppBarTitle: true,
onTap: () {
context.read<MyTrackersViewModel>().disConnectDevice();
Navigator.pop(context);
},
appBarTitle: "Select Tracker",
body: Container(
child: SingleChildScrollView(

@ -13,11 +13,11 @@ class BleChannel {
static Future<String> scanResults(List<String> deviceType) async {
try {
String result;
print("----------Flutter Init -------");
print("----------Flutter scanResults -------");
// if (Platform.isIOS && deviceType[0] == "ekg") {
// result = await platform_ios_ekg.invokeMethod('scanEKG', deviceType);
// } else {
result = await platform.invokeMethod('scan');
result = await platform.invokeMethod('scanDevices');
// }
print("----------Flutter Result -------");
print(result);
@ -44,10 +44,10 @@ class BleChannel {
}
}
static Future<String> getEKGFilesList(List<String> deviceType) async {
static Future<String> getECGFilesList(List<String> device) async {
try {
print("----------Flutter Init -------");
final String result = await platform.invokeMethod('ekg_files_list', deviceType);
print("----------Flutter getECGFilesList -------");
final String result = await platform.invokeMethod('ecgFilesList', device);
print("----------Flutter Result -------");
print(result);
return result;
@ -56,10 +56,10 @@ class BleChannel {
}
}
static Future<String> getBP2FilesList(List<String> deviceType) async {
static Future<String> factoryResetECG(List<String> device) async {
try {
print("----------Flutter Init -------");
final String result = await platform.invokeMethod('bp2_files_list', deviceType);
print("----------Flutter duoEkFactoryReset -------");
final String result = await platform.invokeMethod('factoryResetECG', device);
print("----------Flutter Result -------");
print(result);
return result;
@ -68,10 +68,10 @@ class BleChannel {
}
}
static Future<String> getEKGFileDetails(String fileName) async {
static Future<String> getBP2FilesList(List<String> deviceType) async {
try {
print("----------Flutter Init -------");
final String result = await platform.invokeMethod('ekg_file_detail', fileName);
print("----------Flutter getBP2FilesList -------");
final String result = await platform.invokeMethod('bp2FilesList', deviceType);
print("----------Flutter Result -------");
print(result);
return result;
@ -82,8 +82,8 @@ class BleChannel {
static Future<String> disconnect() async {
try {
print("----------Flutter Init disconnect_device -------");
final String result = await platform.invokeMethod('disconnect_device');
print("----------Flutter disconnect -------");
final String result = await platform.invokeMethod('disconnectDevice');
print("----------Flutter Result -------");
print(result);
return result;

@ -1,8 +1,11 @@
import 'package:diplomaticquarterapp/pages/medical/my_trackers/my_trackers_view_model/my_trackers_view_model.dart';
class BleDeviceModel {
String macAddr;
int model;
String name;
int rssi;
TrackerTypeEnum deviceType;
BleDeviceModel({this.macAddr, this.model, this.name, this.rssi});
@ -11,19 +14,11 @@ class BleDeviceModel {
model = json['model'];
name = json['name'];
rssi = json['rssi'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['macAddr'] = this.macAddr;
data['model'] = this.model;
data['name'] = this.name;
data['rssi'] = this.rssi;
return data;
deviceType = TrackerTypeEnum.AllInOneTracker;
}
@override
String toString() {
return 'BleDeviceModel{macAddr: $macAddr, model: $model, name: $name, rssi: $rssi}';
return 'BleDeviceModel{macAddr: $macAddr, model: $model, name: $name, rssi: $rssi, deviceType: $deviceType}';
}
}

@ -56,3 +56,126 @@ class BpRtResultModel {
return data;
}
}
class ECGRtMeasuringModelFromBP {
int curDuration;
int hr;
bool leadOff;
bool poolSignal;
ECGRtMeasuringModelFromBP({this.curDuration, this.hr, this.leadOff, this.poolSignal});
ECGRtMeasuringModelFromBP.fromJson(Map<String, dynamic> json) {
curDuration = json['curDuration'];
hr = json['hr'];
leadOff = json['leadOff'];
poolSignal = json['poolSignal'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['curDuration'] = this.curDuration;
data['hr'] = this.hr;
data['leadOff'] = this.leadOff;
data['poolSignal'] = this.poolSignal;
return data;
}
}
class ECGRtResultModelFromBP {
Diagnosis diagnosis;
int hr;
int pvcs;
int qrs;
int qtc;
int result;
ECGRtResultModelFromBP({this.diagnosis, this.hr, this.pvcs, this.qrs, this.qtc, this.result});
ECGRtResultModelFromBP.fromJson(Map<String, dynamic> json) {
diagnosis = json['diagnosis'] != null ? new Diagnosis.fromJson(json['diagnosis']) : null;
hr = json['hr'];
pvcs = json['pvcs'];
qrs = json['qrs'];
qtc = json['qtc'];
result = json['result'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.diagnosis != null) {
data['diagnosis'] = this.diagnosis.toJson();
}
data['hr'] = this.hr;
data['pvcs'] = this.pvcs;
data['qrs'] = this.qrs;
data['qtc'] = this.qtc;
data['result'] = this.result;
return data;
}
}
class Diagnosis {
List<int> bytes;
bool isFastHr;
bool isFibrillation;
bool isHeartPause;
bool isIrregular;
bool isLeadOff;
bool isPoorSignal;
bool isProlongedQtc;
bool isPvcs;
bool isRegular;
bool isShortQtc;
bool isSlowHr;
bool isWideQrs;
Diagnosis(
{this.bytes,
this.isFastHr,
this.isFibrillation,
this.isHeartPause,
this.isIrregular,
this.isLeadOff,
this.isPoorSignal,
this.isProlongedQtc,
this.isPvcs,
this.isRegular,
this.isShortQtc,
this.isSlowHr,
this.isWideQrs});
Diagnosis.fromJson(Map<String, dynamic> json) {
bytes = json['bytes'].cast<int>();
isFastHr = json['isFastHr'];
isFibrillation = json['isFibrillation'];
isHeartPause = json['isHeartPause'];
isIrregular = json['isIrregular'];
isLeadOff = json['isLeadOff'];
isPoorSignal = json['isPoorSignal'];
isProlongedQtc = json['isProlongedQtc'];
isPvcs = json['isPvcs'];
isRegular = json['isRegular'];
isShortQtc = json['isShortQtc'];
isSlowHr = json['isSlowHr'];
isWideQrs = json['isWideQrs'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['bytes'] = this.bytes;
data['isFastHr'] = this.isFastHr;
data['isFibrillation'] = this.isFibrillation;
data['isHeartPause'] = this.isHeartPause;
data['isIrregular'] = this.isIrregular;
data['isLeadOff'] = this.isLeadOff;
data['isPoorSignal'] = this.isPoorSignal;
data['isProlongedQtc'] = this.isProlongedQtc;
data['isPvcs'] = this.isPvcs;
data['isRegular'] = this.isRegular;
data['isShortQtc'] = this.isShortQtc;
data['isSlowHr'] = this.isSlowHr;
data['isWideQrs'] = this.isWideQrs;
return data;
}
}

@ -1,13 +1,13 @@
class EKGFileDetailResponseModel {
class ECGFileDetailModel {
int duration;
String fileName;
List<int> shortData;
int startTime;
EKGFileDetailResponseModel(
ECGFileDetailModel(
{this.duration, this.fileName, this.shortData, this.startTime});
EKGFileDetailResponseModel.fromJson(Map<String, dynamic> json) {
ECGFileDetailModel.fromJson(Map<String, dynamic> json) {
duration = json['duration'];
fileName = json['fileName'];
shortData = json['shortData'].cast<int>();

@ -1,10 +1,10 @@
class EKGRealTimeDataResponseModel {
class ECGRtModel {
Param param;
Wave wave;
EKGRealTimeDataResponseModel({this.param, this.wave});
ECGRtModel({this.param, this.wave});
EKGRealTimeDataResponseModel.fromJson(Map<String, dynamic> json) {
ECGRtModel.fromJson(Map<String, dynamic> json) {
param = json['param'] != null ? new Param.fromJson(json['param']) : null;
wave = json['wave'] != null ? new Wave.fromJson(json['wave']) : null;
}

@ -1,4 +1,4 @@
class OxyRtParamModel {
class OxyRtModel {
int battery;
bool isCheckProbe;
bool isProbeOff;
@ -7,9 +7,9 @@ class OxyRtParamModel {
int pr;
int spo2;
OxyRtParamModel({this.battery, this.isCheckProbe, this.isProbeOff, this.isPulseSearching, this.pi, this.pr, this.spo2});
OxyRtModel({this.battery, this.isCheckProbe, this.isProbeOff, this.isPulseSearching, this.pi, this.pr, this.spo2});
OxyRtParamModel.fromJson(Map<String, dynamic> json) {
OxyRtModel.fromJson(Map<String, dynamic> json) {
battery = json['battery'];
isCheckProbe = json['isCheckProbe'];
isProbeOff = json['isProbeOff'];

@ -2,7 +2,13 @@ import 'dart:convert';
import 'dart:developer';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/ble_devices_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/bp_rt_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/oxy_rt_param_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ecg_file_detail_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ecg_rt_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/oxy_rt_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/viatom_devices/ekg_chart_view.dart';
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
import 'package:flutter/services.dart';
import 'package:flutter/cupertino.dart';
import 'package:permission_handler/permission_handler.dart';
@ -11,6 +17,17 @@ import 'package:flutter/material.dart';
enum TrackerTypeEnum { OxymeterTracker, BloodPressureTracker, BloodSugarTracker, ECGTracker, AllInOneTracker }
//NativeEventNames
String kRealTimeDataBPMeasuring = "RealTimeDataBPMeasuring";
String kRealTimeDataBPResult = "RealTimeDataBPResult";
String kOxyRtParam = "OxyRtParam";
String kDevicesList = "DevicesList";
String kRealTimeDataECGMeasuring = "RealTimeDataECGMeasuring"; // This is for the device that measures BP and ECG also Like BP2 0567
String kRealTimeDataECGResult = "RealTimeDataECGResult";
String kRealTimeDataECG = "RealTimeDataECG";
String kFileDetail = "FileDetail";
class MyTrackersViewModel extends ChangeNotifier {
EventChannel eventChannel = EventChannel('BLE-Platform-Bridge-Event');
@ -25,7 +42,7 @@ class MyTrackersViewModel extends ChangeNotifier {
{"model": "O2Ring"}, // DONE
],
"BloodPressureTracker": [
{"model": "BP2"},
{"model": "BP2"}, //Done
{"model": ""},
{"model": ""},
{"model": ""},
@ -50,12 +67,14 @@ class MyTrackersViewModel extends ChangeNotifier {
],
};
List<String> ecgEnabledDevices = ["BP2 0567", "DuoEK"];
//************************************* OXYMETER *************************************
OxyRtParamModel oxyRtModel;
OxyRtModel oxyRtModel;
void updateOxyRtModel(Map<String, dynamic> mapData) {
oxyRtModel = OxyRtParamModel.fromJson(mapData);
oxyRtModel = OxyRtModel.fromJson(mapData);
notifyListeners();
}
@ -82,20 +101,120 @@ class MyTrackersViewModel extends ChangeNotifier {
notifyListeners();
}
bool isECGSelected = false;
updateIsECGSelected(var value) {
isECGSelected = value;
notifyListeners();
}
//************************************* ECG *************************************
bool filesLoader = false;
updateFilesLoader(var value) {
filesLoader = value;
}
ECGRtModel ecgRtModel;
void updateEcgRtModel(Map<String, dynamic> mapData) {
ecgRtModel = ECGRtModel.fromJson(mapData);
notifyListeners();
}
List<ECGFileDetailModel> ecgHistoryFiles = [];
updateEcgHistoryFiles(var value) {
ecgHistoryFiles = value;
notifyListeners();
}
clearEcgHistoryFiles() {
ecgHistoryFiles.clear();
notifyListeners();
}
parseEcgHistoryFiles(String mapData) {
ecgHistoryFiles.clear();
json.decode(mapData).forEach((v) {
ecgHistoryFiles.add(new ECGFileDetailModel.fromJson(v));
});
notifyListeners();
}
String ecgCurrentStatus;
updateEcgCurrentStatus(var value) {
ecgCurrentStatus = value;
notifyListeners();
}
ECGRtMeasuringModelFromBP ecgRtMeasuringModelFromBP;
void updateEcgRtMeasuringModelFromBP(Map<String, dynamic> mapData) {
ecgRtMeasuringModelFromBP = ECGRtMeasuringModelFromBP.fromJson(mapData);
notifyListeners();
}
ECGRtResultModelFromBP ecgRtResultModelFromBP;
void updateEcgRtResultModelFromBP(Map<String, dynamic> mapData) {
ecgRtResultModelFromBP = ECGRtResultModelFromBP.fromJson(mapData);
notifyListeners();
}
Widget getFilesListWidget(List<ECGFileDetailModel> filesList, BuildContext context) {
return Material(
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.7,
child: ListView.separated(
itemCount: filesList.length,
separatorBuilder: (context, index) => SizedBox(height: 14),
shrinkWrap: true,
reverse: false,
itemBuilder: (context, index) {
ECGFileDetailModel ecgFileDetailModel = filesList[index];
return InkWell(
onTap: () => Navigator.push(context, FadePage(page: EKGChartView(ekgFileDetailResponseModel: ecgFileDetailModel))),
child: Container(
decoration: cardRadius(12),
padding: EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(ecgFileDetailModel.fileName),
mHeight(6.0),
Text("Duration: ${ecgFileDetailModel.duration} seconds"),
mHeight(6.0),
Text("Date: ${DateUtil.getDayMonthYearHourMinuteDateFormatted(DateTime.fromMillisecondsSinceEpoch((ecgFileDetailModel.startTime * 1000)))}"),
],
),
),
);
},
),
),
);
}
void filterOutTheSearchedDevices(List<BleDeviceModel> allDevices) {
devicesList.clear();
notifyListeners();
if (devicesInfoJson.containsKey(currentSelectedTrackerType.name)) {
allDevices.forEach((foundDevice) {
List devicesInSelectedType = devicesInfoJson[currentSelectedTrackerType.name];
for (var device in devicesInSelectedType) {
log("foundDevice.name: ${foundDevice.name.toString()}");
log("device['model']: ${device['model']}");
if (device['model'] != "" && foundDevice.name.contains(device['model'])) {
devicesList.add(foundDevice);
allDevices.forEach(
(foundDevice) {
List devicesInSelectedType = devicesInfoJson[currentSelectedTrackerType.name];
for (var device in devicesInSelectedType) {
log("foundDevice.name: ${foundDevice.name.toString()}");
foundDevice.deviceType = currentSelectedTrackerType;
log("device['model']: ${device['model']}");
if (device['model'] != "" && foundDevice.name.contains(device['model'])) {
devicesList.add(foundDevice);
}
}
}
});
},
);
notifyListeners();
}
}
@ -113,34 +232,56 @@ class MyTrackersViewModel extends ChangeNotifier {
}
Future<void> startSearchingForTracker() async {
log("selectedStracker: ${currentSelectedTrackerType.name}");
log("selectedTracker: ${currentSelectedTrackerType.name}");
await checkBLEPermissions();
eventChannel.receiveBroadcastStream().listen((event) {
print('Received event---: $event');
print(event['type']);
if (event['type'] == "devicesList") {
// Get Devices List
if (event['type'] == kDevicesList) {
parsesDevicesList(json.decode(event['data']) as List);
}
if (event['type'] == "OxyRtParam") {
// Get Oxymeter Readings
if (event['type'] == kOxyRtParam) {
updateOxyRtModel(json.decode(event['data']));
}
if (event['type'] == "fileList") {
print(event['data']);
}
if (event['type'] == 'fileDetail') {
print(event['data']);
}
if (event['type'] == "RealTimeDataBP2Measuring") {
// Get Blood Pressure Readings while measuring
if (event['type'] == kRealTimeDataBPMeasuring) {
updateBpRtMeasuringModel(json.decode(event['data']));
updateBpCurrentStatus("RealTimeDataBP2Measuring");
updateBpCurrentStatus(kRealTimeDataBPMeasuring);
}
if (event['type'] == "RealTimeDataBP2Result") {
// Get Blood Pressure Readings after result
if (event['type'] == kRealTimeDataBPResult) {
updateBpRtResultModel(json.decode(event['data']));
updateBpCurrentStatus("RealTimeDataBP2Result");
updateBpCurrentStatus(kRealTimeDataBPResult);
}
// Get ECG Readings while measuring with Blood Pressure Device (BP 0567)
if (event['type'] == kRealTimeDataECGMeasuring) {
updateEcgRtMeasuringModelFromBP(json.decode(event['data']));
updateEcgCurrentStatus(kRealTimeDataECGMeasuring);
}
// Get ECG Readings after result with Blood Pressure Device (BP 0567)
if (event['type'] == kRealTimeDataECGResult) {
updateEcgRtResultModelFromBP(json.decode(event['data']));
updateEcgCurrentStatus(kRealTimeDataECGResult);
}
// Get ECG Readings from ECG Device like DuoEK
if (event['type'] == kRealTimeDataECG) {
updateEcgRtModel(json.decode(event['data']));
}
// Get ECG File History Details
if ((currentSelectedTrackerType == TrackerTypeEnum.ECGTracker || currentSelectedTrackerType == TrackerTypeEnum.BloodPressureTracker) && event['type'] == kFileDetail) {
updateFilesLoader(false);
parseEcgHistoryFiles(event['data']);
}
});
@ -154,7 +295,14 @@ class MyTrackersViewModel extends ChangeNotifier {
void resetList() {
devicesList.clear();
// BleChannel.disconnect();
}
Future<void> getEcgFilesList(BleDeviceModel device) async {
await BleChannel.getECGFilesList([device.name, device.model.toString()]);
}
Future<void> factoryResetECG(BleDeviceModel device) async {
await BleChannel.factoryResetECG([device.name, device.model.toString()]);
}
Future<void> connectDevice(BleDeviceModel device) async {

@ -1,10 +1,10 @@
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ekg_file_detail_response_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ecg_file_detail_model.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
class EKGChartView extends StatefulWidget {
EKGFileDetailResponseModel ekgFileDetailResponseModel;
ECGFileDetailModel ekgFileDetailResponseModel;
EKGChartView({@required this.ekgFileDetailResponseModel});

@ -1,7 +1,7 @@
import 'dart:async';
import 'dart:convert';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ekg_file_detail_response_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ekg_realtime_data_response.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ecg_file_detail_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/ecg_rt_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/viatom_devices/ekg_chart_view.dart';
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
@ -34,9 +34,9 @@ class _EKG_BLEState extends State<EKG_BLE> {
List<String> ekgFilesList = [];
List<EKGFileDetailResponseModel> ekgFileDetailResponseModelList = [];
List<ECGFileDetailModel> ekgFileDetailResponseModelList = [];
EKGRealTimeDataResponseModel ekgRealTimeDataResponseModel;
ECGRtModel ekgRealTimeDataResponseModel;
List<int> ecgBytesAllDataList = [];
@ -179,7 +179,7 @@ class _EKG_BLEState extends State<EKG_BLE> {
child: DefaultButton(
"Get Files List",
() async {
await BleChannel.getEKGFilesList(["oximeter", "ekg"]);
// await BleChannel.getECGFilesList();
},
textColor: Colors.white,
),
@ -247,7 +247,7 @@ class _EKG_BLEState extends State<EKG_BLE> {
);
}
Widget getECGFileCard(EKGFileDetailResponseModel ekgFileDetailResponseModel) {
Widget getECGFileCard(ECGFileDetailModel ekgFileDetailResponseModel) {
return Container(
decoration: cardRadius(12),
padding: EdgeInsets.all(12.0),
@ -264,7 +264,7 @@ class _EKG_BLEState extends State<EKG_BLE> {
);
}
void showEKGFileDetails(EKGFileDetailResponseModel ekgFileDetailResponseModel) async {
void showEKGFileDetails(ECGFileDetailModel ekgFileDetailResponseModel) async {
print("received file name: ${ekgFileDetailResponseModel.fileName}");
Navigator.push(context, FadePage(page: EKGChartView(ekgFileDetailResponseModel: ekgFileDetailResponseModel)));
// await BleChannel.getEKGFileDetails(fileName);
@ -273,14 +273,14 @@ class _EKG_BLEState extends State<EKG_BLE> {
void parseEKGFileDetailObject(dynamic returnData) {
ekgFileDetailResponseModelList.clear();
json.decode(returnData).forEach((v) {
ekgFileDetailResponseModelList.add(new EKGFileDetailResponseModel.fromJson(v));
ekgFileDetailResponseModelList.add(new ECGFileDetailModel.fromJson(v));
});
print(ekgFileDetailResponseModelList.length);
ekgValueNotifier.value = "Files Received: ${ekgFileDetailResponseModelList.length}";
}
String parseEKGRealTimeDataObject(dynamic returnData) {
ekgRealTimeDataResponseModel = EKGRealTimeDataResponseModel.fromJson(json.decode(returnData));
ekgRealTimeDataResponseModel = ECGRtModel.fromJson(json.decode(returnData));
return "HeartRate: ${ekgRealTimeDataResponseModel.param.hr} - Current State: ${ekgRealTimeDataResponseModel.param.curStatus}";
}
}

@ -1,5 +1,5 @@
import 'dart:convert';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/oxy_rt_param_model.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_models/viatom_devices/oxy_rt_model.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_helpers/ble_connect_helper.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
@ -17,7 +17,7 @@ class _SP20PulseTrackerState extends State<SP20PulseTracker> {
EventChannel eventChannel = EventChannel('BLE-Platform-Bridge-Event');
// final bpDataNotifierMeasuring = ValueNotifier<BpRtDataMeasuringModel>(BpRtDataMeasuringModel());
final sp20RtParamNotifier = ValueNotifier<OxyRtParamModel>(OxyRtParamModel());
final sp20RtParamNotifier = ValueNotifier<OxyRtModel>(OxyRtModel());
final sp20StatusNotifier = ValueNotifier<String>("");
final bpDeviceDataNotifier = ValueNotifier<String>("");
String deviceName = "SP20";
@ -78,7 +78,7 @@ class _SP20PulseTrackerState extends State<SP20PulseTracker> {
if (value == "EventSp20RtParam") {
return ValueListenableBuilder(
valueListenable: sp20RtParamNotifier,
builder: (context, OxyRtParamModel sp20RtModel, _) {
builder: (context, OxyRtModel sp20RtModel, _) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -190,7 +190,7 @@ class _SP20PulseTrackerState extends State<SP20PulseTracker> {
}
if (event['type'] == "EventSp20RtParam") {
sp20RtParamNotifier.value = OxyRtParamModel.fromJson(json.decode(event['data']));
sp20RtParamNotifier.value = OxyRtModel.fromJson(json.decode(event['data']));
sp20StatusNotifier.value = "EventSp20RtParam";
}
});

@ -214,6 +214,7 @@ dependencies:
open_filex: ^4.3.2
path_provider: ^2.0.8
flutter_blue_plus: 1.15.7
flutter_toggle_tab:
# flutter_callkit_incoming: ^1.0.3+3
# firebase_core: 1.12.0

Loading…
Cancel
Save