From 6fd429c883a04ce3902269f9013b682efab353c0 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Mon, 27 May 2024 09:59:35 +0300 Subject: [PATCH] Connected the SmartRing --- .../ble_devices_screen.dart | 19 +- ...=> checkme_all_in-one_connect_screen.dart} | 12 +- .../checkme_all_in_one_info_screen.dart | 4 + .../select_tracker_type.dart | 15 +- .../smart_ring_connect_screen.dart | 181 ++++++++++++++++++ .../my_trackers_view_model.dart | 47 ++++- 6 files changed, 266 insertions(+), 12 deletions(-) rename lib/pages/medical/my_trackers/ble_device_type_screens/{andesfit_device_types/andesfit_all_in-one_connect_screen.dart => checkme_all_in-one_connect_screen.dart} (93%) create mode 100644 lib/pages/medical/my_trackers/ble_device_type_screens/smart_ring_connect_screen.dart diff --git a/lib/pages/medical/my_trackers/ble_device_type_screens/ble_devices_screen.dart b/lib/pages/medical/my_trackers/ble_device_type_screens/ble_devices_screen.dart index 6aca3270..046dbc10 100644 --- a/lib/pages/medical/my_trackers/ble_device_type_screens/ble_devices_screen.dart +++ b/lib/pages/medical/my_trackers/ble_device_type_screens/ble_devices_screen.dart @@ -1,6 +1,6 @@ import 'dart:developer'; -import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_all_in-one_connect_screen.dart'; +import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/checkme_all_in-one_connect_screen.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_blood_pressure_connect_screen.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_blood_sugar_connect_screen.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_spirometer_connect_screen.dart'; @@ -9,6 +9,7 @@ import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_s import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/lepu_device_types/bloodpressure_connect_screen.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/lepu_device_types/ecg_connect_screen.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/lepu_device_types/oxymeter_connect_screen.dart'; +import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/smart_ring_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'; import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart'; @@ -16,7 +17,6 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; -import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; class BleDevicesScreen extends StatefulWidget { @@ -39,6 +39,9 @@ class _BleDevicesScreenState extends State { myTrackersVm = context.read(); if (myTrackersVm.currentSelectedTrackerType == TrackerTypeEnum.AllInOneTracker) { myTrackersVm.startSearchingForCheckMePro(); + } + if (myTrackersVm.currentSelectedTrackerType == TrackerTypeEnum.SmartRing) { + myTrackersVm.startFlutterScan(); } else { myTrackersVm.startSearchingForTracker(); myTrackersVm.startTimerForNativeScan(); @@ -115,13 +118,19 @@ class _BleDevicesScreenState extends State { return; } break; - case TrackerTypeEnum.AllInOneTracker: + + case TrackerTypeEnum.SmartRing: if (myTrackersVm.isDeviceFromAndesFit(device.name)) { + Navigator.pushReplacement(context, FadePage(page: SmartRingAllInOneConnectScreen(deviceModel: device.andesfitBluetoothDevice))); return; } + break; - Navigator.pushReplacement(context, FadePage(page: AndesAllInOneConnectScreen(deviceModel: device))); - + case TrackerTypeEnum.AllInOneTracker: + if (myTrackersVm.isDeviceFromAndesFit(device.name)) { + return; + } + Navigator.pushReplacement(context, FadePage(page: CheckMeAllInOneConnectScreen(deviceModel: device))); break; } } diff --git a/lib/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_all_in-one_connect_screen.dart b/lib/pages/medical/my_trackers/ble_device_type_screens/checkme_all_in-one_connect_screen.dart similarity index 93% rename from lib/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_all_in-one_connect_screen.dart rename to lib/pages/medical/my_trackers/ble_device_type_screens/checkme_all_in-one_connect_screen.dart index 62830dd0..a079c2da 100644 --- a/lib/pages/medical/my_trackers/ble_device_type_screens/andesfit_device_types/andesfit_all_in-one_connect_screen.dart +++ b/lib/pages/medical/my_trackers/ble_device_type_screens/checkme_all_in-one_connect_screen.dart @@ -1,4 +1,3 @@ -import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/ble_devices_screen.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/checkme_all_in_one_info_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'; @@ -9,16 +8,16 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -class AndesAllInOneConnectScreen extends StatefulWidget { +class CheckMeAllInOneConnectScreen extends StatefulWidget { final BleDeviceModel deviceModel; - const AndesAllInOneConnectScreen({this.deviceModel}); + const CheckMeAllInOneConnectScreen({this.deviceModel}); @override - State createState() => _AndesAllInOneConnectScreenState(); + State createState() => _CheckMeAllInOneConnectScreenState(); } -class _AndesAllInOneConnectScreenState extends State { +class _CheckMeAllInOneConnectScreenState extends State { MyTrackersViewModel myTrackersVm; @override @@ -57,6 +56,9 @@ class _AndesAllInOneConnectScreenState extends State case TrackerTypeEnum.Spirometer: return "Spirometer"; + case TrackerTypeEnum.SmartRing: + return "Smart Ring"; + case TrackerTypeEnum.AllInOneTracker: return "All in One"; } diff --git a/lib/pages/medical/my_trackers/ble_device_type_screens/checkme_all_in_one_info_screen.dart b/lib/pages/medical/my_trackers/ble_device_type_screens/checkme_all_in_one_info_screen.dart index ffc4b021..e4a32d58 100644 --- a/lib/pages/medical/my_trackers/ble_device_type_screens/checkme_all_in_one_info_screen.dart +++ b/lib/pages/medical/my_trackers/ble_device_type_screens/checkme_all_in_one_info_screen.dart @@ -41,6 +41,8 @@ class CheckMeAllInOneInfoScreen extends StatelessWidget { case TrackerTypeEnum.AllInOneTracker: return "All in One"; + case TrackerTypeEnum.SmartRing: + return "Smart Ring"; } return "All in One"; } @@ -65,7 +67,9 @@ class CheckMeAllInOneInfoScreen extends StatelessWidget { case TrackerTypeEnum.Spirometer: case TrackerTypeEnum.WeightScale: case TrackerTypeEnum.AllInOneTracker: + case TrackerTypeEnum.SmartRing: return getNoDataWidget(context); + break; } return getNoDataWidget(context); } diff --git a/lib/pages/medical/my_trackers/ble_device_type_screens/select_tracker_type.dart b/lib/pages/medical/my_trackers/ble_device_type_screens/select_tracker_type.dart index f12b2d1d..aea30209 100644 --- a/lib/pages/medical/my_trackers/ble_device_type_screens/select_tracker_type.dart +++ b/lib/pages/medical/my_trackers/ble_device_type_screens/select_tracker_type.dart @@ -107,6 +107,20 @@ class SelectTrackerType extends StatelessWidget { ), ), ); + medical.add( + InkWell( + onTap: () { + context.read().updateSelectedTrackerType(TrackerTypeEnum.SmartRing); + Navigator.of(context).push(FadePage(page: BleDevicesScreen())); + }, + child: MedicalProfileItem( + title: "SmartRing", + imagePath: 'tracker.svg', + subTitle: "Tracker", + isEnable: true, + ), + ), + ); medical.add( InkWell( onTap: () { @@ -128,7 +142,6 @@ class SelectTrackerType extends StatelessWidget { @override Widget build(BuildContext context) { List myMedicalList = myTrackersTypeList(context: context); - return AppScaffold( isShowDecPage: false, isShowAppBar: false, 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 new file mode 100644 index 00000000..eb999175 --- /dev/null +++ b/lib/pages/medical/my_trackers/ble_device_type_screens/smart_ring_connect_screen.dart @@ -0,0 +1,181 @@ +import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_device_type_screens/checkme_all_in_one_info_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'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; +import 'package:provider/provider.dart'; + +class SmartRingAllInOneConnectScreen extends StatefulWidget { + final BluetoothDevice deviceModel; + + const SmartRingAllInOneConnectScreen({this.deviceModel}); + + @override + State createState() => _SmartRingAllInOneConnectScreenState(); +} + +class _SmartRingAllInOneConnectScreenState extends State { + MyTrackersViewModel myTrackersVm; + + @override + void initState() { + myTrackersVm = context.read(); + myTrackersVm.connectSmartRingDevice(widget.deviceModel); + super.initState(); + } + + @override + void dispose() { + myTrackersVm.disConnectAndesfitDevice(widget.deviceModel); + super.dispose(); + } + + String getTrackerNameByEnum(TrackerTypeEnum trackerTypeEnum) { + switch (trackerTypeEnum) { + case TrackerTypeEnum.OxymeterTracker: + return "Oxymeter"; + + case TrackerTypeEnum.BloodPressureTracker: + return "Blood Pressure"; + + case TrackerTypeEnum.BloodSugarTracker: + return "Blood Glucose"; + + case TrackerTypeEnum.ECGTracker: + return "ECG"; + + case TrackerTypeEnum.WeightScale: + return "Weight Scale"; + + case TrackerTypeEnum.Temperature: + return "Temperature"; + + case TrackerTypeEnum.Spirometer: + return "Spirometer"; + + case TrackerTypeEnum.SmartRing: + return "Smart Ring"; + + case TrackerTypeEnum.AllInOneTracker: + return "All in One"; + } + return "All in One"; + } + + Future onTrackerTypePressed(TrackerTypeEnum trackerTypeEnum, MyTrackersViewModel myTrackersViewModel) async { + switch (trackerTypeEnum) { + case TrackerTypeEnum.BloodPressureTracker: + case TrackerTypeEnum.BloodSugarTracker: + myTrackersViewModel.getCheckMeUsersListDialog(trackerTypeEnum, context); + break; + case TrackerTypeEnum.OxymeterTracker: + myTrackersViewModel.getOxiDataFromCheckMePro(); + Navigator.of(context).push(FadePage(page: CheckMeAllInOneInfoScreen(trackerTypeEnum))); + break; + case TrackerTypeEnum.ECGTracker: + myTrackersViewModel.getECGDataFromCheckMePro(); + Navigator.of(context).push(FadePage(page: CheckMeAllInOneInfoScreen(trackerTypeEnum))); + break; + case TrackerTypeEnum.Temperature: + myTrackersViewModel.getTempDataFromCheckMePro(); + Navigator.of(context).push(FadePage(page: CheckMeAllInOneInfoScreen(trackerTypeEnum))); + break; + case TrackerTypeEnum.Spirometer: + case TrackerTypeEnum.WeightScale: + case TrackerTypeEnum.SmartRing: + case TrackerTypeEnum.AllInOneTracker: + break; + } + } + + Widget buildAllInOneUI(MyTrackersViewModel myTrackersViewModel) { + return Expanded( + child: ListView( + children: [ + if (myTrackersViewModel.checkMeProUsersList == null) ...[ + Padding( + padding: const EdgeInsets.all(24.0), + child: Center( + child: Text( + "Some animation with the instruction", + style: TextStyle(fontSize: 9.0), + ), + ), + ) + ] else ...[ + Center( + child: Column( + children: [ + GridView.builder( + shrinkWrap: true, + primary: false, + physics: NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 2 / 2, crossAxisSpacing: 12, mainAxisSpacing: 12), + padding: EdgeInsets.zero, + itemCount: myTrackersViewModel.checkMeProTrackers.length, + itemBuilder: (BuildContext context, int index) { + return InkWell( + onTap: () => onTrackerTypePressed(myTrackersViewModel.checkMeProTrackers[index], myTrackersViewModel), + child: MedicalProfileItem( + title: getTrackerNameByEnum(myTrackersViewModel.checkMeProTrackers[index]), + imagePath: 'tracker.svg', + subTitle: "", + isEnable: true, + ), + ); + }, + ), + ], + ), + ) + ] + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: "${widget.deviceModel.name}", + showNewAppBar: true, + isShowDecPage: false, + showNewAppBarTitle: true, + backgroundColor: Color(0xffF8F8F8), + body: Padding( + padding: const EdgeInsets.all(24.0), + child: Consumer( + builder: (BuildContext context, MyTrackersViewModel myTrackersViewModel, Widget child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + buildAllInOneUI(myTrackersViewModel), + if (myTrackersViewModel.checkMeProUsersList != null) ...[ + Row( + children: [ + Expanded( + child: DefaultButton( + "Disconnect with ${widget.deviceModel.name}", + () async { + myTrackersVm.disConnectDevice(); + Navigator.pop(context); + }, + textColor: Colors.white, + ), + ), + ], + ), + ] + ], + ); + }, + ), + ), + ); + } +} 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 0d7c1375..29908955 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 @@ -30,7 +30,7 @@ import 'package:diplomaticquarterapp/pages/medical/my_trackers/ble_helpers/ble_c import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -enum TrackerTypeEnum { OxymeterTracker, BloodPressureTracker, BloodSugarTracker, ECGTracker, WeightScale, Temperature, Spirometer, AllInOneTracker } +enum TrackerTypeEnum { OxymeterTracker, BloodPressureTracker, BloodSugarTracker, ECGTracker, WeightScale, Temperature, Spirometer, SmartRing, AllInOneTracker } //NativeEventNames @@ -84,6 +84,9 @@ class MyTrackersViewModel extends ChangeNotifier { "Spirometer": [ {"model": "BLE-MSA"}, ], + "SmartRing": [ + {"model": ""}, + ], "AllInOneTracker": [ {"model": "Checkme 1316"}, ], @@ -111,12 +114,16 @@ class MyTrackersViewModel extends ChangeNotifier { "Spirometer": [ {"model": "BLE-MSA"}, ], + "SmartRing": [ + {"model": "2301A"}, + ], "AllInOneTracker": [ {"model": "Checkme 1316"}, ], }; List ecgEnabledDevices = ["BP2 0567", "DuoEK", "ER1", "PM101897"]; + List checkMeProTrackers = [ TrackerTypeEnum.Temperature, TrackerTypeEnum.BloodPressureTracker, @@ -124,6 +131,7 @@ class MyTrackersViewModel extends ChangeNotifier { TrackerTypeEnum.BloodSugarTracker, TrackerTypeEnum.ECGTracker, ]; + List andesFitDevices = [ "BPM", "PM101897", @@ -131,6 +139,7 @@ class MyTrackersViewModel extends ChangeNotifier { "TEMP", "Samico GL", "BLE-MSA", + "2301A", ]; StreamSubscription bleDevicesStream; @@ -1082,6 +1091,42 @@ class MyTrackersViewModel extends ChangeNotifier { bool isDeviceSelected = false; + Future connectSmartRingDevice(BluetoothDevice device) async { + device.connectionState.listen((BluetoothConnectionState state) async { + if (state == BluetoothConnectionState.disconnected) { + isAndesfitDeviceConnected = false; + notifyListeners(); + } + if (state == BluetoothConnectionState.connected) { + isAndesfitDeviceConnected = true; + notifyListeners(); + bleDevicesStream.cancel(); + List services = await device.discoverServices(); + services.forEach((service) { + if (service.serviceUuid.toString().toLowerCase() == BLEUtils.TEMPERATURE_SERVICE) { + print(service.serviceUuid); + service.characteristics.forEach((characteristic) async { + if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.TEMPERATURE_CHARACTERISTIC) { + print(characteristic.characteristicUuid); + characteristic.onValueReceived.listen((event) { + print("onValueReceived Stream"); + print(event); + updateCurrentTempInCelsius(convertIntListToHexTemp(event)); + String currentTempInFahrenheit = ((num.parse(currentTempInCelsius) * 1.8) + 32).toStringAsFixed(1); + String tempCurrentTempInCelsius = currentTempInCelsius + "\u2103" + " / " + currentTempInFahrenheit + "\u2109"; + updateCurrentTempInCelsius(tempCurrentTempInCelsius); + }); + await characteristic.setNotifyValue(true); + } + }); + return true; + } + }); + } + }); + await device.connect(timeout: Duration(seconds: 35)); + } + Future connectAndesfitAllInOneDevice(BluetoothDevice device) async { log("deviceToConnect: ${device.toString()}"); }