mirror of
https://github.com/ruvnet/RuView.git
synced 2026-08-21 22:44:53 +00:00
Reviews and fixes RuView's 10 most recent substantive issues, plus closes the wiring gap flagged in the perception-substrate review (docs/adr, gist, release notes from the PR #1579 review). ## Fixed - #1526: UI falsely claimed "LIVE — ESP32 Hardware Connected" whenever the unauthenticated /api/v1/status probe 401'd. Now sends the bearer token on the probe (the fallback direction was already fixed by ADR-295). - #1554: top-level `classification` (GET /api/v1/sensing/latest) was the last UDP packet's single node, not the fused room aggregate, so it flapped at packet rate with 2+ disagreeing nodes. Now derived from `RoomInference` (ADR-297's `fuse_room`) at both call sites. - #1541: per-node MQTT `presence`/`presence_score` read a `classification` JSON key that does not exist on `NodeInfo` (the real field is `node_inference`), silently falling back to the room aggregate for every node — reproducing the exact "lockstep publish" the field report measured. Also fixed the *existing* regression test for this bug, which used the same wrong key in its own fixture and so never caught it. - #1557: pose-fusion's `wsPortMap` only knew port 3000, so a remapped host port fell through to `localhost:8765` (nothing there for a remote viewer). WS port is now derived from `location.port` instead of a 2-entry lookup table (the "never render simulated as live" half was already fixed by ADR-295's `onVerifiedFrame` gate). - #1525: the no-model pose path already clamps keypoint confidence to a 0.1 floor, but the renderer's own threshold is also 0.1 compared with `<=`/`>` — a keypoint at exactly the floor was still invisible. Floor raised to 0.15 to clear the client's gate. - #1556: `--mqtt-ca-file`/`--mqtt-client-cert`/`--mqtt-client-key` were parsed and stored but never applied — TLS always used the system trust store, so a self-signed broker always failed UnknownIssuer. Now builds `rumqttc::TlsConfiguration::Simple` from the real PEM files (no new TLS dependency needed). A file that can't be read logs why and falls back to system trust instead of failing opaquely later. - #1555: the MQTT availability heartbeat asserted "online" for every known node on a fixed 30s timer regardless of whether that node's data was still arriving. Now tracks each node's last-seen broadcast snapshot and only reports "online" within a 10s freshness window, otherwise "offline" — a frozen sensor can no longer look available. (The other half — restarting a publisher that goes permanently silent — needs a reproduction the reporter themselves weren't certain of; left for a follow-up rather than guessing at the trigger.) - #1540: already fixed on main (node-keyed RateLimiter, ADR-297). - #1521/#1522: not fixable in this repo (published HF model artifact); replied with the ADR-298 gate status and the exact byte-level fix for the safetensors header, and corrected the README row that claimed the file loads with the reference loader. - #1542, #1527: replied — #1542 is a real, larger firmware+server feature left open for follow-up; #1527's suggested fixes were already applied, the one residual sample is an inherent first-frame paint gap. ## Certificate spine wiring (closes the gap flagged in the PR #1579 review) `ruview-certify` and `ruview-policy` now depend on `ruview-ood` and provide real `From<ruview_ood::DomainState>` adapters plus a composed entry point, `ruview_policy::authorize_from_certificate`, matching the adapter contract `ruview-policy`'s own doc comment already described but that no code actually implemented. A new cross-crate integration test (`acceptance_test_b_real_integration`) mints a real signed `CapabilityCertificate` and proves a real post-drift `ruview_ood::Unknown` denies a `SafetyCritical` action through the composed pipeline — not two disconnected unit tests hand-setting the same enum value. Also: - Wires `evaluate_linear_head` (ADR-298 model-release gate) into a new CI job so the checker itself can't silently regress; documents that gating an actual model publish is still a manual step (no HF automation here). - Wires `SourceState::export_watermark()` into `start_recording`: a recording captured while the source is synthetic is now stamped in its metadata (not the filename or per-line JSON, to avoid breaking `delete_recording`'s path reconstruction or the training dataset loader's schema). - Updates docs/user-guide.md's "Developer Preview" section to describe what's now genuinely wired vs. still not (no live continuous calibration/OOD loop in the running server yet). ## Validation - cargo test --workspace --no-default-features: 4391 passed, 0 failed - cargo build --release -p wifi-densepose-sensing-server --features mqtt: clean - Server smoke-tested end-to-end against the simulator (real startup, UDP/WS/HTTP listeners, /api/v1/sensing/latest stable across calls) - Real ESP32-S3 hardware was NOT reachable this session (no COM port present, zero UDP frames received after 40s bound to 0.0.0.0:5005) — the multi-node fixes are validated by the new unit/integration tests and full-workspace regression, not by live hardware. Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|---|---|---|
| .. | ||
| cog-ha-matter | ||
| cog-person-count | ||
| cog-pose-estimation | ||
| homecore | ||
| homecore-api | ||
| homecore-assist | ||
| homecore-automation | ||
| homecore-hap | ||
| homecore-migrate | ||
| homecore-plugin-example | ||
| homecore-plugins | ||
| homecore-recorder | ||
| homecore-server | ||
| nvsim | ||
| nvsim-server | ||
| ruv-neural@c9638faaf8 | ||
| ruview-active | ||
| ruview-attest | ||
| ruview-auth | ||
| ruview-certify | ||
| ruview-counterfactual | ||
| ruview-evidence | ||
| ruview-fusion | ||
| ruview-groundtruth | ||
| ruview-hal | ||
| ruview-infogain | ||
| ruview-memory | ||
| ruview-ontology | ||
| ruview-ood | ||
| ruview-placement | ||
| ruview-policy | ||
| ruview-scorecard | ||
| ruview-swarm@267aba5be2 | ||
| ruview-track | ||
| ruview-twin | ||
| ruview-unified | ||
| ruview-witness | ||
| wifi-densepose-aether | ||
| wifi-densepose-bfld | ||
| wifi-densepose-calibration | ||
| wifi-densepose-cli | ||
| wifi-densepose-core | ||
| wifi-densepose-desktop | ||
| wifi-densepose-engine | ||
| wifi-densepose-hardware | ||
| wifi-densepose-mat | ||
| wifi-densepose-nn | ||
| wifi-densepose-occworld-candle | ||
| wifi-densepose-pointcloud | ||
| wifi-densepose-privshield | ||
| wifi-densepose-rufield | ||
| wifi-densepose-ruvector | ||
| wifi-densepose-sar | ||
| wifi-densepose-sensing-server | ||
| wifi-densepose-signal | ||
| wifi-densepose-train | ||
| wifi-densepose-vitals | ||
| wifi-densepose-wasm | ||
| wifi-densepose-wasm-edge | ||
| wifi-densepose-wifiscan | ||
| worldgraph@4441bc07b5 | ||
| README.md | ||
WiFi-DensePose Rust Crates
See through walls with WiFi. No cameras. No wearables. Just radio waves.
A modular Rust workspace for WiFi-based human pose estimation, vital sign monitoring, and disaster response using Channel State Information (CSI). Built on RuVector graph algorithms and the WiFi-DensePose research platform by rUv.
Performance
| Operation | Python v1 | Rust v2 | Speedup |
|---|---|---|---|
| CSI Preprocessing | ~5 ms | 5.19 us | ~1000x |
| Phase Sanitization | ~3 ms | 3.84 us | ~780x |
| Feature Extraction | ~8 ms | 9.03 us | ~890x |
| Motion Detection | ~1 ms | 186 ns | ~5400x |
| Full Pipeline | ~15 ms | 18.47 us | ~810x |
| Vital Signs | N/A | 86 us (11,665 fps) | -- |
Crate Overview
Core Foundation
| Crate | Description | crates.io |
|---|---|---|
wifi-densepose-core |
Types, traits, and utilities (CsiFrame, PoseEstimate, SignalProcessor) |
|
wifi-densepose-config |
Configuration management (env, TOML, YAML) | |
wifi-densepose-db |
Database persistence (PostgreSQL, SQLite, Redis) |
Signal Processing & Sensing
| Crate | Description | RuVector Integration | crates.io |
|---|---|---|---|
wifi-densepose-signal |
SOTA CSI signal processing (6 algorithms from SpotFi, FarSense, Widar 3.0) | ruvector-mincut, ruvector-attn-mincut, ruvector-attention, ruvector-solver |
|
wifi-densepose-vitals |
Vital sign extraction: breathing (6-30 BPM) and heart rate (40-120 BPM) | -- | |
wifi-densepose-wifiscan |
Multi-BSSID WiFi scanning for Windows-enhanced sensing | -- |
Neural Network & Training
| Crate | Description | RuVector Integration | crates.io |
|---|---|---|---|
wifi-densepose-nn |
Multi-backend inference (ONNX, PyTorch, Candle) with DensePose head (24 body parts) | -- | |
wifi-densepose-train |
Training pipeline with MM-Fi dataset, 114->56 subcarrier interpolation | All 5 crates |
Disaster Response
| Crate | Description | RuVector Integration | crates.io |
|---|---|---|---|
wifi-densepose-mat |
Mass Casualty Assessment Tool -- survivor detection, triage, multi-AP localization | ruvector-solver, ruvector-temporal-tensor |
Hardware & Deployment
| Crate | Description | crates.io |
|---|---|---|
wifi-densepose-hardware |
ESP32, Intel 5300, Atheros CSI sensor interfaces (pure Rust, no FFI) | |
wifi-densepose-wasm |
WebAssembly bindings for browser-based disaster dashboard | |
wifi-densepose-sensing-server |
Axum server: ESP32 UDP ingestion, WebSocket broadcast, sensing UI |
Applications
| Crate | Description | crates.io |
|---|---|---|
wifi-densepose-api |
REST + WebSocket API layer | |
wifi-densepose-cli |
Command-line tool for MAT disaster scanning |
Architecture
wifi-densepose-core
(types, traits, errors)
|
+-------------------+-------------------+
| | |
wifi-densepose-signal wifi-densepose-nn wifi-densepose-hardware
(CSI processing) (inference) (ESP32, Intel 5300)
+ ruvector-mincut + ONNX Runtime |
+ ruvector-attn-mincut + PyTorch (tch) wifi-densepose-vitals
+ ruvector-attention + Candle (breathing, heart rate)
+ ruvector-solver |
| | wifi-densepose-wifiscan
+--------+---------+ (BSSID scanning)
|
+------------+------------+
| |
wifi-densepose-train wifi-densepose-mat
(training pipeline) (disaster response)
+ ALL 5 ruvector + ruvector-solver
+ ruvector-temporal-tensor
|
+-----------------+-----------------+
| | |
wifi-densepose-api wifi-densepose-wasm wifi-densepose-cli
(REST/WS) (browser WASM) (CLI tool)
|
wifi-densepose-sensing-server
(Axum + WebSocket)
RuVector Integration
All RuVector crates at v2.0.4 from crates.io:
| RuVector Crate | Used In | Purpose |
|---|---|---|
ruvector-mincut |
signal, train | Dynamic min-cut for subcarrier selection & person matching |
ruvector-attn-mincut |
signal, train | Attention-weighted min-cut for antenna gating & spectrograms |
ruvector-temporal-tensor |
train, mat | Tiered temporal compression (4-10x memory reduction) |
ruvector-solver |
signal, train, mat | Sparse Neumann solver for interpolation & triangulation |
ruvector-attention |
signal, train | Scaled dot-product attention for spatial features & BVP |
Signal Processing Algorithms
Six state-of-the-art algorithms implemented in wifi-densepose-signal:
| Algorithm | Paper | Year | Module |
|---|---|---|---|
| Conjugate Multiplication | SpotFi (SIGCOMM) | 2015 | csi_ratio.rs |
| Hampel Filter | WiGest | 2015 | hampel.rs |
| Fresnel Zone Model | FarSense (MobiCom) | 2019 | fresnel.rs |
| CSI Spectrogram | Standard STFT | 2018+ | spectrogram.rs |
| Subcarrier Selection | WiDance (MobiCom) | 2017 | subcarrier_selection.rs |
| Body Velocity Profile | Widar 3.0 (MobiSys) | 2019 | bvp.rs |
Quick Start
As a Library
use wifi_densepose_core::{CsiFrame, CsiMetadata, SignalProcessor};
use wifi_densepose_signal::{CsiProcessor, CsiProcessorConfig};
// Configure the CSI processor
let config = CsiProcessorConfig::default();
let processor = CsiProcessor::new(config);
// Process a CSI frame
let frame = CsiFrame { /* ... */ };
let processed = processor.process(&frame)?;
Vital Sign Monitoring
use wifi_densepose_vitals::{
CsiVitalPreprocessor, BreathingExtractor, HeartRateExtractor,
VitalAnomalyDetector,
};
let mut preprocessor = CsiVitalPreprocessor::new(56); // 56 subcarriers
let mut breathing = BreathingExtractor::new(100.0); // 100 Hz sample rate
let mut heartrate = HeartRateExtractor::new(100.0);
// Feed CSI frames and extract vitals
for frame in csi_stream {
let residuals = preprocessor.update(&frame.amplitudes);
if let Some(bpm) = breathing.push_residuals(&residuals) {
println!("Breathing: {:.1} BPM", bpm);
}
}
Disaster Response (MAT)
use wifi_densepose_mat::{DisasterResponse, DisasterConfig, DisasterType};
let config = DisasterConfig {
disaster_type: DisasterType::Earthquake,
max_scan_zones: 16,
..Default::default()
};
let mut responder = DisasterResponse::new(config);
responder.add_scan_zone(zone)?;
responder.start_continuous_scan().await?;
Hardware (ESP32)
use wifi_densepose_hardware::{Esp32CsiParser, CsiFrame};
let parser = Esp32CsiParser::new();
let raw_bytes: &[u8] = /* UDP packet from ESP32 */;
let frame: CsiFrame = parser.parse(raw_bytes)?;
println!("RSSI: {} dBm, {} subcarriers", frame.metadata.rssi, frame.subcarriers.len());
Training
# Check training crate (no GPU needed)
cargo check -p wifi-densepose-train --no-default-features
# Run training with GPU (requires tch/libtorch)
cargo run -p wifi-densepose-train --features tch-backend --bin train -- \
--config training.toml --dataset /path/to/mmfi
# Verify deterministic training proof
cargo run -p wifi-densepose-train --features tch-backend --bin verify-training
Building
# Clone the repository
git clone https://github.com/ruvnet/wifi-densepose.git
cd wifi-densepose/v2
# Check workspace (no GPU dependencies)
cargo check --workspace --no-default-features
# Run all tests
cargo test --workspace --no-default-features
# Build release
cargo build --release --workspace
Feature Flags
| Crate | Feature | Description |
|---|---|---|
wifi-densepose-nn |
onnx (default) |
ONNX Runtime backend |
wifi-densepose-nn |
tch-backend |
PyTorch (libtorch) backend |
wifi-densepose-nn |
candle-backend |
Candle (pure Rust) backend |
wifi-densepose-nn |
cuda |
CUDA GPU acceleration |
wifi-densepose-train |
tch-backend |
Enable GPU training modules |
wifi-densepose-mat |
ruvector (default) |
RuVector graph algorithms |
wifi-densepose-mat |
api (default) |
REST + WebSocket API |
wifi-densepose-mat |
distributed |
Multi-node coordination |
wifi-densepose-mat |
drone |
Drone-mounted scanning |
wifi-densepose-hardware |
esp32 |
ESP32 protocol support |
wifi-densepose-hardware |
intel5300 |
Intel 5300 CSI Tool |
wifi-densepose-hardware |
linux-wifi |
Linux commodity WiFi |
wifi-densepose-wifiscan |
wlanapi |
Windows WLAN API async scanning |
wifi-densepose-core |
serde |
Serialization support |
wifi-densepose-core |
async |
Async trait support |
Testing
# Unit tests (all crates)
cargo test --workspace --no-default-features
# Signal processing benchmarks
cargo bench -p wifi-densepose-signal
# Training benchmarks
cargo bench -p wifi-densepose-train --no-default-features
# Detection benchmarks
cargo bench -p wifi-densepose-mat
Supported Hardware
| Hardware | Crate Feature | CSI Subcarriers | Cost |
|---|---|---|---|
| ESP32-S3 Mesh (3-6 nodes) | hardware/esp32 |
52-56 | ~$54 |
| Intel 5300 NIC | hardware/intel5300 |
30 | ~$50 |
| Atheros AR9580 | hardware/linux-wifi |
56 | ~$100 |
| Any WiFi (Windows/Linux) | wifiscan |
RSSI-only | $0 |
Architecture Decision Records
Key design decisions documented in docs/adr/:
| ADR | Title | Status |
|---|---|---|
| ADR-014 | SOTA Signal Processing | Accepted |
| ADR-015 | MM-Fi + Wi-Pose Training Datasets | Accepted |
| ADR-016 | RuVector Training Pipeline | Accepted (Complete) |
| ADR-017 | RuVector Signal + MAT Integration | Accepted |
| ADR-021 | Vital Sign Detection Pipeline | Accepted |
| ADR-022 | Windows WiFi Enhanced Sensing | Accepted |
| ADR-024 | Contrastive CSI Embedding Model | Accepted |
Related Projects
- WiFi-DensePose -- Main repository (Python v1 + Rust v2)
- RuVector -- Graph algorithms for neural networks (5 crates, v2.0.4)
- rUv -- Creator and maintainer
License
All crates are dual-licensed under MIT OR Apache-2.0.
Copyright (c) 2024 rUv