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 SpirometerBLE extends StatefulWidget { @override State createState() => _SpirometerBLEState(); } class _SpirometerBLEState extends State { String connectionStatus = "disconnected"; BluetoothDevice currentConnectedDevice; StreamSubscription bleDevicesStream; BluetoothCharacteristic spirometerReadCharacteristicFf0a; BluetoothCharacteristic spirometerWriteCharacteristicFf0b; final bleConnectionStatus = ValueNotifier("Disconnected"); Timer _timer; Timer _timerRead; bool isHistoryCommandWritten = false; @override void dispose() { super.dispose(); if (currentConnectedDevice != null) currentConnectedDevice.disconnect(); if (_timer != null && _timer.isActive) _timer.cancel(); if (_timerRead != null && _timerRead.isActive) _timerRead.cancel(); bleConnectionStatus.dispose(); if (bleDevicesStream != null) bleDevicesStream.cancel(); } @override Widget build(BuildContext context) { return AppScaffold( appBarTitle: TranslationBase.of(context).spirometer, showNewAppBar: true, isShowDecPage: false, 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, ), ValueListenableBuilder( valueListenable: bleConnectionStatus, builder: (context, value, _) { return Text("Connection state: $value"); }, ), SizedBox( height: 50.0, ), // Text("Current Temp: $currentTempInCelsius"), ], ), ); } 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) { bleConnectionStatus.value = "Connecting..."; bleDevicesStream = FlutterBluePlus.scanResults.listen( (results) { List blueToothDevices = results; blueToothDevices.forEach( (element) { if (element.device.localName.isNotEmpty) { if (element.device.localName.toLowerCase() == "ble-msa") { 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(); List services = await element.device.discoverServices(timeout: 5); services.forEach( (service) { if (service.serviceUuid.toString().toLowerCase() == BLEUtils.BLE_TO_MSA100_SERVICE) { print(service.serviceUuid); service.characteristics.forEach( (characteristic) async { if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.BLE_TO_MSA100_READ_CHARACTERISTIC) { spirometerReadCharacteristicFf0a = characteristic; print(spirometerReadCharacteristicFf0a.characteristicUuid); print(spirometerReadCharacteristicFf0a.properties.toString()); spirometerReadCharacteristicFf0a.onValueReceived.listen((event) async { print("onValueReceived ff0a Stream"); print(event); //Sample response // dd14d93d5c1f01a302f8de3d5c1c017302 if (event[0] == 170) { _timer.cancel(); // Write get history command to ff0b if (!isHistoryCommandWritten) { await Future.delayed(Duration(milliseconds: 1000)).then((value) async { spirometerWriteCharacteristicFf0b.write([0x55, 0x01], withoutResponse: false).then((value) { print("----ff0b get history command data written----"); isHistoryCommandWritten = true; }); }); // Write get 1st history command to ff0b await Future.delayed(Duration(milliseconds: 1000)).then((value) async { spirometerWriteCharacteristicFf0b.write([0x55, 0x02, 0x01, 0x00], withoutResponse: false).then((value) { print("----ff0b get 1st history command data written----"); isHistoryCommandWritten = true; }); }); // Write delete history command to ff0b // await Future.delayed(Duration(milliseconds: 1000)).then((value) async { // spirometerWriteCharacteristicFf0b.write([0x55, 0x03], withoutResponse: false).then((value) { // print("----ff0b delete history command data written----"); // isHistoryCommandWritten = true; // }); // }); } } }); await Future.delayed(Duration(milliseconds: 1000)).then((value) async { print("Delayed ff0a done"); if (!spirometerReadCharacteristicFf0a.isNotifying) await spirometerReadCharacteristicFf0a.setNotifyValue(true).catchError((err) {}); }); } if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.BLE_TO_MSA100_WRITE_CHARACTERISTIC) { spirometerWriteCharacteristicFf0b = characteristic; print(spirometerWriteCharacteristicFf0b.characteristicUuid); print(spirometerWriteCharacteristicFf0b.properties.toString()); // Write ACK command to ff0b every 500 ms await Future.delayed(Duration(milliseconds: 1000)).then((value) async { _timer = Timer.periodic(Duration(milliseconds: 500), (Timer t) { spirometerWriteCharacteristicFf0b.write([0x55, 0x06], withoutResponse: false).then((value) { print("----ff0b ACK command data written----"); }); }); }); } }, ); } }, ); }); } } }, ); }, // onError(e) => print(e); ); FlutterBluePlus.startScan(timeout: const Duration(seconds: 5), androidUsesFineLocation: false); } } } 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) {} }, ), ], ), ), ), ); } }