dotintent / FlutterBleLib

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

startPeripheralScan does not return anything. Debug log shows scan finished in 16ms #535

Closed RickVM closed 3 years ago

RickVM commented 3 years ago

When starting the peripheral scan I'm expecting my device to be found but this does not happen. Nevertheless, In the end I expect onDone to be called, or onError (especially if i stop the scan) but this does not happen either.

Debug log seems to show the scan finishes in 16ms, which seems strange. D/RxBle#ClientOperationQueue( 6183): FINISHED ScanOperationApi21(164449828) in 16 ms

I've tried balanced and lowLatency scanMode's, also the firstMatch callback besides allmatches. Am I missing something? The uuids entered are some of the services the my device lists. Also, bluetooth and location service are both enabled.

    await bleManager.createClient();
    await _checkPermissions();
    bleManager.setLogLevel(LogLevel.debug);

    Future.delayed(Duration(seconds: 15), () async {
      print("Timeout triggered");
      await bleManager.stopPeripheralScan();
      print("Scan stopped");
    });

    await bleManager.startPeripheralScan(
      scanMode: ScanMode.lowLatency,
      callbackType: CallbackType.allMatches,
      uuids: [
         "99db2100-ac2d-11e3-a5e2-0800200c9a66",
        "99db2000-ac2d-11e3-a5e2-0800200c9a66",
         "f000ffc0-0451-4000-b000-000000000000"
      ],
    ).listen((event) {
      print("CHECK");
      print("Found a device: ${event.rssi} ${event.peripheral.name}");
    },
        onError: (Object err) => print("An error occuredd"),
        onDone: () => print("OnDone is called")).asFuture(null);
    print("Done scanning");
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin( 6183): on native side observed method: createClient
I/flutter ( 6183): Permission was granted for location access
I/flutter ( 6183): set log level to debug
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin( 6183): on native side observed method: setLogLevel
D/com.polidea.flutter_ble_lib.delegate.LogLevelDelegate( 6183): set log level to: debug
I/flutter ( 6183): Starting scan
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin( 6183): on native side observed method: startDeviceScan
D/RxBle#ClientOperationQueue( 6183): QUEUED   ScanOperationApi21(164449828)
D/RxBle#ClientOperationQueue( 6183): STARTED  ScanOperationApi21(164449828)
I/RxBle#QueueOperation( 6183): Scan operation is requested to start.
D/BluetoothAdapter( 6183): isLeEnabled(): ON
D/BluetoothLeScanner( 6183): onScannerRegistered() - status=0 scannerId=13 mScannerId=0
D/RxBle#ClientOperationQueue( 6183): FINISHED ScanOperationApi21(164449828) in 16 ms
I/flutter ( 6183): Timeout triggered
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin( 6183): on native side observed method: stopDeviceScan
I/RxBle#CancellableSubscription( 6183): Scan operation is requested to stop.
D/BluetoothAdapter( 6183): isLeEnabled(): ON
I/flutter ( 6183): Done scanning
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin( 6183): on native side observed method: stopDeviceScan
I/flutter ( 6183): Transition { currentState: PamSearchInProgress, event: PamSearchStarted, nextState: PamSearchFailure { error: NoSuchMethodError: The method 'retainWhere' was called on null.
I/flutter ( 6183): Receiver: null
I/flutter ( 6183): Tried calling: retainWhere(Closure: (ScanResult) => bool) } }
I/flutter ( 6183): Scan stopped
mikolak commented 3 years ago

Does it also happen if that delayed future that stops scan is commented out?

RickVM commented 3 years ago

Yes, same result except we never get past the scan. I have also tried to run the scan as documented, where the scan is stopped on the first scanresult

RickVM commented 3 years ago

@mikolak I have found that the api does in fact detect other devices if I change the scan filter. Still, onDone is never called. Is this intentional?

Also, for some reason, on at least android (havent tried ios) my device is not discoved with any of the used UUIDS :(

mikolak commented 3 years ago

Are you sure your device advertises those UUIDs? Is any of them in scanResult.advertisementData.serviceUuids?

RickVM commented 3 years ago

Yes, quite sure. I can see the services with the app BLE Scanner. Also, I have a working implementation with FlutterBlue. Scanning is handled differently there though, every ble device is returned, after which I filter on the name. Later in the process, I interact with multiple of the said services.

I cannot tell if if any of them is in scanResult.advertisementData.serviceUuids , since no scanResults are returned for the device I am looking for

Would prefer FlutterBleLib if we can get this working

mikolak commented 3 years ago

Can you change library's log level (bleManager.setLogLevel(LogLevel.verbose)), remove UUID filters and get logs from logcat? If your device is advertising, then it must be found. You can filter the scan results after receiving all of them - just call bleManager.startPeripheralScan().where(). You can pair with .first to return only the first result. Scan will automatically be stopped when you unsubscribe from the Stream, so if you only want the first result and you're looking for it for a duration, you could do:

try {
  final scanResult = await bleManager.startPeripheralScan().where().first.timeout(duration);
  return scanResult.peripheral;
} catch (e) {
  print('$e');
  return null;
}

onDone not being called is most probably an oversight, it will probably need to be fixed.

RickVM commented 3 years ago

Well that fixed it for me, now I am able to find the device. Thanks! If I print out the services after connecting i can see the services I was using for the filter being listed so thats still a bit strange.

Personally though, I dont really care as this will work fine for me. Close?

mikolak commented 3 years ago

Advertised services are a different thing than those on the peripheral itself. It's just a UUID sent in the advertising packet - it may or may not be available on the peripheral itself, it may be in a shorter form. The filtering in startPeripheralScan(uuids) is by those advertised UUIDs. You can see how your advertisement packet looks like by capturing and printing it with the library or by launching nRF Connect and checking it there.

Since it seems there's no issue with the library itself, I'm closing this for now.