Summary
The per-node MQTT entities presence (binary) and presence_score do not reflect the individual node's state — they carry an array-global value stamped into each node's snapshot. The engine demonstrably computes per-node state (visible in /ws/sensing → sensing_update.node_features[]), but what reaches the per-node MQTT topics makes room-level attribution impossible for any multi-node deployment consuming the Home Assistant integration.
Environment
- Docker image
ruvnet/wifi-densepose:v2051 (--features mqtt), host networking
- 5× M5Stack Atom S3 Lite (
esp32-csi-node) in five different rooms of a residential deployment, one node per room
- Independent per-room ground truth (mmWave presence + PIR sensors in a separate Home Assistant) used to label the observations below
Observation 1 — per-node presence binaries publish in lockstep
Over a 21 h capture, all five per-node binary_sensor .../presence/state topics published identical transition streams: 52,916 transitions each, same timestamps, same intervals — including sub-second flaps (peaks ~42 transitions/min). Rooms were occupied/empty in completely different patterns per ground truth. The value appears to be the array-level presence copied into every node snapshot.
Observation 2 — per-node presence_score excursions are ~fully correlated across nodes
With the rate-limiter starvation fixed locally (#1540) so all five nodes publish at an equal 2 Hz (~82k samples/node overnight):
- Score distributions are identical across all five nodes in every condition (occupied room, empty room, whole house asleep): median ≈ 50, p95 ≈ 53.4, ~2 % of samples ≥ 65.
- Sustained excursions (score ≥ 65 held ≥ 60 s) fire simultaneously across nodes: of 112 sustained-episode clusters in one night, 41 spanned all five nodes with near-identical start/end times; only 29 were single-node.
- Pairwise Pearson correlation of 30-second mean score between nodes, during 6.7 h in which ground truth confirms the entire household asleep in one room: +0.62 to +0.89 for every pair.
- Per ground truth, each node produced ~35–45 sustained 1–3 min "presence" episodes in that window with its room verifiably empty.
The per-sample values do differ slightly between nodes (noise), but the dynamics are a common component — so neither single-node thresholds nor cross-node comparison can attribute presence to a room from these topics.
The engine has the per-node data
/ws/sensing sensing_update.node_features[] carries genuinely per-node classification (nodes concurrently report e.g. present_still vs present_moving, with per-node variance/band-power features). It appears the MQTT snapshot path (VitalsSnapshot construction) receives array-global presence / presence_score values rather than that node's own state.
Expected
Per-node MQTT topics reflect the node's own presence/score (as node_features does on the WebSocket), so that a one-node-per-room deployment can do room-level presence in Home Assistant.
Related: #1540 (rate limiter; fixing it is what made this measurable at equal rates).
Summary
The per-node MQTT entities
presence(binary) andpresence_scoredo not reflect the individual node's state — they carry an array-global value stamped into each node's snapshot. The engine demonstrably computes per-node state (visible in/ws/sensing→sensing_update.node_features[]), but what reaches the per-node MQTT topics makes room-level attribution impossible for any multi-node deployment consuming the Home Assistant integration.Environment
ruvnet/wifi-densepose:v2051(--features mqtt), host networkingesp32-csi-node) in five different rooms of a residential deployment, one node per roomObservation 1 — per-node
presencebinaries publish in lockstepOver a 21 h capture, all five per-node
binary_sensor .../presence/statetopics published identical transition streams: 52,916 transitions each, same timestamps, same intervals — including sub-second flaps (peaks ~42 transitions/min). Rooms were occupied/empty in completely different patterns per ground truth. The value appears to be the array-level presence copied into every node snapshot.Observation 2 — per-node
presence_scoreexcursions are ~fully correlated across nodesWith the rate-limiter starvation fixed locally (#1540) so all five nodes publish at an equal 2 Hz (~82k samples/node overnight):
The per-sample values do differ slightly between nodes (noise), but the dynamics are a common component — so neither single-node thresholds nor cross-node comparison can attribute presence to a room from these topics.
The engine has the per-node data
/ws/sensingsensing_update.node_features[]carries genuinely per-node classification (nodes concurrently report e.g.present_stillvspresent_moving, with per-node variance/band-power features). It appears the MQTT snapshot path (VitalsSnapshotconstruction) receives array-globalpresence/presence_scorevalues rather than that node's own state.Expected
Per-node MQTT topics reflect the node's own presence/score (as
node_featuresdoes on the WebSocket), so that a one-node-per-room deployment can do room-level presence in Home Assistant.Related: #1540 (rate limiter; fixing it is what made this measurable at equal rates).