Closed mrSilkie closed 1 year ago
Hi @mrSilkie,
Are you able to share some code examples of what your read
and startNotification
snippets look like? Also, just to confirm, is this Android only, or iOS too? What version of the plugin are you currently using?
I assume that both read and write return the same bufferArray type and should return the same value (if it has not changed between readings). However, this is not what I'm seeing.
There's a slight difference between the two callbacks, in that the notification callback includes a sequence number along with the data as a second argument to the data handler: https://github.com/don/cordova-plugin-ble-central/blob/master/src/android/SequentialCallbackContext.java#L39
But, I wouldn't have thought that this impacted what you're describing.
Hi @peitschie
I think you've hit the nail on the head. The method for processing the read and notification are the same. which is why one works and the other probable doesn't. In my original post, the console log is a JSON.stringify of the incomming data so I expect that the console log would have revealed the nested elements.
To begin the read / notify
async subscribeToCharacteristics(peripheral) {
for (const service in this.stateMap) {
for (const characteristic in this.stateMap[service]) {
// IGNORE VARIABLES NOT ASSIGNED TO UUID
if(characteristic === 'pumpType' || characteristic === 'pumping' || characteristic === 'pumpAmount') {
continue;
}
this.ble.read(peripheral.id, service, characteristic).then(data => {
const buffer = new Uint8Array(data);
// Msg: Reading 75c8226c-283f-11ed-bf69-0242ac120001:75c8226c-283f-11ed-a261-0242ac120021 : 0s - 0.00kg - 48 115 32 45 32 48 46 48 48 107 103
console.log('Reading ' + service + ':' + characteristic + ' : ' + new TextDecoder().decode(buffer) + ' - ' + Array.from(buffer).join(' '));
this.processNotification(service, characteristic, buffer);
},
error => {
});
//const characteristicUUID = this.stateMap[service][characteristic];
this.ble.startNotification(peripheral.id, service, characteristic).subscribe(
data => {
this.ngZone.run(() => {
const buffer = new Uint8Array(data);
this.processNotification(service, characteristic, buffer);
});
},
error => console.error(`Error starting notifications on ${service}:${characteristic}`, error)
);
}
}
}
Notice how there is no difference between the input into processNotification for the Read and Notify cases. The startNotification should call buffer[0] if I'm correct.
In processNotification()
if (serviceUUID === ServiceNames.serviceScale) {
if (characteristicUUID === CharacteristicNames.characteristicScaleMeasurement && buffer.length === 3) {
const arrayBuffer = new Uint8Array(2);
arrayBuffer[0] = buffer[2];
arrayBuffer[1] = buffer[1];
console.log('Changing Weight BUFFER = ' + JSON.stringify(buffer));
// convert arrayBuffer to weightInt
const dataView = new DataView(arrayBuffer.buffer);
const weightInt = dataView.getUint16(0, false);
const weightFloat = weightInt * 0.005;
console.log('Changing Weight = ' + weightFloat + 'kg');
this.stateMap[ServiceNames.serviceScale][CharacteristicNames.characteristicScaleMeasurement] = weightFloat;
return;
}
}
I am running Android using the package '@awesome-cordova-plugins/ble/ngx' with 5.45.0
The startNotification should call buffer[0] if I'm correct.
Agreed, that sounds like a reasonable tweak based on what I've seen with other bug reports. I'll be interested to hear how the change goes!
Not sure what changes I made to get it to work but this is the new startNotification function
this.ble.startNotification(peripheral.id, service, characteristic).subscribe(
data => {
this.ngZone.run(() => {
const buffer = new Uint8Array(data[0]);
console.log('Notification RX: ' + service + ':' + characteristic + ' = ' + buffer);
this.processNotification(service, characteristic, buffer);
});
},
error => console.error(`Error starting notifications on ${service}:${characteristic}`, error)
);
I copied the change from here.
Simply changing the value to data[0] didn't make it work though, the real magic is the 'const buffer = new Uint8Array(data[0]);' line
Thanks for the update! Glad you've figured out the issue 🙂
I have an array of the services on the device, then each service is an array of characteristics. This lets me iterate through all of the characteristics and first read the value, then begin the notifications.
Here is the console log of what I'm seeing.
The first value, of length 3 is correct and was retreived from the read function.
The second value, of length 1, is incorrect and was retreived from notification.
I assume that both read and write return the same bufferArray type and should return the same value (if it has not changed between readings). However, this is not what I'm seeing.
I've even tried to say 'if buffer.length < 3, then ble.read()' and the return was a buffer of length 1. I am a bit stuck here. I am using ESP32 and nkolban's BLE library for Arduino. It could be that my settings on my device are wrong and is why I'm not getting the correct buffer back. However, it works in nRF connect so I am a bit stuck here.
Any advice?