diff --git a/lib/core/service/client/base_app_client.dart b/lib/core/service/client/base_app_client.dart index fb3c900a..639e044b 100644 --- a/lib/core/service/client/base_app_client.dart +++ b/lib/core/service/client/base_app_client.dart @@ -149,7 +149,7 @@ class BaseAppClient { // body['IdentificationNo'] = 1023854217; // body['MobileNo'] = "531940021"; - // body['PatientID'] = 4767370; //3844083 + // body['PatientID'] = 3615065; //3844083 // body['TokenID'] = "@dm!n"; // Patient ID: 3027574 diff --git a/lib/models/ble_devices/ble_scan_response.dart b/lib/models/ble_devices/ble_scan_response.dart deleted file mode 100644 index e69de29b..00000000 diff --git a/lib/pages/medical/my_trackers/blood_pressure/BloodPressureBLE.dart b/lib/pages/medical/my_trackers/blood_pressure/BloodPressureBLE.dart new file mode 100644 index 00000000..2dee12d8 --- /dev/null +++ b/lib/pages/medical/my_trackers/blood_pressure/BloodPressureBLE.dart @@ -0,0 +1,233 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/ble_utils.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class BloodPressureBLE extends StatefulWidget { + @override + State createState() => _BloodPressureBLEState(); +} + +class _BloodPressureBLEState extends State { + String connectionStatus = "disconnected"; + String currentBPmmHG = "0/0 mmHG"; + String currentPulse = "0 PPM"; + + BluetoothDevice currentConnectedDevice; + + StreamSubscription bloodPressureReadingStream; + + Timer _timer; + + @override + void dispose() { + super.dispose(); + if (bloodPressureReadingStream != null) bloodPressureReadingStream.cancel(); + if (currentConnectedDevice != null) currentConnectedDevice.disconnect(); + if (_timer != null && _timer.isActive) _timer.cancel(); + } + + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).bloodPressure, + showNewAppBar: true, + isShowDecPage: true, + showNewAppBarTitle: true, + backgroundColor: Color(0xffF8F8F8), + body: SingleChildScrollView( + child: StreamBuilder( + stream: FlutterBluePlus.adapterState, + initialData: BluetoothAdapterState.unknown, + builder: (c, snapshot) { + final adapterState = snapshot.data; + if (adapterState == BluetoothAdapterState.on) { + return Container( + margin: EdgeInsets.only(top: 200.0, left: 50.0, right: 50.0), + child: Column( + children: [ + Center( + child: DefaultButton( + TranslationBase.of(context).start.toUpperCase(), + () { + checkBLEPermissions(); + }, + color: CustomColors.green, + ), + ), + SizedBox( + height: 50.0, + ), + Text("Connection state: $connectionStatus"), + SizedBox( + height: 50.0, + ), + Text("Current BP Level: $currentBPmmHG"), + SizedBox( + height: 20.0, + ), + Text("Current Pulse: $currentPulse"), + ], + ), + ); + } else { + FlutterBluePlus.stopScan(); + return SizedBox(height: 300.0, child: BluetoothOffScreen(adapterState: adapterState)); + } + }), + ), + ); + } + + void checkBLEPermissions() { + [Permission.location, Permission.storage, Permission.bluetooth, Permission.bluetoothConnect, Permission.bluetoothScan].request().then((status) { + startBLEConnection(); + }); + } + + void startBLEConnection() { + if (FlutterBluePlus.isScanningNow == false) { + setState(() { + connectionStatus = "Connecting..."; + }); + + FlutterBluePlus.startScan(timeout: const Duration(seconds: 5), androidUsesFineLocation: false).then((value) { + List blueToothDevices = value; + blueToothDevices.forEach((element) async { + if (element.device.localName.isNotEmpty) { + if (element.device.localName.toLowerCase() == "bpm") { + 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! + + // _timer = Timer.periodic(Duration(seconds: 2), (Timer timer) { + // startBLEConnection(); + // }); + } + if (state == BluetoothConnectionState.connected) { + currentConnectedDevice = element.device; + // _timer.cancel(); + List services = await element.device.discoverServices(); + services.forEach((service) { + if (service.serviceUuid.toString().toLowerCase() == BLEUtils.BLOOD_PRESSURE_SERVICE) { + print(service.serviceUuid); + service.characteristics.forEach((characteristic) async { + if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.BLOOD_PRESSURE_CHARACTERISTIC) { + print(characteristic.characteristicUuid); + bloodPressureReadingStream = characteristic.onValueReceived.listen((event) { + print("onValueReceived Stream"); + print(event); + setState(() { + if (event.length < 12) { + currentBPmmHG = "Measuring..."; + } else { + currentBPmmHG = "Measurement complete!"; + Map results = handleBPResult(event, characteristic); + currentBPmmHG = results["systolic"] + "/" + results["diastolic"] + " - " + (results["isBPHigh"] == "true" ? "High BP" : "Normal BP"); + currentPulse = results["pulse"] + " - " + (results["isPulseHigh"] == "true" ? "High pulse" : "Normal Pulse"); + } + }); + }); + await characteristic.setNotifyValue(true); + } + }); + return true; + } + }); + } + }); + await element.device.connect(timeout: Duration(seconds: 35)); + return true; + } + } + }); + }); + } + } +} + +Map handleBPResult(List byteArray, BluetoothCharacteristic characteristic) { + // [28, 0, 148, 0, 118, 0, 0, 0, 106, 0, 0, 0] + + // {isBPHigh: true, systolic: 145, diastolic: 111, pulse: 109, isPulseHigh: true} + + Map results = Map(); + + if (byteArray[1] != 0 && byteArray[3] != 0) { + results["isBPHigh"] = "false"; + results["systolic"] = byteArray[1].toString(); + results["diastolic"] = byteArray[3].toString(); + } else { + results["isBPHigh"] = "true"; + results["systolic"] = byteArray[2].toString(); + results["diastolic"] = byteArray[4].toString(); + } + + if (byteArray[8] != 0) { + results["pulse"] = byteArray[8].toString(); + results["isPulseHigh"] = "true"; + } else { + results["pulse"] = byteArray[9].toString(); + results["isPulseHigh"] = "false"; + } + + if (characteristic.isNotifying) characteristic.setNotifyValue(false); + + print(results); + + return results; +} + +class BluetoothOffScreen extends StatelessWidget { + const BluetoothOffScreen({Key key, this.adapterState}) : super(key: key); + + final BluetoothAdapterState adapterState; + + @override + Widget build(BuildContext context) { + return ScaffoldMessenger( + child: Scaffold( + backgroundColor: Colors.lightBlue, + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon( + Icons.bluetooth_disabled, + size: 200.0, + color: Colors.white54, + ), + Text( + 'Bluetooth Adapter is ${adapterState != null ? adapterState.toString().split(".").last + ", Please turn on your bluetooth to continue." : 'not available'}.', + textAlign: TextAlign.center, + style: Theme.of(context).primaryTextTheme.titleSmall?.copyWith(color: Colors.white), + ), + if (Platform.isAndroid) + ElevatedButton( + child: const Text('TURN ON'), + onPressed: () async { + try { + if (Platform.isAndroid) { + await FlutterBluePlus.turnOn(); + } + } catch (e) {} + }, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/medical/my_trackers/my_trackers.dart b/lib/pages/medical/my_trackers/my_trackers.dart index 8f9fe10a..7d3abefb 100644 --- a/lib/pages/medical/my_trackers/my_trackers.dart +++ b/lib/pages/medical/my_trackers/my_trackers.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/Weight/WeightHomePage.dart'; +import 'package:diplomaticquarterapp/pages/medical/my_trackers/blood_pressure/BloodPressureBLE.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/blood_suger/blood_sugar_home_page.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/temperature.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; @@ -70,14 +71,27 @@ class MyTrackers extends StatelessWidget { width: 45.0, height: 45.0, ), + ), + InkWell( + onTap: () { + Navigator.push(context, FadePage(page: TemperatureHomePage())); + }, + child: MedicalProfileItem( + title: TranslationBase.of(context).temperature, + imagePath: 'assets/tracker/weight.png', + subTitle: null, + isPngImage: true, + width: 45.0, + height: 45.0, + ), ), InkWell( onTap: () { - Navigator.push(context, FadePage(page: TemperatureHomePage())); + Navigator.push(context, FadePage(page: BloodPressureBLE())); }, child: MedicalProfileItem( - title: TranslationBase.of(context).temperature, - imagePath: 'assets/tracker/weight.png', + title: TranslationBase.of(context).bloodPressure + " BLE", + imagePath: 'assets/tracker/blood-pressure.png', subTitle: null, isPngImage: true, width: 45.0, diff --git a/lib/pages/medical/my_trackers/temperature.dart b/lib/pages/medical/my_trackers/temperature.dart index c745e157..1ca0cd03 100644 --- a/lib/pages/medical/my_trackers/temperature.dart +++ b/lib/pages/medical/my_trackers/temperature.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/ble_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -103,10 +104,10 @@ class _TemperatureHomePageState extends State { currentConnectedDevice = element.device; List services = await element.device.discoverServices(); services.forEach((service) { - if (service.serviceUuid.toString().contains("1809")) { + if (service.serviceUuid.toString().toLowerCase() == BLEUtils.TEMPERATURE_SERVICE) { print(service.serviceUuid); service.characteristics.forEach((characteristic) async { - if (characteristic.characteristicUuid.toString().toLowerCase().contains("2a1c")) { + if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.TEMPERATURE_CHARACTERISTIC) { print(characteristic.characteristicUuid); characteristic.onValueReceived.listen((event) { print("onValueReceived Stream"); diff --git a/lib/uitl/ble_utils.dart b/lib/uitl/ble_utils.dart new file mode 100644 index 00000000..83a3ec01 --- /dev/null +++ b/lib/uitl/ble_utils.dart @@ -0,0 +1,9 @@ +class BLEUtils { + //Blood Pressure + static const String BLOOD_PRESSURE_SERVICE = "0000fff0-0000-1000-8000-00805f9b34fb"; + static const String BLOOD_PRESSURE_CHARACTERISTIC = "0000fff4-0000-1000-8000-00805f9b34fb"; + + //Temperature + static const String TEMPERATURE_SERVICE = "00001809-0000-1000-8000-00805f9b34fb"; + static const String TEMPERATURE_CHARACTERISTIC = "00002a1c-0000-1000-8000-00805f9b34fb"; +}