dotintent / FlutterBleLib

Bluetooth Low Energy library for Flutter with support for simulating peripherals
Apache License 2.0
535 stars 197 forks source link

[iOS] disconnectOrCancelConnection() will cause BleError when device is connecting. #495

Open dokinkon opened 4 years ago

dokinkon commented 4 years ago

flutter_ble_lib version = 2.2.6

How to reproduce?

  1. Launch App on iOS physical device.
  2. Scan ble devices and keep device identifier.
  3. Power off the ble device, and connect to this device. (To simulate connection takes long time)
  4. When connection state is "CONNECTING", invoke Peripheral.disconnectOrCancelConnection()

Expect result: Peripheral's state can back to "DISCONNECTED", and no error or exception happened

Actual result: Peripheral's state always keeps on "CONNECTING", and got a BleError which code = 2.

Android is fine on above operation flow.

dariuszseweryn commented 4 years ago

Hi

Could you add a code snippet you use to get states?

dokinkon commented 4 years ago

Hi

Could you add a code snippet you use to get states?

@dariuszseweryn

Here you are:

void tryConnect(Peripheral peripheral) async {
  print("Make sure the device was power-off before connection.");
  subscription = peripheral
    .observeConnectionState(emitCurrentValue: true)
    .listen((connectionState) {
      print("connectionState => $connectionState");
    });

  subscription.onError((e) {
    print("Error: $e");
  });

  await Future.delayed(Duration(seconds: 1));

  peripheral.connect(timeout: Duration(seconds: 3)).catchError((e) {
    print("Catch connect error => $e");
  });

  print("Waiting 3 seconds then cancel the connection...");
  await Future.delayed(Duration(seconds: 3));
  tryDisconnect(peripheral);
}

void tryDisconnect(Peripheral peripheral) {
  try {
    print("Canceling connection...");
    peripheral.disconnectOrCancelConnection().catchError((e) {
      print("Catch disconnectOrCancelConnection error => $e");
    });
  } catch (e, s) {
    print("Try disconnect error: $e");
  }
}

And the printed result in console is:


2020-07-18 11:56:31.892952+0800 Runner[1461:972642] flutter: Make sure the device was power-off before connection.
2020-07-18 11:56:32.915744+0800 Runner[1461:972642] flutter: Waiting 3 seconds then cancel the connection...
2020-07-18 11:56:32.928632+0800 Runner[1461:972642] flutter: connectionState => PeripheralConnectionState.connecting
2020-07-18 11:56:35.922968+0800 Runner[1461:972642] flutter: Canceling connection...
2020-07-18 11:56:35.945972+0800 Runner[1461:972642] flutter: Catch connect error => BleError (Error code: 2, ATT error code: null, iOS error code: null, Android error code: null, reason: null, internal message: null, device ID: null, service UUID: null, characteristic UUID: null, descriptor UUID: null)
2020-07-18 11:56:35.947902+0800 Runner[1461:972642] flutter: Catch disconnectOrCancelConnection error => BleError (Error code: 2, ATT error code: null, iOS error code: null, Android error code: null, reason: null, internal message: null, device ID: null, service UUID: null, characteristic UUID: null, descriptor UUID: null)

You can also checkout full sample project here https://bitbucket.org/dokinkon/flutter_ble_lib_issue_495

Thank you~

dokinkon commented 4 years ago

BTW, peripheral.observePeripheralConnectionState() will cause exception after v2.2.7. v2.2.6 was fine.

2020-07-18 12:08:19.718255+0800 Runner[1470:975390] [VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: type '_BroadcastStream<dynamic>' is not a subtype of type 'Stream<String>'
#0      DeviceConnectionMixin.observePeripheralConnectionState (package:flutter_ble_lib/src/bridge/device_connection_mixin.dart:41:20)
#1      InternalBleManager.observePeripheralConnectionState (package:flutter_ble_lib/src/internal_ble_manager.dart:94:26)
#2      Peripheral.observeConnectionState (package:flutter_ble_lib/peripheral.dart:68:16)
#3      _MyHomePageState.tryConnect (package:flutter_app_test_ble/main.dart:105:10)
#4      _MyHomePageState.build.<anonymous closure>.<anonymous closure> (package:flutter_app_test_ble/main.dart:94:15)
#5      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:779:19)
#6      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:862:36)
#7      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
#8      TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:504:11)
#9      BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:282:5)
#10     BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:254:7)
#11     GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
#12     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:222:20)
#13     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22)
#14     GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
#15     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)
#16     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)
#17     _rootRunUnary (dart:async/zone.dart:1196:13)
#18     _CustomZone.runUnary (dart:async/zone.dart:1085:19)
#19     _CustomZone.runUnaryGuarded (dart:async/zone.dart:987:7)
#20     _invoke1 (dart:ui/hooks.dart:275:10)
#21     _dispatchPointerDataPacket (dart:ui/hooks.dart:184:5)
flutterboi commented 3 years ago

Any update on this or any work arounds?

mikolak commented 3 years ago

Is it still happening? I think I might've fixed it accidentally in December.