Search code examples
node.jsbluetoothtype-conversiongatt

BLE GATT: why storing decimal in integer types?


I'm learning bluetooth, specifically how to implement GATT characteristic specs so I can write peripheral drivers. In almost all specs, they look to be using integer data types to hold decimal values (when the data is a decimal value).

For example, the Cycling Power Measurement spec spec stores the Pedal Power Balance into a uint8. As you can see the Pedal Power Balance value has resolution of 1 decimal place (ex: 10.1). The GATT format types spec has plenty of types for decimal point numbers (float32 etc).

Why does GATT not use a data type designed to hold decimal numbers? My guess is to limit size of data sent over BLE. Is that correct?

I'm writing NodeJs code to quickly prove out some tech. With my hypothesis, here is how I'm guessing one "packs" a decimal with one digit of precision into a signed 8-bit integer. I'm using acceleration here (can be +/- so using signed int):

'use strict';

const oneG = -9.806649999788;

let int8Buf = new Buffer.alloc(8); //to hold signed 8-bit integer

int8Buf.writeInt8(oneG * 10, 0);
console.log(int8Buf.readInt8(0) / 10);

Running this outputs -9.8 as I expected.

Questions:

  1. Does GATT use this "packing" technique to save space over the air?
  2. Am I doing this correctly?
  3. Does NodeJS have a library that handles this data packing and un-packing? Seems like a very common scenario. I've searched NPM but I'm not sure what this concept is called.

Solution

  • Scaled integers like these are used to simplify the implementation on small embedded devices.

    For cost and power consumption reasons, the microcontrollers used often do not have an FPU (i.e. hardware support for floating point calculations). On those that don't have an FPU it is possible to use software floating point libraries, but these are slow (and so they consume power), and they take up code space. Even on microcontrollers that do have an FPU, using it increases power consumption, and using four bytes for a floating point number will also increase RAM usage (another scarce resource) compared to only one byte for the scaled integer version.

    For these reasons, it is the norm in the embedded world to use scaled integers when fractional quantities are needed.

    In the case of a GATT characteristic, it is also desirable to use smaller data types because you usually want your characteristic's value to be no longer than 20 bytes. This is because the ATT MTU is usually set to 23 bytes (and ATT has a 3 bytes overhead), as this is the longest ATT packet that can be included in a single Link Layer packet (if the Data Length Extension of Bluetooth 4.2 is not implemented).