PhilipsHue / flutter_reactive_ble

Flutter library that handles BLE operations for multiple devices.
https://developers.meethue.com/
Other
660 stars 321 forks source link

Android: Writing to disconnected device creates a new connection #589

Open maBarabas opened 2 years ago

maBarabas commented 2 years ago

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:

To Reproduce Steps to reproduce the behavior:

  1. Have a connectable peripheral device advertising
  2. Initialise BLE
  3. Scan to get the device ID
  4. Write to a characteristic without connecting to the device
  5. See in the logs that a new connection is created
  6. Try to use connectToAdvertisingDevice on the same device ID
  7. 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.

The nRF connect UI does not allow read write while the device is not connected.

Smartphone / tablet

Peripheral device

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.

tnchoe98 commented 1 year ago

I am also running into the same issue

rolandmosimann commented 6 months ago

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?