don / cordova-plugin-ble-central

Bluetooth Low Energy (BLE) Central plugin for Apache Cordova (aka PhoneGap)
Apache License 2.0
941 stars 601 forks source link

startNotification sometimes throws Peripheral not connected or code 133 #1003

Closed fudom closed 2 months ago

fudom commented 2 months ago

We use startNotification after BLE connect (incl. scan before) on app start. It works. But sometimes it fails with error:

Peripheral {id} is not connected.

or

Write descriptor failed: 133

Tested on Android 8.1 and other versions.

Error 133 (0x85) is GATT_ERROR. But the reason or source is not clear. Any experience with that?

peitschie commented 2 months ago

@fudom perhaps see if the summary from here has any hints. Specifically, I'd recommend either:

  1. Use autoConnect and don't explicitly scan (i.e., let the OS schedule this itself)
  2. Explicitly scan and then use connect
  3. (Maybe) for a non-bonded device, it's safe to just use connect without an explicit scan (to be confirmed)
fudom commented 2 months ago

Thanks for the advice. We always need to scan before connect. Otherwise, some information are missing (e.g. name) or connection will fail. I love Bluetooth/BLE on Android and its quirks. ;-) Anyway...

Btw. another error I get is Failed to set client characteristic notification for {uuid}...

It would be great if we got a success callback upon successful subscription to the notification.

I return Promise<Observable> which sould be only resolved, when the notification is actually started. But currently there is no way to find out, if a notification started successfully, if I see it correctly in the docs. The success callback is used for received data instead. Maybe a limitation of Cordova plugins to only have two callbacks?

A workaround on my side could be to wait a certain amount of time for an error. And continue (resolve/return) if timed out as "ok". One idea could be, that the first success callback is for successfully started. But other ideas are welcome.

I only want return on a working notification. I would retry the startNotification on error. Maybe with reconnect. Just to avoid an invalid state.

Btw. I use the awesome-cordova-plugins wrapper for Ionic/Angular.

peitschie commented 2 months ago

It would be great if we got a success callback upon successful subscription to the notification.

This is possible, by using await ble.withPromises.startNotification(device_id, success, failure) instead. I can't change the existing callback for fear of breaking backward compatibility, but the promise-returning version instead does exactly what you're requesting.

fudom commented 2 months ago

Ok thanks, I'll give this a try and will bypass the outdated plugin wrapper for TypeScript. I wish all Cordova plugins would provide strong types for TypeScript and use modern methods like Promises (async/await) and Observable. Then we wouldn't need wrappers. Anyway... Btw. I see some related issues:

635 > #95 > #903

This includes the option { emitOnRegistered: true }. I haven't checked the code yet, but If it works (I think I try the promise solution), I can try again to start the notification if it fails. Maybe with reconnect. I would prefer a better solution than trial and error. Maybe with a ready state. Anway, I think it's better to do this automatically in background than to fail in front of users.

I'm closing the issue for now, although I can't reproduce the error and so can't say for sure if it works. But it looks like it's exactly what I wanted. Getting the status of startNotification. Thanks again.