Skip to content

6.2 Command definition

Roland Jax edited this page Oct 13, 2026 · 3 revisions

6.2 Command definition

A command is a match rule plus decoders: read_cmd recognizes a telegram on the bus, fields decode its data bytes into named values. Commands ship as a JSON array; upload via HTTP (doc/commands.md) or MQTT. They persist in LittleFS and load at restart.

This replaces the old flat format: there is no active flag and no inline datatype/divider/digits/unit/ha_* keys. Decoding lives in profiles, commands only reference them.

Top-level keys

  • key (string) — unique id, e.g. "01".
  • name (string) — display name and MQTT topic base, e.g. "Outside_Temperature".
  • read_cmd (hex string) — ZZ PB SB NN + data bytes to match (see below). The source address QQ is omitted — the firmware adds its own eBUS address automatically.
  • write_cmd (hex string, may be empty) — header template for writes; the encoded value is appended (see below).
  • interval (seconds) — 0 = passive: only evaluate when the telegram appears on the bus. > 0 = active: poll it ourselves every interval seconds. (Active = interval > 0; there is no separate flag.)
  • master (boolean) — value lives in the master part (true) or the slave answer (false).
  • fields (array, up to 4) — one entry per decoded value.

read_cmd anatomy

Bytes: ZZ PB SB NN D1…Dn. Example 08b509030d1700:

Byte Hex Meaning
ZZ 08 Destination (heat generator).
PB b5 Manufacturer command class.
SB 09 Data operation.
NN 03 3 data bytes follow.
Data 0d1700 Parameter id.

On the wire the telegram starts with QQ (arbitration), followed by your ZZ… bytes, CRC, the slave answer, and closes with SYN (end-of-message; it releases the bus for the next participant). Logs show both sides: ff08b509030d1700 / 031d0300.

fields entries

  • name — value name within the command, e.g. "value".
  • profile — data profile reference, e.g. "data2b_celsius". Profiles bundle datatype, divider, digits, and unit (28 built in, generated at build; see doc/datatype_mapping.md). This is where the old inline datatype/divider/digits/unit keys went.
  • position — 1-based index into the data bytes (after NN), e.g. 1.
  • ha_profile — Home Assistant profile reference, e.g. "sensor_temperature" (21 built in), or "" for none. This is where the old flat ha_* keys went.
  • raw (optional, default false) — skip sentinel-to-null mapping and always render the raw numeric value (e.g. UINT16 0xFFFF → 65535 instead of null). For "no data" diagnosis; graphs will show the extreme. See doc/datatype_mapping.md.
  • min / max (optional) — per-field plausibility overrides.

Write commands

write_cmd is a header template: the new value is encoded per the field's profile and appended after the header, then sent. Only commands with a non-empty write_cmd accept writes (HTTP values/write, MQTT set/).

Limits

Strings (key, name, field names) live in a shared pool: max 256 strings, 2 KB total, each effectively below 255 chars. Past that, names silently stop resolving — keep names short; ~50 commands with one field each use roughly half the pool.

read_cmd/write_cmd hold at most 16 bytes (32 hex chars). Up to 4 fields per command.

Example

{
  "key": "01",
  "name": "Outside_Temperature",
  "read_cmd": "fe070009",
  "write_cmd": "",
  "interval": 0,
  "master": true,
  "fields": [
    {
      "name": "value",
      "profile": "data2b_celsius",
      "position": 1,
      "ha_profile": "sensor_temperature"
    }
  ]
}

Broadcast (fe…), passive (interval 0), single value from data byte 1, decoded as DATA2B Celsius, exposed to Home Assistant as a temperature sensor.

Clone this wiki locally