flutter_reactive_ble icon indicating copy to clipboard operation
flutter_reactive_ble copied to clipboard

Not Able To Disconnect When BLE Device Is Disconnected/Switched Off Manually

Open mrdesai109 opened this issue 2 years ago • 10 comments

Bug

When I try connect to a BLE Device with 'flutterReactiveBle.connectTo()' after manually switching off the BLE device, the code stays in the 'connecting' state. Any other BLE device is also not connecting after this. Note that, I am calling 'openStream?.cancel()' for disconnection before calling flutterReactiveBle.connectTo().

To Reproduce

  1. Connect to one BLE device with connectTo(). This will work.
  2. Switch off that BLE.
  3. Again connect using **connectTo()**. Connection state stream will get stuck at 'DeviceConnectionState.Connecting' for current or any other BLE device.

Expected behavior Current BLE stream should produce DeviceConnectionState.Disconnected state and app should be able to connect to any other BLE and the connection state stream should produce a DeviceConnectionState.Connected state.

Smartphone / tablet

  • Samsung M32
  • Android 11
  • Reactive BLE 5.0.2

Code Snippet

void connectToBLEDevice(String connectionMACID)async{
      if (isConnectionInProgress == false) {
      await Future.delayed(Duration(milliseconds: 1));
      await openStreamSubs?.cancel();
      Stream<ConnectionStateUpdate>? connectStream =
          flutterReactiveBle.connectToDevice(
              id: connectionMACID.trim(),
              servicesWithCharacteristicsToDiscover:
                  getDiscoverCharacteristics(),
              connectionTimeout: Duration(milliseconds: 3500));
      openStreamSubs = connectStream.listen(
        (state) async {
          if (state.connectionState == DeviceConnectionState.connecting) {
            connectingCheckTimerOpen?.cancel();
            connectingCheckTimerOpen =
                Timer(Duration(milliseconds: 3500), () async {
              isBLEConnected = false;
              isConnectionInProgress = false;      
              await openStreamSubs?.cancel();
            });
          } else if (state.connectionState == DeviceConnectionState.connected) {
            isBLEConnected = true;
            connectingCheckTimerOpen?.cancel();
            //? proceed write operation
            final characteristic =
                getWriteCharacteristic(connectionMACID.trim());
            flutterReactiveBle
                .writeCharacteristicWithResponse(characteristic,
                    value: CommandStructures.writeCommand)
                .then((value) async {            
              isLockOpenWriteSuccess = true;
              openLockRetryCount = 0;                   
              isConnectionInProgress = false;
              await openStreamSubs?.cancel();
              isBLEConnected = false;
              connectingCheckTimerOpen?.cancel();
            }, onError: (err, stackTrace) async {          
              isLockOpenWriteSuccess = false;             
              isConnectionInProgress = false;                   
              await openStreamSubs?.cancel();
              isLockConnectedOpen = false;
              connectingCheckTimerOpen?.cancel();
            });
          } else if (state.connectionState ==
              DeviceConnectionState.disconnected) {       
            isBLEConnected = false;
            connectingCheckTimerOpen?.cancel();
            isConnectionInProgress = false;
            await openStreamSubs?.cancel();           
        },
        onError: (err) async {
          await openStreamSubs?.cancel();
          isConnectionInProgress = false;         
        },
      );
    } else {
     print('Connection In Progress');
    }
}

mrdesai109 avatar Jun 13 '22 13:06 mrdesai109

This looks like something wrong with your code, can you reproduce this in example app?

Taym95 avatar Jun 13 '22 22:06 Taym95

I can confirm this is happening with example app also. After I manually switch off the BLE device, connection state is stuck at 'Connecting'. Also when I tried to connect with another BLE device which is switched on, connection state is again stuck at 'Connecting'.

Expected behaviour is if it can't connect it should go to state of 'Disconnected' after some time.

Have a look at attached screenshot.

example_app_sc

mrdesai109 avatar Jun 14 '22 06:06 mrdesai109

Any suggestions? Same issue here.

yuriboeira11tx avatar Aug 04 '22 13:08 yuriboeira11tx

Encountering the same issue also :)

Wassim24 avatar Aug 09 '22 22:08 Wassim24

I have similar issue too with iOS 15 (not tested Android) When I tried to lose device connection dispose function give error.

@override void dispose() { subscribeStream?.cancel(); super.dispose(); }

Error is:

flutter: Error unsubscribing from notifications: PlatformException(reactive_ble_mobile.Central.(unknown context at $104f8ba50).Failure:1, The operation couldn’t be completed. (reactive_ble_mobile.Central.(unknown context at $104f8ba50).Failure error 1.), {}, null) reactive_ble_mobile/ConnectTaskController.swift:16: Assertion failed reactive_ble_mobile/ConnectTaskController.swift:16: Assertion failed

  • thread #1, queue = 'com.apple.main-thread', stop reason = Assertion failed frame #0: 0x00000001b9df2458 libswiftCore.dylib_swift_runtime_on_report libswiftCore.dylib_swift_runtime_on_report: -> 0x1b9df2458 <+0>: ret
    libswiftCore.dylib_swift_reportToDebugger: 0x1b9df245c <+0>: b 0x1b9df2458 ; _swift_runtime_on_report libswiftCore.dylib_swift_shouldReportFatalErrorsToDebugger: 0x1b9df2460 <+0>: adrp x8, 334840 0x1b9df2464 <+4>: ldrb w0, [x8, #0x65c] Target 0: (Runner) stopped. Lost connection to device.

sercan-uzun avatar Aug 17 '22 13:08 sercan-uzun

I have the same problem here. I have two BLE boxes. When I connect to one at first, it works fine. When I detect the other one and then connect to it (and both are on) I can also connect to the other one. However, when I turn off one of them, quit the application and then try to reconnect to one of the two boxes (the only one that remains on), I get a "connecting" status that remains without ever connecting...

florianToribio avatar Nov 07 '22 11:11 florianToribio

The same issue, but Stream<ConnectionStateUpdate> even has no cancel() member now (for some reason?), so I even can't cancel the subscription.

Nargott avatar Dec 14 '22 05:12 Nargott

similar issue. after Bluetooth device is powered off, no DeviceConnectionState.disconnected is received.

pmagnuson avatar May 02 '23 06:05 pmagnuson

Any update on this issue guys ? I am facing this issue still

Maniarasan avatar Jun 30 '23 12:06 Maniarasan

I was able solved this by using a state listener, I am using Riverpod.

add this function

void connectingListener() {
    ref.listen(connectionStateUpdateStateprovider, (previous, next) {
      if (ref.watch(connectionStateUpdateStateprovider).connectionState ==
          DeviceConnectionState.connecting) {
        Future.delayed(Duration(seconds: 5), () {
          if (ref.watch(connectionStateUpdateStateprovider).connectionState ==
              DeviceConnectionState.connecting) {
            ref
                .watch(connectorProvider)
                .disconnect(onConnectingDevice.id, onConnectingDevice.name);
            connectFailAlert();
          }
        });
      }
    });
  }

then place connectingListener(); inside build

The code is listening the change of DeviceConnectionState, then if it still connecting after a delay (I use 5 seconds here) then cancel the connecting (using disconnect method). The method is a little bit bloated but it is useful.

effmuhammad avatar Aug 31 '23 05:08 effmuhammad