|
Home IO Control
ESPHome add-on for IO-Homecontrol devices
|
Status: Accepted · Recorded: 2026-08
ADR 0010 established the corpus's core contract: real captured frames are the regression-test source of truth, validate.py enforces crypto and structural self-consistency regardless of where a capture came from, and every capture carries a source.origin explaining its provenance. Until now that field had three values, each implying a specific real-world process:
All three assume the capture either came from this project's own hardware or was volunteered to this project's own support channel. That covers a real but narrow slice of the io-homecontrol device landscape — the specific Somfy motors on three radio chips the maintainer happens to own, plus whatever community members happened to file issues about. It does not, and structurally cannot, cover the much larger set of devices from other vendors and other markets (Velux gateways and sensors, French-market climate/heating actuators, other Somfy product lines) that nobody connected to this project has ever had in hand.
That gap is real, but other people have already done the work: other open-source implementations' own documentation contain genuine captured or precisely decoded frames for exactly these device families. Reusing own-hardware or github-issue to absorb that material would misrepresent how it was actually obtained — the same failure mode ADR 0010's own reasoning warns against ("a byte sequence someone invented to look plausible proves nothing when the question is what real hardware actually sends"; a byte sequence mislabeled as this project's own capture proves just as little the moment someone checks). synthetic-bootstrap is the wrong label too — this data describes real devices, it isn't self-test scaffolding.
Added reference-material as a fourth source.origin value (scripts/corpus/validate.py/build.py/ingest.py, tests/corpus/README.md). It covers a real device this project has no hardware access to, documented precisely enough elsewhere to build a faithful capture from — and is never used for a device family this project could plausibly capture itself; that would just be the "reuse an existing label" option above wearing a new name.
Two sub-cases exist under this one origin, and a capture must say in its description or a per-frame note which applies:
A source's license or terms must be checked before it's used, and that check must actually be capable of blocking a source, not just recorded after the fact:
Either way, real third-party key material (a CMD_KEY_TRANSFER/0x32 payload) is never included, if applicable this is re-keyed using our projects system key protection mechanism. validate.py's existing crypto enforcement (ADR 0010) is used to verify this.
That mechanism assumed the re-keyer holds the real key (ingest.py --rekey --system-key-from), which is true for own-hardware and false by definition here. scripts/corpus/rekey_capture.py closes the gap without weakening anything: the 0x32 payload is encrypted under the public TRANSFER_KEY, so the key can be recovered from the capture itself, in memory, and fed to the same verify-and-rewrite pipeline — which is precisely why such a capture could never have been committed as published in the first place.
The complete set of source.origin values, for reference:
| Origin | Real device? | Captured by this project? | Used for |
|---|---|---|---|
| own-hardware | Yes | Yes | The maintainer's own devices, captured directly. |
| github-issue | Yes | No (volunteered to this project) | A community member's own log, pasted into this project's issue tracker. |
| reference-material | Yes | No (found elsewhere) | A real device with no hardware access, documented precisely enough by a third party to reconstruct or reuse faithfully. |
| synthetic-bootstrap | No | — | Hand-generated bytes for pipeline self-tests; not a device capture at all. |