wifi-densepose/docs/DOCKER-CASAOS.md

6.1 KiB

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.

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)

cd ruview
CSI_SOURCE=simulated docker compose -f docker-compose.casaos.yml up -d

Then open the dashboard:

http://<host-ip>:3030/ui/index.html

The bare root http://<host-ip>:3030/ 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:

docker compose -f docker-compose.casaos.yml down

2. Ports

The compose file (docker-compose.casaos.yml) publishes non-default host ports because 3000/3001 are commonly already in use:

Service Container Host (this compose) Notes
REST API + web UI 3000/tcp 3030 Dashboard lives here (/, /ui/...)
WebSocket sensing feed 3001/tcp 3031 ws://host:3031/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.casaos.yml. 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:

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/*:

RUVIEW_API_TOKEN=$(openssl rand -hex 32) docker compose -f docker-compose.casaos.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 StoreCustom Install (the + / "Install a customized app").
  2. Switch to the Import / YAML view and paste the contents of docker-compose.casaos.yml.
  3. Install. The tile opens http://<host-ip>:3030/ui/index.html.

Option B — CLI (CasaOS still detects the container)

cd /DATA/AppData/ruview
docker compose -f docker-compose.casaos.yml up -d

Icon: the manifest points at https://cdn.jsdelivr.net/gh/Aiacos/ruview@main/assets/ruview-icon.png. jsDelivr serves it from the GitHub repo, so commit & push assets/ruview-icon.png to the main branch for the icon to resolve. Until then CasaOS shows a placeholder; everything else works. To use a fully local icon instead, replace both icon: URLs (in labels: and x-casaos:) with 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:
    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

# Logs
docker logs ruview -f --tail 100

# Restart / update to the latest image
docker compose -f docker-compose.casaos.yml pull
docker compose -f docker-compose.casaos.yml up -d

# Status of the running server
curl -s http://<host-ip>:3030/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 3030/3031: edit published: in docker-compose.casaos.yml.