CBOR Payload Structure
GLIDER reports measurements to HARDWARIO Cloud using the CBOR binary format (RFC 8949). To keep messages small, the schema uses numeric keys rather than strings - every payload typically fits in 70 to 150 bytes on the wire.
The schema is defined in application/codec/cbor-decoder.yaml of the GLIDER firmware, and the cloud automatically applies the matching decoder.
The send frequency is controlled by app config interval-send (default 300 s = 5 minutes).
Top-level structure
After decoding, every message contains five top-level objects:
| Key | Description |
|---|---|
message | Metadata: schema version, sequence number, timestamp. |
system | System information: device uptime. |
thermometers | Array of measured temperatures, one entry per populated DS18B20 slot. |
alarms | Alarm activation / deactivation history since the previous message. |
inputs | Digital input counters and recent events for CH1 / CH2. |
message
Message header. CBOR key: 0.
| Field | Type | Unit | Description |
|---|---|---|---|
version | uint | - | Schema version, currently 1. Used for forward compatibility. |
sequence | uint32 | - | Incremental sequence number. Starts at 0 after every reboot - the cloud uses gaps to detect lost uplinks. |
timestamp | int64 | Unix epoch (s) | Time of transmission, taken from the RTC. |
system
CBOR key: 4.
| Field | Type | Unit | Description |
|---|---|---|---|
uptime | uint64 | seconds | Time since the last boot. |
thermometers
An array of maps - one entry per configured DS18B20 slot. Empty slots (no ROM bound, or not yet validated) are omitted from the payload.
CBOR key: 6.
| Field | Type | Unit | Description |
|---|---|---|---|
slot | uint (1-8) | - | Slot number (APP_W1_THERM_MAX_SLOTS = 8). |
temperature | int (×0.01 °C) or null | °C | Last successful read. Encoded as temperature × 100; the decoder rescales ($div: 100, $fpp: 2). null = NaN (failed read). |
Only the most recent sample per slot is sent, not the full history between uplinks. If you need a time series, sample at a higher rate and accept the proportionally higher data cost - or open a feature request.
Example
thermometers:
- slot: 1
temperature: 22.68 # encoded on the wire as 2268
- slot: 2
temperature: 23.62
alarms
CBOR key: 9.
| Field | Type | Description |
|---|---|---|
events | TSO list | Alarm activation / deactivation events accumulated since the last successful uplink. The buffer is cleared after the send. |
events - Time-Series Object (TSO) format
The events value is a flat list in this order:
[timestamp_abs, offset_1, alarm_1, active_1, offset_2, alarm_2, active_2, …]
timestamp_abs- Unix epoch (s) of the first event in the list (anchor).offset_N- seconds relative totimestamp_abs.alarm_N- rule number (1-based, 1-32).active_N-1= activated,0= deactivated.
The buffer holds up to 100 events (APP_ALARM_MAX_EVENTS).
Example
alarms:
events:
- 1747142400 # timestamp_abs
- 0 # offset → alarm 1 activated at 1747142400
- 1
- 1
- 120 # offset → alarm 1 deactivated at 1747142520
- 1
- 0
inputs
Array of maps, one entry per digital input channel (APP_INPUTS_NUM_CHANNELS = 2).
CBOR key: 11.
| Field | Type | Description |
|---|---|---|
channel | uint (1 / 2) | Channel number. |
counter_rising | uint64 | Cumulative count of rising edges since boot. Resets on reboot. |
counter_falling | uint64 | Cumulative count of falling edges since boot. |
events | TSO list | Edge timeline (only populated when the channel is in event mode). Cleared after each send. |
events - TSO format
[timestamp_abs, offset_1, active_1, offset_2, active_2, …]
timestamp_abs- Unix epoch (s) of the first event.offset_N- seconds relative totimestamp_abs.active_N-1= activation (rising),0= deactivation (falling).
The buffer holds up to 64 events per channel (APP_INPUTS_MAX_EVENTS).
The channel mode (disabled / counter / event) is set via configuration - see Configuration → Digital Inputs.
Example
inputs:
- channel: 1
counter_rising: 142
counter_falling: 141
events:
- 1747142400 # timestamp_abs
- 0 # active=1
- 1
- 30 # active=0
- 0
- channel: 2
counter_rising: 0
counter_falling: 0
events: []
Complete example
A typical decoded payload from a GLIDER monitoring two DS18B20 probes, with no recent alarm events and one input counting pulses:
message:
version: 1
sequence: 33
timestamp: 1747142400
system:
uptime: 2772
thermometers:
- slot: 1
temperature: 22.68
- slot: 2
temperature: 23.62
alarms:
events: [] # no alarm transitions since the last uplink
inputs:
- channel: 1
counter_rising: 142
counter_falling: 141
events: []
- channel: 2
counter_rising: 0
counter_falling: 0
events: []
On the wire this payload is ~95 bytes of CBOR.
Codec hash
To make sure the cloud uses the right decoder for the right firmware, every schema has a 64-bit hash baked into the firmware:
#define CODEC_CLOUD_DECODER_HASH ((uint64_t)0xcfef6b4543a9ddb7)
Changing the schema regenerates the hash and the cloud must be updated with the matching decoder. The generator command is:
west gen-codec
It reads application/codec/cbor-decoder.yaml, writes application/src/app_codec.h with the new hash, and produces the binary decoder buffer that gets embedded into the firmware image.
Related
- CBOR spec: RFC 8949
- Encoder source:
application/src/app_cbor.c - Schema source:
application/codec/cbor-decoder.yaml