171 void record_debug(
const char *stage, uint8_t tries,
bool saw_challenge);
175 void log_debug(
const char *device_id)
const;
184 bool transmit_request_(
const IoFrame &request, uint32_t freq, uint16_t preamble,
201 const uint8_t *node_id_;
202 const uint8_t *system_key_;
208 uint32_t last_hop_us_{0};
std::function< void(const IoFrame &frame, int16_t rssi_dbm)> BroadcastReplyHandler
Invoked for each matching broadcast reply, as it arrives.
void hop_frequency()
Advance to the next IO-Homecontrol channel (CH1→CH2→CH3→CH1).
void maybe_hop()
Unconditionally hop only if the minimum dwell has elapsed.
void reset_debug(uint8_t request_cmd)
Clear the debug snapshot and record the upcoming request command.
uint8_t collect_broadcast_responses(const IoFrame &request, uint32_t freq, uint8_t expected_cmd, uint32_t window_ms, const BroadcastReplyHandler &on_reply)
Transmit request once and hand every matching broadcast reply to on_reply within window_ms.
void log_debug(const char *device_id) const
Log the debug snapshot as a WARN-level structured line.
const DebugInfo & get_debug() const
Read-only access to the current debug snapshot.
void set_pairing_telemetry(PairingTelemetry *telemetry)
Attach a telemetry recorder so transmit_frame()'s LBT loop records defer events.
ExchangeEngine(RadioDriver **radio_ptr, const uint8_t *node_id, const uint8_t *system_key, const TuningConfig *tuning)
Construct the engine with double-pointer indirection into the hub's RadioDriver pointer and direct po...
bool transmit_frame(const IoFrame &frame, uint32_t freq, uint16_t preamble)
Transmit a raw IoFrame with LBT and the given preamble length.
bool authenticate_request(const IoFrame &request, uint32_t freq)
Authenticate an inbound device command via 0x3C challenge / 0x3D HMAC.
bool send_and_receive(const IoFrame &request, IoFrame &response, uint32_t freq)
Execute an outbound authenticated exchange with retry.
void reset_hop_timestamp()
Reset the hop-timer (called after radio init in hub setup()).
ExchangeEngine & operator=(const ExchangeEngine &)=delete
ExchangeEngine(const ExchangeEngine &)=delete
void record_debug(const char *stage, uint8_t tries, bool saw_challenge)
Update the debug snapshot with the current stage and radio capture.
Fixed-size per-attempt telemetry recorder for the pairing flow.
Abstract radio driver for IO-Homecontrol.
Pure transition helpers for hub-owned exchange and pairing frame decisions.
Internal exchange-state model for hub-owned authenticated non‑pairing flows.
ExchangeFinalResponseDisposition
Disposition for the final response after authentication.
ExchangeFirstResponseDisposition
Disposition for the first response in an authenticated exchange.
Structured per-attempt telemetry recorder for the pairing flow.
IO-Homecontrol 2W frame container: control bytes, IoFrame and (de)serialization.
Physical-layer radio and timing parameters for the IO-Homecontrol protocol.
Radio abstraction layer for IO-Homecontrol.
Snapshot of the last exchange attempt for diagnostics.
bool saw_challenge
True if a 0x3C was seen during this exchange.
uint8_t capture_reported_len
Length reported by radio packet engine.
int16_t capture_rssi_dbm
RSSI of the captured packet (dBm).
bool capture_crc_error
True if CRC error flagged (chip-dependent; see RadioCaptureInfo::crc_error).
uint8_t tries
Retry count (1-based).
uint16_t capture_irq_status
Raw IRQ register value.
uint8_t capture_frame_len
Parsed protocol frame length.
uint8_t capture_packet_status
Chip packet-status byte.
bool capture_valid
True if radio capture is meaningful.
uint8_t request_cmd
Command ID of the original request.
bool capture_rx_done
True if RxDone IRQ fired.
const char * stage
Last recorded stage label.
uint32_t capture_freq_hz
RF frequency of the captured packet.
Parsed IO‑Homecontrol frame (CTRL0/1 + addresses + command + data).
All runtime tunable parameters for pairing and radio diagnostics.
Context carried across one outbound authenticated exchange.
Runtime tuning configuration for pairing and radio diagnostics.