dotintent / FlutterBleLib

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

Not receiving notifications when monitoring a characteristic on iOS #463

Open cbreezier opened 4 years ago

cbreezier commented 4 years ago

Hi,

Thanks for your hard work and this wonderful library :)

I'm attempting to monitor a characteristic and setup notifications - it's working well on Android but I'm failing to receive any notifications on iOS.

The protocol looks something like this:

  1. the phone writes to a characteristic to indicate that it wishes to receive data
  2. the phone monitors that same characteristic
  3. data is emitted by the peripheral on that characteristic

Here is the code I have:

    final notification = device.monitorCharacteristic(
      SERVICE_UUID,
      CHARACTERISTIC_UUID,
    )
        .timeout(Duration(seconds: 3))
        .first;

    final readRequest = Uint8List.fromList([
      blockNumber,
      16 // number of bytes to read
    ]);

    device.writeCharacteristic(
        SERVICE_UUID,
        CHARACTERISTIC_UUID,
        readRequest,
        false
    );

    return notification
        .then((characteristicWithValue) => characteristicWithValue.value);

Am I doing something wrong? Or could there be a bug in the iOS implementation?

Other info:

mikolak commented 4 years ago

Hi!

Your code looks OK, I think, especially since it's working on Android. Can you try changing log level to verbose to see if anything out of ordinary pops out? I don't have access to iOS devices 'cause of lockdown.

cbreezier commented 4 years ago

Thanks for your quick reply!

I set the log level before creating the Ble client like so:

    _bleManager = BleManager();
    _bleManager.setLogLevel(LogLevel.verbose);
    _bleManager.createClient()
        .then((_) => _setupBleScan());

I'm not seeing anything out of the ordinary - actually it doesn't feel like I'm seeing more logs at all. This is a very calm "verbose" logging level :P

flutter: Initialising state of nearby devices
flutter: set log level to verbose
flutter: Resuming state of nearby devices
flutter: Initialising state of remote settings
flutter: Blutooth device state: PeripheralConnectionState.connected
flutter: Failed to read em number: TimeoutException after 0:00:03.000000: No stream event

All outputs other than set log level to verbose is from my business logic. The PeripheralConnecttionState.connected is simply a listener on the observeConnectionState method.

The code to setup notifications comes after the connection is setup and discovery of services is complete:

    _setupConnection() // this awaits on connection and also discovery of services
        .then((_) => _readAllSettings());

The TimeoutException log is from the stream subscription timeout as per my first snippet of code. If I don't add a timeout, I never receive notifications and the stream never closes.

I'm able to perform other operations (scan, connect, discover, read characteristics, write characteristics) with no issues.

When using NRF Connect on the same iPhone hardware, I'm able to set up notifications and receive the correct data from the peripheral, so it's not a hardware problem.

mikolak commented 4 years ago

There should be a lot more logs from native part (multiplatform ble adapter). Could you try running from xcode to see if there aren't more of them?

trixidis commented 4 years ago

got a similar problem and running from xcode helped me find what was wrong, thats real verbose there, thanks @mikolak i tried to write with a int list and not Uint8list.

cbreezier commented 4 years ago

Thank you @mikolak and @trixidis!

I knew I was doing something wrong :)

2020-05-21 09:53:29.235201+1000 Runner[975:644992] [CoreBluetooth] WARNING: Characteristic <CBCharacteristic: 0x28291a520, UUID = 0000AC49-53A6-4F72-96C8-FD6E6964BAE3, properties = 0x18, value = (null), notifying = YES> does not specify the "Write Without Response" property - ignoring response-less write

I wonder if it would be possible to propagate this up as an error rather than silently ignoring the write an logging a warning?

cbreezier commented 4 years ago

(Feel free to close this issue now - unless you want to use it to track work on making warnings like these more visible)