-
Notifications
You must be signed in to change notification settings - Fork 518
= FAQ: Passing And Retrieving Of Characteristic Value
One of the obscure topics in BLE is how to interpret or write value to a characteristic.
BLE is a low level protocol that allows for raw bytes transmission between the client and a peripheral and that is exactly what this library do.
To properly pass the value between JS and native parts the library uses Base64
encoding of hex string values.
For an example lets use a proper bluetooth specified height characteristic wich is a part of the user data service.
const userDataServiceUUID = '0000181C-0000-1000-8000-00805F9B34FB'; // assigned number 0x2A8E to the base specification UUID
const heightCharacteristicUUID = '00002A8E-0000-1000-8000-00805F9B34FB'; // assigned number 0x2A8E to the base specification UUID
From the specification we know that the height is to be stored as a 16 bit unsigned integer with a decimal exponent of -2. Most of the Bluetooth Core Specification characteristic encode integers in Little Endian (citation needed).
Using Buffer for base64
encoding/decoding.
Say the user height is 1.83 meter. Since the decimal exponent is -2 the value to write should be 1.83 * 10^2 = 183
The JS implementation of writing the value would look like this:
const heightInMeters = 1.83;
const heightInCentimeters = heightInMeters * 100;
const heightInCentimetersToWrite = Math.round(heightInCentimeters); // in case the height would be more precise i.e. 183.5
const heightMostSignificantByte = (heightInCentimetersToWrite >> 8) & 0xFF;
const heightLeastSignificantByte = heightInCentimetersToWrite & 0xFF;
const heightByteArrayInLittleEndian = [heightLeastSignificantByte, heightMostSignificantByte];
const heightInBase64 = Buffer.from(heightByteArrayInLittleEndian).toString('base64');
device.writeCharacteristicWithResponseForService(userDataServiceUUID, heightCharacteristicUUID, heightInBase64); // assuming the device is already connected
The JS implementation of reading the value would look like this:
const readCharacteristic = await device.readCharacteristicForService(userDataServiceUUID, heightCharacteristicUUID); // assuming the device is already connected
const readValueInBase64 = readCharacteristic.value;
const readValueInRawBytes = Buffer.from(readValueInBase64, 'base64');
const heightMostSignificantByte = readValueInRawBytes[1];
const heightLeastSignificantByte = readValueInRawBytes[0];
const heightInCentimeters = (heightMostSignificantByte << 8) | heightLeastSignificantByte;
The above is just an example given to understand how the data encoding/decoding should be made in order to work with BLE peripherals and the library according to the Bluetooth Specification. There are shorter ways to describe the same functionality:
const heightBuffer = Buffer.alloc(2);
heightBuffer.writeUInt16LE(heightInCentimeters, 0);
device.writeCharacteristicWithResponseForService(userDataServiceUUID, heightCharacteristicUUID, heightBuffer.toString('base64')); // assuming the device is already connected
const readCharacteristic = await device.readCharacteristicForService(userDataServiceUUID, heightCharacteristicUUID); // assuming the device is already connected
const heightInCentimeters = Buffer.from(readCharacteristic.value, 'base64').readUInt16LE(0);