Skip to content

Packet Frame

Nick Berardi edited this page Jul 19, 2026 · 7 revisions

Packet Frame

Frame layout

Same for host and thermostat:

Field Size Description
REV 1 Protocol revision (1–255; examples use 0x01)
SEQ 1 Sequence number (see ranges)
CNT 2 Payload length, big-endian
PAYLOAD CNT Action + domain + attribute + data (or NACK form)
CRC 1 8-bit CRC over REV ‖ SEQ ‖ CNT ‖ PAYLOAD
Byte: 0 1 2 3 4 ............... 4+CNT-1 4+CNT
Field: REV SEQ CNT_H CNT_L [ PAYLOAD ] CRC

Sequence numbers

Source Range
Home automation / cloud 0–127
Thermostat 128–255
Read Response Same SEQ as initiating Read Request
Retries Same SEQ as original packet

Count

  • High byte first: length 512 (0x0200) → bytes 0x02 0x00.
  • For normal messages: CNT = 3 + data_length (Action + Domain + Attribute + data).
  • For NACK: CNT = 2 (Action + Status only).

CRC

  • Computed over REV, SEQ, CNT, and entire PAYLOAD.
  • Implementation in this project: lookup-table CRC in AprilaireClient.ts.

Some diagrams in the guide label the trailer as Reserved 0xFF — the guide's examples show 0xFF because they don't compute the CRC, and its prose says the byte's return value "will vary (it is a development function)". The formal frame definition (guide note 5) defines it as an 8-bit CRC over REV+SEQ+CNT+PAYLOAD, and all real traffic uses the CRC. Implementations must compute it.

Payload structure (non-NACK)

Field Size Description
Action 1 Write / Read / COS / …
Functional domain 1 Attribute group
Attribute 1 Attribute within domain
Data 0…N Attribute-specific

Guide example

Write Control / Setpoint & Mode: Null mode, Fan On, Heat 21.0 °C, Cool 26.5 °C:

01 00 00 07 01 02 01 00 01 15 5A [CRC]
│ │ └───┘ │ │ │ │ │ │ └── cool 26.5°C = 0x5A
│ │ CNT=7 │ │ │ │ │ └──── heat 21.0°C = 0x15
│ │ │ │ │ │ └─────── fan On = 0x01
│ │ │ │ │ └────────── mode Null = 0x00
│ │ │ │ └────────────── attribute 0x01
│ │ │ └───────────────── domain Control 0x02
│ │ └──────────────────── action Write 0x01
│ └────────────────────────────── sequence 0x00
└───────────────────────────────── revision 0x01

Null convention

When a multi-field attribute is written, a data sub-field of 0 / Null means do not modify that sub-field. For temperature fields, Null also uses positive sign and .0 fraction bits cleared (value magnitude 0).

Clone this wiki locally