Skip to content

= FAQ: Passing And Retrieving Of Characteristic Value

Dariusz Seweryn edited this page Jan 11, 2019 · 1 revision

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.

Example

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.

Writing value to a characteristic

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

Reading value from a characteristic

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;

Footnote

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:

Write

const heightBuffer = Buffer.alloc(2);
heightBuffer.writeUInt16LE(heightInCentimeters, 0);
device.writeCharacteristicWithResponseForService(userDataServiceUUID, heightCharacteristicUUID, heightBuffer.toString('base64')); // assuming the device is already connected

Read

const readCharacteristic = await device.readCharacteristicForService(userDataServiceUUID, heightCharacteristicUUID); // assuming the device is already connected
const heightInCentimeters = Buffer.from(readCharacteristic.value, 'base64').readUInt16LE(0);