Skip to content

Multi-node deployments collapse into a single Home-Assistant device — MQTT discovery hard-codes node_id to 1, contradicting the "one device per node" docs #898

@mschabhuettl

Description

@mschabhuettl

Bug Report

Description

After the MQTT wiring fix (PR #874, ghcr.io/ruvnet/wifi-densepose:latest,
image Created: 2026-05-31T15:44:26Z), --mqtt works and the publisher
starts — but every node is published as the same Home-Assistant device
wifi_densepose_wifi-densepose-1, regardless of how many physical ESP32 nodes
are sending CSI frames.

This contradicts docs/integrations/home-assistant.md, which states the
integration creates one device per RuView node.

Expected behaviour

With N nodes provisioned with distinct node-ids/zones, Home Assistant should
auto-discover N devices (one per node/room), each with its own presence /
person-count / motion entities — as the documentation promises.

Actual behaviour

All nodes are merged into a single device with a hard-coded identifier:

"identifiers":["wifi_densepose_wifi-densepose-1"]   "name":"RuView"

The broker logs confirm the publisher connects as a single fixed client:

New client connected ... as wifi-densepose-1 (p4, c1, k30, u'mqtt').
[mqtt] publisher started host=127.0.0.1 port=1883 prefix=homeassistant entities=20 privacy=false

entities=20 = one device, 20 entities — never per-node.

Key contrast: the REST API DOES separate the nodes

The same server's REST endpoint correctly distinguishes every node, with
independent state per node_id:

GET http://<server>:3000/api/v1/nodes
{
  "nodes": [
    { "node_id": 1, "status": "active", "motion_level": "absent",        "person_count": 1 },
    { "node_id": 2, "status": "active", "motion_level": "present_still",  "person_count": 1 }
  ],
  "total": 2
}

So the per-node data exists internally — only the MQTT discovery/publisher
throws it away and emits a single fixed node_id = 1.

Steps to reproduce

  1. Provision two (or more) ESP32 nodes with distinct node-ids/zones, all
    targeting the same sensing-server (--source esp32, UDP 5005).
  2. Run ghcr.io/ruvnet/wifi-densepose:latest with
    --mqtt --mqtt-host <broker> --mqtt-username <user> (MQTT password via env).
  3. Power on two different nodes (e.g. node 1 and node 2).
  4. Subscribe to discovery configs:
    mosquitto_sub -t 'homeassistant/+/+/presence/config' -v \
      | grep -o 'wifi-densepose-[0-9]*' | sort -u
    
  5. Observed: only wifi-densepose-1.
    Expected: wifi-densepose-1 and wifi-densepose-2.

Root-cause pointer (from source on main)

  • v2/crates/wifi-densepose-sensing-server/src/mqtt/publisher.rs holds a
    single OwnedDiscoveryBuilder { node_id: String } (singular). The publisher
    task does not iterate over multiple nodes — there is no
    for node in nodes / per-node map anywhere under src/mqtt/.
  • src/mqtt/discovery.rs builds the device identifier from that single id:
    identifiers: vec![format!("wifi_densepose_{}", self.node_id)] — so one
    server instance can only ever describe one device.
  • There is no CLI flag to set the identity: --help exposes no
    --node-id, --zone, or --device-name (checked on latest and on
    v0.12.0). --mqtt-client-id only sets the broker connection id, not the
    HA device identifiers.

This means neither a single server nor multiple parallel containers can produce
per-room devices today: a single server merges all nodes onto node_id = 1,
and parallel containers would all publish the identical
wifi_densepose_wifi-densepose-1, colliding into one HA device.

Suggested fix (one of)

  • Have the MQTT publisher iterate the live node set (same source the REST
    /api/v1/nodes endpoint already uses) and emit one discovery device per
    node_id, OR
  • Add a --node-id / --zone / --device-name flag (and matching
    RUVIEW_* env) so multiple single-node server instances can each own a
    distinct HA device identity.

Environment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions