Merge a5fd752b78 into 9e7fa83210
This commit is contained in:
commit
d969ee7079
|
|
@ -78,6 +78,8 @@ RuView turns ordinary WiFi into a contactless sensor. A $9 ESP32 board reads the
|
|||
docker pull ruvnet/wifi-densepose:latest
|
||||
docker run -p 3000:3000 ruvnet/wifi-densepose:latest
|
||||
# Open http://localhost:3000
|
||||
# CasaOS / docker compose? See docs/DOCKER-CASAOS.md (ready-made
|
||||
# docker-compose.yml with an app tile)
|
||||
|
||||
# Option 2a: Live sensing with ESP32-S3 hardware ($9)
|
||||
# Flash firmware, provision WiFi, and start sensing:
|
||||
|
|
@ -587,6 +589,7 @@ Verify the plugin structure: `bash plugins/ruview/scripts/smoke.sh`. Full detail
|
|||
| Document | Description |
|
||||
|----------|-------------|
|
||||
| [User Guide](docs/user-guide.md) | Step-by-step guide: installation, first run, API usage, hardware setup, training |
|
||||
| [Docker & CasaOS](docs/DOCKER-CASAOS.md) | Run the sensing server via Docker / `docker-compose.yml`, import as a CasaOS app tile, and connect ESP32-S3 nodes |
|
||||
| [Build Guide](docs/build-guide.md) | Building from source (Rust and Python) |
|
||||
| [**Home Assistant + Matter Integration**](docs/integrations/home-assistant.md) | **Works with Home Assistant** via MQTT auto-discovery + **Works with Matter** (Apple Home / Google Home / Alexa / SmartThings) — full entity catalog, 3 starter blueprints, Lovelace dashboards, privacy mode, threshold tuning ([ADR-115](docs/adr/ADR-115-home-assistant-integration.md)). |
|
||||
| [**BFLD — Beamforming Feedback Layer for Detection**](v2/crates/wifi-densepose-bfld/README.md) | New privacy-gated WiFi sensing layer that measures + structurally prevents identity leakage from 802.11ac/ax Beamforming Feedback Information. Three type-enforced invariants (raw BFI never exits node, identity embedding is in-RAM-only, cross-site correlation cryptographically impossible via per-site BLAKE3 keyed hash + daily rotation). Ships full operator surface (`BfldPipeline`, `BfldPipelineHandle`, Soul Signature `SoulMatchOracle` integration), MQTT topic router + HA-DISCO + availability + LWT, 3 operator HA blueprints, two runnable examples, eclipse-mosquitto:2 CI service container. 327+ tests. [ADR-118](docs/adr/ADR-118-bfld-beamforming-feedback-layer-for-detection.md) umbrella + sub-ADRs [119](docs/adr/ADR-119-bfld-frame-format-and-wire-protocol.md)/[120](docs/adr/ADR-120-bfld-privacy-class-and-hash-rotation.md)/[121](docs/adr/ADR-121-bfld-identity-risk-scoring.md)/[122](docs/adr/ADR-122-bfld-ruview-ha-matter-exposure.md)/[123](docs/adr/ADR-123-bfld-capture-path-nexmon-and-esp32.md). Research dossier: [`docs/research/BFLD/`](docs/research/BFLD/) (11 files, 13,544 words). |
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 412 KiB |
|
|
@ -0,0 +1,122 @@
|
|||
# RuView — WiFi DensePose sensing server, CasaOS-ready compose.
|
||||
#
|
||||
# Uses the prebuilt image from Docker Hub, so the host does NOT need to compile
|
||||
# the Rust workspace. (The published `:latest` tag is amd64; on arm64 hosts build
|
||||
# locally first: `docker compose -f docker/docker-compose.yml build`.) The server
|
||||
# hosts the REST API + web UI on one port, a WebSocket stream, and a UDP listener
|
||||
# for ESP32-S3 CSI nodes.
|
||||
#
|
||||
# Import into CasaOS: App Store → Custom Install → paste this file, OR
|
||||
# docker compose -f docker-compose.casaos.yml up -d
|
||||
#
|
||||
# Open the dashboard at: http://<host-ip>:3000/ui/index.html
|
||||
# (the bare http://<host-ip>:3000/ root is just an API index — the visual
|
||||
# dashboards live under /ui/: index.html, observatory.html, pose-fusion.html)
|
||||
#
|
||||
# If host ports 3000/3001 are already taken on your machine, change the
|
||||
# `published:` values below (and `port_map` / `webui_port` to match the new UI port).
|
||||
#
|
||||
# Data source (CSI_SOURCE):
|
||||
# auto probe UDP 5005 for an ESP32, else fall back to simulation (default)
|
||||
# esp32 require real CSI frames from an ESP32-S3 node on UDP 5005
|
||||
# simulated synthetic CSI, no hardware needed (good for first evaluation)
|
||||
|
||||
name: ruview
|
||||
|
||||
services:
|
||||
ruview:
|
||||
image: ruvnet/wifi-densepose:latest
|
||||
container_name: ruview
|
||||
hostname: ruview
|
||||
labels:
|
||||
icon: https://cdn.jsdelivr.net/gh/ruvnet/RuView@main/assets/ruview-icon.png
|
||||
ports:
|
||||
- mode: ingress
|
||||
target: 3000
|
||||
published: "3000"
|
||||
protocol: tcp
|
||||
- mode: ingress
|
||||
target: 3001
|
||||
published: "3001"
|
||||
protocol: tcp
|
||||
- mode: ingress
|
||||
target: 5005
|
||||
published: "5005"
|
||||
protocol: udp
|
||||
environment:
|
||||
- RUST_LOG=info
|
||||
# auto | esp32 | wifi | simulated (see header)
|
||||
- CSI_SOURCE=${CSI_SOURCE:-auto}
|
||||
- MODELS_DIR=/app/models
|
||||
# Optional bearer-token auth on /api/v1/*. Leave empty for LAN-only use;
|
||||
# set a token to require `Authorization: Bearer <token>`:
|
||||
# RUVIEW_API_TOKEN=$(openssl rand -hex 32)
|
||||
- RUVIEW_API_TOKEN=${RUVIEW_API_TOKEN:-}
|
||||
volumes:
|
||||
# Drop .rvf model files here to make them visible to the API.
|
||||
- ./data/models:/app/models
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
default: null
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: ruview_default
|
||||
|
||||
x-casaos:
|
||||
architectures:
|
||||
- amd64
|
||||
main: ruview
|
||||
author: self
|
||||
developer: ruvnet
|
||||
category: HomeAutomation
|
||||
hostname: ""
|
||||
icon: https://cdn.jsdelivr.net/gh/ruvnet/RuView@main/assets/ruview-icon.png
|
||||
index: /ui/index.html
|
||||
is_uncontrolled: false
|
||||
port_map: "3000"
|
||||
webui_port: 3000
|
||||
scheme: http
|
||||
tagline:
|
||||
en_us: See through walls with WiFi — contactless presence, breathing & pose sensing
|
||||
description:
|
||||
en_us: |
|
||||
RuView (WiFi DensePose) turns ordinary WiFi into a contactless spatial
|
||||
sensor. Using Channel State Information (CSI) from low-cost ESP32-S3 nodes,
|
||||
it detects people through walls, estimates breathing and heart rate, tracks
|
||||
motion and falls, and runs 17-keypoint pose estimation — no cameras, no
|
||||
wearables. This image runs the Rust sensing server with its web dashboard.
|
||||
With CSI_SOURCE=simulated it works with synthetic data and no hardware;
|
||||
point one or more ESP32-S3 CSI nodes at UDP 5005 for live sensing.
|
||||
title:
|
||||
en_us: RuView
|
||||
thumbnail: https://cdn.jsdelivr.net/gh/ruvnet/RuView@main/assets/ruview-icon.png
|
||||
screenshot_link:
|
||||
- https://cdn.jsdelivr.net/gh/ruvnet/RuView@main/assets/ruview-icon.png
|
||||
envs:
|
||||
- container: CSI_SOURCE
|
||||
description:
|
||||
en_us: "Data source: auto (default) | esp32 | simulated. 'simulated' needs no hardware."
|
||||
- container: RUVIEW_API_TOKEN
|
||||
description:
|
||||
en_us: "(Optional) bearer token to protect /api/v1/*. Leave empty for LAN-only use."
|
||||
- container: MODELS_DIR
|
||||
description:
|
||||
en_us: "In-container path scanned for .rvf model files (default /app/models)."
|
||||
- container: RUST_LOG
|
||||
description:
|
||||
en_us: "Log level: info (default), debug, warn, error."
|
||||
ports:
|
||||
- container: "3000"
|
||||
description:
|
||||
en_us: "Web UI + REST API (HTTP)."
|
||||
- container: "3001"
|
||||
description:
|
||||
en_us: "WebSocket sensing stream."
|
||||
- container: "5005"
|
||||
description:
|
||||
en_us: "ESP32-S3 CSI ingest (UDP)."
|
||||
volumes:
|
||||
- container: /app/models
|
||||
description:
|
||||
en_us: "Holds .rvf model files exposed via /api/v1/models."
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
# Running RuView with Docker (and CasaOS)
|
||||
|
||||
This guide covers running the RuView **sensing server** (the Rust + Axum service
|
||||
that hosts the REST API, WebSocket stream, and web dashboard) as a Docker
|
||||
container, and importing it into [CasaOS](https://casaos.io/).
|
||||
|
||||
It uses the prebuilt image `ruvnet/wifi-densepose:latest` from Docker Hub, so the
|
||||
host does **not** need to compile the Rust workspace.
|
||||
|
||||
> **Architecture note:** the published `:latest` tag currently ships an **amd64**
|
||||
> layer only. On an amd64 host (e.g. an x86 mini-PC / NUC / Ryzen box) it runs as
|
||||
> is. On arm64 (Raspberry Pi, etc.) build locally first:
|
||||
> `docker compose -f docker/docker-compose.yml build`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Quick start (no hardware)
|
||||
|
||||
```bash
|
||||
cd ruview
|
||||
CSI_SOURCE=simulated docker compose -f docker-compose.yml up -d
|
||||
```
|
||||
|
||||
Then open the dashboard:
|
||||
|
||||
```
|
||||
http://<host-ip>:3000/ui/index.html
|
||||
```
|
||||
|
||||
> The bare root `http://<host-ip>:3000/` is only an **API index** (a plain list
|
||||
> of endpoints) — the visual dashboards live under `/ui/`:
|
||||
> `index.html` (main), `observatory.html` (live feed), `pose-fusion.html`
|
||||
> (webcam + CSI), `viz.html` (3D).
|
||||
|
||||
`CSI_SOURCE=simulated` feeds the pipeline with synthetic CSI so you can explore
|
||||
the dashboard, API, and vital-sign/pose visualizations without any hardware.
|
||||
|
||||
Stop / remove:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml down
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Ports
|
||||
|
||||
The compose file (`docker-compose.yml`) publishes these host ports:
|
||||
|
||||
| Service | Container | Host | Notes |
|
||||
|------------------------|-----------|------|-------|
|
||||
| REST API + web UI | 3000/tcp | **3000** | Dashboard lives here (`/`, `/ui/...`) |
|
||||
| WebSocket sensing feed | 3001/tcp | **3001** | `ws://host:3001/ws/sensing` |
|
||||
| ESP32 CSI ingest | 5005/udp | **5005** | ESP32-S3 nodes stream CSI frames here |
|
||||
|
||||
If a host port clashes on your machine, edit the `published:` values in
|
||||
`docker-compose.yml` (and update `port_map` / `webui_port` in the
|
||||
`x-casaos` block to match the new UI port). The dashboard's WebSocket URL is
|
||||
derived from the page host, so keep the API and WS ports reachable from the same
|
||||
hostname.
|
||||
|
||||
Verified endpoints (all return `200` once running):
|
||||
|
||||
```
|
||||
/ /ui/index.html /ui/observatory.html
|
||||
/api/v1/status /api/v1/sensing/latest /api/v1/models
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Data source modes (`CSI_SOURCE`)
|
||||
|
||||
| Value | Behaviour |
|
||||
|-------------|-----------|
|
||||
| `auto` | (default) Probe UDP 5005 for an ESP32 node; fall back to `simulated`. |
|
||||
| `esp32` | Require real CSI frames from an ESP32-S3 node on UDP 5005. |
|
||||
| `simulated` | Synthetic CSI — no hardware. Best for first evaluation. |
|
||||
| `wifi` | Host Wi-Fi RSSI/scan (Windows `netsh`) — **not** available inside a Linux container. |
|
||||
|
||||
Set it inline (`CSI_SOURCE=esp32 docker compose ... up -d`) or via a `.env` file
|
||||
next to the compose, or in the CasaOS environment-variable UI.
|
||||
|
||||
### Models
|
||||
|
||||
Drop `.rvf` model files into `./data/models/` (mounted to `/app/models`); the API
|
||||
exposes them under `/api/v1/models`. Pretrained weights:
|
||||
|
||||
```bash
|
||||
pip install huggingface_hub
|
||||
huggingface-cli download ruvnet/wifi-densepose-pretrained --local-dir data/models/wifi-densepose-pretrained
|
||||
```
|
||||
|
||||
### Optional API auth
|
||||
|
||||
Leave `RUVIEW_API_TOKEN` empty for LAN-only use. Set it to require
|
||||
`Authorization: Bearer <token>` on `/api/v1/*`:
|
||||
|
||||
```bash
|
||||
RUVIEW_API_TOKEN=$(openssl rand -hex 32) docker compose -f docker-compose.yml up -d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Importing into CasaOS
|
||||
|
||||
The compose file includes an `x-casaos:` metadata block (icon, title, category,
|
||||
description, port map), so CasaOS shows it as a proper app tile.
|
||||
|
||||
**Option A — CasaOS UI (Custom Install)**
|
||||
|
||||
1. CasaOS dashboard → **App Store** → **Custom Install** (the `+` / "Install a
|
||||
customized app").
|
||||
2. Switch to the **Import** / YAML view and paste the contents of
|
||||
`docker-compose.yml`.
|
||||
3. Install. The tile opens `http://<host-ip>:3000/ui/index.html`.
|
||||
|
||||
**Option B — CLI (CasaOS still detects the container)**
|
||||
|
||||
```bash
|
||||
cd ruview
|
||||
docker compose -f docker-compose.yml up -d
|
||||
```
|
||||
|
||||
> **Icon:** the manifest points at
|
||||
> `https://cdn.jsdelivr.net/gh/ruvnet/RuView@main/assets/ruview-icon.png`
|
||||
> (jsDelivr serves `assets/ruview-icon.png` straight from the repo). To use a
|
||||
> different or fully local icon, replace both `icon:` URLs (in `labels:` and
|
||||
> `x-casaos:`) with another URL or a file path served by your own host.
|
||||
|
||||
---
|
||||
|
||||
## 5. Connecting live ESP32-S3 CSI nodes
|
||||
|
||||
RuView's full capability set (presence through walls, breathing/heart rate, fall
|
||||
detection, pose) needs **Channel State Information** from a CSI-capable node.
|
||||
|
||||
1. Flash the firmware from `firmware/esp32-csi-node/` to an **ESP32-S3**
|
||||
(8 MB or 4 MB). See the repo `CLAUDE.md` "ESP32 Firmware Build" section.
|
||||
2. Provision Wi-Fi + the sink (this server's) IP:
|
||||
```bash
|
||||
python firmware/esp32-csi-node/provision.py --port /dev/ttyUSB0 \
|
||||
--ssid "YourWiFi" --password "secret" --target-ip <host-ip>
|
||||
```
|
||||
Point `--target-ip` at the host running this container; frames arrive on
|
||||
**UDP 5005**.
|
||||
3. Start with `CSI_SOURCE=esp32` (or `auto`).
|
||||
|
||||
> **Supported chips:** ESP32-**S3** (dual-core) and ESP32-**C6**. The original
|
||||
> ESP32 and ESP32-**C3** are **single-core** and cannot run the CSI DSP pipeline.
|
||||
|
||||
---
|
||||
|
||||
## 6. Operations
|
||||
|
||||
```bash
|
||||
# Logs
|
||||
docker logs ruview -f --tail 100
|
||||
|
||||
# Restart / update to the latest image
|
||||
docker compose -f docker-compose.yml pull
|
||||
docker compose -f docker-compose.yml up -d
|
||||
|
||||
# Status of the running server
|
||||
curl -s http://<host-ip>:3000/api/v1/status
|
||||
```
|
||||
|
||||
**Troubleshooting**
|
||||
|
||||
- *Dashboard loads but no data:* check the data source — with `auto` and no ESP32
|
||||
present it falls back to `simulated`; logs print `Data source: ...`.
|
||||
- *Multiple ESP32 nodes on Docker Desktop for Windows:* multi-source UDP collapses
|
||||
to one source IP at the WSL boundary. Use the host relay (see
|
||||
`docs/TROUBLESHOOTING.md §9`). Native Linux/CasaOS hosts are unaffected.
|
||||
- *Port clash on 3000/3001:* edit `published:` in `docker-compose.yml`.
|
||||
Loading…
Reference in New Issue