From 0830b4d248bf02ca6288333865aca3ae36059513 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Wed, 5 Jun 2024 18:21:55 +0300 Subject: [PATCH] Added rtSportsMode --- .../diplomaticquarterapp/ble/BleBridge.kt | 61 ++- .../smart_ring_2301/BaseActivity.kt | 1 + .../smart_ring_connect_screen.dart | 31 +- .../smart_ring_info_screen.dart | 366 +++++++++--------- .../ble_helpers/ble_connect_helper.dart | 40 +- .../ble_models/smart_ring_models.dart | 69 +++- .../my_trackers_view_model.dart | 81 +++- 7 files changed, 439 insertions(+), 210 deletions(-) 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 548e66ee..fe8dc8ac 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 @@ -31,13 +31,17 @@ import com.cloud.diplomaticquarterapp.utils.UiChannel import com.google.gson.Gson import com.jeremyliao.liveeventbus.LiveEventBus import com.jstyle.blesdk2301.Util.BleSDK +import com.jstyle.blesdk2301.Util.BleSDK.EnterActivityMode import com.jstyle.blesdk2301.Util.BleSDK.GetDynamicHRWithMode import com.jstyle.blesdk2301.Util.BleSDK.GetHRVDataWithMode import com.jstyle.blesdk2301.Util.BleSDK.GetStaticHRWithMode import com.jstyle.blesdk2301.Util.BleSDK.GetTemperature_historyData +import com.jstyle.blesdk2301.Util.BleSDK.GetTotalActivityDataWithMode import com.jstyle.blesdk2301.Util.BleSDK.Oxygen_data import com.jstyle.blesdk2301.callback.BleConnectionListener import com.jstyle.blesdk2301.constant.BleConst +import com.jstyle.blesdk2301.constant.DeviceKey +import com.jstyle.blesdk2301.model.ExerciseMode import com.lepu.blepro.event.EventMsgConst import com.lepu.blepro.event.EventMsgConst.Ble.* import com.lepu.blepro.event.InterfaceEvent @@ -116,6 +120,9 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi private const val GET_STATIC_HEART_RATE_SMART_RING = "getStaticHeartRateSmartRing" private const val GET_HRV_SMART_RING = "getHRVSmartRing" private const val GET_BLOOD_OXYGEN_SMART_RING = "getBloodOxygenSmartRing" + private const val GET_TOTAL_STEP_COUNT_SMART_RING = "getTotalStepCountSmartRing" + private const val GET_SPORTS_MODE_DATA_SMART_RING = "getSportsModeDataSmartRing" + private const val STOP_SPORTS_MODE_DATA_SMART_RING = "stopSportsModeDataSmartRing" val scan = BleScanManager() @@ -307,7 +314,7 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi } else if (methodCall.method == DISCONNECT_DEVICE_SMART_RING) { disConnectDeviceSmartRing() } else if (methodCall.method == GET_BATTERY_LEVEL_SMART_RING) { - getBatteryLevelSmartRing(); + getBatteryLevelSmartRing() } else if (methodCall.method == GET_TEMPERATURE_SMART_RING) { getTemperatureSmartRing(modeStart); } else if (methodCall.method == GET_DYNAMIC_HEART_RATE_SMART_RING) { @@ -318,6 +325,12 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi getHRVSmartRing(modeStart); } else if (methodCall.method == GET_BLOOD_OXYGEN_SMART_RING) { getBloodOxygenSmartRing(modeStart); + } else if (methodCall.method == GET_TOTAL_STEP_COUNT_SMART_RING) { + getTotalStepCountSmartRing(modeStart); + } else if (methodCall.method == GET_SPORTS_MODE_DATA_SMART_RING) { + getSportsModeDataSmartRing(modeStart); + } else if (methodCall.method == STOP_SPORTS_MODE_DATA_SMART_RING) { + stopSportsModeDataSmartRing(modeStart); } else { result.notImplemented() } @@ -1132,12 +1145,29 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi sendValue(Oxygen_data(mode)) } + private fun getTotalStepCountSmartRing(mode: Byte) { + sendValue(GetTotalActivityDataWithMode(mode, "")) + } + + private fun getSportsModeDataSmartRing(mode: Byte) { + // 9 for walt + sendValue(EnterActivityMode(2, 9, ExerciseMode.Status_START)) + + } + + private fun stopSportsModeDataSmartRing(mode: Byte) { + // 9 for walt + sendValue(EnterActivityMode(2, 9, ExerciseMode.Status_FINISH)) + + } + private var temperatureDataCount = 0 private var dynamicHeartRateDataCount = 0 private var staticHeartRateDataCount = 0 private var hrvDataCount = 0 private var bloodOxygenDataCount = 0 + private var totalActityDataCount = 0 override fun dataCallback(maps: Map?) { super.dataCallback(maps) val dataType = getDataType(maps) @@ -1234,7 +1264,7 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi } } - BleConst.Blood_oxygen -> { + BleConst.GetAutomaticSpo2Monitoring -> { bloodOxygenDataCount++ if (finish) { bloodOxygenDataCount = 0 @@ -1255,6 +1285,33 @@ class BleBridge(private var flutterEngine: FlutterEngine, private var mainActivi } } } + + BleConst.GetTotalActivityData -> { + totalActityDataCount++ + if (finish) { + totalActityDataCount = 0 + Log.d("TotalStepCountSmartRing", maps.toString()) + val returnData = mapOf("type" to "TotalStepCountSmartRing", "data" to gson.toJson(maps)) + eventSink?.success(returnData) + } + if (totalActityDataCount == 50) { + totalActityDataCount = 0 + if (finish) { + totalActityDataCount = 0 + Log.d("TotalStepCountSmartRing", maps.toString()) + val returnData = mapOf("type" to "TotalStepCountSmartRing", "data" to gson.toJson(maps)) + eventSink?.success(returnData) + } else { + getTotalStepCountSmartRing(modeContinue) //继续读取 + } + } + } + + BleConst.SportData -> { + Log.d("RTSportDataSmartRing", maps.toString()) + val returnData = mapOf("type" to "RTSportDataSmartRing", "data" to gson.toJson(maps)) + eventSink?.success(returnData) + } } } diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/smart_ring_2301/BaseActivity.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/smart_ring_2301/BaseActivity.kt index 4748d532..0060cb10 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/smart_ring_2301/BaseActivity.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/smart_ring_2301/BaseActivity.kt @@ -98,6 +98,7 @@ open class BaseActivity : AppCompatActivity(), DataListener2301 { } else maps[DeviceKey.DataType] as String? } + @JvmStatic protected fun getData(maps: Map): Map? { return maps[DeviceKey.Data] as Map? } diff --git a/lib/pages/medical/my_trackers/ble_device_type_screens/smart_ring_connect_screen.dart b/lib/pages/medical/my_trackers/ble_device_type_screens/smart_ring_connect_screen.dart index 8b4d519c..7aa66b24 100644 --- a/lib/pages/medical/my_trackers/ble_device_type_screens/smart_ring_connect_screen.dart +++ b/lib/pages/medical/my_trackers/ble_device_type_screens/smart_ring_connect_screen.dart @@ -38,11 +38,14 @@ class _SmartRingAllInOneConnectScreenState extends State createState() => _SmartRingInfoScreenState(); +} + +class _SmartRingInfoScreenState extends State { + MyTrackersViewModel myTrackersViewModel; + + @override + void initState() { + myTrackersViewModel = context.read(); + super.initState(); + } + + @override + void dispose() { + myTrackersViewModel.stopSportsModeDataSmartRing(); + super.dispose(); + } + String getTrackerNameByEnum(SmartRingOperationsEnum typeEnum) { switch (typeEnum) { case SmartRingOperationsEnum.Temperature: @@ -28,10 +37,10 @@ class SmartRingInfoScreen extends StatelessWidget { case SmartRingOperationsEnum.BloodOxygen: return "Blood Oxygen"; - case SmartRingOperationsEnum.HeartRateDynamic: + case SmartRingOperationsEnum.RealTimeHeartRate: return "HeartRate Dynamic"; - case SmartRingOperationsEnum.HeartRateStatic: + case SmartRingOperationsEnum.HeartRate: return "HeartRate Static"; case SmartRingOperationsEnum.HRV: @@ -39,6 +48,12 @@ class SmartRingInfoScreen extends StatelessWidget { case SmartRingOperationsEnum.BatteryLevel: return "Battery Level"; + + case SmartRingOperationsEnum.TotalStepCount: + return "Total Step Count"; + + case SmartRingOperationsEnum.SportsMode: + return "Sports Mode"; } return "Battery Level"; } @@ -47,17 +62,21 @@ class SmartRingInfoScreen extends StatelessWidget { switch (smartRingOperationsEnum) { case SmartRingOperationsEnum.Temperature: return buildTemperatureWidget(myTrackersVm, context); - case SmartRingOperationsEnum.HeartRateStatic: + case SmartRingOperationsEnum.HeartRate: return buildHeartRateStaticWidget(myTrackersVm, context); - case SmartRingOperationsEnum.HeartRateDynamic: + case SmartRingOperationsEnum.RealTimeHeartRate: return buildHeartRateDynamicWidget(myTrackersVm, context); + case SmartRingOperationsEnum.TotalStepCount: + return buildTotalStepCountHistoryWidget(myTrackersVm, context); case SmartRingOperationsEnum.HRV: return buildHrvWidget(myTrackersVm, context); case SmartRingOperationsEnum.BloodOxygen: - // TODO: Handle this case. - break; + return buildBloodOxygenWidget(myTrackersVm, context); case SmartRingOperationsEnum.BatteryLevel: return buildBatteryLevelWidget(myTrackersVm, context); + case SmartRingOperationsEnum.SportsMode: + return buildRtSportsDataSmartRingWidget(myTrackersVm, context); + break; } return getNoDataWidget(context); } @@ -167,6 +186,64 @@ class SmartRingInfoScreen extends StatelessWidget { } } + Widget buildRtSportsDataSmartRingWidget(MyTrackersViewModel myTrackersVm, BuildContext context) { + if (myTrackersVm.filesLoader) { + return Center(child: CircularProgressIndicator()); + } else if (myTrackersVm.rtSportDataSmartRingModel != null) { + return Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + mHeight(24.0), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + Text("Step", style: TextStyle(fontSize: 20)), + Text(myTrackersViewModel.rtSportDataSmartRingModel.step.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)), + Text("", style: TextStyle(fontSize: 10)), + ], + ), + Column( + children: [ + Text("Calories", style: TextStyle(fontSize: 20)), + Text(myTrackersViewModel.rtSportDataSmartRingModel.calories.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)), + Text("kCal", style: TextStyle(fontSize: 10)), + ], + ), + Column( + children: [ + Text("♥︎", style: TextStyle(fontSize: 20)), + Text(myTrackersViewModel.rtSportDataSmartRingModel.heartRate.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)), + Text("/min", style: TextStyle(fontSize: 10)), + ], + ), + ], + ), + mHeight(30.0), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Column( + children: [ + Text("Time", style: TextStyle(fontSize: 20)), + Text(myTrackersViewModel.rtSportDataSmartRingModel.exerciseTime.toString(), style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold)), + Text("seconds", style: TextStyle(fontSize: 10)), + ], + ), + ], + ), + // buildStatusForBP(myTrackersViewModel.bpRtResultModel.result), + // mHeight(24.0), + ], + ), + ); + } else { + return getNoDataWidget(context); + } + } + Widget buildHrvWidget(MyTrackersViewModel myTrackersVm, BuildContext context) { if (myTrackersVm.filesLoader) { return Center(child: CircularProgressIndicator()); @@ -187,6 +264,8 @@ class SmartRingInfoScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text("Date: ${smartRingHrvModel.date}"), + mHeight(4.0), Text("highBP: ${smartRingHrvModel.highBP}"), mHeight(4.0), Text("lowBP: ${smartRingHrvModel.lowBP}"), @@ -210,189 +289,104 @@ class SmartRingInfoScreen extends StatelessWidget { } } - Widget buildBatteryLevelWidget(MyTrackersViewModel myTrackersVm, BuildContext context) { + Widget buildTotalStepCountHistoryWidget(MyTrackersViewModel myTrackersVm, BuildContext context) { if (myTrackersVm.filesLoader) { return Center(child: CircularProgressIndicator()); - } else if (myTrackersVm.smartRingBatteryLevel != null && myTrackersVm.smartRingBatteryLevel.isNotEmpty) { - return Center( - child: Text("Battery Level: ${myTrackersVm.smartRingBatteryLevel}"), + } else if (myTrackersVm.smartRingStepCountHistory != null && myTrackersVm.smartRingStepCountHistory.isNotEmpty) { + return Expanded( + child: ListView.separated( + itemCount: myTrackersVm.smartRingStepCountHistory.length, + separatorBuilder: (context, index) => SizedBox(height: 14), + shrinkWrap: true, + reverse: false, + itemBuilder: (context, index) { + SmartRingStepCountModel smartRingStepCountModel = myTrackersVm.smartRingStepCountHistory[index]; + return InkWell( + onTap: () => Navigator.pop(context), + child: Container( + decoration: cardRadius(12), + padding: EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("date: ${smartRingStepCountModel.date}"), + mHeight(4.0), + Text("calories: ${smartRingStepCountModel.calories}"), + mHeight(4.0), + Text("distance: ${smartRingStepCountModel.distance}"), + mHeight(4.0), + Text("exerciseMinutes: ${smartRingStepCountModel.exerciseMinutes}"), + mHeight(4.0), + Text("exerciseTime: ${smartRingStepCountModel.exerciseTime}"), + mHeight(4.0), + Text("distance: ${smartRingStepCountModel.distance}"), + mHeight(4.0), + Text("goal: ${smartRingStepCountModel.goal}"), + mHeight(4.0), + Text("step: ${smartRingStepCountModel.step}"), + ], + ), + ), + ); + }, + ), ); } else { return getNoDataWidget(context); } } - Widget buildECGWidget(MyTrackersViewModel myTrackersVm, BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.max, - children: [ - if (myTrackersVm.filesLoader) ...[ - Center(child: CircularProgressIndicator()) - ] else if (myTrackersVm.checkMeEcg != null && myTrackersVm.checkMeEcg.isNotEmpty) ...[ - Material( - child: ListView.separated( - itemCount: myTrackersVm.checkMeEcg.length, - separatorBuilder: (context, index) => SizedBox(height: 14), - shrinkWrap: true, - reverse: false, - itemBuilder: (context, index) { - CheckMeECGModel checkMeECGModel = myTrackersVm.checkMeEcg[index]; - return InkWell( - onTap: () { - myTrackersVm.getEcgWaveDataFromCheckMePro(checkMeECGModel.timeString); - // Navigator.push(context, MaterialPageRoute(builder: (context) => CheckMeECGInfoScreen(SmartRingOperationsEnum.ECGTracker))); - }, - child: Container( - decoration: cardRadius(12), - padding: EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Date: ${checkMeECGModel.date}"), - mHeight(8), - Text("TimeString: ${checkMeECGModel.timeString}"), - ], - ), - ), - ); - }, - ), - ) - ] else ...[ - getNoDataWidget(context), - ] - ], - ); - } - - Widget buildOxiWidget(MyTrackersViewModel myTrackersVm, BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.max, - children: [ - if (myTrackersVm.filesLoader) ...[ - Center(child: CircularProgressIndicator()) - ] else if (myTrackersVm.checkMeOxi != null && myTrackersVm.checkMeOxi.isNotEmpty) ...[ - Material( - child: ListView.separated( - itemCount: myTrackersVm.checkMeOxi.length, - separatorBuilder: (context, index) => SizedBox(height: 14), - shrinkWrap: true, - reverse: false, - itemBuilder: (context, index) { - CheckMeOxiModel checkMeOxiModel = myTrackersVm.checkMeOxi[index]; - return InkWell( - onTap: () => Navigator.pop(context), - child: Container( - decoration: cardRadius(12), - padding: EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("PR: ${checkMeOxiModel.pr} PI: ${checkMeOxiModel.pi}"), - mHeight(4.0), - Text("Oxi: ${checkMeOxiModel.oxy}"), - mHeight(4.0), - Text("Date: ${checkMeOxiModel.date}"), - ], - ), - ), - ); - }, - ), - ) - ] else ...[ - getNoDataWidget(context), - ] - ], - ); - } - - Widget buildBPWidget(MyTrackersViewModel myTrackersVm, BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.max, - children: [ - if (myTrackersVm.filesLoader) ...[ - Center(child: CircularProgressIndicator()) - ] else if (myTrackersVm.checkMeBP != null && myTrackersVm.checkMeBP.isNotEmpty) ...[ - Material( - child: ListView.separated( - itemCount: myTrackersVm.checkMeBP.length, - separatorBuilder: (context, index) => SizedBox(height: 14), - shrinkWrap: true, - reverse: false, - itemBuilder: (context, index) { - CheckMeBPModel checkMeBPModel = myTrackersVm.checkMeBP[index]; - return InkWell( - onTap: () => Navigator.pop(context), - child: Container( - decoration: cardRadius(12), - padding: EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("DIA: ${checkMeBPModel.dia} SYS: ${checkMeBPModel.sys}"), - mHeight(4.0), - Text("PR: ${checkMeBPModel.pr}"), - mHeight(4.0), - Text("Date: ${checkMeBPModel.date}"), - ], - ), - ), - ); - }, - ), - ) - ] else ...[ - getNoDataWidget(context), - ] - ], - ); + Widget buildBloodOxygenWidget(MyTrackersViewModel myTrackersVm, BuildContext context) { + if (myTrackersVm.filesLoader) { + return Center(child: CircularProgressIndicator()); + } else if (myTrackersVm.smartRingBloodOxygenHistory != null && myTrackersVm.smartRingBloodOxygenHistory.isNotEmpty) { + return Expanded( + child: ListView.separated( + itemCount: myTrackersVm.smartRingBloodOxygenHistory.length, + separatorBuilder: (context, index) => SizedBox(height: 14), + shrinkWrap: true, + reverse: false, + itemBuilder: (context, index) { + SmartRingGenericModel smartRingGenericModel = myTrackersVm.smartRingBloodOxygenHistory[index]; + return InkWell( + onTap: () => Navigator.pop(context), + child: Container( + decoration: cardRadius(12), + padding: EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Date: ${smartRingGenericModel.date}"), + mHeight(4.0), + Text("BloodOxygen: ${smartRingGenericModel.value}"), + ], + ), + ), + ); + }, + ), + ); + } else { + return getNoDataWidget(context); + } } - Widget buildGlucoseWidget(MyTrackersViewModel myTrackersVm, BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.max, - children: [ - if (myTrackersVm.filesLoader) ...[ - Center(child: CircularProgressIndicator()) - ] else if (myTrackersVm.checkMeGlucose != null && myTrackersVm.checkMeGlucose.isNotEmpty) ...[ - Material( - child: ListView.separated( - itemCount: myTrackersVm.checkMeGlucose.length, - separatorBuilder: (context, index) => SizedBox(height: 14), - shrinkWrap: true, - reverse: false, - itemBuilder: (context, index) { - CheckMeGlucoseModel checkMeGlucoseModel = myTrackersVm.checkMeGlucose[index]; - return InkWell( - onTap: () => null, - child: Container( - decoration: cardRadius(12), - padding: EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Glucose: ${checkMeGlucoseModel.glu}"), - mHeight(4.0), - Text("Date: ${checkMeGlucoseModel.date}"), - ], - ), - ), - ); - }, - ), - ) - ] else ...[ - getNoDataWidget(context), - ] - ], - ); + Widget buildBatteryLevelWidget(MyTrackersViewModel myTrackersVm, BuildContext context) { + if (myTrackersVm.filesLoader) { + return Center(child: CircularProgressIndicator()); + } else if (myTrackersVm.smartRingBatteryLevel != null && myTrackersVm.smartRingBatteryLevel.isNotEmpty) { + return Center( + child: Text("Battery Level: ${myTrackersVm.smartRingBatteryLevel}"), + ); + } else { + return getNoDataWidget(context); + } } @override Widget build(BuildContext context) { return AppScaffold( - appBarTitle: "${getTrackerNameByEnum(smartRingOperationsEnum)}", + appBarTitle: "${getTrackerNameByEnum(widget.smartRingOperationsEnum)}", showNewAppBar: true, isShowDecPage: false, showNewAppBarTitle: true, @@ -403,7 +397,7 @@ class SmartRingInfoScreen extends StatelessWidget { children: [ Consumer( builder: (BuildContext context, MyTrackersViewModel myTrackersVm, Widget child) { - return getAllInOneOperationWidgets(myTrackersVm, smartRingOperationsEnum, context); + return getAllInOneOperationWidgets(myTrackersVm, widget.smartRingOperationsEnum, context); }, ), ], diff --git a/lib/pages/medical/my_trackers/ble_helpers/ble_connect_helper.dart b/lib/pages/medical/my_trackers/ble_helpers/ble_connect_helper.dart index 261a0c7a..5bee3fb0 100644 --- a/lib/pages/medical/my_trackers/ble_helpers/ble_connect_helper.dart +++ b/lib/pages/medical/my_trackers/ble_helpers/ble_connect_helper.dart @@ -302,7 +302,7 @@ class BleChannel { } } - static Future getStaticHeartRateSmartRing() async { + static Future getStaticHeartRateSmartRing() async { try { print("----------Flutter getStaticHeartRateSmartRing -------"); final String result = await platform.invokeMethod('getStaticHeartRateSmartRing'); @@ -314,7 +314,7 @@ class BleChannel { } } - static Future getHRVSmartRing() async { + static Future getHRVSmartRing() async { try { print("----------Flutter getHRVSmartRing -------"); final String result = await platform.invokeMethod('getHRVSmartRing'); @@ -326,7 +326,7 @@ class BleChannel { } } - static Future getBloodOxygenSmartRing() async { + static Future getBloodOxygenSmartRing() async { try { print("----------Flutter getBloodOxygenSmartRing -------"); final String result = await platform.invokeMethod('getBloodOxygenSmartRing'); @@ -338,5 +338,39 @@ class BleChannel { } } + static Future getTotalStepCountSmartRing() async { + try { + print("----------Flutter getTotalStepCountSmartRing -------"); + final String result = await platform.invokeMethod('getTotalStepCountSmartRing'); + print("----------Flutter getTotalStepCountSmartRing result -------"); + + return result; + } catch (e) { + return "Error: $e"; + } + } + + static Future startSportsModeDataSmartRing() async { + try { + print("----------Flutter getSportsModeDataSmartRing -------"); + final String result = await platform.invokeMethod('getSportsModeDataSmartRing'); + print("----------Flutter getSportsModeDataSmartRing result -------"); + + return result; + } catch (e) { + return "Error: $e"; + } + } + + static Future stopSportsModeDataSmartRing() async { + try { + print("----------Flutter stopSportsModeDataSmartRing -------"); + final String result = await platform.invokeMethod('stopSportsModeDataSmartRing'); + print("----------Flutter stopSportsModeDataSmartRing result -------"); + return result; + } catch (e) { + return "Error: $e"; + } + } } diff --git a/lib/pages/medical/my_trackers/ble_models/smart_ring_models.dart b/lib/pages/medical/my_trackers/ble_models/smart_ring_models.dart index 491a4c69..03380caa 100644 --- a/lib/pages/medical/my_trackers/ble_models/smart_ring_models.dart +++ b/lib/pages/medical/my_trackers/ble_models/smart_ring_models.dart @@ -6,16 +6,14 @@ String getValueKeyBySmartRingOperation(SmartRingOperationsEnum smartRingOperatio switch (smartRingOperationsEnum) { case SmartRingOperationsEnum.Temperature: return "temperature"; - case SmartRingOperationsEnum.HeartRateStatic: + case SmartRingOperationsEnum.HeartRate: return "onceHeartValue"; - case SmartRingOperationsEnum.HeartRateDynamic: + case SmartRingOperationsEnum.RealTimeHeartRate: return "arrayDynamicHR"; case SmartRingOperationsEnum.HRV: - // TODO: Handle this case. break; case SmartRingOperationsEnum.BloodOxygen: - // TODO: Handle this case. - break; + return "Blood_oxygen"; case SmartRingOperationsEnum.BatteryLevel: return "batteryLevel"; } @@ -36,7 +34,41 @@ class SmartRingGenericModel { Map toJson(SmartRingOperationsEnum smartRingOperationsEnum) { final Map data = new Map(); data['date'] = this.date; - data['arrayDynamicHR'] = getValueKeyBySmartRingOperation(smartRingOperationsEnum); + data['${getValueKeyBySmartRingOperation(smartRingOperationsEnum)}'] = this.value; + return data; + } +} + +class SmartRingStepCountModel { + String date; + String goal; + String distance; + String step; + String exerciseTime; + String calories; + String exerciseMinutes; + + SmartRingStepCountModel({this.date, this.goal, this.distance, this.step, this.exerciseTime, this.calories, this.exerciseMinutes}); + + SmartRingStepCountModel.fromJson(Map json) { + date = json['date']; + goal = json['goal']; + distance = json['distance']; + step = json['step']; + exerciseTime = json['ExerciseTime']; + calories = json['calories']; + exerciseMinutes = json['exerciseMinutes']; + } + + Map toJson() { + final Map data = new Map(); + data['date'] = this.date; + data['goal'] = this.goal; + data['distance'] = this.distance; + data['step'] = this.step; + data['ExerciseTime'] = this.exerciseTime; + data['calories'] = this.calories; + data['exerciseMinutes'] = this.exerciseMinutes; return data; } } @@ -74,3 +106,28 @@ class SmartRingHrvModel { return data; } } + +class RtSportDataSmartRingModel { + String heartRate; + String step; + String exerciseTime; + String calories; + + RtSportDataSmartRingModel({this.heartRate, this.step, this.exerciseTime, this.calories}); + + RtSportDataSmartRingModel.fromJson(Map json) { + heartRate = json['heartRate']; + step = json['step']; + exerciseTime = json['ExerciseTime']; + calories = json['calories']; + } + + Map toJson() { + final Map data = new Map(); + data['heartRate'] = this.heartRate; + data['step'] = this.step; + data['ExerciseTime'] = this.exerciseTime; + data['calories'] = this.calories; + return data; + } +} 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 f708d27f..96581cca 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 @@ -34,7 +34,7 @@ import 'package:provider/provider.dart'; enum TrackerTypeEnum { OxymeterTracker, BloodPressureTracker, BloodSugarTracker, ECGTracker, WeightScale, Temperature, Spirometer, SmartRing, AllInOneTracker } -enum SmartRingOperationsEnum { Temperature, HeartRateStatic, HeartRateDynamic, HRV, BloodOxygen, BatteryLevel } +enum SmartRingOperationsEnum { Temperature, HeartRate, RealTimeHeartRate, TotalStepCount, HRV, BloodOxygen, SportsMode, BatteryLevel } //NativeEventNames @@ -62,6 +62,8 @@ String kDynamicHeartRateSmartRing = "DynamicHeartRateSmartRing"; String kStaticHeartRateSmartRing = "StaticHeartRateSmartRing"; String kHrvSmartRing = "HrvSmartRing"; String kBloodOxygenSmartRing = "BloodOxygenSmartRing"; +String kTotalStepCountSmartRing = "TotalStepCountSmartRing"; +String kRTSportDataSmartRing = "RTSportDataSmartRing"; class MyTrackersViewModel extends ChangeNotifier { EventChannel eventChannel = EventChannel('BLE-Platform-Bridge-Event'); @@ -145,8 +147,9 @@ class MyTrackersViewModel extends ChangeNotifier { ]; List smartRingTrackers = [ SmartRingOperationsEnum.Temperature, - SmartRingOperationsEnum.HeartRateStatic, - SmartRingOperationsEnum.HeartRateDynamic, + SmartRingOperationsEnum.HeartRate, + SmartRingOperationsEnum.TotalStepCount, + SmartRingOperationsEnum.SportsMode, SmartRingOperationsEnum.HRV, SmartRingOperationsEnum.BloodOxygen, SmartRingOperationsEnum.BatteryLevel, @@ -1396,6 +1399,7 @@ class MyTrackersViewModel extends ChangeNotifier { if (event['type'] == kBloodOxygenSmartRing) { logger.i(event['data']); + updateSmartRingBloodOxygenHistory(json.decode(event['data'])); } if (event['type'] == kHrvSmartRing) { @@ -1412,6 +1416,16 @@ class MyTrackersViewModel extends ChangeNotifier { logger.i(event['data']); updateSmartRingHeartRateDynamicHistory(json.decode(event['data'])); } + + if (event['type'] == kTotalStepCountSmartRing) { + logger.i(event['data']); + updateSmartRingStepCountHistory(json.decode(event['data'])); + } + + if (event['type'] == kRTSportDataSmartRing) { + logger.i(event['data']); + updateRtSportDataSmartRingModel(json.decode(event['data'])); + } }); await scanForSmartRing(); @@ -1487,6 +1501,21 @@ class MyTrackersViewModel extends ChangeNotifier { logger.i(jsonEncode(data.toString())); } + Future getTotalStepCountSmartRing() async { + String data = await BleChannel.getTotalStepCountSmartRing(); + logger.i(jsonEncode(data.toString())); + } + + Future getSportsModeDataSmartRing() async { + String data = await BleChannel.startSportsModeDataSmartRing(); + logger.i(jsonEncode(data.toString())); + } + + Future stopSportsModeDataSmartRing() async { + String data = await BleChannel.stopSportsModeDataSmartRing(); + logger.i(jsonEncode(data.toString())); + } + String smartRingBatteryLevel; void updateSmartRingBatteryLevelModel(dynamic returnData) { @@ -1515,6 +1544,23 @@ class MyTrackersViewModel extends ChangeNotifier { notifyListeners(); } + //BLOOD OXYGEN + + List smartRingBloodOxygenHistory; + + void updateSmartRingBloodOxygenHistory(dynamic returnData) { + Map data = returnData; + List response = (data["dicData"]) as List; + + List list = List.generate(response.length, (index) => SmartRingGenericModel.fromJson(response[index], SmartRingOperationsEnum.BloodOxygen)); + if (smartRingBloodOxygenHistory == null) { + smartRingBloodOxygenHistory = list; + } else { + smartRingBloodOxygenHistory.addAll(list); + } + notifyListeners(); + } + //HEART RATE DYNAMIC List smartRingHeartRateDynamicHistory; @@ -1523,7 +1569,7 @@ class MyTrackersViewModel extends ChangeNotifier { Map data = returnData; List response = (data["dicData"]) as List; - List list = List.generate(response.length, (index) => SmartRingGenericModel.fromJson(response[index], SmartRingOperationsEnum.HeartRateDynamic)); + List list = List.generate(response.length, (index) => SmartRingGenericModel.fromJson(response[index], SmartRingOperationsEnum.RealTimeHeartRate)); if (smartRingHeartRateDynamicHistory == null) { smartRingHeartRateDynamicHistory = list; } else { @@ -1539,7 +1585,7 @@ class MyTrackersViewModel extends ChangeNotifier { Map data = returnData; List response = (data["dicData"]) as List; - List list = List.generate(response.length, (index) => SmartRingGenericModel.fromJson(response[index], SmartRingOperationsEnum.HeartRateStatic)); + List list = List.generate(response.length, (index) => SmartRingGenericModel.fromJson(response[index], SmartRingOperationsEnum.HeartRate)); if (smartRingHeartRateStaticHistory == null) { smartRingHeartRateStaticHistory = list; } else { @@ -1564,4 +1610,29 @@ class MyTrackersViewModel extends ChangeNotifier { log("smartRingHrvHistory: ${smartRingHrvHistory.length}"); notifyListeners(); } + + List smartRingStepCountHistory; + + void updateSmartRingStepCountHistory(dynamic returnData) { + Map data = returnData; + List response = (data["dicData"]) as List; + + List list = List.generate(response.length, (index) => SmartRingStepCountModel.fromJson(response[index])); + if (smartRingStepCountHistory == null) { + smartRingStepCountHistory = list; + } else { + smartRingStepCountHistory.addAll(list); + } + log("smartRingStepCountHistory: ${smartRingStepCountHistory.length}"); + notifyListeners(); + } + + RtSportDataSmartRingModel rtSportDataSmartRingModel; + + void updateRtSportDataSmartRingModel(dynamic returnData) { + Map data = returnData; + rtSportDataSmartRingModel = RtSportDataSmartRingModel.fromJson(data["dicData"] as Map); + log("rtSportDataSmartRingModel: ${data.toString()}"); + notifyListeners(); + } }