Sensor BLE supports decoding BLE advertisement data and streaming data from a variety of Bluetooth devices. This library is used in the Sensor Logger app. The device decoders are intentionally designed with no external dependencies, so that they can be used with any bluetooth library.
import { decoders } from "sensor-ble";
// Find the appropriate decoder
const ruuviDecoder = decoders.find((d) => d.decoderName === "ruuvi");
// Example Ruuvi tag data
const manufacturerData = Buffer.from(
"99040512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F",
"hex"
);
// Decode the data
console.log(ruuviDecoder.advertisementDecode(manufacturerData));This is more complex than decoding advertisement data - see the startStreaming function in harness/main.js as an example.
This project welcomes contributions, especially for supporting additional devices. Please note that all contributors must agree to the Contributor License Agreement (CLA).
To add support for a new device:
- Create a new file in the devices folder named after your device.
- Implement the
decoderobject andtestsarray as described above. Follow the pattern from existing decoders like ruuvi.js for advertisement decoding, or muse_v3.js for streaming data. - Add your decoder to main.js.
- Ensure there is at least one test for the decoder.
- Run
npm testto verify your implementation works as expected.
Each device decoder must export:
-
A
decoderobject that implements the Decoder interface:decoderName: A unique identifier for the decodername(optional): If specified, the BLE device name must match this for the decoder to applymanufacturer(optional): If specified, the BLE manufacturer data must begin with this 2-byte manufacturer ID (in hex string form e.g. "9904")serviceUUID(optional): If specified, advertisement must contain this service UUID to match (in hex string form e.g. "fcd2")advertisementDecode(optional): Function to decode BLE manufacturer or service data in advertisementsstart(optional): Function called to start data collection from the device, typically for sending the command to start data streamingstop(optional): Function to stop data collection, typically for sending the command to stop data streamingnotify(optional): Listeners to set up given a serviceUUID and characteristicUUID, these may return decoded data (or null when listening for other information, such as the device sensor scale factor)units(optional): Description of unit semanticsfrequency(optional): Description of sampling frequency
-
A
testsarray containing test cases to validate the decoder functionality. The test array differs depending on if the decoder decodes advertisement data or is streaming. See ruuvi.js for advertisement decoding, or muse_v3.js for streaming data.
The expected workflow followed by Sensor Logger (or any client) is outlined below:
- Identify the Decoder: Use either the
manufacturerornameattribute to locate the appropriate decoder for the target device. - Handle Advertised Data: For data broadcasted passively, use the
advertisementDecodemethod to interpret the advertised information. - Manage Active Data Streams: For devices requiring explicit interaction:
- Use the
startmethod to initiate data collection. - The
notifymethod will listen for incoming data streams. - The decoded data is then processed and stored by the data logger (e.g. Sensor Logger).
- When data collection is complete or no longer needed, use the
stopmethod to terminate the data stream and release resources.
- Use the
When data is decoded (via advertisementDecode or notify), the column names used should be consistent with the following conventions. The intention is for the column names to be self-documenting for visualization, even in the absence of a schema (e.g. CSV).
- Use column name
group_name_unit(e.g. accelerometer_x_mg) when multiple values are decoded under a group (e.g. accelerometer). - Use column name
name_unit(e.g. temperature_c) when a single value is decoded and no others are in the group. - Use
unitas "dimensionless" when the value has no unit. - Use column name
name(without underscoes) when the value is not expected to be shown on a plot, e.g. timestamp - Where possible, the decoded data should include a timestamp if the device sends one.
- Do not use additional underscores in column names, e.g.
hdr_accelerometer_x_mgis not allowed by convention. Instead usehdrAccelerometer_x_mgso the group is clear.
This repository is structured in two parts:
-
The devices folder, which contains decoders for each supported device. Devices must follow the Sensor BLE API, and should contain minimal external dependencies.
-
The harness folder, containing an implementation of the Sensor BLE API for use on desktop environments. You may find
node harness/main.jsuseful for testing your BLE devices. The harness uses the@abandonware/noblebluetooth package, although the sensor ble decoders can be used with any reasonable bluetooth package.