Skip to main content

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:

KeyDescription
messageMetadata: schema version, sequence number, timestamp.
systemSystem information: device uptime.
thermometersArray of measured temperatures, one entry per populated DS18B20 slot.
alarmsAlarm activation / deactivation history since the previous message.
inputsDigital input counters and recent events for CH1 / CH2.

message

Message header. CBOR key: 0.

FieldTypeUnitDescription
versionuint-Schema version, currently 1. Used for forward compatibility.
sequenceuint32-Incremental sequence number. Starts at 0 after every reboot - the cloud uses gaps to detect lost uplinks.
timestampint64Unix epoch (s)Time of transmission, taken from the RTC.

system

CBOR key: 4.

FieldTypeUnitDescription
uptimeuint64secondsTime 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.

FieldTypeUnitDescription
slotuint (1-8)-Slot number (APP_W1_THERM_MAX_SLOTS = 8).
temperatureint (×0.01 °C) or null°CLast successful read. Encoded as temperature × 100; the decoder rescales ($div: 100, $fpp: 2). null = NaN (failed read).
info

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.

FieldTypeDescription
eventsTSO listAlarm 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 to timestamp_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.

FieldTypeDescription
channeluint (1 / 2)Channel number.
counter_risinguint64Cumulative count of rising edges since boot. Resets on reboot.
counter_fallinguint64Cumulative count of falling edges since boot.
eventsTSO listEdge 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 to timestamp_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.

  • CBOR spec: RFC 8949
  • Encoder source: application/src/app_cbor.c
  • Schema source: application/codec/cbor-decoder.yaml