Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
hub_names.py
Go to the documentation of this file.
1## @file
2## @brief Shared vocabulary of the Home IO Control codegen: YAML keys and generated C++ handles.
3## @ingroup hioc_codegen
4##
5## The ``CONF_*`` keys of the ``home_io_control:`` block and its ``oneway_controllers:`` /
6## ``lr1121_firmware_update:`` sub-blocks (tuning.py keeps the ``tuning:`` keys), the
7## ``home_io_control`` C++ namespace, and the class/enum handles of the hub and of the
8## hub-level entities it generates. The other codegen modules import from here; this
9## module imports none of them.
10
11import esphome.codegen as cg
12from esphome.components import spi
13# Aliased: this package has its own switch.py/button.py platform submodules, so the real ESPHome
14# components are always imported under names that cannot be mistaken for them. In the package's
15# __init__.py an unaliased `switch`/`button` would even be overwritten: __init__.py's namespace IS
16# the package object, the slot ESPHome's loader binds `esphome.components.home_io_control.switch`
17# into when it imports our platform file, so whichever import ran last would silently win.
18from esphome.components import button as button_component
19from esphome.components import switch as switch_component
20from esphome.components import text_sensor as text_sensor_component
21
22
23CONF_HOME_IO_CONTROL_ID = "home_io_control_id"
24CONF_RST_PIN = "rst_pin"
25CONF_DIO0_PIN = "dio0_pin"
26CONF_DIO4_PIN = "dio4_pin"
27CONF_DIO1_PIN = "dio1_pin"
28CONF_BUSY_PIN = "busy_pin"
29CONF_NODE_ID = "node_id"
30CONF_SYSTEM_KEY = "system_key"
31CONF_TX_POWER = "tx_power"
32CONF_PA_PIN = "pa_pin"
33CONF_RADIO_TYPE = "radio_type"
34CONF_FEM_EN_PIN = "fem_en_pin"
35CONF_VFEM_PIN = "vfem_pin"
36CONF_FEM_PA_PIN = "fem_pa_pin"
37# Which RF front-end part fem_pa_pin (and, for the parts that have one, fem_en_pin) is wired to
38# (ADR 0035) -- selects the driver's per-transmission switching behaviour and which pins that
39# behaviour requires; never supplies a pin number itself. See FEM_REQUIRED_PINS in hub_validators.py.
40# ("Part", not "chip" -- see FEM_PROFILES' own comment there for why.)
41CONF_FEM = "fem"
42CONF_TCXO_VOLTAGE = "tcxo_voltage"
43CONF_EXPOSED_SENDERS = "exposed_senders"
44CONF_ACCEPT_FOREIGN_PAIRING = "accept_foreign_pairing"
45CONF_RECOVER_ONEWAY_KEY = "recover_oneway_key"
46CONF_SCAN_PAIRED_DEVICES_BUTTON = "scan_paired_devices_button"
47CONF_DISCOVER_AND_PAIR_BUTTON = "discover_and_pair_button"
48CONF_ONEWAY_CONTROLLERS = "oneway_controllers"
49# Internal marker recording that an identity's node_id was derived rather than configured, so
50# validation errors and the boot log can say which it was.
51CONF_NODE_ID_DERIVED = "_node_id_derived"
52CONF_MANUFACTURER = "manufacturer"
53# Same YAML key as platform_common.py's CONF_DEVICE_TYPE, spelled here rather than imported:
54# platform_common imports from this package, whose modules import this one, so the dependency
55# cannot run the other way.
56CONF_IO_DEVICE_TYPE = "io_device_type"
57CONF_INITIAL_SEQUENCE = "initial_sequence"
58CONF_COMMANDS = "commands"
59# Per-identity 1W wire overrides (ADR 0031). execute_acei: overrides the manufacturer-derived
60# ACEI byte for CMD_EXECUTE; execute_broadcast: all|typed picks the all-devices (00 00 3F) vs
61# typed-class destination — a handheld-remote-vs-class-bound axis, not a vendor axis.
62CONF_EXECUTE_ACEI = "execute_acei"
63CONF_EXECUTE_BROADCAST = "execute_broadcast"
64# The build flag for this identity's "Enroll 1W Controller" button. Presence/absence is the whole
65# gate -- adding or removing this line and reflashing is the enrollment feature's entire
66# lifecycle, same shape as accept_foreign_pairing/recover_oneway_key.
67CONF_ENROLLMENT = "enrollment"
68# Whether the "Enroll 1W Controller" button's 0x30 carries a trailing MAC. Only meaningful with
69# enrollment: true -- see ONEWAY_CONTROLLER_SCHEMA's own comment and create_1w_add_controller()'s
70# @warning (proto_commands.h) for why real hardware disagrees on this byte.
71CONF_ENROLLMENT_WITH_MAC = "enrollment_with_mac"
72# Override for the device classes a VELUX enrollment 0x30 sweep targets. Unset -> the manufacturer
73# profile's list (velux: {roller_shutter, awning, dual_shutter}). Ignored by the somfy gesture.
74# See resolve_oneway_wire_profile() / effective_enrollment_classes() (oneway_controller.h), ADR 0032.
75CONF_ENROLLMENT_CLASSES = "enrollment_classes"
76# Same YAML key as platform_common.py's per-device 2W low_power (ADR 0029), tri-state here: unset
77# keeps every 1W burst in the legacy shape (LONG_PREAMBLE on every copy, CTRL1 0x00); `false`/`true`
78# opt an identity into the ADR 0038 shapes instead. One definition, shared: platform_common.py
79# imports this constant rather than keeping its own copy. See ONEWAY_CONTROLLER_SCHEMA's own
80# comment on this key for the full tri-state semantics, and ADR 0038.
81CONF_LOW_POWER = "low_power"
82# Injected at schema time, never user-supplied: the generated buttons' IDs and the identity's
83# diagnostic sensor ID (ADR 0009).
84CONF_BUTTON_IDS = "button_ids"
85CONF_LAST_COMMAND_SENSOR_ID = "last_command_sensor_id"
86# Only present when enrollment: true (ADR 0009 -- an ID created late in to_code() is silently
87# dropped at runtime).
88CONF_ENROLL_BUTTON_ID = "_enroll_button_id"
89CONF_DIAGNOSTIC_PROBES = "diagnostic_probes"
90CONF_LR1121_FIRMWARE_UPDATE = "lr1121_firmware_update"
91CONF_LR1121_BOOTLOADER = "bootloader"
92CONF_CHECKSUM_MD5 = "checksum_md5"
93CONF_TARGET_VERSION = "target_version"
94MIN_STATUS_POLL_INTERVAL_MS = 500
95
96# Internal config key for the "Accept Foreign Pairing" companion switch ID (injected by
97# post-validator, same pattern as tuning.py's companion entity IDs — ESPHome 2026.x sizes the
98# runtime component vector from IDs known at the end of schema validation, so a companion
99# entity created only in to_code() would silently drop; see tuning.py::_inject_tuning_companion_ids
100# for the fuller rationale).
101CONF_ACCEPT_FOREIGN_PAIRING_SWITCH_ID = "_accept_foreign_pairing_switch_id"
102# Internal config key for the "Recover 1W Controller Key" companion switch ID (injected by
103# post-validator; same rationale as CONF_ACCEPT_FOREIGN_PAIRING_SWITCH_ID above).
104CONF_RECOVER_ONEWAY_KEY_SWITCH_ID = "_recover_oneway_key_switch_id"
105# Internal config key for the "Flash LR1121 Radio Firmware" companion button ID (injected by
106# post-validator; same rationale as CONF_ACCEPT_FOREIGN_PAIRING_SWITCH_ID above).
107CONF_LR1121_FIRMWARE_UPDATE_BUTTON_ID = "_lr1121_firmware_update_button_id"
108# Internal config key for the "Scan Paired Devices" companion button ID (injected by
109# post-validator; same rationale as CONF_ACCEPT_FOREIGN_PAIRING_SWITCH_ID above).
110CONF_SCAN_PAIRED_DEVICES_BUTTON_ID = "_scan_paired_devices_button_id"
111# Internal config key for the "Discover & Pair" button ID (injected by post-validator; same
112# rationale as CONF_ACCEPT_FOREIGN_PAIRING_SWITCH_ID above).
113CONF_DISCOVER_AND_PAIR_BUTTON_ID = "_discover_and_pair_button_id"
114# Internal config key for the "Last Pairing Result" companion sensor ID that ships with the button
115# above (injected by the same post-validator, gated on the same flag). Deliberately NOT shared
116# with button.py's identically-purposed CONF_PAIRING_RESULT_SENSOR_ID: during the deprecation
117# window (see button.py) both exist, keying different config dicts -- the hub block here, vs. a
118# legacy button: entry there.
119CONF_DISCOVER_AND_PAIR_RESULT_SENSOR_ID = "_discover_and_pair_result_sensor_id"
120# Internal config key for the "Allow LR1121 Bootloader Rewrite (Irreversible)" companion switch ID
121# (injected by post-validator; same rationale as CONF_ACCEPT_FOREIGN_PAIRING_SWITCH_ID above --
122# only present when lr1121_firmware_update.bootloader: is configured).
123CONF_LR1121_BOOTLOADER_SWITCH_ID = "_lr1121_bootloader_switch_id"
124
125home_io_control_ns = cg.esphome_ns.namespace("home_io_control")
126IOHomeControlComponent = home_io_control_ns.class_(
127 "IOHomeControlComponent", cg.Component, spi.SPIDevice
128)
129# Hub-level "Recover System Key" switch (key extraction, key_extraction_responder.cpp /
130# platform_hub_controls.h). Deliberately NOT exposed via a `switch:` platform entry: earlier
131# revisions dispatched on the presence/absence of `io_device_id` within switch.py, which meant an
132# ordinary device-bound switch missing `io_device_id` by mistake would silently become this
133# security-sensitive switch instead of failing validation. Gating it behind this boolean (created
134# dynamically, like the `tuning:` UI controls) makes that class of mistake structurally
135# impossible: there is no shared schema for the two to be confused under.
136IOHomeAcceptForeignPairingSwitch = home_io_control_ns.class_(
137 "IOHomeAcceptForeignPairingSwitch", switch_component.Switch, cg.Component
138)
139# Hub-level "Recover 1W Controller Key" switch (key adoption, oneway_key_adoption.cpp /
140# platform_hub_controls.h). Same dynamically-created, hub-bound shape and rationale as the switch
141# above. Independent of accept_foreign_pairing — the two arm different listeners (2W pairing
142# responder vs. 1W add-controller broadcast).
143IOHomeRecoverOneWayKeySwitch = home_io_control_ns.class_(
144 "IOHomeRecoverOneWayKeySwitch", switch_component.Switch, cg.Component
145)
146# Hub-level "Flash LR1121 Radio Firmware" button (lr1121_firmware_update_controller.cpp /
147# platform_lr1121_controls.h). Same "created dynamically from a home_io_control: sub-block, not a
148# device-bound platform entry" shape as the switch above — there is no `io_device_id` to bind this
149# to, it targets the hub's own radio.
150IOHomeLr1121FirmwareUpdateButton = home_io_control_ns.class_(
151 "IOHomeLr1121FirmwareUpdateButton", button_component.Button, cg.Component
152)
153# Hub-level "Scan Paired Devices" button (management_actions.cpp / platform_hub_controls.h). An
154# additional trigger for the already-registered `scan_paired_devices` native API action, which is
155# unchanged. Same "created dynamically from the home_io_control: block" shape as the entities
156# above -- there is no `io_device_id` to bind a roll-call to.
157IOHomeScanPairedDevicesButton = home_io_control_ns.class_(
158 "IOHomeScanPairedDevicesButton", button_component.Button, cg.Component
159)
160# Hub-level "Discover & Pair" button and its companion "Last Pairing Result" diagnostic sensor
161# (platform_hub_controls.h). Created from `home_io_control.discover_and_pair_button: true`, the
162# same shape as the entity above. Declared here (rather than in button.py, which historically owned
163# both) because the deprecated `button:` platform (button.py) also still instantiates them for the
164# duration of its deprecation window and imports both names from the package.
165IOHomeDiscoverButton = home_io_control_ns.class_(
166 "IOHomeDiscoverButton", button_component.Button, cg.Component
167)
168IOHomePairingResultTextSensor = home_io_control_ns.class_(
169 "IOHomePairingResultTextSensor", text_sensor_component.TextSensor, cg.Component
170)
171# Generated 1W command buttons and their per-identity diagnostic sensor
172# (platform_oneway_entities.h). Created from the `oneway_controllers:` block, never a `button:`
173# entry, for the same reason as the switch above.
174IOHomeOneWayCommandButton = home_io_control_ns.class_(
175 "IOHomeOneWayCommandButton", button_component.Button, cg.Component
176)
177IOHomeOneWayLastCommandTextSensor = home_io_control_ns.class_(
178 "IOHomeOneWayLastCommandTextSensor", text_sensor_component.TextSensor, cg.Component
179)
180# Generated 1W enrollment button (platform_oneway_entities.h), one per identity with
181# `enrollment: true`. Same "created from the hub block, never a `button:` entry" reasoning as
182# IOHomeOneWayCommandButton above -- see that class's comment.
183IOHomeOneWayEnrollButton = home_io_control_ns.class_(
184 "IOHomeOneWayEnrollButton", button_component.Button, cg.Component
185)
186OneWayButtonAction = home_io_control_ns.enum("OneWayButtonAction", is_class=True)
187
188
189# Hub-level "Allow LR1121 Bootloader Rewrite (Irreversible)" arming switch
190# (lr1121_firmware_update_controller.cpp / platform_lr1121_controls.h). Same dynamically-created,
191# hub-bound shape as the two entities above; created only when lr1121_firmware_update.bootloader:
192# is configured (see _create_lr1121_bootloader_update()).
193IOHomeLr1121BootloaderRewriteSwitch = home_io_control_ns.class_(
194 "IOHomeLr1121BootloaderRewriteSwitch", switch_component.Switch, cg.Component
195)