flutter_reactive_ble
flutter_reactive_ble copied to clipboard
Android: Writing to disconnected device creates a new connection
Describe the bug On Android, when I try to write to a disconnected device, a new connection is created with an infinite timeout. This causes several issues:
- If the device is not in range, then the future returned by the write function is never completed. There is no way to configure the timeout on this connection.
- If the connection succeeds then the connection is leaked, as the write function does not return a
Stream<ConnectionStateUpdate>
that we could cancel likeconnectToDevice
does. There is no way to cancel this connection, and all subsequent calls toconnectToAdvertisingDevice
fail.
To Reproduce Steps to reproduce the behavior:
- Have a connectable peripheral device advertising
- Initialise BLE
- Scan to get the device ID
- Write to a characteristic without connecting to the device
- See in the logs that a new connection is created
- Try to use connectToAdvertisingDevice on the same device ID
- Connection will fail as we are still connected to the device and it is not advertising any more
I/flutter (32695): INFO: 2022-07-11 10:36:46.900749: Trying to write without connecting
D/BluetoothGatt(32695): connect() - device: FC:F5:C4:65:8B:7A, auto: true
D/BluetoothGatt(32695): registerApp()
D/BluetoothGatt(32695): registerApp() - UUID=1292522e-2cd4-4320-b7b9-b6182d097935
D/BluetoothGatt(32695): onClientRegistered() - status=0 clientIf=8
I/flutter (32695): FINE: 2022-07-11 10:36:46.967818: ConnectionStateUpdate(deviceId: FC:F5:C4:65:8B:7A, connectionState: DeviceConnectionState.connecting, failure: null)
D/BluetoothGatt(32695): onClientConnectionState() - status=0 clientIf=8 device=FC:F5:C4:65:8B:7A
D/BluetoothGatt(32695): discoverServices() - device: FC:F5:C4:65:8B:7A
I/flutter (32695): FINE: 2022-07-11 10:36:59.007188: ConnectionStateUpdate(deviceId: FC:F5:C4:65:8B:7A, connectionState: DeviceConnectionState.connected, failure: null)
D/BluetoothGatt(32695): onSearchComplete() = Device=FC:F5:C4:65:8B:7A Status=0
I/flutter (32695): INFO: 2022-07-11 10:36:59.427412: Write without connecting completed
I/flutter (32695): INFO: 2022-07-11 10:37:09.441815: Trying to connect
D/BluetoothAdapter(32695): isLeEnabled(): ON
D/BluetoothLeScanner(32695): onScannerRegistered() - status=0 scannerId=9 mScannerId=0
D/BluetoothAdapter(32695): isLeEnabled(): ON
I/flutter (32695): SEVERE: 2022-07-11 10:37:14.505441: Device is disconnected
Expected behavior
I expect an error to be reported by the library when trying to perform illegal operations such as writing to a disconnected device.
-
Calls to write/read/subscribe with a disconnected device to raise an exception.
-
Calls to write/read/subscribe with a disconnected device do not create new connections. The only way to create connections is using the
connectToDevice
,connectToAdvertisingDevice
functions. -
[ ] I tried doing the same with a general BLE scanner application (e.g. nRF Connect) and it exhibits the expected behavior as described above
The nRF connect UI does not allow read write while the device is not connected.
Smartphone / tablet
- Device: Nokia 4.2
- OS: Android 11
- Package version: 5.0.2
Peripheral device
- Vendor, model: CUSTOM
- Does it run a custom firmware / software: yes
This issue should be reproducible on any peripheral device.
Additional context
This seems to be caused by this line: https://github.com/PhilipsHue/flutter_reactive_ble/blob/c25bedf9bc00abdac60927f42a8aafdc5ae5dbf8/packages/reactive_ble_mobile/android/src/main/kotlin/com/signify/hue/flutterreactiveble/ble/ReactiveBleClient.kt#L245
When the connection for the selected deviceId is not active, a new connection is created. I've looked through the git history for clues as to why a new connection is created here, but that line of code has been there since the inital commit to the repo.
On iOS, an exception is raised as expected:
flutter: SEVERE: 2022-07-08 16:57:34.075327: Exception: GenericFailure<WriteCharacteristicFailure>(code: WriteCharacteristicFailure.unknown, message: "A peripheral 26C77996-F075-9120-8B13-1571327087C7 is unknown (make sure it has been discovered)")
flutter: SEVERE: 2022-07-08 16:57:34.075642: #0 Result.dematerialize.<anonymous closure> (package:reactive_ble_platform_interface/src/model/result.dart:22:13)
flutter: #1 Result.iif (package:reactive_ble_platform_interface/src/model/result.dart:34:21)
flutter: #2 Result.dematerialize (package:reactive_ble_platform_interface/src/model/result.dart:15:28)
flutter: #3 ConnectedDeviceOperationImpl.writeCharacteristicWithResponse.<anonymous closure> (package:flutter_reactive_ble/src/connected_device_operation.dart:63:39)
flutter: #4 _rootRunUnary (dart:async/zone.dart:1434:47)
flutter: #5 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
flutter: <asynchronous suspension>
flutter: #6 SystemSetupModel.setWifiCredentials (package:attessa_ui_test/system_setup/model/system_setup.dart:95:5)
flutter: <asynchronous suspension>
flutter:
flutter: INFO: 2022-07-08 16:57:34.075845: Write without connecting completed
I'll try wrapping the write/read/subscribe function so that using them on a device that is not in the connected state throws. Monitoring the connection state for all devices should be possible using the bleStatusStream property.
I am also running into the same issue
I also have the same issue.
@maBarabas did you succeed with listening to the bleStatusStream. I added gates on the write/read/subscribe functions in my code, for when state != connected
but somehow this is not always working out.
Is this issue still being tracked?