wifi-densepose/v2/crates/wifi-densepose-sensing-server
ruv b2a692369e feat(adr-115): P4.5b — 6 remaining semantic primitives — all 10 HA-MIND v1 done (66 tests)
Lands the remaining six §3.12 v1 primitives:

- `distress` (PossibleDistress) — EWMA baseline HR + 1.5× multiplier
  + agitated motion + no-fall + 60 s dwell → ON. Refractory 5 min
  after exit. Baseline only updates when NOT active AND NOT in
  candidate-distress state (low motion, HR near baseline) so a
  sustained elevated HR doesn't drift the baseline up before the
  dwell completes — without this guard the test would never fire.
- `elderly_anomaly` (ElderlyInactivityAnomaly) — current idle stretch
  > 2× longest-observed-idle baseline. Baseline floor at 30 min so
  the first day doesn't fire spuriously. 24 h refractory per resident.
- `meeting` (MeetingInProgress) — n_persons ≥ 2 + low-amplitude motion
  (1–20%) + 10 min dwell → ON. 2 min exit dwell on count drop.
- `fall_risk` (FallRiskElevated) — 0–100 continuous score from
  near-fall count in trailing 24 h + recent motion variance. Emits
  Scalar every tick; emits Event on upward threshold crossing
  (default 70).
- `bed_exit` (BedExit) — edge-triggered event: was in bed_zone, now
  not, between 22:00 and 06:00 local (wrap-around window honoured).
- `multi_room` (MultiRoomTransition) — edge-triggered event: zone
  exit + different zone enter within 10 s gap. Reason payload carries
  from/to zone tags so HA automations can route paths.

Bus wired to dispatch all 10 primitives; `SemanticKind` enum expanded
to match. `tick()` returns up to 10 events per snapshot.

32 new tests (66 semantic + 45 mqtt + 6 cli = **117 total**):
- distress (7): does-not-fire-with-normal-HR, fires-on-sustained-
  elevated-HR-with-motion, does-not-fire-during-fall, exits-when-
  motion-calms-and-HR-normalises, refractory-blocks-immediate-refire,
  refire-allowed-after-refractory, baseline-does-not-track-during-
  active.
- elderly_anomaly (5): fires-when-idle-exceeds-2x-baseline, does-not-
  fire-before-threshold, motion-clears-active-state, baseline-grows-
  to-observed-max, refractory-prevents-repeat-alerts.
- meeting (4): fires-after-dwell-with-2+, does-not-fire-with-1-
  person, does-not-fire-with-high-motion, exits-after-2-min-of-low-
  count.
- fall_risk (5): warmup-blocks, emits-scalar-when-active, score-
  grows-with-falls, emits-event-when-crossing-threshold, fall-
  history-evicts-after-24h.
- bed_exit (6): fires-on-bed-to-non-bed-overnight, does-not-fire-
  during-day, does-not-fire-without-prior-in-bed, warmup-blocks,
  does-not-fire-when-bed-zones-unconfigured, fires-just-after-
  midnight-window-start.
- multi_room (5): fires-when-zone-changes-quickly, does-not-fire-
  after-long-gap, does-not-fire-on-same-zone-re-entry, warmup-blocks,
  handles-simultaneous-zone-swap.

ADR-115 §3.12 inference layer now complete. Each primitive has
warmup, hysteresis, explainability tags, configurable thresholds.
Adding a v2 primitive is one file + one bus entry.

Refs #776.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-05-23 14:07:21 -04:00
..
src feat(adr-115): P4.5b — 6 remaining semantic primitives — all 10 HA-MIND v1 done (66 tests) 2026-05-23 14:07:21 -04:00
tests fix(security): audit — fix RUSTSEC vulns, clippy warnings, dead code (#769) 2026-05-23 05:36:13 -04:00
Cargo.toml feat(adr-115): P1 — Cargo features + CLI flags for MQTT/Matter/Semantic 2026-05-23 13:43:02 -04:00
README.md chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427) 2026-04-25 21:28:13 -04:00

README.md

wifi-densepose-sensing-server

Crates.io Documentation License

Lightweight Axum server for real-time WiFi sensing with RuVector signal processing.

Overview

wifi-densepose-sensing-server is the operational backend for WiFi-DensePose. It receives raw CSI frames from ESP32 hardware over UDP, runs them through the RuVector-powered signal processing pipeline, and broadcasts processed sensing updates to browser clients via WebSocket. A built-in static file server hosts the sensing UI on the same port.

The crate ships both a library (wifi_densepose_sensing_server) exposing the training and inference modules, and a binary (sensing-server) that starts the full server stack.

Integrates wifi-densepose-wifiscan for multi-BSSID WiFi scanning per ADR-022 Phase 3.

Features

  • UDP CSI ingestion -- Receives ESP32 CSI frames on port 5005 and parses them into the internal CsiFrame representation.
  • Vital sign detection -- Pure-Rust FFT-based breathing rate (0.1--0.5 Hz) and heart rate (0.67--2.0 Hz) estimation from CSI amplitude time series (ADR-021).
  • RVF container -- Standalone binary container format for packaging model weights, metadata, and configuration into a single .rvf file with 64-byte aligned segments.
  • RVF pipeline -- Progressive model loading with streaming segment decoding.
  • Graph Transformer -- Cross-attention bottleneck between antenna-space CSI features and the COCO 17-keypoint body graph, followed by GCN message passing (ADR-023 Phase 2). Pure std, no ML dependencies.
  • SONA adaptation -- LoRA + EWC++ online adaptation for environment drift without catastrophic forgetting (ADR-023 Phase 5).
  • Contrastive CSI embeddings -- Self-supervised SimCLR-style pretraining with InfoNCE loss, projection head, fingerprint indexing, and cross-modal pose alignment (ADR-024).
  • Sparse inference -- Activation profiling, sparse matrix-vector multiply, INT8/FP16 quantization, and a full sparse inference engine for edge deployment (ADR-023 Phase 6).
  • Dataset pipeline -- Training dataset loading and batching.
  • Multi-BSSID scanning -- Windows netsh integration for BSSID discovery via wifi-densepose-wifiscan (ADR-022).
  • WebSocket broadcast -- Real-time sensing updates pushed to all connected clients at ws://localhost:8765/ws/sensing.
  • Static file serving -- Hosts the sensing UI on port 8080 with CORS headers.

Modules

Module Description
vital_signs Breathing and heart rate extraction via FFT spectral analysis
rvf_container RVF binary format builder and reader
rvf_pipeline Progressive model loading from RVF containers
graph_transformer Graph Transformer + GCN for CSI-to-pose estimation
trainer Training loop orchestration
dataset Training data loading and batching
sona LoRA adapters and EWC++ continual learning
sparse_inference Neuron profiling, sparse matmul, INT8/FP16 quantization
embedding Contrastive CSI embedding model and fingerprint index

Quick Start

# Build the server
cargo build -p wifi-densepose-sensing-server

# Run with default settings (HTTP :8080, UDP :5005, WS :8765)
cargo run -p wifi-densepose-sensing-server

# Run with custom ports
cargo run -p wifi-densepose-sensing-server -- \
    --http-port 9000 \
    --udp-port 5005 \
    --static-dir ./ui

Using as a library

use wifi_densepose_sensing_server::vital_signs::VitalSignDetector;

// Create a detector with 20 Hz sample rate
let mut detector = VitalSignDetector::new(20.0);

// Feed CSI amplitude samples
for amplitude in csi_amplitudes.iter() {
    detector.push_sample(*amplitude);
}

// Extract vital signs
if let Some(vitals) = detector.detect() {
    println!("Breathing: {:.1} BPM", vitals.breathing_rate_bpm);
    println!("Heart rate: {:.0} BPM", vitals.heart_rate_bpm);
}

Architecture

ESP32 ──UDP:5005──> [ CSI Receiver ]
                          |
                    [ Signal Pipeline ]
                    (vital_signs, graph_transformer, sona)
                          |
                    [ WebSocket Broadcast ]
                          |
Browser <──WS:8765── [ Axum Server :8080 ] ──> Static UI files
Crate Role
wifi-densepose-wifiscan Multi-BSSID WiFi scanning (ADR-022)
wifi-densepose-core Shared types and traits
wifi-densepose-signal CSI signal processing algorithms
wifi-densepose-hardware ESP32 hardware interfaces
wifi-densepose-wasm Browser WASM bindings for the sensing UI
wifi-densepose-train Full training pipeline with ruvector
wifi-densepose-mat Disaster detection module

License

MIT OR Apache-2.0