Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
proto_constants.h
Go to the documentation of this file.
1#pragma once
2
3/// @file proto_constants.h
4/// @brief IO-Homecontrol command IDs, result codes and protocol enumerations.
5/// @ingroup hioc_protocol
6///
7/// Command bytes, CMD_ERROR_RESP result codes, wire position/status flags,
8/// cryptographic constants, and the manufacturer/originator/ACEI/discovery
9/// lookups. These describe *what* travels on the wire, independent of the
10/// frame container (proto_frame.h) and the device model (proto_device_model.h).
11
12#include "proto_sizes.h"
13
14#include <cstdint>
15
16namespace esphome {
17namespace home_io_control {
18
19// ============================================================================
20// Command IDs
21// ============================================================================
22
23// Normal operation commands
24static constexpr uint8_t CMD_EXECUTE = 0x00; ///< Set position/open/close/stop — requires authentication
25static constexpr uint8_t CMD_ACTIVATE_MODE = 0x01; ///< Activate device mode (scene, ventilation) — requires auth
26static constexpr uint8_t CMD_PRIVATE = 0x03; ///< Get device status — no authentication needed
27static constexpr uint8_t CMD_PRIVATE_RESP = 0x04; ///< Response to 0x00 and 0x03 (contains position data)
28static constexpr uint8_t CMD_PRIVATE2 =
29 0x0C; ///< Content otherwise undecoded by the wire parser. Its request payload matches
30 ///< CMD_EXECUTE's POS_FAVORITE/POS_VENT_MODIFIER stored-position selector with the
31 ///< execution prefix stripped, so it reads like a stored-position readback rather
32 ///< than a live telemetry poll — see tests/corpus/captures/somfy_rs100_oximo/ and
33 ///< captures/issues/issue_45_*.yaml for real request/response pairs. Not handled by
34 ///< any dispatch path in this codebase.
35static constexpr uint8_t CMD_PRIVATE2_RESP = 0x0D; ///< Response to CMD_PRIVATE2. See CMD_PRIVATE2's comment.
36
37// Sensor and private register commands
38static constexpr uint8_t CMD_SET_SENSOR = 0x19; ///< Inject sensor value into a device
39static constexpr uint8_t CMD_SET_SENSOR_ACK = 0x1A; ///< Acknowledgment to CMD_SET_SENSOR
40
41// Device identification
42static constexpr uint8_t CMD_IDENTIFY = 0x1E; ///< Device physical identification / jog — requires authentication
43
44static constexpr uint8_t CMD_WRITE_PRIVATE = 0x20; ///< Write private register (climate/heating devices)
45static constexpr uint8_t CMD_WRITE_PRIVATE_ACK = 0x21; ///< Acknowledgment to CMD_WRITE_PRIVATE
46
47// Discovery and pairing commands
48static constexpr uint8_t CMD_DISCOVER_REQ = 0x28; ///< Broadcast discovery request
49static constexpr uint8_t CMD_DISCOVER_RESP = 0x29; ///< Device responds with its ID and type
50static constexpr uint8_t CMD_DISCOVER_SPE_REQ =
51 0x2A; ///< Broadcast roll-call answered by every device that already holds this controller's
52 ///< system key, regardless of device type. A device that holds no key yet — one in
53 ///< learning mode, mid-pairing — has nothing to authenticate the request against and
54 ///< stays silent, so this enumerates already-managed devices and cannot discover new
55 ///< ones. Do not offer it as a pairing-discovery command: it can only ever add replies
56 ///< from devices already paired, never help reach an unpaired one.
57 ///< The 12-byte payload authenticates itself in a single frame — 6 random challenge
58 ///< bytes followed by a 6-byte HMAC over the command byte alone — instead of the usual
59 ///< 0x3C/0x3D round trip, which is what lets it be broadcast;
60 ///< create_discovery_request() (proto_commands.cpp) builds it to match. Real captured
61 ///< bytes: tests/corpus/captures/velux_kux100/pairing_full.yaml (request shape, HMAC
62 ///< recomputed under that installation's key before the capture was re-keyed) and
63 ///< tests/corpus/captures/somfy_awning/discover_spe_paired_rollcall.yaml plus
64 ///< tests/corpus/captures/somfy_dimmer/discover_spe_paired_rollcall.yaml (two awnings
65 ///< and a dimmer answering one broadcast). No dispatch path consumes the reply yet;
66 ///< classify_pairing_discovery_response() accepts only 0x29 and must not be extended to
67 ///< accept 0x2B, because a roll-call reply from an already-paired device is not a
68 ///< newly-discovered one and must never enter the pairing flow. See
69 ///< CMD_DISCOVER_SPE_RESP.
70static constexpr uint8_t CMD_DISCOVER_SPE_RESP =
71 0x2B; ///< Roll-call reply to CMD_DISCOVER_SPE_REQ, sent only by devices that already hold the
72 ///< requesting controller's system key. The payload is the same DISCOVERY_RESP_FULL_SIZE
73 ///< layout as a CMD_DISCOVER_RESP (0x29), so every DISCOVERY_RESP_*_OFFSET constant
74 ///< below applies unchanged — packed type/subtype at data[0..1], backbone address at
75 ///< DISCOVERY_RESP_BACKBONE_OFFSET, manufacturer at DISCOVERY_RESP_MANUFACTURER_OFFSET,
76 ///< Multi Information Byte at DISCOVERY_RESP_FLAGS_OFFSET, timestamp at
77 ///< DISCOVERY_RESP_TIMESTAMP_OFFSET — and PairingEngine::parse_device_from_discovery()
78 ///< decodes a 0x2B correctly with no special-casing. Real captured replies (two awnings
79 ///< and a dimmer) are in tests/corpus/captures/somfy_awning/ and .../somfy_dimmer/
80 ///< discover_spe_paired_rollcall.yaml. The timestamp is the field that advances between
81 ///< successive replies from one device; it is not a response to the request's random
82 ///< challenge, since that HMAC covers only the constant command byte. Treat a reply as
83 ///< self-description, not proof of identity: nothing in it is bound to the request, so
84 ///< report it, never act on it. No dispatch path consumes a 0x2B yet.
85static constexpr uint8_t CMD_DISCOVER_CONFIRM = 0x2C; ///< Confirm discovery to device
86static constexpr uint8_t CMD_DISCOVER_CONFIRM_ACK = 0x2D; ///< Device acknowledges confirmation
87static constexpr uint8_t CMD_DISCOVER_ALT_REQ =
88 0x2E; ///< Alternate discovery. Broadcast (to 0x00003F) draws no response at all on every
89 ///< device this project has real evidence for — a Somfy Izymo dimmer
90 ///< (tests/corpus/captures/somfy_dimmer/discover_alt_no_response.yaml) and a Velux
91 ///< KLR200/KUX100 pair (tests/corpus/captures/velux_kux100/
92 ///< discover_alt_broadcast_no_response.yaml) both went unanswered; the older
93 ///< "response is 0x29" guess never had real evidence and appears to have been wrong.
94 ///< Directly *addressed* to a known device instead of broadcast, it does draw a
95 ///< response, but a 0x3C/0x3D challenge-response followed by CMD_DISCOVER_ALT_RESP
96 ///< (0x2F), not 0x29 — see tests/corpus/captures/velux_kux100/
97 ///< discover_alt_addressed_challenge_response.yaml.
98static constexpr uint8_t CMD_DISCOVER_ALT_RESP =
99 0x2F; ///< Reply to an addressed (non-broadcast) CMD_DISCOVER_ALT_REQ, following a
100 ///< 0x3C/0x3D challenge-response. See CMD_DISCOVER_ALT_REQ's comment and
101 ///< tests/corpus/captures/velux_kux100/discover_alt_addressed_challenge_response.yaml
102 ///< — the only capture this project has of it. Not otherwise used anywhere in this
103 ///< codebase (no dispatch logic added).
104static constexpr uint8_t CMD_ONEWAY_ADD_CONTROLLER =
105 0x30; ///< 1W "add controller": a 1W device broadcasts this while its key-copy gesture is
106 ///< active, handing its network's wrapped system key to whichever controller is
107 ///< listening — see docs/commands.md#30-send-1w-key in the reference project linked
108 ///< from issue #66. Not parsed or handled anywhere in this codebase (no 1W key-adoption
109 ///< feature exists here); the constant exists solely so redaction.h can recognize and
110 ///< mask any such frame this hub's radio passively overhears from a neighboring
111 ///< installation's 1W pairing gesture, the same way it already does for CMD_ONEWAY_REMOVE
112 ///< in pairing_advisor.cpp.
113static constexpr uint8_t CMD_ONEWAY_REMOVE = 0x39; ///< 1W "remove controller" (un-pair a 1W remote from a device);
114 ///< same payload shape as 0x2E.
115
116// Key exchange commands (used during pairing)
117static constexpr uint8_t CMD_KEY_INIT = 0x31; ///< Initiate key transfer to device
118static constexpr uint8_t CMD_KEY_TRANSFER = 0x32; ///< Send encrypted system key to device
119static constexpr uint8_t CMD_KEY_CONFIRM = 0x33; ///< Device confirms key was received
120
121// Address and device-initiated key exchange
122static constexpr uint8_t CMD_ADDRESS_REQ = 0x36; ///< Address assignment request
123static constexpr uint8_t CMD_ADDRESS_RESP =
124 0x37; ///< Address assignment response: the device returns its own 3-byte backbone address,
125 ///< byte-identical to the one it reported at data[2..4]
126 ///< (DISCOVERY_RESP_BACKBONE_OFFSET) of its CMD_DISCOVER_RESP earlier in the same
127 ///< session — an independent confirmation of that offset. Only capture of this pair:
128 ///< tests/corpus/captures/velux_kux100/pairing_full.yaml, where a Velux KLR200 closes
129 ///< pairing with 0x36 and then challenges the 0x37 it gets back (see
130 ///< CMD_CHALLENGE_REQ). Neither command is sent or handled anywhere in this codebase.
131static constexpr uint8_t CMD_LAUNCH_KEY_TRANSFER =
132 0x38; ///< Device-initiated ("pull") key transfer request. `reference/iown-homecontrol`
133 ///< documents its shape as a command ID plus a 6-byte challenge, nothing more. Never
134 ///< observed in our corpus or in any field log, and not sent or handled anywhere in
135 ///< this codebase — the constant is used only to construct a hypothetical device-side
136 ///< IV in tests/proto_crypto_test.cpp, exercising the crypto primitive, not a dispatch
137 ///< path.
138
139// Authentication commands (challenge-response for secured commands)
140static constexpr uint8_t CMD_CHALLENGE_REQ =
141 0x3C; ///< 6-byte random challenge. Usually a device challenging a controller's command —
142 ///< the only direction this codebase implements — but the protocol is symmetric and
143 ///< controllers challenge devices too: in
144 ///< tests/corpus/captures/velux_kux100/pairing_full.yaml a KLR200 issues 0x3C against
145 ///< the device's own CMD_ADDRESS_RESP.
146static constexpr uint8_t CMD_CHALLENGE_RESP =
147 0x3D; ///< HMAC proof answering a 0x3C. Whoever is challenged authenticates *its own*
148 ///< preceding frame: the transcript is [cmd, data...] of the challenged party's last
149 ///< frame (create_challenge_resp()), never the challenger's. That holds in both
150 ///< directions — the device-side 0x3D in pairing_full.yaml (over its own 0x37) was
151 ///< recomputed under that installation's recovered key and confirmed before the
152 ///< capture was re-keyed, so it is measured, not assumed by symmetry.
153
154// File/blob management block (0x48-0x4B)
155static constexpr uint8_t CMD_UNKNOWN4A_REQ =
156 0x4A; ///< Content undecoded. The leading published interpretation of this opcode is "Delete
157 ///< File" (a large-data-transfer / "ioblob" request), with "Rename File" as a
158 ///< conflicting second reading — both writes, and no project this codebase draws on
159 ///< has ever transmitted it. Never captured on the wire either. This constant exists
160 ///< solely so a received 0x4A frame renders by name in the log instead of as
161 ///< UNKNOWN_CMD; it must never be sent, and no builder for it exists anywhere in this
162 ///< codebase — see CMD_ONEWAY_ADD_CONTROLLER for the same "named but never sent"
163 ///< precedent, and docs/adr/ for the standing decision not to add one.
164static constexpr uint8_t CMD_UNKNOWN4A_RESP =
165 0x4B; ///< Observed on the wire (tests/corpus/captures/issues/) answering an ON_OFF_SWITCH-type device's
166 ///< traffic, but its request opcode is unconfirmed — it is not established to be
167 ///< CMD_UNKNOWN4A_REQ's reply rather than CMD_GET_GENERAL_INFO3's. Content undecoded.
168 ///< Not sent or handled anywhere in this codebase.
169
170// Device info commands
171static constexpr uint8_t CMD_GET_NAME = 0x50; ///< Request device name
172static constexpr uint8_t CMD_GET_NAME_RESP = 0x51; ///< Device name response
173static constexpr uint8_t CMD_SET_NAME = 0x52; ///< Set device name (authenticated)
174static constexpr uint8_t CMD_SET_NAME_RESP = 0x53; ///< Device-name write response
175static constexpr uint8_t CMD_GET_INFO1 =
176 0x54; ///< Request device general info 1 (unimplemented; we only use 0x56/0x57)
177static constexpr uint8_t CMD_GET_INFO1_RESP = 0x55; ///< Device general info 1 response (unimplemented; we only use
178 ///< 0x56/0x57). Never observed in our corpus or in any field log —
179 ///< this codebase has never sent CMD_GET_INFO1 to prompt one.
180static constexpr uint8_t CMD_GET_INFO2 = 0x56; ///< Request device type/model info
181static constexpr uint8_t CMD_GET_INFO2_RESP = 0x57; ///< Device type/model response
182static constexpr uint8_t CMD_GET_GENERAL_INFO3 =
183 0x58; ///< Observed on the wire (tests/corpus/captures/issues/) with no payload. Content
184 ///< undecoded. Not sent or handled anywhere in this codebase.
185static constexpr uint8_t CMD_GET_GENERAL_INFO3_RESP =
186 0x59; ///< Never captured on our own wire. This constant exists so a received 0x59 frame
187 ///< renders by name instead of as UNKNOWN_CMD. Not sent or handled anywhere in this
188 ///< codebase.
189
190// Configuration and status update commands
191static constexpr uint8_t CMD_SET_CONFIG1 = 0x6F; ///< Configure device to auto-send status updates
192static constexpr uint8_t CMD_SET_CONFIG1_RESP =
193 0x70; ///< Config response. `reference/iown-homecontrol` does not document this opcode at
194 ///< all. Never observed in our corpus or in any field log, and not sent or handled
195 ///< anywhere in this codebase beyond the generic "is this a known command byte" check
196 ///< in radio_soft_phy.cpp.
197static constexpr uint8_t CMD_STATUS_UPDATE = 0x71; ///< Device-initiated status update (needs auth)
198static constexpr uint8_t CMD_STATUS_UPDATE_RESP = 0x72; ///< Acknowledge status update
199
200static constexpr uint8_t CMD_SEND_RAW_MESSAGE =
201 0xF0; ///< `reference/iown-homecontrol` heads this "Send Raw Message / Find Hardware
202 ///< ("Service")" — its own quoting, not settled naming. Never observed in our corpus
203 ///< or in any field log, and not sent or handled anywhere in this codebase.
204static constexpr uint8_t CMD_READ_GROUPS =
205 0xF1; ///< `reference/iown-homecontrol` heads this "Actuator: Read Groups /
206 ///< "ActuatorAnyConfigIsLocal" (?) / "Service ACK"" — three candidate names, one
207 ///< flagged with its own question mark, from the source itself. Never observed in our
208 ///< corpus or in any field log, and not sent or handled anywhere in this codebase.
209static constexpr uint8_t CMD_REBOOT =
210 0xF2; ///< `reference/iown-homecontrol` heads this "Reboot / Service Status" — two candidate
211 ///< names, one of them destructive-sounding, on no field evidence at all. Never
212 ///< observed in our corpus or in any field log, and not sent or handled anywhere in
213 ///< this codebase; treat the "reboot" reading with particular caution; it is a guess.
214static constexpr uint8_t CMD_SERVICE_STATUS_ACK =
215 0xF3; ///< `reference/iown-homecontrol` lists this opcode with its body marked TBD — no
216 ///< description at all, not even a hedge to reproduce. Never observed in our corpus
217 ///< or in any field log, and not sent or handled anywhere in this codebase.
218
219static constexpr uint8_t CMD_ERROR_RESP = 0xFE; ///< Error response to any command
220
221// Command-result / limitation codes carried in CMD_ERROR_RESP DATA[0].
222static constexpr uint8_t RESULT_UNKNOWN_STATUS_REPLY = 0x00; ///< Device returned an unknown status reply.
223static constexpr uint8_t RESULT_COMMAND_COMPLETED_OK = 0x01; ///< No errors detected.
224static constexpr uint8_t RESULT_NO_CONTACT = 0x02; ///< No communication to node.
225static constexpr uint8_t RESULT_MANUALLY_OPERATED = 0x03; ///< Manually operated by a user.
226static constexpr uint8_t RESULT_BLOCKED = 0x04; ///< Node blocked by an object.
227static constexpr uint8_t RESULT_WRONG_SYSTEMKEY = 0x05; ///< Node contains the wrong system key.
228static constexpr uint8_t RESULT_PRIORITY_LEVEL_LOCKED = 0x06; ///< Node is locked on this priority level.
229static constexpr uint8_t RESULT_REACHED_WRONG_POSITION = 0x07; ///< Node stopped in another position than expected.
230static constexpr uint8_t RESULT_ERROR_DURING_EXECUTION = 0x08; ///< Generic execution failure.
231static constexpr uint8_t RESULT_NO_EXECUTION = 0x09; ///< Node did not move.
232static constexpr uint8_t RESULT_CALIBRATING = 0x0A; ///< Node is calibrating.
233static constexpr uint8_t RESULT_POWER_CONSUMPTION_TOO_HIGH = 0x0B; ///< Node power consumption is too high.
234static constexpr uint8_t RESULT_POWER_CONSUMPTION_TOO_LOW = 0x0C; ///< Node power consumption is too low.
235static constexpr uint8_t RESULT_LOCK_POSITION_OPEN = 0x0D; ///< Lock command failed because the door is open.
236static constexpr uint8_t RESULT_MOTION_TIME_TOO_LONG = 0x0E; ///< Target was not reached in time.
237static constexpr uint8_t RESULT_THERMAL_PROTECTION = 0x0F; ///< Node entered thermal protection mode.
238static constexpr uint8_t RESULT_PRODUCT_NOT_OPERATIONAL = 0x10; ///< Node is not currently operational.
239static constexpr uint8_t RESULT_FILTER_MAINTENANCE_NEEDED = 0x11; ///< Filter needs maintenance.
240static constexpr uint8_t RESULT_BATTERY_LEVEL = 0x12; ///< Battery level is low.
241static constexpr uint8_t RESULT_TARGET_MODIFIED = 0x13; ///< Node modified the requested target value.
242static constexpr uint8_t RESULT_MODE_NOT_IMPLEMENTED = 0x14; ///< Mode is not supported by the node.
243static constexpr uint8_t RESULT_COMMAND_INCOMPATIBLE_TO_MOVEMENT = 0x15; ///< Command cannot move the node that way.
244static constexpr uint8_t RESULT_USER_ACTION = 0x16; ///< User action overrode the command.
245static constexpr uint8_t RESULT_DEAD_BOLT_ERROR = 0x17; ///< Dead bolt error.
246static constexpr uint8_t RESULT_AUTOMATIC_CYCLE_ENGAGED = 0x18; ///< Node entered automatic cycle mode.
247static constexpr uint8_t RESULT_WRONG_LOAD_CONNECTED = 0x19; ///< Wrong load connected to node.
248static constexpr uint8_t RESULT_COLOUR_NOT_REACHABLE = 0x1A; ///< Requested colour not reachable.
249static constexpr uint8_t RESULT_TARGET_NOT_REACHABLE = 0x1B; ///< Requested target not reachable.
250static constexpr uint8_t RESULT_BAD_INDEX_RECEIVED = 0x1C; ///< Invalid index received.
251static constexpr uint8_t RESULT_COMMAND_OVERRULED = 0x1D; ///< Command was overruled by a newer command.
252static constexpr uint8_t RESULT_NODE_WAITING_FOR_POWER = 0x1E; ///< Node is waiting for power.
253static constexpr uint8_t RESULT_NODE_LOCKED = 0x20; ///< Node is locked.
254static constexpr uint8_t RESULT_WRONG_POSITION = 0x21; ///< Node reports wrong position.
255static constexpr uint8_t RESULT_LIMITS_NOT_SET = 0x22; ///< Device limits are not set.
256static constexpr uint8_t RESULT_IP_NOT_SET = 0x23; ///< Intermediate position is not set.
257static constexpr uint8_t RESULT_OUT_OF_RANGE = 0x24; ///< Requested value is out of range.
258static constexpr uint8_t RESULT_PRIORITY_LOCKED_NON_EXEC =
259 0x38; ///< Priority locked, command not executed (ACEI priority too low).
260static constexpr uint8_t RESULT_INFORMATION_CODE = 0xDF; ///< Information-only code with unknown semantics.
261static constexpr uint8_t RESULT_PARAMETER_LIMITED = 0xE0; ///< Parameter limited by an unknown device.
262static constexpr uint8_t RESULT_LIMITATION_BY_LOCAL_USER = 0xE1; ///< Parameter limited by local button.
263static constexpr uint8_t RESULT_LIMITATION_BY_USER = 0xE2; ///< Parameter limited by a remote control.
264static constexpr uint8_t RESULT_LIMITATION_BY_RAIN = 0xE3; ///< Parameter limited by a rain sensor.
265static constexpr uint8_t RESULT_LIMITATION_BY_TIMER = 0xE4; ///< Parameter limited by a timer.
266static constexpr uint8_t RESULT_LIMITATION_BY_SCD = 0xE5; ///< Parameter limited by a security actuator.
267static constexpr uint8_t RESULT_LIMITATION_BY_UPS = 0xE6; ///< Parameter limited by a power supply.
268static constexpr uint8_t RESULT_LIMITATION_BY_UNKNOWN_DEVICE = 0xE7; ///< Parameter limited by an unknown device.
269static constexpr uint8_t RESULT_LIMITATION_BY_SAAC = 0xEA; ///< Parameter limited by a standalone automatic controller.
270static constexpr uint8_t RESULT_LIMITATION_BY_WIND = 0xEB; ///< Parameter limited by a wind sensor.
271static constexpr uint8_t RESULT_LIMITATION_BY_MYSELF = 0xEC; ///< Parameter limited by the node itself.
272static constexpr uint8_t RESULT_LIMITATION_BY_AUTOMATIC_CYCLE = 0xED; ///< Parameter limited by an automatic cycle.
273static constexpr uint8_t RESULT_LIMITATION_BY_EMERGENCY = 0xEE; ///< Parameter limited by an emergency.
274
275// ============================================================================
276// Position and Status Wire Constants
277// ============================================================================
278
279/// Position values in the IO protocol.
280/// Normal positions are 0-100 (0=fully open, 100=fully closed).
281/// Special values above 100 are control commands encoded as the "main" parameter
282/// byte in CMD_EXECUTE payloads. These are internal wire constants — callers should
283/// prefer CoverCommand for type-safe command dispatch.
284static constexpr uint8_t POS_STOP = 0xD2; ///< Wire value: stop movement.
285static constexpr uint8_t POS_UNKNOWN = 0xD4; ///< Wire value: position unknown / keep current.
286static constexpr uint8_t POS_FAVORITE = 0xD8; ///< Wire value: move to favorite/"My" position.
287
288/// @brief Wire value for the secured target position command.
289///
290/// Moves the actuator to its pre-programmed secured/safety position from the
291/// Execution Parameter Buffer. Typically sent by environmental sensors (wind, rain)
292/// to retract an awning or close a shutter to a wind-safe state.
293static constexpr uint8_t POS_SECURED_TARGET = 0xD1;
294
295/// @brief Wire value for the default position command.
296///
297/// Moves the actuator to its factory or user-configured default position.
298static constexpr uint8_t POS_DEFAULT = 0xD3;
299
300/// @brief Ambiguous wire value used only for passive 1W-traffic intent decoding
301/// (decode_1w_main_intent() / oneway_intent_to_target() in proto_codecs.cpp).
302///
303/// 0x64 (100) is simultaneously the ordinary doubled-position wire value for 50% and a value
304/// some physical 1W remotes send for their "force open" button — the protocol has no dedicated
305/// override code, so the two are indistinguishable on the wire. For passively decoding someone
306/// else's remote traffic, "FORCE_OPEN" is the more useful diagnostic label (physical remotes
307/// rarely send a numeric 50%). This is NOT used by any outbound builder in this codebase:
308/// real-hardware testing confirmed that sending main=0x64 as an outbound 2W
309/// CMD_EXECUTE command makes a real device move to 50% open, not bypass anything — see
310/// create_force_open() in proto_commands.cpp for the actual (ACEI-priority-based) force-open
311/// implementation.
312static constexpr uint8_t POS_FORCE_OPEN = 0x64;
313
314/// @brief Modifier byte for the ventilation command.
315///
316/// Both favorite and ventilation use POS_FAVORITE (0xD8) as the main parameter byte,
317/// but ventilation sets the secondary byte (main[1]) to 0x03 while favorite leaves it 0x00.
318static constexpr uint8_t POS_VENT_MODIFIER = 0x03;
319
320/// Status byte flags in CMD_PRIVATE_RESP and CMD_STATUS_UPDATE.
321static constexpr uint8_t STATUS_STOPPED = 0x01; ///< Byte 0 bit 0: device is not moving
322static constexpr uint8_t STATUS_EXPECTED = 0x80; ///< Byte 1 bit 7: device will send auto status update
323static constexpr uint8_t STATUS_TILT_SELECTOR = 0x20; ///< Extended status payload marker for tilt-capable devices
324
325// ============================================================================
326// Cryptographic Constants
327// ============================================================================
328
329/// The transfer key is a hardcoded key used ONLY during pairing to obfuscate
330/// the system key during over-the-air transfer. It is NOT the system key.
331/// This is the same across all IO-Homecontrol devices worldwide.
332static constexpr uint8_t TRANSFER_KEY[AES_KEY_SIZE] = {0x34, 0xC3, 0x46, 0x6E, 0xD8, 0x8F, 0x4E, 0x8E,
333 0x16, 0xAA, 0x47, 0x39, 0x49, 0x88, 0x43, 0x73};
334static constexpr uint16_t CRC_POLYNOMIAL_REVERSED = 0x8408; ///< Reversed CRC-CCITT polynomial used by IO-homecontrol
335static constexpr uint16_t CRC_LSB_MASK = 0x0001; ///< Least-significant-bit mask for reflected CRC update
336
337/// Broadcast address for device discovery (0x00003B).
338/// Used as destination in CMD_DISCOVER_REQ frames to trigger all pairable devices to respond.
339static constexpr uint8_t BROADCAST_DISCOVER[NODE_ID_SIZE] = {0x00, 0x00, 0x3B};
340
341/// Alternate discovery / 1W broadcast address (0x00003F).
342/// Used as destination for CMD_DISCOVER_ALT_REQ (0x2E) alternate discovery, and the address
343/// on which devices in 1W-triggered pairing mode listen. Distinct from the 2W discovery
344/// broadcast BROADCAST_DISCOVER (0x00003B).
345static constexpr uint8_t BROADCAST_DISCOVER_ALT[NODE_ID_SIZE] = {0x00, 0x00, 0x3F};
346
347// ============================================================================
348// Command Name Lookup
349// ============================================================================
350
351/// @brief Get a human-readable name for any IO-Homecontrol command ID.
352///
353/// Returns a short uppercase identifier suitable for log lines (e.g., "EXECUTE",
354/// "DISCOVER_REQ", "CHALLENGE_RESP"). Unknown commands return "UNKNOWN_CMD".
355/// @param cmd Command byte from the frame header.
356/// @return Null-terminated string.
357const char *command_name(uint8_t cmd);
358
359// ============================================================================
360// Manufacturer ID Lookup
361// ============================================================================
362
363/// @brief Maximum manufacturer ID with a known name in the lookup table.
364static constexpr uint8_t MANUFACTURER_ID_MAX = 12;
365
366/// @brief IO-Homecontrol manufacturer ID constants.
367///
368/// These 1-based identifiers are assigned by the IO-Homecontrol alliance and
369/// appear in the discovery response payload at DISCOVERY_RESP_MANUFACTURER_OFFSET.
370/// @{
371static constexpr uint8_t MANUFACTURER_VELUX = 1; ///< VELUX (roof windows, skylights).
372static constexpr uint8_t MANUFACTURER_SOMFY = 2; ///< Somfy (shutters, awnings, blinds).
373static constexpr uint8_t MANUFACTURER_HONEYWELL = 3; ///< Honeywell.
374static constexpr uint8_t MANUFACTURER_HORMANN = 4; ///< Hörmann (garage doors, gates).
375static constexpr uint8_t MANUFACTURER_ASSA_ABLOY = 5; ///< ASSA ABLOY (locks, access).
376static constexpr uint8_t MANUFACTURER_NIKO = 6; ///< Niko (switches, home automation).
377static constexpr uint8_t MANUFACTURER_WINDOW_MASTER = 7; ///< WINDOW MASTER (ventilation).
378static constexpr uint8_t MANUFACTURER_RENSON = 8; ///< Renson (ventilation, sun protection).
379static constexpr uint8_t MANUFACTURER_CIAT = 9; ///< CIAT (HVAC).
380static constexpr uint8_t MANUFACTURER_SECUYOU = 10; ///< Secuyou (security).
381static constexpr uint8_t MANUFACTURER_OVERKIZ = 11; ///< OVERKIZ (Somfy connectivity platform).
382static constexpr uint8_t MANUFACTURER_ATLANTIC_GROUP = 12; ///< Atlantic Group (heating, hot water).
383/// @}
384
385/// @brief Get a human-readable manufacturer name from the protocol manufacturer byte.
386///
387/// The manufacturer ID is a 1-based index assigned by the IO-Homecontrol alliance.
388/// IDs outside the known range return "unknown". When an unknown ID appears at runtime,
389/// the pairing flow logs a warning suggesting the user file a GitHub issue.
390/// @param id Manufacturer ID byte (1–12 for known manufacturers).
391/// @return Null-terminated lowercase string such as "unknown", or mixed-case name like "Somfy".
392const char *manufacturer_name(uint8_t id);
393
394// ============================================================================
395// Command Originator Codes
396// ============================================================================
397
398/// @brief Command originator codes indicating what or who triggered a command.
399///
400/// The originator byte is the first byte of the CMD_EXECUTE payload. It tells
401/// the actuator (and any eavesdropping controller) who initiated the movement.
402/// This is useful for understanding device-initiated status updates.
403/// @{
404static constexpr uint8_t ORIGINATOR_LOCAL_USER = 0x00; ///< User pressed a button on the actuator.
405static constexpr uint8_t ORIGINATOR_USER_REMOTE = 0x01; ///< User sent command from a remote control.
406static constexpr uint8_t ORIGINATOR_RAIN_SENSOR = 0x02; ///< Rain sensor triggered the movement.
407static constexpr uint8_t ORIGINATOR_TIMER = 0x03; ///< Timer or schedule triggered the movement.
408static constexpr uint8_t ORIGINATOR_SECURITY = 0x04; ///< Security controlling device (SCD) action.
409static constexpr uint8_t ORIGINATOR_UPS = 0x05; ///< Uninterruptible power supply action.
410static constexpr uint8_t ORIGINATOR_SMART_CONTROLLER = 0x06; ///< Smart function controller.
411static constexpr uint8_t ORIGINATOR_LIFESTYLE = 0x07; ///< Lifestyle scenario controller.
412static constexpr uint8_t ORIGINATOR_SAAC = 0x08; ///< Stand-alone automatic controller (SAAC).
413static constexpr uint8_t ORIGINATOR_WIND_SENSOR = 0x09; ///< Wind sensor triggered the movement.
414static constexpr uint8_t ORIGINATOR_LOAD_SHEDDING = 0x0B; ///< Load-shedding manager.
415static constexpr uint8_t ORIGINATOR_LOCAL_LIGHT = 0x0C; ///< Local light sensor.
416static constexpr uint8_t ORIGINATOR_ENVIRONMENT = 0x0D; ///< Unspecified environment sensor.
417static constexpr uint8_t ORIGINATOR_MYSELF = 0x10; ///< Actuator decided to move by itself.
418static constexpr uint8_t ORIGINATOR_AUTOMATIC_CYCLE = 0xFE; ///< Automatic cycle / external access.
419static constexpr uint8_t ORIGINATOR_EMERGENCY = 0xFF; ///< Emergency command (never disabled).
420/// @}
421
422/// @brief Get a human-readable name for a command originator byte.
423///
424/// @param originator Originator code from the first data byte of CMD_EXECUTE.
425/// @return Null-terminated string such as "rain_sensor" or "user_remote".
426const char *originator_name(uint8_t originator);
427
428// ============================================================================
429// ACEI (Application Command Execution Interface)
430// ============================================================================
431
432/// @brief ACEI byte bit-field definitions.
433///
434/// The ACEI byte is the second byte of the CMD_EXECUTE payload. It encodes the
435/// priority level and service class of the command, controlling which commands
436/// can override others. Devices reject commands with lower priority than their
437/// current locked level (resulting in RESULT_PRIORITY_LEVEL_LOCKED).
438/// @{
439static constexpr uint8_t ACEI_VALID_BIT = 0x01; ///< Bit 0: command validity flag.
440static constexpr uint8_t ACEI_EXTENDED_MASK = 0x06; ///< Bits [2:1]: extended field.
441static constexpr uint8_t ACEI_EXTENDED_SHIFT = 1; ///< Shift for extended field extraction.
442static constexpr uint8_t ACEI_SERVICE_MASK = 0x18; ///< Bits [4:3]: service type.
443static constexpr uint8_t ACEI_SERVICE_SHIFT = 3; ///< Shift for service field extraction.
444static constexpr uint8_t ACEI_LEVEL_MASK = 0xE0; ///< Bits [7:5]: priority level (0–7).
445static constexpr uint8_t ACEI_LEVEL_SHIFT = 5; ///< Shift for priority level extraction.
446/// @}
447
448/// @brief ACEI priority level values (0–7).
449///
450/// These values are extracted from the ACEI byte via (acei & ACEI_LEVEL_MASK) >> ACEI_LEVEL_SHIFT.
451/// @{
452static constexpr uint8_t ACEI_LEVEL_PROTECTION_HUMAN = 0; ///< Personal safety (highest, overrides all).
453static constexpr uint8_t ACEI_LEVEL_PROTECTION_SENSOR = 1; ///< Goods/environment protection via sensors.
454static constexpr uint8_t ACEI_LEVEL_USER_HIGH = 2; ///< High-priority user controller.
455static constexpr uint8_t ACEI_LEVEL_USER_DEFAULT = 3; ///< Default remote controller priority.
456static constexpr uint8_t ACEI_LEVEL_COMFORT_1 = 4; ///< Comfort automation level 1.
457static constexpr uint8_t ACEI_LEVEL_COMFORT_2 = 5; ///< Comfort automation level 2.
458static constexpr uint8_t ACEI_LEVEL_AUTO_SAAC = 6; ///< Stand-alone automatic controller.
459static constexpr uint8_t ACEI_LEVEL_AUTO_DEFAULT = 7; ///< Default automatic level (lowest).
460/// @}
461
462/// @brief Get a human-readable name for an ACEI priority level (0–7).
463///
464/// Priority levels form a hierarchy: level 0 (human protection) is highest
465/// and overrides all others. Level 3 is the default for remote controllers.
466/// @param level Priority level value (0–7).
467/// @return Null-terminated string such as "user_default" or "protection_sensor".
468const char *acei_level_name(uint8_t level);
469
470// ============================================================================
471// Discovery Response Extended Fields
472// ============================================================================
473
474/// @brief Byte offsets within CMD_DISCOVER_RESP (0x29) payload data.
475///
476/// The full discovery response carries up to 9 bytes of device metadata:
477/// bytes 0–1 hold the packed device type/subtype (already parsed by
478/// decode_packed_device_type()), and bytes 2–8 hold additional fields.
479/// @{
480static constexpr uint8_t DISCOVERY_RESP_BACKBONE_OFFSET = 2; ///< Backbone address starts at data[2] (3 bytes);
481 ///< cross-confirmed by CMD_ADDRESS_RESP (0x37),
482 ///< which returns the same 3 bytes for the same
483 ///< device (see that constant's comment).
484static constexpr uint8_t DISCOVERY_RESP_MANUFACTURER_OFFSET = 5; ///< Manufacturer ID at data[5].
485static constexpr uint8_t DISCOVERY_RESP_FLAGS_OFFSET = 6; ///< Flags byte at data[6].
486static constexpr uint8_t DISCOVERY_RESP_TIMESTAMP_OFFSET = 7; ///< Timestamp starts at data[7] (2 bytes).
487static constexpr uint8_t DISCOVERY_RESP_FULL_SIZE = 9; ///< Full discovery response payload size.
488/// @}
489
490// === Multi Information Byte (Discovery Response data[6]) ===
491// The flags byte in the discovery response encodes device capabilities and timing
492// characteristics that help a controller tune its interaction with the actuator.
493
494/// @brief Bit masks and shifts for the Multi Information Byte fields.
495/// @{
496static constexpr uint8_t DISCOVERY_FLAGS_ATT_MASK = 0xC0; ///< Bits [7:6]: actuator turnaround time class.
497static constexpr uint8_t DISCOVERY_FLAGS_ATT_SHIFT = 6; ///< Shift for ATT field extraction.
498static constexpr uint8_t DISCOVERY_FLAGS_SYNC_CTRL_GRP = 0x20; ///< Bit 5: supports sync control group.
499static constexpr uint8_t DISCOVERY_FLAGS_RF_SUPPORT = 0x08; ///< Bit 3: RF support in node (0=yes, 1=no).
500static constexpr uint8_t DISCOVERY_FLAGS_POWER_SAVE_MASK = 0x03; ///< Bits [1:0]: power save mode.
501/// @}
502
503/// @brief Actuator Turnaround Time (ATT) class values.
504///
505/// Indicates the maximum time window in which the actuator normally responds after
506/// receiving a command. Extracted from the Multi Information Byte via
507/// `(flags & DISCOVERY_FLAGS_ATT_MASK) >> DISCOVERY_FLAGS_ATT_SHIFT`.
508/// @{
509static constexpr uint8_t ATT_CLASS_5S = 0; ///< Response within 5 seconds.
510static constexpr uint8_t ATT_CLASS_10S = 1; ///< Response within 10 seconds.
511static constexpr uint8_t ATT_CLASS_20S = 2; ///< Response within 20 seconds.
512static constexpr uint8_t ATT_CLASS_40S = 3; ///< Response within 40 seconds.
513/// @}
514
515/// @brief Power save mode values from the Multi Information Byte.
516///
517/// Extracted from `flags & DISCOVERY_FLAGS_POWER_SAVE_MASK`.
518/// Devices in low-power mode require long preamble (1024 bytes) to wake their receiver.
519/// @{
520static constexpr uint8_t POWER_SAVE_ALWAYS_ALIVE = 0; ///< Device is always listening — short preamble works.
521static constexpr uint8_t POWER_SAVE_LOW_POWER = 1; ///< Device sleeps — needs long preamble to wake.
522/// @}
523
524/// @brief Extract the ATT class field from a discovery response's Multi Information Byte.
525/// @param flags Multi Information Byte (data[DISCOVERY_RESP_FLAGS_OFFSET]).
526/// @return ATT class value (0–3); pass to att_class_name() for a human-readable string.
527inline uint8_t discovery_att_class(uint8_t flags) {
529}
530
531/// @brief Extract the power save mode field from a discovery response's Multi Information Byte.
532/// @param flags Multi Information Byte (data[DISCOVERY_RESP_FLAGS_OFFSET]).
533/// @return Power save mode value (0–1); pass to power_save_mode_name() for a human-readable string.
534inline uint8_t discovery_power_save_mode(uint8_t flags) { return flags & DISCOVERY_FLAGS_POWER_SAVE_MASK; }
535
536/// @brief Get a human-readable turnaround time string for an ATT class value.
537/// @param att_class ATT class (0–3) extracted from the Multi Information Byte.
538/// @return Null-terminated string such as "5s", "10s", "20s", or "40s".
539const char *att_class_name(uint8_t att_class);
540
541/// @brief Get a human-readable power save mode name.
542/// @param mode Power save value (0–1) extracted from the Multi Information Byte.
543/// @return Null-terminated string such as "always_alive" or "low_power".
544const char *power_save_mode_name(uint8_t mode);
545
546// ============================================================================
547// Command Result Codes
548// ============================================================================
549
550/// @brief Return a stable symbolic name for a CMD_ERROR_RESP result code.
551/// @param result Result byte from CMD_ERROR_RESP data[0].
552/// @return Uppercase symbolic name, or "UNKNOWN_RESULT_CODE" when unmapped.
553const char *command_result_name(uint8_t result);
554/// @brief Return a human-readable explanation for a CMD_ERROR_RESP result code.
555/// @param result Result byte from CMD_ERROR_RESP data[0].
556/// @return Short description suitable for warn-level logs.
557const char *command_result_description(uint8_t result);
558/// @brief Check whether a result code represents an environmental or control limitation.
559/// @param result Result byte from CMD_ERROR_RESP data[0].
560/// @return true when the response reports a limitation rather than a generic execution error.
561bool is_limitation_result(uint8_t result);
562
563} // namespace home_io_control
564} // namespace esphome
static constexpr uint8_t ACEI_LEVEL_USER_HIGH
High-priority user controller.
const char * manufacturer_name(uint8_t id)
Get a human-readable manufacturer name from the protocol manufacturer byte.
static constexpr uint8_t RESULT_OUT_OF_RANGE
Requested value is out of range.
static constexpr uint8_t MANUFACTURER_HONEYWELL
Honeywell.
static constexpr uint8_t RESULT_CALIBRATING
Node is calibrating.
static constexpr uint8_t ACEI_LEVEL_COMFORT_1
Comfort automation level 1.
static constexpr uint8_t CMD_SET_SENSOR
Inject sensor value into a device.
uint8_t discovery_power_save_mode(uint8_t flags)
Extract the power save mode field from a discovery response's Multi Information Byte.
static constexpr uint8_t CMD_DISCOVER_REQ
Broadcast discovery request.
static constexpr uint8_t NODE_ID_SIZE
Device/node addresses are 3 bytes (e.g., "123ABC").
Definition proto_sizes.h:20
static constexpr uint8_t CMD_SET_CONFIG1
Configure device to auto-send status updates.
static constexpr uint8_t RESULT_COLOUR_NOT_REACHABLE
Requested colour not reachable.
static constexpr uint8_t RESULT_LIMITATION_BY_AUTOMATIC_CYCLE
Parameter limited by an automatic cycle.
static constexpr uint8_t ORIGINATOR_UPS
Uninterruptible power supply action.
static constexpr uint8_t ORIGINATOR_LOCAL_LIGHT
Local light sensor.
static constexpr uint8_t CMD_KEY_TRANSFER
Send encrypted system key to device.
static constexpr uint8_t RESULT_TARGET_MODIFIED
Node modified the requested target value.
static constexpr uint8_t RESULT_REACHED_WRONG_POSITION
Node stopped in another position than expected.
static constexpr uint8_t RESULT_LIMITATION_BY_MYSELF
Parameter limited by the node itself.
static constexpr uint8_t CMD_SERVICE_STATUS_ACK
reference/iown-homecontrol lists this opcode with its body marked TBD — no description at all,...
static constexpr uint8_t TRANSFER_KEY[AES_KEY_SIZE]
The transfer key is a hardcoded key used ONLY during pairing to obfuscate the system key during over-...
static constexpr uint8_t CMD_ERROR_RESP
Error response to any command.
static constexpr uint8_t CMD_GET_NAME_RESP
Device name response.
static constexpr uint8_t RESULT_AUTOMATIC_CYCLE_ENGAGED
Node entered automatic cycle mode.
static constexpr uint8_t CMD_DISCOVER_CONFIRM_ACK
Device acknowledges confirmation.
static constexpr uint8_t CMD_ACTIVATE_MODE
Activate device mode (scene, ventilation) — requires auth.
static constexpr uint8_t MANUFACTURER_CIAT
CIAT (HVAC).
static constexpr uint8_t RESULT_MODE_NOT_IMPLEMENTED
Mode is not supported by the node.
static constexpr uint8_t ACEI_LEVEL_USER_DEFAULT
Default remote controller priority.
static constexpr uint8_t RESULT_COMMAND_OVERRULED
Command was overruled by a newer command.
const char * att_class_name(uint8_t att_class)
Get a human-readable turnaround time string for an ATT class value.
static constexpr uint8_t MANUFACTURER_VELUX
IO-Homecontrol manufacturer ID constants.
static constexpr uint8_t DISCOVERY_RESP_MANUFACTURER_OFFSET
Manufacturer ID at data[5].
static constexpr uint8_t POS_UNKNOWN
Wire value: position unknown / keep current.
static constexpr uint8_t CMD_ADDRESS_RESP
Address assignment response: the device returns its own 3-byte backbone address, byte-identical to th...
static constexpr uint8_t RESULT_BAD_INDEX_RECEIVED
Invalid index received.
static constexpr uint8_t RESULT_MANUALLY_OPERATED
Manually operated by a user.
static constexpr uint8_t POS_FORCE_OPEN
Ambiguous wire value used only for passive 1W-traffic intent decoding (decode_1w_main_intent() / onew...
static constexpr uint8_t CMD_STATUS_UPDATE
Device-initiated status update (needs auth).
static constexpr uint8_t ACEI_LEVEL_AUTO_SAAC
Stand-alone automatic controller.
const char * power_save_mode_name(uint8_t mode)
Get a human-readable power save mode name.
static constexpr uint8_t CMD_UNKNOWN4A_REQ
Content undecoded.
static constexpr uint8_t DISCOVERY_FLAGS_RF_SUPPORT
Bit 3: RF support in node (0=yes, 1=no).
static constexpr uint8_t ACEI_LEVEL_PROTECTION_SENSOR
Goods/environment protection via sensors.
static constexpr uint8_t RESULT_LIMITATION_BY_UNKNOWN_DEVICE
Parameter limited by an unknown device.
static constexpr uint8_t CMD_DISCOVER_ALT_REQ
Alternate discovery.
static constexpr uint8_t RESULT_LOCK_POSITION_OPEN
Lock command failed because the door is open.
static constexpr uint8_t CMD_PRIVATE2_RESP
Response to CMD_PRIVATE2. See CMD_PRIVATE2's comment.
static constexpr uint8_t RESULT_WRONG_SYSTEMKEY
Node contains the wrong system key.
static constexpr uint8_t CMD_GET_NAME
Request device name.
static constexpr uint8_t MANUFACTURER_RENSON
Renson (ventilation, sun protection).
static constexpr uint8_t POWER_SAVE_ALWAYS_ALIVE
Power save mode values from the Multi Information Byte.
const char * command_name(uint8_t cmd)
Get a human-readable name for any IO-Homecontrol command ID.
static constexpr uint8_t ORIGINATOR_LOAD_SHEDDING
Load-shedding manager.
static constexpr uint8_t ORIGINATOR_LIFESTYLE
Lifestyle scenario controller.
static constexpr uint8_t MANUFACTURER_NIKO
Niko (switches, home automation).
static constexpr uint8_t CMD_DISCOVER_SPE_RESP
Roll-call reply to CMD_DISCOVER_SPE_REQ, sent only by devices that already hold the requesting contro...
static constexpr uint8_t ACEI_LEVEL_MASK
Bits [7:5]: priority level (0–7).
static constexpr uint8_t RESULT_LIMITATION_BY_EMERGENCY
Parameter limited by an emergency.
static constexpr uint8_t CMD_DISCOVER_ALT_RESP
Reply to an addressed (non-broadcast) CMD_DISCOVER_ALT_REQ, following a 0x3C/0x3D challenge-response.
static constexpr uint8_t RESULT_NODE_WAITING_FOR_POWER
Node is waiting for power.
static constexpr uint8_t ACEI_EXTENDED_SHIFT
Shift for extended field extraction.
static constexpr uint8_t ATT_CLASS_40S
Response within 40 seconds.
static constexpr uint8_t RESULT_BATTERY_LEVEL
Battery level is low.
static constexpr uint8_t CMD_WRITE_PRIVATE
Write private register (climate/heating devices).
static constexpr uint8_t RESULT_MOTION_TIME_TOO_LONG
Target was not reached in time.
static constexpr uint8_t RESULT_THERMAL_PROTECTION
Node entered thermal protection mode.
static constexpr uint8_t DISCOVERY_RESP_BACKBONE_OFFSET
Byte offsets within CMD_DISCOVER_RESP (0x29) payload data.
static constexpr uint8_t RESULT_POWER_CONSUMPTION_TOO_HIGH
Node power consumption is too high.
static constexpr uint8_t ORIGINATOR_MYSELF
Actuator decided to move by itself.
static constexpr uint8_t RESULT_ERROR_DURING_EXECUTION
Generic execution failure.
static constexpr uint8_t CMD_KEY_CONFIRM
Device confirms key was received.
static constexpr uint8_t CMD_WRITE_PRIVATE_ACK
Acknowledgment to CMD_WRITE_PRIVATE.
static constexpr uint8_t ACEI_LEVEL_PROTECTION_HUMAN
ACEI priority level values (0–7).
static constexpr uint8_t RESULT_PARAMETER_LIMITED
Parameter limited by an unknown device.
static constexpr uint8_t CMD_KEY_INIT
Initiate key transfer to device.
static constexpr uint8_t RESULT_LIMITATION_BY_RAIN
Parameter limited by a rain sensor.
static constexpr uint8_t RESULT_USER_ACTION
User action overrode the command.
static constexpr uint8_t CMD_GET_GENERAL_INFO3_RESP
Never captured on our own wire.
const char * command_result_description(uint8_t result)
Return a human-readable explanation for a CMD_ERROR_RESP result code.
static constexpr uint8_t POS_VENT_MODIFIER
Modifier byte for the ventilation command.
static constexpr uint8_t CMD_GET_INFO1_RESP
Device general info 1 response (unimplemented; we only use 0x56/0x57).
static constexpr uint8_t ACEI_LEVEL_AUTO_DEFAULT
Default automatic level (lowest).
static constexpr uint8_t POS_DEFAULT
Wire value for the default position command.
static constexpr uint8_t MANUFACTURER_OVERKIZ
OVERKIZ (Somfy connectivity platform).
static constexpr uint8_t CMD_ONEWAY_ADD_CONTROLLER
1W "add controller": a 1W device broadcasts this while its key-copy gesture is active,...
const char * command_result_name(uint8_t result)
Return a stable symbolic name for a CMD_ERROR_RESP result code.
static constexpr uint8_t DISCOVERY_FLAGS_ATT_MASK
Bit masks and shifts for the Multi Information Byte fields.
static constexpr uint8_t CMD_SET_NAME_RESP
Device-name write response.
static constexpr uint8_t RESULT_DEAD_BOLT_ERROR
Dead bolt error.
static constexpr uint8_t RESULT_NO_EXECUTION
Node did not move.
static constexpr uint16_t CRC_LSB_MASK
Least-significant-bit mask for reflected CRC update.
static constexpr uint8_t ATT_CLASS_20S
Response within 20 seconds.
static constexpr uint8_t ACEI_LEVEL_COMFORT_2
Comfort automation level 2.
static constexpr uint8_t DISCOVERY_RESP_FLAGS_OFFSET
Flags byte at data[6].
static constexpr uint8_t ORIGINATOR_SECURITY
Security controlling device (SCD) action.
static constexpr uint8_t ORIGINATOR_EMERGENCY
Emergency command (never disabled).
static constexpr uint8_t ACEI_SERVICE_SHIFT
Shift for service field extraction.
static constexpr uint8_t MANUFACTURER_ID_MAX
Maximum manufacturer ID with a known name in the lookup table.
static constexpr uint8_t RESULT_LIMITATION_BY_WIND
Parameter limited by a wind sensor.
static constexpr uint8_t RESULT_LIMITATION_BY_UPS
Parameter limited by a power supply.
static constexpr uint8_t CMD_DISCOVER_SPE_REQ
Broadcast roll-call answered by every device that already holds this controller's system key,...
static constexpr uint8_t CMD_EXECUTE
Set position/open/close/stop — requires authentication.
static constexpr uint8_t CMD_PRIVATE_RESP
Response to 0x00 and 0x03 (contains position data).
static constexpr uint8_t RESULT_LIMITATION_BY_USER
Parameter limited by a remote control.
static constexpr uint8_t RESULT_COMMAND_COMPLETED_OK
No errors detected.
static constexpr uint8_t ORIGINATOR_WIND_SENSOR
Wind sensor triggered the movement.
static constexpr uint8_t MANUFACTURER_ATLANTIC_GROUP
Atlantic Group (heating, hot water).
static constexpr uint8_t CMD_CHALLENGE_REQ
6-byte random challenge.
static constexpr uint8_t CMD_STATUS_UPDATE_RESP
Acknowledge status update.
static constexpr uint8_t RESULT_WRONG_POSITION
Node reports wrong position.
static constexpr uint8_t RESULT_COMMAND_INCOMPATIBLE_TO_MOVEMENT
Command cannot move the node that way.
static constexpr uint8_t ACEI_SERVICE_MASK
Bits [4:3]: service type.
static constexpr uint8_t ACEI_EXTENDED_MASK
Bits [2:1]: extended field.
static constexpr uint8_t RESULT_PRODUCT_NOT_OPERATIONAL
Node is not currently operational.
static constexpr uint8_t ATT_CLASS_5S
Actuator Turnaround Time (ATT) class values.
static constexpr uint8_t ATT_CLASS_10S
Response within 10 seconds.
const char * acei_level_name(uint8_t level)
Get a human-readable name for an ACEI priority level (0–7).
static constexpr uint8_t CMD_SET_NAME
Set device name (authenticated).
static constexpr uint8_t CMD_SET_CONFIG1_RESP
Config response.
static constexpr uint8_t CMD_LAUNCH_KEY_TRANSFER
Device-initiated ("pull") key transfer request.
static constexpr uint8_t DISCOVERY_FLAGS_SYNC_CTRL_GRP
Bit 5: supports sync control group.
static constexpr uint8_t CMD_DISCOVER_CONFIRM
Confirm discovery to device.
static constexpr uint8_t ACEI_LEVEL_SHIFT
Shift for priority level extraction.
static constexpr uint8_t CMD_ONEWAY_REMOVE
1W "remove controller" (un-pair a 1W remote from a device); same payload shape as 0x2E.
static constexpr uint8_t POS_FAVORITE
Wire value: move to favorite/"My" position.
static constexpr uint8_t STATUS_EXPECTED
Byte 1 bit 7: device will send auto status update.
static constexpr uint8_t CMD_SEND_RAW_MESSAGE
reference/iown-homecontrol heads this "Send Raw Message / Find Hardware ("Service")" — its own...
static constexpr uint8_t BROADCAST_DISCOVER[NODE_ID_SIZE]
Broadcast address for device discovery (0x00003B).
static constexpr uint8_t CMD_DISCOVER_RESP
Device responds with its ID and type.
static constexpr uint8_t RESULT_POWER_CONSUMPTION_TOO_LOW
Node power consumption is too low.
static constexpr uint8_t RESULT_FILTER_MAINTENANCE_NEEDED
Filter needs maintenance.
static constexpr uint8_t DISCOVERY_RESP_FULL_SIZE
Full discovery response payload size.
static constexpr uint8_t MANUFACTURER_ASSA_ABLOY
ASSA ABLOY (locks, access).
static constexpr uint8_t DISCOVERY_RESP_TIMESTAMP_OFFSET
Timestamp starts at data[7] (2 bytes).
static constexpr uint8_t RESULT_WRONG_LOAD_CONNECTED
Wrong load connected to node.
static constexpr uint8_t STATUS_TILT_SELECTOR
Extended status payload marker for tilt-capable devices.
static constexpr uint8_t MANUFACTURER_HORMANN
Hörmann (garage doors, gates).
static constexpr uint8_t CMD_READ_GROUPS
reference/iown-homecontrol heads this "Actuator: Read Groups / "ActuatorAnyConfigIsLocal" (?...
static constexpr uint8_t BROADCAST_DISCOVER_ALT[NODE_ID_SIZE]
Alternate discovery / 1W broadcast address (0x00003F).
uint8_t discovery_att_class(uint8_t flags)
Extract the ATT class field from a discovery response's Multi Information Byte.
static constexpr uint8_t DISCOVERY_FLAGS_ATT_SHIFT
Shift for ATT field extraction.
static constexpr uint8_t POWER_SAVE_LOW_POWER
Device sleeps — needs long preamble to wake.
static constexpr uint8_t CMD_SET_SENSOR_ACK
Acknowledgment to CMD_SET_SENSOR.
static constexpr uint8_t DISCOVERY_FLAGS_POWER_SAVE_MASK
Bits [1:0]: power save mode.
static constexpr uint8_t CMD_GET_GENERAL_INFO3
Observed on the wire (tests/corpus/captures/issues/) with no payload.
static constexpr uint8_t ORIGINATOR_RAIN_SENSOR
Rain sensor triggered the movement.
static constexpr uint8_t CMD_IDENTIFY
Device physical identification / jog — requires authentication.
static constexpr uint8_t RESULT_LIMITATION_BY_SAAC
Parameter limited by a standalone automatic controller.
static constexpr uint8_t CMD_PRIVATE
Get device status — no authentication needed.
static constexpr uint8_t MANUFACTURER_WINDOW_MASTER
WINDOW MASTER (ventilation).
static constexpr uint8_t RESULT_LIMITATION_BY_TIMER
Parameter limited by a timer.
static constexpr uint8_t CMD_PRIVATE2
Content otherwise undecoded by the wire parser.
static constexpr uint8_t AES_KEY_SIZE
AES-128 key size.
Definition proto_sizes.h:23
static constexpr uint8_t MANUFACTURER_SECUYOU
Secuyou (security).
static constexpr uint8_t CMD_GET_INFO2_RESP
Device type/model response.
static constexpr uint8_t RESULT_PRIORITY_LEVEL_LOCKED
Node is locked on this priority level.
static constexpr uint8_t ORIGINATOR_SAAC
Stand-alone automatic controller (SAAC).
static constexpr uint8_t POS_STOP
Position values in the IO protocol.
static constexpr uint8_t ORIGINATOR_USER_REMOTE
User sent command from a remote control.
static constexpr uint8_t CMD_CHALLENGE_RESP
HMAC proof answering a 0x3C.
bool is_limitation_result(uint8_t result)
Check whether a result code represents an environmental or control limitation.
static constexpr uint8_t CMD_GET_INFO2
Request device type/model info.
const char * originator_name(uint8_t originator)
Get a human-readable name for a command originator byte.
static constexpr uint8_t RESULT_UNKNOWN_STATUS_REPLY
Device returned an unknown status reply.
static constexpr uint8_t CMD_GET_INFO1
Request device general info 1 (unimplemented; we only use 0x56/0x57).
static constexpr uint8_t MANUFACTURER_SOMFY
Somfy (shutters, awnings, blinds).
static constexpr uint8_t ORIGINATOR_ENVIRONMENT
Unspecified environment sensor.
static constexpr uint8_t RESULT_LIMITS_NOT_SET
Device limits are not set.
static constexpr uint8_t CMD_REBOOT
reference/iown-homecontrol heads this "Reboot / Service Status" — two candidate names,...
static constexpr uint8_t RESULT_NODE_LOCKED
Node is locked.
static constexpr uint8_t RESULT_PRIORITY_LOCKED_NON_EXEC
Priority locked, command not executed (ACEI priority too low).
static constexpr uint8_t ORIGINATOR_TIMER
Timer or schedule triggered the movement.
static constexpr uint16_t CRC_POLYNOMIAL_REVERSED
Reversed CRC-CCITT polynomial used by IO-homecontrol.
static constexpr uint8_t RESULT_NO_CONTACT
No communication to node.
static constexpr uint8_t ORIGINATOR_SMART_CONTROLLER
Smart function controller.
static constexpr uint8_t STATUS_STOPPED
Status byte flags in CMD_PRIVATE_RESP and CMD_STATUS_UPDATE.
static constexpr uint8_t RESULT_BLOCKED
Node blocked by an object.
static constexpr uint8_t CMD_ADDRESS_REQ
Address assignment request.
static constexpr uint8_t RESULT_INFORMATION_CODE
Information-only code with unknown semantics.
static constexpr uint8_t ORIGINATOR_AUTOMATIC_CYCLE
Automatic cycle / external access.
static constexpr uint8_t RESULT_LIMITATION_BY_LOCAL_USER
Parameter limited by local button.
static constexpr uint8_t RESULT_TARGET_NOT_REACHABLE
Requested target not reachable.
static constexpr uint8_t ACEI_VALID_BIT
ACEI byte bit-field definitions.
static constexpr uint8_t RESULT_IP_NOT_SET
Intermediate position is not set.
static constexpr uint8_t POS_SECURED_TARGET
Wire value for the secured target position command.
static constexpr uint8_t CMD_UNKNOWN4A_RESP
Observed on the wire (tests/corpus/captures/issues/) answering an ON_OFF_SWITCH-type device's traffic...
static constexpr uint8_t ORIGINATOR_LOCAL_USER
Command originator codes indicating what or who triggered a command.
static constexpr uint8_t RESULT_LIMITATION_BY_SCD
Parameter limited by a security actuator.
Fundamental IO-Homecontrol frame and crypto size constants.