Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
esphome::home_io_control::KeyExtractionResponder Class Reference

Device-role responder for the "Recover System Key" feature. More...

#include <key_extraction_responder.h>

Collaboration diagram for esphome::home_io_control::KeyExtractionResponder:

Public Member Functions

 KeyExtractionResponder (const uint8_t *node_id, RadioDriver **radio, const TuningConfig *tuning, DeviceRegistry &registry, TransmitFrameFn transmit, NamedTimeoutFn schedule_auto_off)
 KeyExtractionResponder (const KeyExtractionResponder &)=delete
 Non-copyable — holds injected callbacks and references into hub member addresses.
KeyExtractionResponderoperator= (const KeyExtractionResponder &)=delete
void set_armed (bool armed)
 Arm or disarm the "Recover System Key" (key extraction) responder.
void set_armed_callback (std::function< void(bool)> cb)
 Register a callback invoked whenever the key-extraction armed state changes — manual toggle, successful extraction, or auto-off timeout — so the switch entity can keep its displayed state in sync when the responder disarms itself rather than the user.
bool try_handle_frame (const IoFrame &frame)
 Dispatch a frame to the responder if it's one of its 0x28/0x2C/0x31/0x32/0x36/0x3C frames and the responder is armed.
void generate_throwaway_id (uint8_t out[NODE_ID_SIZE])
 Generate a random throwaway node ID for one key-extraction arm cycle, avoiding collisions with the broadcast addresses, this hub's own real node ID, and any registered device.
void arm_post_extraction_grace ()
 (Re)arm the post-extraction grace window that replaces the old immediate disarm-on-extraction: called once when the key is first recovered, and again on every sign of hub progress after that (an inbound 0x36, an outbound 0x3D) so a slow multi-retry hub isn't cut off mid-round.
bool awaiting_reply () const
 True whenever the responder has replied at least once, is waiting on the hub's next step, and that wait is still within its bounded hold window — i.e.

Public Attributes

pairing_responder::ResponderContext key_extraction_ctx_
 State for the current "Accept Foreign Pairing" (key-extraction) arm cycle; DISARMED by default so a fresh boot never responds to foreign pairing traffic.
uint32_t key_extraction_hold_deadline_ms_ {0}
 Deadline (millis()) until which loop() should hold CH2 for the key-extraction responder, deliberately independent of key_extraction_ctx_.state itself.

Detailed Description

Device-role responder for the "Recover System Key" feature.

Constructed once by IOHomeControlComponent; non-copyable because it is wired with injected callbacks and references into hub member addresses (mirrors ManagementActions / ExchangeEngine).

Definition at line 36 of file key_extraction_responder.h.

Constructor & Destructor Documentation

◆ KeyExtractionResponder() [1/2]

esphome::home_io_control::KeyExtractionResponder::KeyExtractionResponder ( const uint8_t * node_id,
RadioDriver ** radio,
const TuningConfig * tuning,
DeviceRegistry & registry,
TransmitFrameFn transmit,
NamedTimeoutFn schedule_auto_off )
Parameters
node_idHub's real 3-byte node ID (throwaway-ID collision check).
radioDouble pointer to the hub's active radio driver, so a test's comp.radio_ = &mock propagates (mirrors ExchangeEngine).
tuningRuntime tuning config, owned by the hub (cold_broadcast_reply_preamble).
registryDevice registry, for the throwaway-ID collision check only.
transmitHow to put a reply frame on air (see TransmitFrameFn).
schedule_auto_offNamed-timeout scheduler for the 10-minute arm window and the post-extraction grace window (see NamedTimeoutFn).

Definition at line 114 of file key_extraction_responder.cpp.

◆ KeyExtractionResponder() [2/2]

esphome::home_io_control::KeyExtractionResponder::KeyExtractionResponder ( const KeyExtractionResponder & )
delete

Non-copyable — holds injected callbacks and references into hub member addresses.

Here is the call graph for this function:

Member Function Documentation

◆ arm_post_extraction_grace()

void esphome::home_io_control::KeyExtractionResponder::arm_post_extraction_grace ( )

(Re)arm the post-extraction grace window that replaces the old immediate disarm-on-extraction: called once when the key is first recovered, and again on every sign of hub progress after that (an inbound 0x36, an outbound 0x3D) so a slow multi-retry hub isn't cut off mid-round.

Uses the same named-timer replace-on-reschedule idiom as the 10-minute auto-off timer — see key_extraction_responder.cpp for why a naive "only disarm if DISARMED" guard inside the callback is not enough once a manual disarm-and-rearm can happen inside the window.

Definition at line 411 of file key_extraction_responder.cpp.

Here is the call graph for this function:

◆ awaiting_reply()

bool esphome::home_io_control::KeyExtractionResponder::awaiting_reply ( ) const
inlinenodiscard

True whenever the responder has replied at least once, is waiting on the hub's next step, and that wait is still within its bounded hold window — i.e.

key_extraction_ctx_.state is neither DISARMED (feature unused) nor ARMED_IDLE (armed, but no discovery request seen yet), AND key_extraction_hold_deadline_ms_ has not yet passed. loop() uses this to hold CH2 instead of running the generic idle-hop scan, and to defer background status polls, while an attempt is in flight.

The deadline is a plain timestamp, not a named set_timeout() timer: releasing the CH2 hold is purely a radio-scheduling optimization (see key_extraction_hold_deadline_ms_'s own doc comment for why it is deliberately decoupled from key_extraction_ctx_.state itself), so nothing needs to fire a callback when it lapses — the next loop() iteration simply stops taking the CH2-hold branch on its own. Default-constructed, the deadline is 0, which is always in the past relative to any real millis() reading once the device has been running — so a mid-exchange state reached without the deadline having been (re)set (e.g. a reply-builder failure between the state guard and the deadline update) safely never holds CH2, rather than holding it unboundedly.

Defined inline: defer_background_poll_() calls this every loop() iteration.

Definition at line 112 of file key_extraction_responder.h.

◆ generate_throwaway_id()

void esphome::home_io_control::KeyExtractionResponder::generate_throwaway_id ( uint8_t out[NODE_ID_SIZE])

Generate a random throwaway node ID for one key-extraction arm cycle, avoiding collisions with the broadcast addresses, this hub's own real node ID, and any registered device.

Parameters
outOutput: 3-byte node ID.

Definition at line 124 of file key_extraction_responder.cpp.

Here is the call graph for this function:

◆ operator=()

KeyExtractionResponder & esphome::home_io_control::KeyExtractionResponder::operator= ( const KeyExtractionResponder & )
delete
Here is the call graph for this function:

◆ set_armed()

void esphome::home_io_control::KeyExtractionResponder::set_armed ( bool armed)

Arm or disarm the "Recover System Key" (key extraction) responder.

Arming picks a fresh throwaway node ID, resets the pairing_responder state machine to ARMED_IDLE, and schedules a 10-minute auto-off. While armed, the 0x28/0x2C/0x31/0x32 branches in process_received_packet_() emulate an unpaired device so a user's existing hub can pair to it and hand over its node_id/system_key (see pairing_responder.h). Disarming — manual, via the HA switch, on successful extraction, or on auto-off — immediately stops those branches from responding; it never touches the real device registry or the hub's own node_id_/ system_key_. This is the body that was IOHomeControlComponent::set_key_extraction_armed().

Parameters
armedDesired state.

Definition at line 144 of file key_extraction_responder.cpp.

Here is the call graph for this function:

◆ set_armed_callback()

void esphome::home_io_control::KeyExtractionResponder::set_armed_callback ( std::function< void(bool)> cb)
inline

Register a callback invoked whenever the key-extraction armed state changes — manual toggle, successful extraction, or auto-off timeout — so the switch entity can keep its displayed state in sync when the responder disarms itself rather than the user.

Single-slot.

Parameters
cbCallable receiving the new armed state.

Definition at line 70 of file key_extraction_responder.h.

◆ try_handle_frame()

bool esphome::home_io_control::KeyExtractionResponder::try_handle_frame ( const IoFrame & frame)
nodiscard

Dispatch a frame to the responder if it's one of its 0x28/0x2C/0x31/0x32/0x36/0x3C frames and the responder is armed.

Kept a separate function (rather than inlined into process_received_packet_()) purely to keep that function's cognitive complexity under the clang-tidy threshold, mirroring PairingEngine::record_discovery_rx_telemetry_()'s reason for existing.

Parameters
frameParsed inbound frame.
Returns
true if the frame was handled (caller should stop further dispatch for it).

Definition at line 190 of file key_extraction_responder.cpp.

Member Data Documentation

◆ key_extraction_ctx_

pairing_responder::ResponderContext esphome::home_io_control::KeyExtractionResponder::key_extraction_ctx_

State for the current "Accept Foreign Pairing" (key-extraction) arm cycle; DISARMED by default so a fresh boot never responds to foreign pairing traffic.

See pairing_responder.h. Public so the host tests that script individual RX branches can preset and inspect it.

Definition at line 121 of file key_extraction_responder.h.

◆ key_extraction_hold_deadline_ms_

uint32_t esphome::home_io_control::KeyExtractionResponder::key_extraction_hold_deadline_ms_ {0}

Deadline (millis()) until which loop() should hold CH2 for the key-extraction responder, deliberately independent of key_extraction_ctx_.state itself.

Set (not "armed" — this is a plain timestamp, not a named set_timeout() timer) on every sign of hub progress: the three pre-extraction reply handlers (handle_discover_(), handle_discover_confirm_(), handle_key_init_(), key_extraction_responder.cpp) push it out by KEY_EXTRACTION_MID_ATTEMPT_TIMEOUT_MS, and arm_post_extraction_grace() pushes it out by KEY_EXTRACTION_POST_EXTRACT_GRACE_MS so the hold also covers the (much longer) post-extraction address-verification phase it governs.

Deliberately independent of key_extraction_ctx_.state: the pure guards in pairing_responder.cpp decide whether an inbound frame is accepted by checking state alone, never this deadline, so a real (slower) hub's next frame still completes the exchange correctly even if it arrives after the hold has expired. Coupling the two — letting the deadline also force state back to ARMED_IDLE — would silently discard that live protocol progress instead of just releasing the radio hold. See awaiting_reply()'s doc comment for how this is consumed.

Definition at line 138 of file key_extraction_responder.h.


The documentation for this class was generated from the following files: