Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
hub_pairing.h
Go to the documentation of this file.
1#pragma once
2
3/// @file hub_pairing.h
4/// @brief Internal pairing-state model for hub‑owned discovery and key‑exchange flows.
5/// @ingroup hioc_hub
6///
7/// This header defines the state machine enum and context structures for the
8/// three‑phase pairing procedure (the flow itself is implemented by PairingEngine),
9/// which temporarily tracks a newly paired device in the controller's runtime
10/// registry and installs the system key on the device:
11///
12/// Phase 1 — Discovery (broadcast 0x28 → device responds 0x29 → confirm 0x2C → ack 0x2D):
13/// Controller broadcasts a discovery packet on the primary channel. A device in
14/// pairing mode (PROG button pressed) responds with its node ID and type/subtype.
15/// The controller validates the response and extracts device metadata, then sends a
16/// discover-confirm (0x2C) directly to that device and — unless the `pairing_discover_confirm`
17/// tuning mode is `skip` — waits up to a few seconds for its 0x2D before proceeding. This step
18/// never fails the attempt; see PairingEngine::run_discover_confirm_step_().
19///
20/// Phase 2 — Authenticated Key Exchange (0x31 → 0x3C → 0x32 → 0x33):
21/// The controller sends CMD_KEY_INIT (0x31) to the device. The device challenges
22/// with CMD_CHALLENGE_REQ (0x3C). The controller proves knowledge of the system
23/// key with CMD_CHALLENGE_RESP (0x3D) and simultaneously sends the encrypted system
24/// key via CMD_KEY_TRANSFER (0x32). The device confirms with CMD_KEY_CONFIRM (0x33).
25///
26/// Phase 3 — Configuration (CMD_SET_CONFIG1):
27/// The controller sends a configuration frame (0x6F) to enable automatic status
28/// updates from the device. This phase completes even if the config frame fails;
29/// the device will still operate in polled mode.
30///
31/// All frames use the standard authenticated exchange flow (state types in
32/// hub_exchange.h, implementation in ExchangeEngine). PairingEngine serializes these
33/// phases, logs the YAML metadata the user should add, and keeps the paired device
34/// in the current runtime registry until reboot.
35
36#include "proto_device_model.h"
37#include "proto_frame.h"
38#include "radio_interface.h"
39#include <cstdint>
40#include <string>
41
42namespace esphome {
43namespace home_io_control {
44
45namespace pairing {
46
47/// @brief State machine for the three‑phase pairing flow.
48enum class PairingState : uint8_t {
49 IDLE, ///< No pairing in progress; idle state.
50 TX_DISCOVER, ///< Discovery broadcast (0x28) sent; awaiting device response.
51 WAIT_DISCOVER_RESPONSE, ///< Listening for discovery response (0x29) from a device in pairing mode.
52 TX_DISCOVER_CONFIRM, ///< Discovery-confirm (0x2C) sent to the discovered device.
53 WAIT_DISCOVER_CONFIRM, ///< Listening for the device's discovery-confirm ack (0x2D).
54 TX_KEY_INIT, ///< Key‑init (0x31) sent to the discovered device.
55 WAIT_KEY_CHALLENGE, ///< Waiting for challenge (0x3C) from device as part of key transfer.
56 TX_KEY_TRANSFER, ///< Key‑transfer (0x32) sent with encrypted system key.
57 WAIT_KEY_CONFIRM, ///< Waiting for key‑confirm (0x33) from device (key receipt acknowledgement).
58 REGISTER_DEVICE, ///< Registering device in the runtime registry for the current boot.
59 COMPLETE, ///< Pairing completed successfully; device ready for use.
60 FAILED, ///< Pairing failed (timeout, radio error, or protocol violation).
61};
62
63/// @brief Context object that lives for the duration of a single pairing attempt.
65 PairingState state{PairingState::IDLE}; ///< Current state machine state.
66 IoDevice device{}; ///< Resolved device metadata after discovery (node_id, type, subtype, etc.).
67 IoFrame req{}; ///< Outbound frame buffer (reused across all phases).
68 IoFrame resp{}; ///< Inbound frame buffer (holds key‑confirm response).
69 IoFrame rx{}; ///< Raw RX frame during waiting phases (discovery, challenge, confirm).
70 IoFrame key_init{}; ///< Key‑init frame retained for key‑transfer IV derivation.
71 RadioRxPacket packet{}; ///< Raw radio capture for the current phase.
72 std::string device_id; ///< Hex string representation of the paired node ID.
73 bool discovery_metadata_complete{false}; ///< True when discovery carried type/subtype bytes.
74 bool discovery_low_power{false}; ///< True when discovery reported POWER_SAVE_LOW_POWER.
75};
76
77/// @brief What PairingEngine::run_discover_confirm_step_() actually observed.
78///
79/// Not stored in PairingContext — nothing downstream reads it, so it is returned directly to the
80/// caller, which logs the details (reply channel, try number, elapsed time) and otherwise ignores
81/// the result: the step never fails a pairing attempt (see run_discover_confirm_step_()'s doc).
82enum class DiscoverConfirmResult : uint8_t {
83 SKIPPED, ///< `pairing_discover_confirm` tuning mode is `skip` — no 0x2C was sent.
84 ACKED, ///< The device answered with CMD_DISCOVER_CONFIRM_ACK (0x2D).
85 ERROR_REPLY, ///< The device answered with CMD_ERROR_RESP.
86 NO_REPLY, ///< Every try was silent (or every transmit failed).
87};
88
89} // namespace pairing
90
91/// @brief Get a short, log/telemetry-friendly name for a pairing state.
92/// @param state Pairing state.
93/// @return Null-terminated lowercase string such as "wait_key_challenge".
94inline const char *pairing_stage_name(pairing::PairingState state) {
95 switch (state) {
97 return "idle";
99 return "tx_discover";
101 return "wait_discover_response";
103 return "tx_discover_confirm";
105 return "wait_discover_confirm";
107 return "tx_key_init";
109 return "wait_key_challenge";
111 return "tx_key_transfer";
113 return "wait_key_confirm";
115 return "register_device";
117 return "complete";
119 default:
120 return "failed";
121 }
122}
123
124} // namespace home_io_control
125} // namespace esphome
DiscoverConfirmResult
What PairingEngine::run_discover_confirm_step_() actually observed.
Definition hub_pairing.h:82
@ ERROR_REPLY
The device answered with CMD_ERROR_RESP.
Definition hub_pairing.h:85
@ SKIPPED
pairing_discover_confirm tuning mode is skip — no 0x2C was sent.
Definition hub_pairing.h:83
@ NO_REPLY
Every try was silent (or every transmit failed).
Definition hub_pairing.h:86
@ ACKED
The device answered with CMD_DISCOVER_CONFIRM_ACK (0x2D).
Definition hub_pairing.h:84
PairingState
State machine for the three‑phase pairing flow.
Definition hub_pairing.h:48
@ REGISTER_DEVICE
Registering device in the runtime registry for the current boot.
Definition hub_pairing.h:58
@ TX_DISCOVER
Discovery broadcast (0x28) sent; awaiting device response.
Definition hub_pairing.h:50
@ WAIT_DISCOVER_RESPONSE
Listening for discovery response (0x29) from a device in pairing mode.
Definition hub_pairing.h:51
@ COMPLETE
Pairing completed successfully; device ready for use.
Definition hub_pairing.h:59
@ TX_DISCOVER_CONFIRM
Discovery-confirm (0x2C) sent to the discovered device.
Definition hub_pairing.h:52
@ WAIT_KEY_CHALLENGE
Waiting for challenge (0x3C) from device as part of key transfer.
Definition hub_pairing.h:55
@ WAIT_KEY_CONFIRM
Waiting for key‑confirm (0x33) from device (key receipt acknowledgement).
Definition hub_pairing.h:57
@ TX_KEY_INIT
Key‑init (0x31) sent to the discovered device.
Definition hub_pairing.h:54
@ TX_KEY_TRANSFER
Key‑transfer (0x32) sent with encrypted system key.
Definition hub_pairing.h:56
@ IDLE
No pairing in progress; idle state.
Definition hub_pairing.h:49
@ FAILED
Pairing failed (timeout, radio error, or protocol violation).
Definition hub_pairing.h:60
@ WAIT_DISCOVER_CONFIRM
Listening for the device's discovery-confirm ack (0x2D).
Definition hub_pairing.h:53
@ FAILED
No usable reply; the device may never have heard the request.
const char * pairing_stage_name(pairing::PairingState state)
Get a short, log/telemetry-friendly name for a pairing state.
Definition hub_pairing.h:94
IO-Homecontrol device-type model, capabilities and runtime device state.
IO-Homecontrol 2W frame container: control bytes, IoFrame and (de)serialization.
Radio abstraction layer for IO-Homecontrol.
Runtime state of a paired IO‑Homecontrol device.
Parsed IO‑Homecontrol frame (CTRL0/1 + addresses + command + data).
Definition proto_frame.h:93
Raw packet received from the radio.
Context object that lives for the duration of a single pairing attempt.
Definition hub_pairing.h:64
IoFrame req
Outbound frame buffer (reused across all phases).
Definition hub_pairing.h:67
bool discovery_low_power
True when discovery reported POWER_SAVE_LOW_POWER.
Definition hub_pairing.h:74
PairingState state
Current state machine state.
Definition hub_pairing.h:65
IoFrame resp
Inbound frame buffer (holds key‑confirm response).
Definition hub_pairing.h:68
RadioRxPacket packet
Raw radio capture for the current phase.
Definition hub_pairing.h:71
IoDevice device
Resolved device metadata after discovery (node_id, type, subtype, etc.).
Definition hub_pairing.h:66
IoFrame key_init
Key‑init frame retained for key‑transfer IV derivation.
Definition hub_pairing.h:70
std::string device_id
Hex string representation of the paired node ID.
Definition hub_pairing.h:72
bool discovery_metadata_complete
True when discovery carried type/subtype bytes.
Definition hub_pairing.h:73
IoFrame rx
Raw RX frame during waiting phases (discovery, challenge, confirm).
Definition hub_pairing.h:69