don / cordova-plugin-ble-central

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

ble.startNotification on IOS , notifications are sent even if value doesn't change #913

Closed playrobotics-alex closed 2 years ago

playrobotics-alex commented 2 years ago

Hi! I am using ble.startNotification in order to subscribe to notifications. On Andorid works great(I am only getting notifications when there is a change in value), but on IOS I am getting notifications with the exact same data over and over again. Am I doing anything wrong? this.ble.startNotification(this.ID,SERVICE_UUID, "7E400003-B5A3-F393-E0A9-E50E24DCCA9E").subscribe( (data) => { this.onNotify(data); }, (error) => console.error('Unexpected Error', 'Failed to subscribe') )

peitschie commented 2 years ago

That looks ok to me @playrobotics-alex

What should trigger the notifications? Is it in response to a write of some sort or related to physical interactions with the device?

If you haven't already checked, it might be worth checking if you get the same behaviour with LightBlue or a similar app, just in case it's something to do with the peripheral behaviour.

playrobotics-alex commented 2 years ago

Thanks, the peripheral is ESP32 and it responds to write from the phone.
pCharacteristic->setValue(value); pCharacteristic->notify(); once the above code is exectuted by the ESP32(only once) - the notifications don't stop coming (all with the same data)

playrobotics-alex commented 2 years ago

ok, so I made some more testing and it looks that this is happening because inside my onNotify function I am making ble.read so maybe ios is expecting some kind of response to the notification and once it is not getting it it is retrying and sending the notification over and over again or something like this?

peitschie commented 2 years ago

Right! It's actually a bit simpler than that... iOS doesn't provide a way to distinguish whether the characteristic has updated due to a notification or due to a read value. See https://github.com/don/cordova-plugin-ble-central/blob/master/src/ios/BLECentralPlugin.m#L706

Android on the other hand has different methods for notify vs. read: https://github.com/don/cordova-plugin-ble-central/blob/master/src/android/Peripheral.java#L415

Good detective work hunting that down @playrobotics-alex

playrobotics-alex commented 2 years ago

yes that make sense thank you for the explanation! The only reason I was making the read call was because I was not able to parse the value from the notification and had to re-read it. Maybe you can point me in the right direction here :-) I am getting the notification from ESP32(which has my code on it) and it seems like it can only notify string value as explained here: https://rntlab.com/question/esp32-ble-characteristic-value-datatype/ So when I am reading the notification value it will be a string and not buffer array? Because currently I am using the following code to print the data I am getting , and just an empty object is printed: this.ble.startNotification(this.ID, TRAINER_SERVICE_UUID, "7E400003-B5A3-F393-E0A9-E50E24DCCA9E").subscribe( (buffer) => { let data = new Uint8Array(buffer); console.log(data) }, (error) => console.log(error) )

Thank you so much for your help!!!

playrobotics-alex commented 2 years ago

I found out that the object was empty because buffer[0] should be used instead of buffer like explained here: https://github.com/don/cordova-plugin-ble-central/issues/805 I think it might be worth to update the docs at the ble.startNotification section :-)

peitschie commented 2 years ago

Glad you were able to solve the issue @playrobotics-alex

Yeah... the ionic wrapper (not maintained by me) has some unexpected quirks that I don't really understand 😢