180 lines
10 KiB
Markdown
180 lines
10 KiB
Markdown
# RuView — WiFi CSI spatial-intelligence nodes (Phase 2)
|
||
|
||
Real upstream project: **[github.com/ruvnet/ruview](https://github.com/ruvnet/ruview)**
|
||
— a WiFi Channel-State-Information (CSI) platform that detects presence, tracks
|
||
movement/pose, and infers semantic room states (see §2 below) through walls,
|
||
without a camera. **This repo does not reimplement any of RuView's CSI
|
||
firmware or signal processing** — that's genuine DSP research code (Rust +
|
||
ESP-IDF, running on-device), and fabricating it from scratch rather than
|
||
integrating the real thing would be exactly the kind of guess this project's own
|
||
conventions exist to avoid. What lives in this directory is a thin, honest wrapper
|
||
around RuView's own tooling, matching how this repo already treats Frigate/
|
||
Zigbee2MQTT/Grocy — integrated, not forked.
|
||
|
||
This is a different device from `firmware/esphome-ble-proxy/` — separate
|
||
hardware, separate job, per `docs/project-plan.md` §1.5's "separate hardware from
|
||
RuView nodes" note. BLE proxies resolve *who* (via Bermuda/Private BLE Device);
|
||
RuView nodes sense *room activity/vitals*, camera-free.
|
||
|
||
## 1. Hardware
|
||
|
||
Per RuView's own README (confirmed via the link above, not guessed):
|
||
|
||
| Board | Price | Role |
|
||
|---|---|---|
|
||
| **ESP32-S3** | ~€9 | Primary target — CSI capture + edge processing |
|
||
| ESP32-C6 | €6–10 | Research variant, WiFi 6 + dual-band |
|
||
| Intel 5300 / Atheros AR9580 (research NICs) | €50–100 | Higher-fidelity research hardware, not a household pick |
|
||
| Cognitum Seed (optional) | ~€140 | Persistent storage / vector search / witness-chain, not required for basic presence |
|
||
|
||
**ESP32-C3 and the original ESP32 are explicitly NOT supported** (RuView's own
|
||
README: "single-core, insufficient for CSI DSP") — this updates
|
||
`docs/project-plan.md` §1.6's original "ESP32-S3 dev board" pick from a general
|
||
recommendation to a confirmed hard requirement.
|
||
|
||
## 2. What it publishes — and why that's more sensitive than plain presence
|
||
|
||
RuView ships **21 MQTT entities per node** via its own `HA-DISCO` MQTT
|
||
auto-discovery publisher: 11 raw signals plus 10 inferred semantic states —
|
||
`someone-sleeping`, `possible-distress`, `room-active`, `elderly-inactivity-
|
||
anomaly`, `meeting-in-progress`, `bathroom-occupied`, `fall-risk-elevated`,
|
||
`bed-exit`, `no-movement`, `multi-room-transition`. It can also estimate
|
||
breathing/heart rate.
|
||
|
||
**This is a meaningfully bigger privacy surface than the plain occupancy sensor
|
||
`docs/project-plan.md`'s original Phase 2 sketch assumed.** Bathroom-occupancy,
|
||
sleep state, and vitals-adjacent inference are the kind of data this project has
|
||
otherwise been careful about (see `identity/README.md`'s "Anti-spoofing" and
|
||
"People without a device" sections for the same care applied to identity/consent).
|
||
**Nothing in this repo currently gives household members a way to opt out of a
|
||
specific room's RuView sensing, or restricts who these MQTT topics are visible
|
||
to beyond the same trust boundary as every other entity on this network.** Treat
|
||
this as an explicit open decision (`docs/project-plan.md` §4) before wiring
|
||
automations against the more sensitive semantic states, not something silently
|
||
safe by default just because the network is local.
|
||
|
||
## 3. Build + flash — RuView's own tooling, not this repo's
|
||
|
||
This repo does not vendor RuView's source. Clone and build it yourself per its own
|
||
README:
|
||
|
||
```sh
|
||
git clone https://github.com/ruvnet/ruview ~/ruview
|
||
cd ~/ruview
|
||
# Rust 1.85+ and the ESP-IDF toolchain are prerequisites — see RuView's own docs
|
||
idf.py set-target esp32s3 # or esp32c6 for that variant
|
||
idf.py build
|
||
python -m esptool --chip esp32s3 --port /dev/ttyUSB0 --baud 460800 write_flash ...
|
||
```
|
||
|
||
**VERIFY the exact build/flash command against whatever version you actually
|
||
clone** — the commands above are transcribed from RuView's own README as fetched
|
||
during this session, not independently run against real hardware from within this
|
||
project; upstream commands/flags can and do change between releases.
|
||
|
||
## 4. Provisioning per room — `provision-room.sh`
|
||
|
||
Once a node is flashed, it needs Wi-Fi + this stack's MQTT broker credentials.
|
||
RuView ships its own `firmware/esp32-csi-node/provision.py` for this;
|
||
`provision-room.sh` in this directory is a **thin wrapper** that fills in this
|
||
project's own settings (same Mosquitto broker every other service already uses,
|
||
Phase 1) so you don't retype them per node:
|
||
|
||
```sh
|
||
cp rooms.env.example rooms.env # fill in RUVIEW_REPO_DIR, Wi-Fi, MQTT_BROKER_HOST
|
||
chmod 600 rooms.env
|
||
./provision-room.sh living-room /dev/ttyUSB0
|
||
```
|
||
|
||
Only `--port`/`--ssid`/`--password`/`--mqtt` are passed by the wrapper — those
|
||
four flags are the ones confirmed against RuView's own README during this
|
||
session. **Anything else `provision.py` might need in your specific installed
|
||
version (MQTT auth flags, a node-naming flag, etc.) is NOT guessed here** — pass
|
||
it as an extra argument to `provision-room.sh` after checking
|
||
`python3 ~/ruview/firmware/esp32-csi-node/provision.py --help` against your real
|
||
checkout first.
|
||
|
||
## 5. Automations built on RuView's semantic states
|
||
|
||
You've confirmed you want these wired up despite §2's privacy note — the concrete
|
||
rules requested, all in `automations.yaml.example` (paste whichever ones you want
|
||
into your own HA config, same "nothing under this repo merges into your HA config
|
||
for you" convention as identity's own worked `rest_command` example):
|
||
|
||
1. **Someone asleep → dim that room's lights.** Straightforward state trigger →
|
||
`light.turn_on` at low brightness/warm color temp.
|
||
2. **Possible distress → alert everyone home.** Mapped to RuView's own
|
||
`possible-distress` semantic state — **this is RuView's closest documented
|
||
inference to "a heart attack," there is no literal heart-attack-detection
|
||
entity, and this repo does not build its own medical-anomaly detection on top
|
||
of RuView's raw signals.** The automation bridges that state to an urgent
|
||
`ntfy` push (via a `rest_command:`, same pattern as every other ntfy-posting
|
||
service in this stack) plus a whole-house TTS announcement across every
|
||
`media_player` you list, plus flashing every light red as a visual backup.
|
||
Whatever RuView's real accuracy turns out to be is entirely upstream's, not
|
||
something this bridge changes — **do not treat this as a substitute for an
|
||
actual medical alert device/service.**
|
||
3. **Two people's heart rate elevated concurrently in the same room → red/
|
||
magenta/violet lighting.** Approximated as "both above an elevated threshold
|
||
at the same time" rather than a true rate-of-change trigger (deliberately —
|
||
derivative triggers on noisy CSI-derived vitals are far more false-trigger-
|
||
prone than a plain threshold). **This is the single most uncertain rule in
|
||
this file**: RuView's fetched README doesn't confirm whether one node can
|
||
actually distinguish and report two distinct people's heart rates
|
||
concurrently at all — multi-target vital-sign separation from WiFi CSI is a
|
||
genuinely hard, actively-researched problem. Confirm you have two real
|
||
per-person heart-rate entities for a room before trusting this can fire as
|
||
described; if there's only one aggregate entity per node, this rule needs a
|
||
different design once you know that, not a guess made now.
|
||
4. **Bathroom occupied → an external indicator outside the door.** You mentioned
|
||
you'll likely add a dedicated light/actor for this — the automation targets a
|
||
placeholder `switch.bathroom_door_indicator`; swap it for whatever you end up
|
||
choosing (worth adding to `components.md`'s Zigbee list once picked, same as
|
||
every other Zigbee actuator in this project).
|
||
|
||
**Every `entity_id` in `automations.yaml.example` is a placeholder** — RuView's
|
||
README documents semantic-state *names*, not their exact post-MQTT-discovery HA
|
||
`entity_id`s (domain, underscore-vs-hyphen, per-node naming). Confirm every one
|
||
against Developer Tools → States on a real HA instance after provisioning a real
|
||
node before relying on any of this.
|
||
|
||
## 6. Home Assistant integration — likely nothing to build, but unverified
|
||
|
||
RuView's `HA-DISCO` publisher uses MQTT auto-discovery against the **same
|
||
Mosquitto broker** every other service in this stack already connects to (Phase 1)
|
||
— if that's accurate, entities should appear in HA automatically once a node is
|
||
provisioned and online, no manual entity/automation setup required to just *see*
|
||
the data. RuView's own docs reportedly include `docs/integrations/home-assistant.md`
|
||
and three starter HA Blueprints (per its README) for turning the semantic states
|
||
into actual automations — **none of that has been read in detail or verified from
|
||
within this project**, only the top-level README summary this section is built
|
||
from. Confirm the real doc before wiring anything beyond "the entities show up."
|
||
|
||
Same "nothing under this repo builds the HA side" convention as every entry in
|
||
`docs/project-plan.md`'s HA-integrations catalog (§2) — automations against
|
||
RuView's semantic states are a decision for you to make deliberately, especially
|
||
given §2's privacy note above, not something this repo pre-wires.
|
||
|
||
## Manual verification still outstanding
|
||
|
||
1. Nothing here has been run against real hardware, a real RuView checkout, or a
|
||
real MQTT broker from within this project — §3's build commands and §4's
|
||
`provision.py` flags are transcribed from RuView's own README, not
|
||
independently confirmed.
|
||
2. `docs/integrations/home-assistant.md` / RuView's HA Blueprints (§6) — described
|
||
secondhand from the top-level README, not read directly.
|
||
3. The privacy/consent gap in §2 — the household-level decision has been made
|
||
(you want this data and the automations built on it), but there is still no
|
||
technical opt-out for a specific person/room, and no access restriction on
|
||
these MQTT topics beyond this network's normal trust boundary. Worth revisiting
|
||
if anyone who isn't fully on board with being sensed this way ever stays over.
|
||
4. `docs/project-plan.md` §1.6/§2's RuView entries — updated this session to
|
||
match §1 above (ESP32-C3/original-ESP32 unsupported, real hardware tiers), but
|
||
the phased implementation plan (Phase 2) itself still describes RuView only at
|
||
the "deploy nodes per room" level of detail from before this integration pass.
|
||
5. **`automations.yaml.example`'s entity_ids are ALL placeholders** — none of
|
||
§5's four automations have been run against real RuView entities; in
|
||
particular rule 3 (concurrent two-person heart rate) rests on an unconfirmed
|
||
assumption that a single node can even report two people's heart rates at
|
||
once, see that automation's own prominent warning comment.
|