capacitor-community / bluetooth-le

Capacitor plugin for Bluetooth Low Energy
MIT License
279 stars 84 forks source link

Incorrect notified value on fast changes #688

Open paolosanchi opened 1 month ago

paolosanchi commented 1 month ago

Describe the bug On consecutive notifications of a characteristic, only the latest value is received multiple times.

I have a bluetooth device (esp32) that uses a characteristic to submit text messages via notification. It may happen that N messages are sent one suddenly after the other. In such case the startNotifications 's callback may be called N times with the latest value, and the previous messages are lost.

I could verify this behaviour on an android pad with android 8 sdk 26 (Huawei MediaPad 5 Lite). I'm sure that the device (that sends the notifications) works correctly, because this bug doesn't happen other devices (android, ios and web).

Based on the code, the issue seems come from the sdk:

https://github.com/capacitor-community/bluetooth-le/blob/ee6d9671090eb1bca6841086e8da95cde074fd54/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/Device.kt#L211

Side note: I understand right now the difference from PROPERTY_NOTIFY and PROPERTY_INDICATE https://community.nxp.com/t5/Wireless-Connectivity-Knowledge/Indication-and-Notification/ta-p/1129270

So I've tried to change the characteristic property from PROPERTY_NOTIFY to PROPERTY_INDICATE, but the android onCharacteristicChanged() event is not fired anymore.

To Reproduce Steps to reproduce the behavior:

  1. Register to startnotifications() to listen for value changes of a characteristic.
  2. Notify different values N times from the device's characteristic in a fast sequence.
  3. Only the latest value is received for N times. The previous value are lost.

Expected behavior Every value change notification should reach the client.

Plugin version:

Smartphone (please complete the following information):

Additional context Add any other context about the problem here.

peitschie commented 1 month ago

Hi @paolosanchi

Are you saying this issue only occurs with Android 8 + the Huawei device? You mention that the bug doesn't happen on other devices, including some other android devices.

Something to try to see if the notifications become more reliable is to explicitly request a higher connection priority via https://github.com/capacitor-community/bluetooth-le/blob/main/README.md#requestconnectionpriority

This can sometimes force Android to wake-up more actively and process packets. This increases battery usage, but may stop the lower parts of the stack from discarding the notification.

NOTIFY can be slightly lossy, as it has no requirement for acknowledgement at the GATT layer. If the notifications are important for the phone to receive, you definitely want to be using INDICATE instead of NOTIFY. However, this requires firmware support to implement, as the firmware must advertise the property as INDICATE as well, and perform retries as necessary.

paolosanchi commented 1 month ago

Yes, only on this device, which memory is actually almost full (maybe it is slowed down somehow).

Thanks for the requestconnectionpriority advice, I'll check it out, I've also tried the INDICATE property, but it seems I got no ACK from the device. I should test it deeper. I have control over the firmware, I could actually provide an arduino sketch for ESP32 if necessary.

The strange fact, is that for each notification the related onCharacteristicChanged() is fired. So NONE of the notification is lost. The fact is that the VALUE is overwritten by the last notification, and the other values are lost (not the event).

Because of this, It doesn't seems not related to priority or indicate.