|
Home IO Control
ESPHome add-on for IO-Homecontrol devices
|
Status: Accepted · Recorded: 2026-08
Several platforms generate companion entities alongside their main one — the per-device diagnostic sensors (device name, active issue, RSSI, last contact, exchange failures), a favorite-position button next to a cover, a ventilation button for window-type covers. Each needs an ESPHome component ID.
Creating that ID inside to_code() is the intuitive place, and it used to work. Current ESPHome sizes its runtime component vector (StaticVector) from the number of component IDs known at the end of schema validation — before to_code() runs at all. An ID created later isn't counted. Nothing errors: the vector overflows at runtime and later components are silently dropped, so their setup() never executes.
That failure has no build-time or validation-time signal. It shows up as an entity mysteriously missing from a device, which is a far worse thing to debug than a build error.
Every companion ID is created by a post-validator during CONFIG_SCHEMA evaluation. to_code() only reads the already-declared ID back out of the validated config — it never creates one.
flowchart TB
Y["User YAML"]
V["CONFIG_SCHEMA validation"]
PV["post-validator:<br/>inject_companion_sensor_ids()<br/><i>declares every companion ID</i>"]
F(["component count frozen —<br/>StaticVector sized here"])
TC["to_code()<br/><i>reads the declared IDs,<br/>creates no new ones</i>"]
OK["Runtime: all components fit"]
BAD["Component dropped at runtime<br/>no error — the entity is just missing"]
Y --> V --> PV --> F --> TC --> OK
TC -.->|"creating an ID here<br/>is counted too late"| BAD
classDef freeze stroke:#856404,stroke-width:3px
classDef bad stroke:#c0392b,stroke-width:3px
class F freeze
class BAD bad
The injection lives once in the shared platform module and is reused by every device-bound platform, so adding a companion sensor touches one file rather than four.