-
Notifications
You must be signed in to change notification settings - Fork 3
Multi Command Sensors
Some sensors don't stream data on their own. They must be woken up, configured, and then polled — often with a different reply format for each command. The commands array handles this.
- The sensor needs an initialisation sequence (e.g. Sensirion SCD30, SEN63C, SCD41).
- Data must be requested with a command and read back.
- Different commands return different frame formats.
- The sensor sits behind a bridge (e.g. I²C-to-USB) that needs its own protocol.
| Field | Required | Type | Description |
|---|---|---|---|
command |
yes | string | Hex bytes to send, e.g. "1B 41 6B 57 00 52 03 53"
|
repeat |
no | number |
0 = run once during init; ≥ 1 = run N times per measurement cycle |
postDelay_ms |
no | number | Wait this long after sending before the next step |
frame |
no | object | How to detect this command's reply (same as top-level frame) |
checksum |
no | object | How to validate the reply |
data |
no | object | Signals to extract from the reply |
id |
no | number | Only used by child sensors to override a parent command — see Inheritance |
Extra keys such as _comment inside a command are a handy way to document each step.
Connect
│
├─ Init phase: every command with repeat: 0, in order, once
│
└─ Measurement loop (while connected):
every command with repeat ≥ 1, in order,
each sent `repeat` times, waiting postDelay_ms after each
Disconnect
└─ stop_command (if defined)
- A command without
frame/datais just sent (e.g. a configuration write). - A command with
frame/checksum/datahas its reply parsed; any command's data can feed the charts.
| Classic mode | Multi-command mode | |
|---|---|---|
start_command |
Sent after connect |
Ignored — use a repeat: 0 command instead |
stop_command |
Sent on disconnect | Sent on disconnect |
Command bytes, frame length and expressions below are placeholders — replace them with values from your sensor's datasheet.
{
"name": "My Polled Sensor",
"port": { "baudRate": 115200, "dataBits": 8, "stopBits": 1, "parity": "none" },
"stop_command": "7E 00 01 00 FE 7E",
"commands": [
{
"_comment": "start measurement (once)",
"command": "7E 00 00 02 01 03 F9 7E",
"repeat": 0,
"postDelay_ms": 1000
},
{
"_comment": "read measured values (every cycle)",
"command": "7E 00 03 00 FC 7E",
"repeat": 1,
"postDelay_ms": 1000,
"frame": { "startByte": "0x7E", "endByte": "0x7E", "length": 10,
"stuffing": [["7D 5E", "0x7E"], ["7D 5D", "0x7D"]] },
"checksum": { "eval": "...", "compare": "..." },
"data": {
"PM2.5": { "value": "...", "unit": "μg/m³" }
}
}
]
}For a fully annotated walkthrough — protocol, frames, checksum and how each byte maps to the JSON — see SEN5x UART Protocol. For more complete working examples, look at Sensirion SPS30, Sensirion SCD41 via KEL I2C to UART and Sensirion SEN55 UART in sensors.json.
- Give the sensor enough time: check the datasheet's execution time for each command and set
postDelay_msaccordingly. - The first reading after starting a measurement is often invalid; a
repeat: 0"priming" read can discard it. - Checksums can include extra validity checks — the SCD41 config, for example, returns
1only if every CRC-8 matches, and compares against"1".
polluSensWeb · MIT License · Repository · Report an issue
Using the app
Sensor definitions
Sensor notes
Deployment
Help