From efba7faa787d587d44a3ac62f00d911ef6c22650 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 20 Sep 2023 15:40:56 +0300 Subject: [PATCH] updates --- lib/config/config.dart | 4 +- lib/models/ble_devices/weight_scale_data.dart | 9 + lib/pages/ble_screen.dart | 9 +- lib/pages/landing/landing_page.dart | 5 +- .../medical/my_trackers/my_trackers.dart | 14 ++ .../viatom_devices/oxymeter_ble.dart | 116 +++++++++ .../medical/my_trackers/weight_scale_ble.dart | 231 ++++++++++++++---- pubspec.yaml | 2 +- 8 files changed, 337 insertions(+), 53 deletions(-) create mode 100644 lib/models/ble_devices/weight_scale_data.dart create mode 100644 lib/pages/medical/my_trackers/viatom_devices/oxymeter_ble.dart diff --git a/lib/config/config.dart b/lib/config/config.dart index 5c9912e4..e93af7c8 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -20,8 +20,8 @@ var PACKAGES_ORDERS = '/api/orders'; var PACKAGES_ORDER_HISTORY = '/api/orders/items'; var PACKAGES_TAMARA_OPT = '/api/orders/paymentoptions/tamara'; // var BASE_URL = 'http://10.50.100.198:2018/'; -// var BASE_URL = 'https://uat.hmgwebservices.com/'; -var BASE_URL = 'https://hmgwebservices.com/'; +var BASE_URL = 'https://uat.hmgwebservices.com/'; +// var BASE_URL = 'https://hmgwebservices.com/'; // var BASE_URL = 'https://orash.cloudsolutions.com.sa/'; // var BASE_URL = 'https://vidauat.cloudsolutions.com.sa/'; diff --git a/lib/models/ble_devices/weight_scale_data.dart b/lib/models/ble_devices/weight_scale_data.dart new file mode 100644 index 00000000..0745fc3e --- /dev/null +++ b/lib/models/ble_devices/weight_scale_data.dart @@ -0,0 +1,9 @@ +class WeightScaleData { + String weight; + String bmi; + String fat; + String bone; + String water; + String muscle; + String bmr; +} \ No newline at end of file diff --git a/lib/pages/ble_screen.dart b/lib/pages/ble_screen.dart index c0dc0fc4..eec1fb85 100644 --- a/lib/pages/ble_screen.dart +++ b/lib/pages/ble_screen.dart @@ -10,9 +10,8 @@ class BLEScreen extends StatefulWidget { } class _BLEScreenState extends State { - String abc = ""; EventChannel eventChannel = EventChannel('BLE-Platform-Bridge-Event'); - String recivedData = ''; + String receivedData = ''; @override void initState() { @@ -23,7 +22,7 @@ class _BLEScreenState extends State { print('Received event---: $event'); setState(() { - recivedData = event; + receivedData = event; }); // You can update your UI or perform any other actions based on the event. }); @@ -40,7 +39,7 @@ class _BLEScreenState extends State { Center( child: GestureDetector( onTap: () async { - abc = await BleChannel.getScanningResult(); + await BleChannel.getScanningResult(); }, child: Container( width: 50, @@ -49,7 +48,7 @@ class _BLEScreenState extends State { ), ), ), - Center(child: Text(recivedData)) + Center(child: Text(receivedData)) ], ), ), diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 0c044e6b..0a33698c 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -17,6 +17,7 @@ import 'package:diplomaticquarterapp/pages/DrawerPages/family/my-family.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/ToDo.dart'; import 'package:diplomaticquarterapp/pages/landing/home_page_2.dart'; import 'package:diplomaticquarterapp/pages/medical/medical_profile_page_new.dart'; +import 'package:diplomaticquarterapp/pages/medical/my_trackers/weight_scale_ble.dart'; import 'package:diplomaticquarterapp/pages/videocall-webrtc-rnd/webrtc/start_video_call.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; @@ -36,6 +37,7 @@ import 'package:diplomaticquarterapp/widgets/buttons/floatingActionButton.dart'; import 'package:diplomaticquarterapp/widgets/drawer/app_drawer_widget.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/others/not_auh_page.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -565,7 +567,8 @@ class _LandingPageState extends State with WidgetsBindingObserver { changeCurrentTab(1); }, onLoginClick: () { - login(); + // login(); + Navigator.push(context, FadePage(page: WeightScaleBLE())); }, onMedicalFileClick: () { changeCurrentTab(1); diff --git a/lib/pages/medical/my_trackers/my_trackers.dart b/lib/pages/medical/my_trackers/my_trackers.dart index 4b1904f3..3d16b18a 100644 --- a/lib/pages/medical/my_trackers/my_trackers.dart +++ b/lib/pages/medical/my_trackers/my_trackers.dart @@ -6,6 +6,7 @@ import 'package:diplomaticquarterapp/pages/medical/my_trackers/blood_suger/blood import 'package:diplomaticquarterapp/pages/medical/my_trackers/ecg_ble.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/spirometer.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/temperature.dart'; +import 'package:diplomaticquarterapp/pages/medical/my_trackers/viatom_devices/oxymeter_ble.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/weight_scale_ble.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart'; @@ -154,6 +155,19 @@ class MyTrackers extends StatelessWidget { height: 45.0, ), ), + InkWell( + onTap: () { + Navigator.push(context, FadePage(page: Oxymeter_BLE())); + }, + child: MedicalProfileItem( + title: "Oxymeter BLE", + imagePath: 'assets/tracker/weight.png', + subTitle: null, + isPngImage: true, + width: 45.0, + height: 45.0, + ), + ), ], ), ), diff --git a/lib/pages/medical/my_trackers/viatom_devices/oxymeter_ble.dart b/lib/pages/medical/my_trackers/viatom_devices/oxymeter_ble.dart new file mode 100644 index 00000000..804c2616 --- /dev/null +++ b/lib/pages/medical/my_trackers/viatom_devices/oxymeter_ble.dart @@ -0,0 +1,116 @@ +import 'package:diplomaticquarterapp/viatom_ble/ble_connect.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class Oxymeter_BLE extends StatefulWidget { + @override + State createState() => _Oxymeter_BLEState(); +} + +class _Oxymeter_BLEState extends State { + EventChannel eventChannel = EventChannel('BLE-Platform-Bridge-Event'); + String receivedData = ''; + + final oxymeterValueNotifier = ValueNotifier("start"); + + @override + void dispose() { + oxymeterValueNotifier.dispose(); + super.dispose(); + } + + @override + void initState() { + // TODO: implement initState + super.initState(); + eventChannel.receiveBroadcastStream().listen((event) { + print('Received event---: $event'); + oxymeterValueNotifier.value = event; + }); + } + + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: "Oxymeter", + showNewAppBar: true, + isShowDecPage: true, + showNewAppBarTitle: true, + backgroundColor: Color(0xffF8F8F8), + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: GestureDetector( + onTap: () async { + await BleChannel.getScanningResult(); + }, + child: Container( + width: 50, + height: 50, + color: Colors.blueAccent, + ), + ), + ), + ValueListenableBuilder( + valueListenable: oxymeterValueNotifier, + builder: (context, value, _) { + return value != "start" + ? Column( + children: [ + Text( + getSPO2( + value.toString().replaceAll("RtParam", ""), + ), + ), + Text( + getPR( + value.toString().replaceAll("RtParam", ""), + ), + ), + Text( + getPI( + value.toString().replaceAll("RtParam", ""), + ), + ), + ], + ) + : Text(value); + }, + ), + ], + ), + ), + ); + } + + String getSPO2(String value) { + return "SpO2: " + value.split(",")[0].replaceAll("{spo2=", ""); + } + + String getPR(String value) { + return "Pulse Rate: " + value.split(",")[1].replaceAll("pr=", ""); + } + + String getPI(String value) { + return "Perfusion Index: " + value.split(",")[2].replaceAll("pi=", "") + "%"; + } + +// List setResult(String value) { +// List values = value.split(","); +// +// print(values[0].replaceAll("{spo2=", "")); +// print(values[1].replaceAll("pr=", "")); +// print(values[2].replaceAll("pi=", "")); +// +// values.clear(); +// values.add(values[0].replaceAll("{spo2=", "")); +// values.add(values[1].replaceAll("pr=", "")); +// values.add(values[2].replaceAll("pi=", "")); +// +// return values; +// } +} diff --git a/lib/pages/medical/my_trackers/weight_scale_ble.dart b/lib/pages/medical/my_trackers/weight_scale_ble.dart index dc2c0e82..4329dd77 100644 --- a/lib/pages/medical/my_trackers/weight_scale_ble.dart +++ b/lib/pages/medical/my_trackers/weight_scale_ble.dart @@ -1,6 +1,8 @@ import 'dart:async'; +import 'package:diplomaticquarterapp/models/ble_devices/weight_scale_data.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/ble_utils.dart'; import 'package:diplomaticquarterapp/uitl/bluetooth_off.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; @@ -17,18 +19,39 @@ class WeightScaleBLE extends StatefulWidget { class _WeightScaleBLEState extends State { String connectionStatus = "disconnected"; - String currentBloodGlucose = "0.0"; + String currentWeight = "0.0"; BluetoothDevice currentConnectedDevice; StreamSubscription bleDevicesStream; + StreamSubscription weightValuesStream; + + WeightScaleData weightScaleData = WeightScaleData(); + + final bleConnectionStatus = ValueNotifier("Disconnected"); + + BluetoothCharacteristic ble_fff1; + BluetoothCharacteristic ble_fff2; + BluetoothCharacteristic ble_fff3; + + String resultSet1 = ""; + String resultSet2 = ""; + + @override + void dispose() { + super.dispose(); + bleConnectionStatus.dispose(); + bleDevicesStream.cancel(); + weightValuesStream.cancel(); + currentConnectedDevice.disconnect(); + } @override Widget build(BuildContext context) { return AppScaffold( appBarTitle: TranslationBase.of(context).weight, showNewAppBar: true, - isShowDecPage: true, + isShowDecPage: false, showNewAppBarTitle: true, backgroundColor: Color(0xffF8F8F8), body: SingleChildScrollView( @@ -47,6 +70,7 @@ class _WeightScaleBLEState extends State { TranslationBase.of(context).start.toUpperCase(), () { checkBLEPermissions(); + // parseResultData(); }, color: CustomColors.green, ), @@ -54,11 +78,27 @@ class _WeightScaleBLEState extends State { SizedBox( height: 50.0, ), - Text("Connection state: $connectionStatus"), + ValueListenableBuilder( + valueListenable: bleConnectionStatus, + builder: (context, value, _) { + return Text("Connection state: $value"); + }, + ), SizedBox( height: 50.0, ), - Text("Current Temp: $currentBloodGlucose" + " mg/dL"), + Column( + children: [ + Text("Current Weight: ${weightScaleData.weight}" + " kg"), + Text("Current BMI: ${weightScaleData.bmi}"), + Text("Current Body Fat: ${weightScaleData.fat}" + "%"), + Text("Current Bone Weight: ${weightScaleData.bone}" + " kg"), + Text("Current Water: ${weightScaleData.water}" + "%"), + Text("Current Muscle: ${weightScaleData.muscle}" + "%"), + Text("Current BMR: ${weightScaleData.bmr}" + " calories/day"), + ], + ), + // }) ], ), ); @@ -79,9 +119,7 @@ class _WeightScaleBLEState extends State { void startBLEConnection() { if (FlutterBluePlus.isScanningNow == false) { - setState(() { - connectionStatus = "Connecting..."; - }); + bleConnectionStatus.value = "Connecting..."; bleDevicesStream = FlutterBluePlus.scanResults.listen( (results) { @@ -89,45 +127,92 @@ class _WeightScaleBLEState extends State { blueToothDevices.forEach((element) async { if (element.device.localName.isNotEmpty) { if (element.device.localName.toLowerCase() == "sdic") { - element.device.connectionState.listen((BluetoothConnectionState state) async { - setState(() { - connectionStatus = state.toString(); - }); - if (state == BluetoothConnectionState.disconnected) { - // typically, start a periodic timer that tries to periodically reconnect. - // Note: you must always re-discover services after disconnection! - } - if (state == BluetoothConnectionState.connected) { - currentConnectedDevice = element.device; - bleDevicesStream.cancel(); - List services = await element.device.discoverServices(); - services.forEach((service) { - if (service.serviceUuid.toString().toLowerCase() == BLEUtils.WEIGHT_MEASUREMENT_SERVICE) { - print(service.serviceUuid); - service.characteristics.forEach((characteristic) async { - // if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.WEIGHT_MEASUREMENT_CHARACTERISTIC_FFF3) { - // print(characteristic.characteristicUuid); - // characteristic.onValueReceived.listen((event) { - // print("onValueReceived fff3 Stream"); - // print(event); - // }); - // await characteristic.setNotifyValue(true); - // } - if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.WEIGHT_MEASUREMENT_CHARACTERISTIC_FFF1) { - print(characteristic.characteristicUuid); - characteristic.onValueReceived.listen((event) { - print("onValueReceived fff1 Stream"); - print(event); + bleDevicesStream.cancel(); + element.device.connect(timeout: Duration(seconds: 5), autoConnect: false).then((value) async { + bleConnectionStatus.value = "Connected..."; + print("Device Connected-------"); + currentConnectedDevice = element.device; + FlutterBluePlus.stopScan(); + // await currentConnectedDevice.clearGattCache(); + List services = await element.device.discoverServices(timeout: 5); + services.forEach((service) { + if (service.serviceUuid.toString().toLowerCase() == BLEUtils.WEIGHT_MEASUREMENT_SERVICE) { + print(service.serviceUuid); + service.characteristics.forEach((characteristic) async { + if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.WEIGHT_MEASUREMENT_CHARACTERISTIC_FFF1) { + ble_fff1 = characteristic; + print(characteristic.characteristicUuid); + print(characteristic.properties.toString()); + characteristic.onValueReceived.listen((event) { + print("onValueReceived fff1 Stream"); + print(event); + if (event[0] == 129) { + // Issue result ack command + Future.delayed(Duration(milliseconds: 1000)).then((value) async { + characteristic.write([0x01]).then((value) { + print("----fff1 result ack data written----"); + }); + }); + } + // Error + else if (event[0] == 65) { + AppToast.showErrorToast(message: "Measurement Error Occurred!"); + } else { + //Sample Results + // ----------Result Set 1----------: 42;0;1;0;0;0;0;65;9;b0;d2;0;7f;3;44;0;ac;1;cc;0 + // ----------Result Set 2----------: 42;1;32;0;2c;0;1;3;84;9;1b;0;29;2;9c;0;10;0;e9 + + if (event[1] == 0) { + resultSet1 = convertResultSetToString(event); + print("----------Result Set 1----------: $resultSet1"); + print("----------Result Set 2----------: $resultSet2"); + } else { + resultSet2 = convertResultSetToString(event); + print("----------Result Set 1----------: $resultSet1"); + print("----------Result Set 2----------: $resultSet2"); + parseResultData(); + } + } + }); + await Future.delayed(Duration(milliseconds: 500)).then((value) async { + print("Delayed fff1 done"); + if (!characteristic.isNotifying) await characteristic.setNotifyValue(true).catchError((err) {}); + }); + } + + if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.WEIGHT_MEASUREMENT_CHARACTERISTIC_FFF2) { + ble_fff2 = characteristic; + print(characteristic.characteristicUuid); + print(characteristic.properties.toString()); + characteristic.onValueReceived.listen((event) { + print("onValueReceived fff2 Stream"); + print(event); + }); + + await Future.delayed(Duration(milliseconds: 1000)).then((value) async { + print("Delayed fff2 done"); + if (!characteristic.isNotifying) await characteristic.setNotifyValue(true).catchError((err) {}); + }); + + // Write user data to fff2 + await Future.delayed(Duration(milliseconds: 1000)).then((value) async { + characteristic.write([0x81, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x19, 0x01, 0x00, 0x00], withoutResponse: true).then((value) { + print("----fff2 user data written----"); }); - await characteristic.setNotifyValue(true); - } - }); - return true; - } - }); - } + + // Issue get result command + await Future.delayed(Duration(milliseconds: 1000)).then((value) async { + characteristic.write([0x41, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00], withoutResponse: true).then((value) { + print("----fff2 get result data written----"); + }); + }); + }); + } + }); + return true; + } + }); }); - await element.device.connect(timeout: Duration(seconds: 35)); return true; } } @@ -139,4 +224,62 @@ class _WeightScaleBLEState extends State { FlutterBluePlus.startScan(timeout: const Duration(seconds: 5), androidUsesFineLocation: false); } } + + void parseResultData() { + // resultSet1 = "42;0;1;0;0;0;0;65;9;b0;d2;0;7f;3;44;0;ac;1;cc;0"; + // resultSet2 = "42;1;32;0;2c;0;1;3;84;9;1b;0;29;2;9c;0;10;0;e9"; + + List hexStringResSet1 = resultSet1.split(";"); + List hexStringResSet2 = resultSet2.split(";"); + + String hexStringWeight = hexStringResSet1[13] + hexStringResSet1[14]; + String hexStringBMI = hexStringResSet1[15] + hexStringResSet1[16]; + String hexStringFat = hexStringResSet2[3] + hexStringResSet2[4]; + String hexStringBone = hexStringResSet2[11] + hexStringResSet2[12]; + String hexStringWater = hexStringResSet2[13] + hexStringResSet2[14]; + String hexStringMuscle = hexStringResSet2[7] + hexStringResSet2[8]; + String hexStringBMR = hexStringResSet2[9] + hexStringResSet2[10]; + + print((int.parse(hexStringWeight, radix: 16) * 0.1).toStringAsFixed(1)); + print((int.parse(hexStringBMI, radix: 16) * 0.1).toStringAsFixed(1)); + print((int.parse(hexStringFat, radix: 16) * 0.1).toStringAsFixed(1)); + print((int.parse(hexStringMuscle, radix: 16) * 0.1).toStringAsFixed(1)); + print((int.parse(hexStringBMR, radix: 16))); + print((int.parse(hexStringBone, radix: 16) * 0.1).toStringAsFixed(1)); + print((int.parse(hexStringWater, radix: 16) * 0.1).toStringAsFixed(1)); + + setState(() { + weightScaleData.weight = (int.parse(hexStringWeight, radix: 16) * 0.1).toStringAsFixed(1); + weightScaleData.bmi = (int.parse(hexStringBMI, radix: 16) * 0.1).toStringAsFixed(1); + weightScaleData.fat = (int.parse(hexStringFat, radix: 16) * 0.1).toStringAsFixed(1); + weightScaleData.muscle = (int.parse(hexStringMuscle, radix: 16) * 0.1).toStringAsFixed(1); + weightScaleData.bmr = (int.parse(hexStringBMR, radix: 16)).toString(); + weightScaleData.bone = (int.parse(hexStringBone, radix: 16) * 0.1).toStringAsFixed(1); + weightScaleData.water = (int.parse(hexStringWater, radix: 16) * 0.1).toStringAsFixed(1); + }); + } + + String convertResultSetToString(List byteArray) { + String resSet; + resSet = (byteArray.map( + (x) { + return x.toRadixString(16); + }, + )).join(";"); + return resSet; + } + + String convertIntListToHex(List byteArray) { + String b = (byteArray.map((x) { + return x.toRadixString(16); + })).join(";"); + List hexString = b.split(";"); + print("HexString: $hexString"); + String returnString = hexString[2] + hexString[3]; + print("Temp Hex String: $returnString"); + final number = int.parse(returnString, radix: 16); + print("Temp Number: ${number * 0.1}"); + + return (number * 0.1).toStringAsFixed(1); + } } diff --git a/pubspec.yaml b/pubspec.yaml index a1ea4ed2..e18bb30d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -210,7 +210,7 @@ dependencies: # open_file: ^3.2.1 open_filex: ^4.3.2 path_provider: ^2.0.8 - flutter_blue_plus: ^1.15.5 + flutter_blue_plus: 1.15.7 # flutter_callkit_incoming: ^1.0.3+3 # firebase_core: 1.12.0