21constexpr size_t ADVICE_MESSAGE_BUFFER_SIZE = 224;
47 uint8_t occurrences = 0;
48 for (uint8_t i = 0; i < event_count; i++) {
49 if (is_rx_kind(events[i].kind) && !is_seeded_sighting(events[i]) &&
60 if (!is_rx_kind(event.
kind) || !is_oneway_pairing_frame(event))
65 advice.
rssi =
event.rssi;
74 for (uint8_t i = 0; i < event_count; i++) {
76 if (!is_rx_kind(event.
kind) || is_seeded_sighting(event))
78 if (count_occurrences_of_source(events, event_count, event.
src_node) < 2)
83 advice.
rssi =
event.rssi;
90 static const uint8_t ZERO_NODE_ID[
NODE_ID_SIZE] = {0, 0, 0};
94 if (memcmp(own_node_id, ZERO_NODE_ID,
NODE_ID_SIZE) == 0)
105 advice.
rssi =
event.rssi;
116 const uint8_t event_count = telemetry.
event_count();
118 append_one_way_pairing_advice(events, event_count, out, count);
119 append_channel_busy_advice(telemetry, events, event_count, out, count);
120 append_foreign_controller_advice(own_node_id, events, event_count, out, count);
134 return "channel_busy";
136 return "foreign_controller";
146 char buf[ADVICE_MESSAGE_BUFFER_SIZE];
147 switch (advice.
code) {
149 snprintf(buf,
sizeof(buf),
150 "A 1W remote (src %s) is performing 1W pairing. The motor is NOT in 2W learning mode - a PROG "
151 "press on a 1W remote does not enable 2W discovery. Use the Double Power Cut procedure to force "
154 return std::string(buf);
156 snprintf(buf,
sizeof(buf),
157 "Channel busy (device %s beaconing at %d dBm); discovery TX was delayed by listen-before-talk.",
159 return std::string(buf);
161 snprintf(buf,
sizeof(buf),
"Another controller is pairing device %s right now.",
163 return std::string(buf);
165 return "Nothing heard on any channel during the whole discovery window - check the antenna/RF path before "
166 "assuming the device isn't in pairing mode.";
Fixed-size per-attempt telemetry recorder for the pairing flow.
uint8_t event_count() const
uint16_t heard_count() const
const PairingTelemetryEvent * events() const
uint8_t lbt_retries() const
Pure transition helpers for hub-owned exchange and pairing frame decisions.
std::string pairing_advice_message(const PairingAdvice &advice)
static constexpr uint8_t PAIRING_ADVICE_MAX
Maximum number of advice entries a single attempt can produce (one slot per non-NONE code).
const char * pairing_advice_code_name(PairingAdviceCode code)
PairingAdviceCode
Actionable diagnosis derived from a completed pairing attempt's telemetry.
@ RF_SILENT
Nothing at all was heard during the whole window.
@ NONE
Nothing actionable to report.
@ FOREIGN_CONTROLLER_PAIRING
A discovery response was seen addressed to another controller.
@ ONE_WAY_PAIRING_TRAFFIC
A 1W remote is pairing to the target — not 2W learning mode.
@ CHANNEL_BUSY_LBT_DELAYED
LBT retries were consumed while a source kept repeating; the reported subject_node is a best-effort c...
uint8_t analyze_pairing_telemetry(const PairingTelemetry &telemetry, const uint8_t own_node_id[NODE_ID_SIZE], PairingAdvice out[PAIRING_ADVICE_MAX])
Inspect a completed pairing attempt's telemetry and produce actionable advice.
bool is_one_way_pairing_gesture(bool oneway, const uint8_t dst[NODE_ID_SIZE], uint8_t cmd)
True if a frame's shape matches a 1W remote's pairing gesture (issue #27/#65): CTRL0 1W bit set,...
static constexpr uint8_t NODE_ID_SIZE
Device/node addresses are 3 bytes (e.g., "123ABC").
PairingTelemetryEventKind
Kind of a recorded telemetry event.
@ RX_REJECT
We received a frame that parsed but was rejected (wrong source, wrong command, etc....
@ RX
We received and accepted a frame for the current wait (including a seeded pre-window sighting — see P...
static constexpr uint8_t LBT_MAX_RETRIES
Max carrier-sense attempts before TX anyway.
std::string node_id_to_string(const uint8_t id[NODE_ID_SIZE])
Format a 3‑byte node ID as a 6‑character uppercase hex string.
static constexpr uint8_t CMD_DISCOVER_RESP
Device responds with its ID and type.
Read-only advisor that turns PairingTelemetry into actionable diagnostics.
IO-Homecontrol command IDs, result codes and protocol enumerations.
Physical-layer radio and timing parameters for the IO-Homecontrol protocol.
One recorded telemetry event.
uint8_t cmd
Frame command byte (TX/RX/RX_REJECT); unused otherwise.
PairingTelemetryEventKind kind
What happened.
bool oneway
CTRL0 1W-protocol bit (RX/RX_REJECT only); false otherwise.
uint8_t dst_node[NODE_ID_SIZE]
Destination node ID (RX/RX_REJECT only); zero otherwise.
uint8_t src_node[NODE_ID_SIZE]
Sender node ID (RX/RX_REJECT only); zero otherwise.
One piece of advice, with the node/RSSI it pertains to (if any).
uint8_t subject_node[NODE_ID_SIZE]
Node the advice is about; zero if not applicable.
int16_t rssi
RSSI associated with the observation; zero if not applicable.