code wiki / (root) / nx_iot_watchdog.nx

nx_iot_watchdog.nx

buildroot/runtime/nx_iot_watchdog.nx

12214 B316 linesdepth 0pulls 0 transitivereach 1 importersview sourcekind librarytopic iot
docsdependenciesstructsconstsfunctions

about

nx_iot_watchdog.nx -- per-device link healer (closes the blink loop). Roadmap: NISHI_IOT_HUB_ROADMAP.md Epoch 5 (HEAL). The rung that turns "the light dropped + blinks + I re-pair it" into a fully automatic detect -> re-provision -> re-adopt cycle, with a MEASURED count of the manual re-pairs it spared the operator. THE PROBLEM THIS CLOSES (operator-reported): The anchor (WHO) gives a fixture one stable identity for life. The provision state machine (nx_iot_provision_softap) auto-pairs a fixture found in SoftAP mode with no manual step. This organ is the LOOP that ties them together over TIME: it watches each device's reachability, declares it down after a bounded run of missed heartbeats, recognises when it has reverted to pairing mode (the blink), kicks off re-provisioning, and marks it healthy again when the anchor re-adopts it. The blink loop is closed without a human. WHAT THIS ORGAN IS (and is NOT): A pure, deterministic per-device HEALTH state machine. It takes a reachability OBSERVATION each tick (seen / missed / found-in-pairing / re-adopted) and returns the ACTION the daemon should take (probe / mark-unreachable / re-provision / mark-current). It does NOT itself touch the network or the devices -- the daemon wires its actions to nx_iot_provision_softap (re-provision) and nx_iot_anchor (soft-delete / revive), keeping each primitive thin (feedback-hub-primitive-thin- per-site-wiring) + single-responsibility (CLAUDE.md #9). MEASURED-EXCEED HOOK (feedback-no-wave-measured-exceed; mirrors the anchor's duplicates_prevented): recover_count is the number of times the watchdog drove a fixture from RECOVERING back to HEALTHY by re-provisioning it -- i.e. the exact count of MANUAL re-pairs the operator did NOT have to do. The gate asserts it. NEVER-BRICK (CLAUDE.md #26): every action this organ emits is brick-safe -- probe is read-only, mark-unreachable/mark-current touch only the anchor REGISTRY (soft-delete/revive, additive #13), and re-provision delegates to nx_iot_provision_softap whose action alphabet is proven firmware-write-free. No watchdog action writes device firmware. genealogy_id: NISHI_IOT_HUB_ROADMAP.md Epoch 5 + project-iot-hub-multi-vendor-kickoff-2026-05-16

dependencies 0 imports · 1 importers

nx_iot_watchdog.nx nx_iot_watchdog_test.nx

imports: none

imported by: nx_iot_watchdog_test.nx

structs

131struct IotWatchdog

consts

63const WD_ST_HEALTHY: i64 = 0 // seen recently, reachable
64const WD_ST_MISSED: i64 = 1 // missed >=1 heartbeat (transient)
65const WD_ST_UNREACHABLE: i64 = 2 // missed >= threshold -> declared down
66const WD_ST_RECOVERING: i64 = 3 // found in pairing mode -> re-provisioning
67const WD_ST_N: i64 = 4
77const WD_OBS_NONE: i64 = 0
78const WD_OBS_SEEN: i64 = 1 // device replied / present on the LAN
79const WD_OBS_MISS: i64 = 2 // no reply this tick
80const WD_OBS_PAIRING: i64 = 3 // device found back in open pairing mode (the blink)
81const WD_OBS_READOPTED: i64 = 4 // provision+anchor re-adopted it (healed)
82const WD_OBS_N: i64 = 5
94const WD_ACT_NONE: i64 = 0
95const WD_ACT_PROBE: i64 = 1 // actively re-probe the device
96const WD_ACT_MARK_UNREACHABLE: i64 = 2 // anchor soft-delete (additive)
97const WD_ACT_REPROVISION: i64 = 3 // kick nx_iot_provision_softap
98const WD_ACT_MARK_CURRENT: i64 = 4 // anchor revive (re-adopt healthy)
99const WD_ACT_N: i64 = 5
127const NX_IOT_WD_MISS_THRESHOLD: i64 = 3

functions

69func nx_iot_wd_state_is_valid(v: i64) -> i64
called by 1: main
84func nx_iot_wd_obs_is_valid(v: i64) -> i64
101func nx_iot_wd_action_is_valid(v: i64) -> i64
110func nx_iot_wd_action_writes_firmware(act: i64) -> i64
119func nx_iot_wd_action_is_brick_safe(act: i64) -> i64
147func nx_iot_wd_init(w: *IotWatchdog, logical_id: i64,
called by 1: main
170func nx_iot_wd_observe(w: *IotWatchdog, obs: i64, now_ms: i64) -> i64
called by 1: main calls 1: nx_iot_wd_obs_is_valid
275func nx_iot_wd_state(w: *IotWatchdog) -> i64
called by 1: main
280func nx_iot_wd_action(w: *IotWatchdog) -> i64
285func nx_iot_wd_consec_misses(w: *IotWatchdog) -> i64
called by 1: main
290func nx_iot_wd_recover_count(w: *IotWatchdog) -> i64
called by 1: main
295func nx_iot_wd_tick_count(w: *IotWatchdog) -> i64
called by 1: main
300func nx_iot_wd_logical_id(w: *IotWatchdog) -> i64
called by 1: main
305func nx_iot_wd_is_healthy(w: *IotWatchdog) -> i64
called by 1: main
311func nx_iot_wd_is_down(w: *IotWatchdog) -> i64
called by 1: main