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; List blueToothDevices = []; 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) {} }, ), ], ), ), ), ); } }