GATT SensorData Protocol specification
(Note: This document has been revised and reformatted from official Movesense Ltd. document GD-77 "GATT SensorData Protocol specification" version 1.0 )
The purpose of this document is to describe and specify the structure, syntax and functionality of the GATT SensorData Protocol between Movesense sensors and a generic BLE central device.
GATT SensorData Protocol
The purpose of the GATT SensorData Protocol (“GSP”) is to provide a simpler communication protocol in order to communicate with Movesense MD sensor from devices that do not have a possibility to use Whiteboard protocol (MDS). Such devices are typically laptops or Linux based gateway computers, such as Raspberry Pi that have become increasingly popular in data gathering or as parts of larger sensor solutions. GSP is built on top of BLE GATT protocol layer.
GATT Layer
From point of view of BLE, the GATT SensorData Protocol is built as a simple bi-directional data pipe. The protocol uses a single write characteristics implemented by the sensor (GATT server) to transmit simple commands to the sensor. The data (command responses and data) are returned on a simple notification characteristic as data notifications:
- GSP Service (UUID: 34802252-7185-4d5d-b431-630e7050e8f0)
- Client to Server communication:
- UUID: 34800001-7185-4d5d-b431-630e7050e8f0
- Type: Write
- Server to Client communication:
- UUID: 34800002-7185-4d5d-b431-630e7050e8f0
- Type: Notify
- Client to Server communication:
The UUID’s are chosen so that they all use the same 128-bit “root UUID”. This saves resources on sensor because the Bluetooth stack only needs to use RAM to store a single 128-bit UUID.
The consequences of using Notify type response channel are: * Faster sensor->client communication (no bidirectional communication) * Delivery of responses is not guaranteed
Protocol definition (GSP version: 1)
The GSP protocol v.1 consists of a small amount of commands that map almost directly to corresponding Whiteboard requests. Correspondingly the sensor responds mostly with response-messages. The command and response are tied together by a client chosen 8-bit “reference code”. This way, the sensor is free to process the commands asynchronously and there is no issue with interleaved commands and their responses. The following chapters define the generic command packet format, all the available commands and the formats of the responses to each command.
Command packet format (All commands)
All GSP commands are structured as follows:
- Command code: uint8 (1 byte)
- Reference code: uint8 (1 byte, chosen by the client to be unique enough)
- Command specific data: 0...N bytes. NOTE: N cannot be larger than MTU-5!
Command response packet format (Response code = 1)
A typical response to a normal command is formatted as follows:
- Response code: uint8, “0x01 =response to command”
- Reference code: uint8, the reference code that was given in the command by the client
- Status code: uint16, little endian, HTTP status code of the command. Example: (0xFB, 0x01) = 507
- Command specific data: 0..N bytes. Note: N cannot be larger than MTU-7!
Any commands that have a different response format, are documented below in Commands section.
Commands
HELLO
Command ID: 0
Reference code: uint8
Response:
- Response code: =1 (uint8, “COMMAND_RESPONSE”)
- Reference code: uint8
- Data: (if there is no data, the sensor has the pre-GSP gatt_sensordata_app -sample
firmware)
- Protocol version (uint8): =1
- Serial number of sensor (utf8, ‘\0’ terminated)
- ProductName of sensor (utf8, ‘\0’ terminated)
- DFU-MAC address of the sensor (utf8, ‘\0’ terminated)
- AppName of sensor firmware (utf8, ‘\0’ terminated)
- AppVersion of sensor firmware (utf8, ‘\0’ terminated)
SUBSCRIBE
Command ID: 1
Reference code: uint8 (Note: reference code must be unique until UNSUBSCRIBE)
Data: WB resource path as utf8 string. (Example: “/Meas/Acc/13”)
Response:
- Response code: =0x1 (uint8, “COMMAND_RESPONSE”)
- Reference code: uint8 (Note: reference code must be unique until UNSUBSCRIBE)
- Status code: uint16, little endian: HTTP status code of the command.
Data stream (multiple packets until unsubscribed or disconnect occurs):
- Response code: uint8, =0x2 (DATA) or 0x3 (DATA_PART2)
- Reference code: uint8
- Data: sbem formatted binary (Note: see
/generated/sbem-code/sbem_definitions.cpp for sbem format structure). If the data does not fit in the DATA-packet, the rest is sent in the DATA_PART2.
UNSUBSCRIBE
Command ID: =2, (uint8)
Reference code: uint8, MUST match the one given in the SUBSCRIBE-command
Response:
- Response code: =0x1 (uint8)
- Reference code: uint8
- Status code: uint16, little endian: HTTP status code of the command.
FETCH_LOG
Command ID: 3
Reference code: uint8, (Note: reference code must be unique until end of log transfer)
Data: uint32 (little endian), the logID of the log to fetch
Response:
- Response code: =0x1 (uint8, “COMMAND_RESPONSE”)
- Reference code: uint8 (Note: reference code must be unique until end of log transfer)
- Status code: uint16, little endian: HTTP status code of the command.
Data stream
- Response code: uint8, =0x2 (DATA) or 0x3 (DATA_PART2)
- Reference code: uint8
- Data format:
- Uint32: Offset of the data in the logbook log
- Byte []: data bytes from offset forward
- Format: SBEM file
- End Marker:
- Multiple packets with offset=log file size, and empty data
- Sent when end of log has been reached
NOTE: It is the responsibility of the client to check returned file integrity. This can be achieved by keeping track on the data packet offset and lengths and making sure that there are no holes in the received data.
NOTE2: To avoid hanging of the client app in case the end of log markers have been lost during transfer, it is recommended to implement “end of transfer” logic based on timeout without receiving any data packets.
NOTE3: The data stream is the data available from the /Mem/Logbook/byID/
GET
Command ID: 4 (uint8)
Reference code: uint8
Data: WB resource path as utf8 string. (Example: “/Meas/ECG/Info”)
Response:
- Response code: =0x1 (uint8, “COMMAND_RESPONSE”)
- Reference code: uint8
- Status code: uint16, little endian: HTTP status code of the command.
- Data: Resulting object encoded in the GSP binary format (See here)
CLEAR_LOGBOOK
Command ID: =5, (uint8)
Reference code: uint8
Data: no data
Response:
- Response code: =0x1 (uint8)
- Reference code: uint8
- Status code: uint16, little endian: HTTP status code of the command.
PUT_DATALOGGER_CONFIG
Command ID: =6, (uint8)
Reference code: uint8
Data:
- resource path string to add to config (utf8, ‘\0’ terminated)
- resource path string to add to config (utf8, ‘\0’ terminated)
- ...
Response:
- Response code: =0x1 (uint8)
- Reference code: uint8
- Status code: uint16, little endian: HTTP status code of the command.
PUT_SYSTEMMODE
Command ID: 7
Reference code: uint8
Data: uint8, the new system mode (see: Movesense API documentation)
Response:
- Response code: =0x1 (uint8)
- Reference code: uint8
- Status code: uint16, little endian: HTTP status code of the command.
PUT_UTCTIME
Command ID: 8
Reference code: uint8
Data: uint64, utc time in microseconds since 1970-01-01 midnight
Response:
- Response code: =0x1 (uint8)
- Reference code: uint8
- Status code: uint16, little endian: HTTP status code of the command.
Note: This command combined with the v. 2.2 feature “/Time/Detailed -subscription” can imbed the time details (RelativeTime vs UTC time mapping) into the logbook data during the datalogger recording.
PUT_DATALOGGER_STATE
Command ID: 9
Reference code: uint8
Data: uint8, the new DataLogger state
Response:
- Response code: =0x1 (uint8)
- Reference code: uint8
- Status code: uint16, little endian: HTTP status code of the command.
GSP binary format
The GSP GET command returns the API responses as a binary encoded objects that follow closely the structure defined in the API Swagger (.yaml) files. The format is defined as follows:
- All the properties appear in the order that they are defined in the API yaml
- All the native propertytypes (int8,16,32,64, uint8, 16, 32, 64, float, double) are encoded as little endian binary.
- Arrays are preceded with uint8, that specifies the array length in elements. Max array length is therefore 255.