|
|
|
|
@ -19,16 +19,27 @@ class _SpirometerBLEState extends State<SpirometerBLE> {
|
|
|
|
|
String connectionStatus = "disconnected";
|
|
|
|
|
BluetoothDevice currentConnectedDevice;
|
|
|
|
|
|
|
|
|
|
StreamSubscription bleDevicesStream;
|
|
|
|
|
|
|
|
|
|
BluetoothCharacteristic spirometerReadCharacteristicFf0a;
|
|
|
|
|
BluetoothCharacteristic spirometerWriteCharacteristicFf0b;
|
|
|
|
|
|
|
|
|
|
final bleConnectionStatus = ValueNotifier<String>("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
|
|
|
|
|
@ -36,7 +47,7 @@ class _SpirometerBLEState extends State<SpirometerBLE> {
|
|
|
|
|
return AppScaffold(
|
|
|
|
|
appBarTitle: TranslationBase.of(context).spirometer,
|
|
|
|
|
showNewAppBar: true,
|
|
|
|
|
isShowDecPage: true,
|
|
|
|
|
isShowDecPage: false,
|
|
|
|
|
showNewAppBarTitle: true,
|
|
|
|
|
backgroundColor: Color(0xffF8F8F8),
|
|
|
|
|
body: SingleChildScrollView(
|
|
|
|
|
@ -62,7 +73,12 @@ class _SpirometerBLEState extends State<SpirometerBLE> {
|
|
|
|
|
SizedBox(
|
|
|
|
|
height: 50.0,
|
|
|
|
|
),
|
|
|
|
|
Text("Connection state: $connectionStatus"),
|
|
|
|
|
ValueListenableBuilder(
|
|
|
|
|
valueListenable: bleConnectionStatus,
|
|
|
|
|
builder: (context, value, _) {
|
|
|
|
|
return Text("Connection state: $value");
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
SizedBox(
|
|
|
|
|
height: 50.0,
|
|
|
|
|
),
|
|
|
|
|
@ -87,77 +103,105 @@ class _SpirometerBLEState extends State<SpirometerBLE> {
|
|
|
|
|
|
|
|
|
|
void startBLEConnection() {
|
|
|
|
|
if (FlutterBluePlus.isScanningNow == false) {
|
|
|
|
|
setState(() {
|
|
|
|
|
connectionStatus = "Connecting...";
|
|
|
|
|
});
|
|
|
|
|
bleConnectionStatus.value = "Connecting...";
|
|
|
|
|
|
|
|
|
|
FlutterBluePlus.startScan(timeout: const Duration(seconds: 5), androidUsesFineLocation: false).then((value) {
|
|
|
|
|
List<ScanResult> blueToothDevices = [];
|
|
|
|
|
// List<ScanResult> blueToothDevices = value;
|
|
|
|
|
blueToothDevices.forEach((element) async {
|
|
|
|
|
bleDevicesStream = FlutterBluePlus.scanResults.listen(
|
|
|
|
|
(results) {
|
|
|
|
|
List<ScanResult> blueToothDevices = results;
|
|
|
|
|
blueToothDevices.forEach(
|
|
|
|
|
(element) {
|
|
|
|
|
if (element.device.localName.isNotEmpty) {
|
|
|
|
|
if (element.device.localName.toLowerCase() == "ble-msa") {
|
|
|
|
|
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 (_timer != null && _timer.isActive) _timer.cancel();
|
|
|
|
|
if (_timerRead != null && _timerRead.isActive) _timerRead.cancel();
|
|
|
|
|
}
|
|
|
|
|
if (state == BluetoothConnectionState.connected) {
|
|
|
|
|
bleDevicesStream.cancel();
|
|
|
|
|
element.device.connect(timeout: Duration(seconds: 5), autoConnect: false).then((value) async {
|
|
|
|
|
bleConnectionStatus.value = "Connected...";
|
|
|
|
|
print("Device Connected-------");
|
|
|
|
|
currentConnectedDevice = element.device;
|
|
|
|
|
|
|
|
|
|
List<int> BLEToMSAWriteCharacters = [];
|
|
|
|
|
BLEToMSAWriteCharacters.add(int.parse("5506", radix: 16));
|
|
|
|
|
|
|
|
|
|
List<BluetoothService> services = await element.device.discoverServices();
|
|
|
|
|
services.forEach((service) {
|
|
|
|
|
FlutterBluePlus.stopScan();
|
|
|
|
|
List<BluetoothService> 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_CHARACTERISTIC) {
|
|
|
|
|
print(characteristic.characteristicUuid);
|
|
|
|
|
_timer = Timer.periodic(Duration(seconds: 2), (Timer timer) {
|
|
|
|
|
characteristic.write(BLEToMSAWriteCharacters).then((value) {
|
|
|
|
|
print("Characteristic response:");
|
|
|
|
|
}).catchError((err) {});
|
|
|
|
|
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;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (characteristic.characteristicUuid.toString().toLowerCase() == BLEUtils.MSA100_TO_BLE_CHARACTERISTIC) {
|
|
|
|
|
print(characteristic.characteristicUuid);
|
|
|
|
|
_timerRead = Timer.periodic(Duration(seconds: 2), (Timer timer) {
|
|
|
|
|
characteristic.read().then((value) {
|
|
|
|
|
print("Characteristic Read value: ");
|
|
|
|
|
print(value);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// characteristic.onValueReceived.listen((event) {
|
|
|
|
|
// print("onValueReceived Stream");
|
|
|
|
|
// print(event);
|
|
|
|
|
// setState(() {
|
|
|
|
|
// currentTempInCelsius = convertIntListToHex(event);
|
|
|
|
|
// String currentTempInFahrenheit = ((num.parse(currentTempInCelsius) * 1.8) + 32).toStringAsFixed(1);
|
|
|
|
|
// currentTempInCelsius = currentTempInCelsius + "\u2103" + " / " + currentTempInFahrenheit + "\u2109";
|
|
|
|
|
// 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 characteristic.setNotifyValue(true);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return 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----");
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
await element.device.connect(timeout: Duration(seconds: 35));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
// onError(e) => print(e);
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
FlutterBluePlus.startScan(timeout: const Duration(seconds: 5), androidUsesFineLocation: false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|