Covers every way to build, run, and deploy the system -- from a zero-hardware verification to a full ESP32 mesh with 3D visualization.
- Quick Start (Verification Only -- No Hardware)
- Python Pipeline (v1/)
- Rust Pipeline (v2)
- Three.js Visualization
- Docker Deployment
- ESP32 Hardware Setup
- Environment-Specific Builds
The fastest way to confirm the signal processing pipeline is real and deterministic. Requires only Python 3.8+, numpy, and scipy. No WiFi hardware, no GPU, no Docker.
# From the repository root:
./verifyThis runs three phases:
- Environment checks -- confirms Python, numpy, scipy, and proof files are present.
- Proof pipeline replay -- feeds a published reference signal through the full signal processing chain (noise filtering, Hamming windowing, amplitude normalization, FFT-based Doppler extraction, power spectral density via scipy.fft) and computes a SHA-256 hash of the output.
- Production code integrity scan -- scans
v1/src/fornp.random.rand/np.random.randncalls in production code (test helpers are excluded).
Exit codes:
0PASS -- pipeline hash matches the published expected hash1FAIL -- hash mismatch or error2SKIP -- no expected hash file to compare against
Additional flags:
./verify --verbose # Detailed feature statistics and Doppler spectrum
./verify --verbose --audit # Full verification + codebase audit
# Or via make:
make verify
make verify-verbose
make verify-auditIf the expected hash file is missing, regenerate it:
python3 v1/data/proof/verify.py --generate-hashpip install numpy==1.26.4 scipy==1.14.1Or install the pinned set that guarantees hash reproducibility:
pip install -r v1/requirements-lock.txtThe lock file pins: numpy==1.26.4, scipy==1.14.1, pydantic==2.10.4, pydantic-settings==2.7.1.
The Python pipeline lives under v1/ and provides the full API server, signal processing, sensing modules, and WebSocket streaming.
- Python 3.8+
- pip
pip install -r v1/requirements-lock.txtThis installs only the four packages needed for deterministic pipeline verification.
pip install -r requirements.txtThis pulls in FastAPI, uvicorn, torch, OpenCV, SQLAlchemy, Redis client, and all other runtime dependencies.
python3 v1/data/proof/verify.pySame as ./verify but calls the Python script directly, skipping the bash wrapper's codebase scan phase.
uvicorn v1.src.api.main:app --host 0.0.0.0 --port 8000The server exposes:
- REST API docs: http://localhost:8000/docs
- Health check: http://localhost:8000/health
- Latest poses: http://localhost:8000/api/v1/pose/latest
- WebSocket pose stream: ws://localhost:8000/ws/pose/stream
- WebSocket analytics: ws://localhost:8000/ws/analytics/events
For development with auto-reload:
uvicorn v1.src.api.main:app --host 0.0.0.0 --port 8000 --reloadThe commodity sensing module (v1/src/sensing/) extracts presence and motion features from standard Linux WiFi metrics (RSSI, noise floor, link quality) without any hardware modification. See ADR-013 for full design details.
Requirements:
- Any Linux machine with a WiFi interface (laptop, Raspberry Pi, etc.)
- Connected to a WiFi access point (the AP is the signal source)
- No root required for basic RSSI reading via
/proc/net/wireless
The module provides:
LinuxWifiCollector-- reads real RSSI from/proc/net/wirelessandiwcommandsRssiFeatureExtractor-- computes rolling statistics, FFT spectral features, CUSUM change-point detectionPresenceClassifier-- rule-based presence/motion classification
What it can detect:
| Capability | Single Receiver | 3+ Receivers |
|---|---|---|
| Binary presence | Yes (90-95%) | Yes (90-95%) |
| Coarse motion (still/moving) | Yes (85-90%) | Yes (85-90%) |
| Room-level location | No | Marginal (70-80%) |
What it cannot detect: body pose, heartbeat, reliable respiration. See ADR-013 for the honest capability matrix.
v1/
src/
api/
main.py # FastAPI application entry point
routers/ # REST endpoint routers (pose, stream, health)
middleware/ # Auth, rate limiting
websocket/ # WebSocket connection manager, pose stream
config/ # Settings, domain configs
sensing/
rssi_collector.py # LinuxWifiCollector + SimulatedCollector
feature_extractor.py # RssiFeatureExtractor (FFT, CUSUM, spectral)
classifier.py # PresenceClassifier (rule-based)
backend.py # SensingBackend protocol
data/
proof/
sample_csi_data.json # Deterministic reference signal
expected_features.sha256 # Published expected hash
verify.py # One-command verification script
requirements-lock.txt # Pinned deps for hash reproducibility
A high-performance Rust port with ~810x speedup over the Python pipeline for the full signal processing chain.
- Rust 1.70+ (install via rustup)
- cargo (included with Rust)
- System dependencies for OpenBLAS (used by ndarray-linalg):
# Ubuntu/Debian sudo apt-get install build-essential gfortran libopenblas-dev pkg-config # macOS brew install openblas
cd rust-port/wifi-densepose-rs
cargo build --releaseRelease profile is configured with LTO, single codegen unit, and -O3 for maximum performance.
cd rust-port/wifi-densepose-rs
cargo test --workspaceRuns 107 tests across all workspace crates.
cd rust-port/wifi-densepose-rs
cargo bench --package wifi-densepose-signalExpected throughput:
| Operation | Latency | Throughput |
|---|---|---|
| CSI Preprocessing (4x64) | ~5.19 us | 49-66 Melem/s |
| Phase Sanitization (4x64) | ~3.84 us | 67-85 Melem/s |
| Feature Extraction (4x64) | ~9.03 us | 7-11 Melem/s |
| Motion Detection | ~186 ns | -- |
| Full Pipeline | ~18.47 us | ~54,000 fps |
The Rust workspace contains 10 crates under crates/:
| Crate | Description |
|---|---|
wifi-densepose-core |
Core types, traits, and domain models |
wifi-densepose-signal |
Signal processing (FFT, phase unwrapping, Doppler, correlation) |
wifi-densepose-nn |
Neural network inference (ONNX Runtime, candle, tch) |
wifi-densepose-api |
Axum-based HTTP/WebSocket API server |
wifi-densepose-db |
Database layer (SQLx, PostgreSQL, SQLite, Redis) |
wifi-densepose-config |
Configuration loading (env vars, YAML, TOML) |
wifi-densepose-hardware |
Hardware adapters (ESP32, Intel 5300, Atheros, UDP, PCAP) |
wifi-densepose-wasm |
WebAssembly bindings for browser deployment |
wifi-densepose-cli |
Command-line interface |
wifi-densepose-mat |
WiFi-Mat disaster response module (search and rescue) |
Build individual crates:
# Signal processing only
cargo build --release --package wifi-densepose-signal
# API server
cargo build --release --package wifi-densepose-api
# Disaster response module
cargo build --release --package wifi-densepose-mat
# WASM target (see Section 7 for full instructions)
cargo build --release --package wifi-densepose-wasm --target wasm32-unknown-unknownA browser-based 3D visualization dashboard that renders DensePose body models with 24 body parts, signal visualization, and environment rendering.
Open ui/viz.html directly in a browser:
# macOS
open ui/viz.html
# Linux
xdg-open ui/viz.html
# Or serve it locally
python3 -m http.server 3000 --directory ui
# Then open http://localhost:3000/viz.htmlThe visualization connects to ws://localhost:8000/ws/pose for real-time pose data. If no server is running, it falls back to a demo mode with simulated data so you can still see the 3D rendering.
To see live data:
- Start the API server (Python or Rust)
- Open
ui/viz.html - The dashboard will connect automatically
docker compose upThis starts:
wifi-densepose-dev-- API server with--reload, debug logging, auth disabled (port 8000)postgres-- PostgreSQL 15 (port 5432)redis-- Redis 7 with AOF persistence (port 6379)prometheus-- metrics scraping (port 9090)grafana-- dashboards (port 3000, login: admin/admin)nginx-- reverse proxy (ports 80, 443)
# View logs
docker compose logs -f wifi-densepose
# Run tests inside the container
docker compose exec wifi-densepose pytest tests/ -v
# Stop everything
docker compose down
# Stop and remove volumes
docker compose down -vUses the production Dockerfile stage with 4 uvicorn workers, auth enabled, rate limiting, and resource limits.
# Build production image
docker build --target production -t wifi-densepose:latest .
# Run standalone
docker run -d \
--name wifi-densepose \
-p 8000:8000 \
-e ENVIRONMENT=production \
-e SECRET_KEY=your-secret-key \
wifi-densepose:latestFor the full production stack with Docker Swarm secrets:
# Create required secrets first
echo "db_password_here" | docker secret create db_password -
echo "redis_password_here" | docker secret create redis_password -
echo "jwt_secret_here" | docker secret create jwt_secret -
echo "api_key_here" | docker secret create api_key -
echo "grafana_password_here" | docker secret create grafana_password -
# Set required environment variables
export DATABASE_URL=postgresql://wifi_user:db_password_here@postgres:5432/wifi_densepose
export REDIS_URL=redis://redis:6379/0
export SECRET_KEY=your-secret-key
export JWT_SECRET=your-jwt-secret
export ALLOWED_HOSTS=your-domain.com
export POSTGRES_DB=wifi_densepose
export POSTGRES_USER=wifi_user
# Deploy with Docker Swarm
docker stack deploy -c docker-compose.prod.yml wifi-denseposeProduction compose includes:
- 3 API server replicas with rolling updates and rollback
- Resource limits (2 CPU, 4GB RAM per replica)
- Health checks on all services
- JSON file logging with rotation
- Separate monitoring network (overlay)
- Prometheus with alerting rules and 15-day retention
- Grafana with provisioned datasources and dashboards
The multi-stage Dockerfile provides four targets:
| Target | Use | Command |
|---|---|---|
development |
Local dev with hot-reload | docker build --target development . |
production |
Optimized production image | docker build --target production . |
testing |
Runs pytest during build | docker build --target testing . |
security |
Runs safety + bandit scans | docker build --target security . |
Uses ESP32-S3 boards as WiFi CSI sensor nodes. See ADR-012 for the full specification.
| Item | Qty | Unit Cost | Total |
|---|---|---|---|
| ESP32-S3-DevKitC-1 | 3 | $10 | $30 |
| USB-A to USB-C cables | 3 | $3 | $9 |
| USB power adapter (multi-port) | 1 | $15 | $15 |
| Consumer WiFi router (any) | 1 | $0 (existing) | $0 |
| Aggregator (laptop or Pi 4) | 1 | $0 (existing) | $0 |
| Total | $54 |
Install ESP-IDF (Espressif's official development framework):
# Clone ESP-IDF
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
git checkout v5.2 # Pin to tested version
# Install tools
./install.sh esp32s3
# Activate environment (run each session)
. ./export.shcd firmware/esp32-csi-node
# Set target chip
idf.py set-target esp32s3
# Configure WiFi SSID/password and aggregator IP
idf.py menuconfig
# Navigate to: Component config > WiFi-DensePose CSI Node
# - Set WiFi SSID
# - Set WiFi password
# - Set aggregator IP address
# - Set node ID (1, 2, 3, ...)
# - Set sampling rate (10-100 Hz)
# Build and flash (with USB cable connected)
idf.py build flash monitoridf.py monitor shows live serial output including CSI callback data. Press Ctrl+] to exit.
Repeat for each node, incrementing the node ID.
firmware/esp32-csi-node/
CMakeLists.txt
sdkconfig.defaults # Menuconfig defaults with CSI enabled
main/
main.c # Entry point, WiFi init, CSI callback
csi_collector.c # CSI data collection and buffering
feature_extract.c # On-device FFT and feature extraction
stream_sender.c # UDP stream to aggregator
config.h # Node configuration
Kconfig.projbuild # Menuconfig options
components/
esp_dsp/ # Espressif DSP library for FFT
Each node does on-device feature extraction (raw I/Q to amplitude + phase + spectral bands), reducing bandwidth from ~11 KB/frame to ~470 bytes/frame. Nodes stream features via UDP to the aggregator.
The aggregator collects UDP streams from all ESP32 nodes, performs feature-level fusion (not signal-level -- see ADR-012 for why), and feeds the fused data into the Rust or Python pipeline.
# Start the aggregator and pipeline via Docker
docker compose -f docker-compose.esp32.yml up
# Or run the Rust aggregator directly
cd rust-port/wifi-densepose-rs
cargo run --release --package wifi-densepose-hardware -- --mode esp32-aggregator --port 5000docker exec aggregator python verify_esp32.pyThis captures 10 seconds of data, produces feature JSON, and verifies the hash against the proof bundle.
| Capability | 1 Node | 3 Nodes | 6 Nodes |
|---|---|---|---|
| Presence detection | Good | Excellent | Excellent |
| Coarse motion | Good | Excellent | Excellent |
| Room-level location | None | Good | Excellent |
| Respiration | Marginal | Good | Good |
| Heartbeat | Poor | Poor | Marginal |
| Multi-person count | None | Marginal | Good |
| Pose estimation | None | Poor | Marginal |
Compiles the Rust pipeline to WebAssembly for in-browser execution. See ADR-009 for the edge deployment architecture.
Prerequisites:
# Install wasm-pack
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
# Or via cargo
cargo install wasm-pack
# Add the WASM target
rustup target add wasm32-unknown-unknownBuild:
cd rust-port/wifi-densepose-rs
# Build WASM package (outputs to pkg/)
wasm-pack build crates/wifi-densepose-wasm --target web --release
# Build with disaster response module included
wasm-pack build crates/wifi-densepose-wasm --target web --release -- --features matThe output pkg/ directory contains .wasm, .js glue, and TypeScript definitions. Import in a web project:
import init, { WifiDensePoseWasm } from './pkg/wifi_densepose_wasm.js';
async function main() {
await init();
const processor = new WifiDensePoseWasm();
const result = processor.process_frame(csiJsonString);
console.log(JSON.parse(result));
}
main();Run WASM tests:
wasm-pack test --headless --chrome crates/wifi-densepose-wasmContainer size targets by deployment profile:
| Profile | Size | Suitable For |
|---|---|---|
| Browser (int8 quantization) | ~10 MB | Chrome/Firefox dashboard |
| IoT (int4 quantization) | ~0.7 MB | ESP32, constrained devices |
| Mobile (int8 quantization) | ~6 MB | iOS/Android WebView |
| Field (fp16 quantization) | ~62 MB | Offline disaster tablets |
See Section 6 for full ESP32 setup. The firmware runs on the device itself (C, compiled with ESP-IDF). The Rust aggregator runs on a host machine.
For deploying the WASM runtime to a Raspberry Pi or similar:
# Cross-compile for ARM
rustup target add aarch64-unknown-linux-gnu
cargo build --release --package wifi-densepose-cli --target aarch64-unknown-linux-gnuSee Section 5.
Quick reference:
# Development
docker compose up
# Production standalone
docker build --target production -t wifi-densepose:latest .
docker run -d -p 8000:8000 wifi-densepose:latest
# Production stack (Swarm)
docker stack deploy -c docker-compose.prod.yml wifi-densepose# 1. Install Python dependencies
pip install -r requirements.txt
# 2. Set environment variables (copy from example.env)
cp example.env .env
# Edit .env with your settings
# 3. Run with uvicorn (production)
uvicorn v1.src.api.main:app \
--host 0.0.0.0 \
--port 8000 \
--workers 4
# Or run the Rust API server
cd rust-port/wifi-densepose-rs
cargo run --release --package wifi-densepose-apiPython:
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install all dependencies including dev tools
pip install -r requirements.txt
# Run with auto-reload
uvicorn v1.src.api.main:app --host 0.0.0.0 --port 8000 --reload
# Run verification in another terminal
./verify --verbose
# Run tests
pytest tests/ -v
pytest --cov=wifi_densepose --cov-report=htmlRust:
cd rust-port/wifi-densepose-rs
# Build in debug mode (faster compilation)
cargo build
# Run tests with output
cargo test --workspace -- --nocapture
# Watch mode (requires cargo-watch)
cargo install cargo-watch
cargo watch -x 'test --workspace' -x 'build --release'
# Run benchmarks
cargo bench --package wifi-densepose-signalBoth (visualization + API):
# Terminal 1: Start API server
uvicorn v1.src.api.main:app --host 0.0.0.0 --port 8000 --reload
# Terminal 2: Serve visualization
python3 -m http.server 3000 --directory ui
# Open http://localhost:3000/viz.html -- it connects to ws://localhost:8000/ws/pose| File | Purpose |
|---|---|
./verify |
Trust kill switch -- one-command pipeline proof |
Makefile |
make verify, make verify-verbose, make verify-audit |
v1/requirements-lock.txt |
Pinned Python deps for hash reproducibility |
requirements.txt |
Full Python deps (API server, torch, etc.) |
v1/data/proof/verify.py |
Python verification script |
v1/data/proof/sample_csi_data.json |
Deterministic reference signal |
v1/data/proof/expected_features.sha256 |
Published expected hash |
v1/src/api/main.py |
FastAPI application entry point |
v1/src/sensing/ |
Commodity WiFi sensing module (RSSI) |
rust-port/wifi-densepose-rs/Cargo.toml |
Rust workspace root |
ui/viz.html |
Three.js 3D visualization |
Dockerfile |
Multi-stage Docker build (dev/prod/test/security) |
docker-compose.yml |
Development stack (Postgres, Redis, Prometheus, Grafana) |
docker-compose.prod.yml |
Production stack (Swarm, secrets, resource limits) |
docs/adr/ADR-009-rvf-wasm-runtime-edge-deployment.md |
WASM edge deployment architecture |
docs/adr/ADR-012-esp32-csi-sensor-mesh.md |
ESP32 firmware and mesh specification |
docs/adr/ADR-013-feature-level-sensing-commodity-gear.md |
Commodity WiFi (RSSI) sensing |