Skip to content

Releases: ruvnet/RuView

v0.6.2-esp32 — ADR-081 Adaptive CSI Mesh Kernel + Timer Svc stack fix

20 Apr 15:09

Choose a tag to compare

First firmware release of the ADR-081 Adaptive CSI Mesh Kernel, plus the Timer Service stack-overflow regression fix caught by on-device validation. Ships both 8 MB and 4 MB variants from CI.

Highlights

  • 5-layer adaptive CSI kernel (Radio Abstraction → Adaptive Controller → Mesh Plane → Feature State → Rust handoff) — swap radio silicon without touching the Rust signal/ruvector/mat crates
  • 60-byte rv_feature_state_t packet (magic 0xC5110006) replaces raw CSI as the default upstream — ~99.7 % bandwidth reduction (300 B/s at 5 Hz vs ~100 KB/s raw)
  • Mesh sensing plane (rv_mesh) with 4 roles, 7 message types, CRC32-integrity envelope — HEALTH every 30 s, ANOMALY_ALERT on state transitions
  • Host-testable pure decision policy (adaptive_controller_decide.c) — 33/33 assertions, decide() at 3.2 ns/call
  • 4 MB variant (ESP32-S3 SuperMini) now built in CI alongside the 8 MB default

Validated on real hardware

ESP32-S3 QFN56 rev v0.2 (MAC 3c:0f:02:e9:b5:f8), 38 s continuous run after flash:

  • App version: 0.6.2
  • 0 stack-overflow / panic / reboot markers
  • 28 adaptive_ctrl medium ticks, steady state, no drift
  • 149 rv_feature_state_t emissions at ~5 Hz on earlier 30 s validation
  • Real WiFi CSI: 37 – 72 pps yield, RSSI -43 to -57 dBm

Fixes

Fix Detail
Timer Svc stack overflow (new) emit_feature_state() + stream_sender network I/O runs inside FreeRTOS Timer Svc; ESP-IDF default 2 KiB stack overflows ~1 s after boot. Bumped CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=8192 in all three sdkconfig.defaults*. Follow-up: move heavy work out of the timer daemon.
adaptive_controller.c implicit decl (#404) fast_loop_cb called emit_feature_state() before its static definition, tripping -Werror=implicit-function-declaration. Added forward declaration.
provision.py esptool v5 compat (#391) write-flash (hyphenated) in dry-run hint for esptool ≥ 5.
provision.py silent NVS wipe (#391) Now refuses to run without --ssid, --password, --target-ip unless --force-partial is passed; --force-partial prints which keys will be wiped.
Defensive node_id capture (#232, #375, #385, #386, #390) csi_collector_init() now captures g_nvs_config.node_id once into a module-local; a canary WARN fires on divergence.

CI change

firmware-ci.yml is now a matrix job building both variants in parallel and uploading variant-named artifacts — 6-binary releases no longer need local ESP-IDF.

Installing

Six binaries are attached below. The default flash layout for ESP32-S3 8 MB:

esptool.py --chip esp32s3 --port /dev/ttyUSB0 --baud 460800 \
  --before default_reset --after hard_reset \
  write_flash -z --flash_mode dio --flash_freq 80m --flash_size 8MB \
  0x0      bootloader.bin \
  0x8000   partition-table.bin \
  0xf000   ota_data_initial.bin \
  0x20000  esp32-csi-node.bin

For ESP32-S3 SuperMini 4 MB, use esp32-csi-node-4mb.bin at 0x20000 and partition-table-4mb.bin at 0x8000 (reuse the same bootloader and OTA data).

After flash, provision WiFi + target (replaces the full csi_cfg NVS namespace — pass all creds at once):

python firmware/esp32-csi-node/provision.py \
  --port /dev/ttyUSB0 \
  --ssid <SSID> --password <PSK> --target-ip <DEST_IP>

Artifacts

File Size Target
esp32-csi-node.bin 1.06 MB 8 MB app (flash @ 0x20000)
esp32-csi-node-4mb.bin 851 KB 4 MB app (flash @ 0x20000)
bootloader.bin 18 KB Both (flash @ 0x0)
partition-table.bin 3 KB 8 MB layout (flash @ 0x8000)
partition-table-4mb.bin 3 KB 4 MB layout (flash @ 0x8000)
ota_data_initial.bin 8 KB OTA data (flash @ 0xf000)

Compatibility

  • ESP-IDF: v5.4
  • Target: ESP32-S3 (Xtensa dual-core). Not supported: ESP32 (original), ESP32-C3 (single-core, can't run CSI DSP).
  • Supersedes: v0.6.1-esp32
  • Wire format: rv_feature_state_t magic 0xC5110006 is the new default upstream; raw ADR-018 CSI (magic 0xC5110001) remains available as a debug stream gated by the channel plan.

Reference

  • ADR-081 — Adaptive CSI Mesh Firmware Kernel (docs/adr/ADR-081-adaptive-csi-mesh-firmware-kernel.md)
  • Full changelog entry: CHANGELOG.md#v062-esp32
  • Source tag: ae40e2b

ESP32-S3 CSI Firmware v0.6.1 — Defensive node_id Fix

16 Apr 14:38

Choose a tag to compare

ESP32-S3 CSI Firmware v0.6.1

Critical fix: node_id clobber on multi-node deployments

Closes #232, #375, #385, #386, #390.

Users on multi-node deployments reported that every ESP32 node transmitted node_id=1 in UDP frames, despite NVS provisioning showing the correct value. This made multi-node setups indistinguishable downstream.

What changed

Defense-in-depth fix — the firmware now captures node_id into a module-local static at init time, isolating the UDP frame header from any memory corruption of g_nvs_config:

  1. csi_collector_init() captures g_nvs_config.node_id into static uint8_t s_node_id once at init
  2. csi_serialize_frame() writes buf[4] = s_node_id — bypasses the global entirely
  3. All other consumers (edge_processing.c, wasm_runtime.c, display_ui.c, swarm_bridge_init) use the new csi_collector_get_node_id() accessor
  4. Clobber canary logs WARN if g_nvs_config.node_id diverges from the captured value at init — helps isolate the upstream corruption path

Hardware validation (ESP32-S3 on COM8)

Check Result
NVS node_id 2 (provisioned)
Boot log main: Node ID: 2
Defensive capture log Captured node_id=2 at init
csi_collector init log node_id=2, channel=5
UDP packets (15/15) byte[4] = 2
Clobber canary Quiet (no WARN)
App version 0.6.1
Binary size 865 KB (54% flash free)

Binaries

File Flash size Description
esp32-csi-node.bin 8MB Main firmware
bootloader.bin 8MB Bootloader
partition-table.bin 8MB Partition table (dual OTA)
ota_data_initial.bin 8MB OTA data
esp32-csi-node-4mb.bin 4MB Main firmware (SuperMini)
partition-table-4mb.bin 4MB Partition table (SuperMini)

Flash command

python -m esptool --chip esp32s3 -p COM8 -b 460800 \
  --before default_reset --after hard_reset \
  write_flash --flash_mode dio --flash_size 8MB --flash_freq 80m \
  0x0 bootloader.bin \
  0x8000 partition-table.bin \
  0xf000 ota_data_initial.bin \
  0x20000 esp32-csi-node.bin

For 4MB SuperMini boards, use esp32-csi-node-4mb.bin and partition-table-4mb.bin with --flash_size 4MB.

SHA-256 hashes

7f943b26...88197f7  bootloader.bin
9e650bf1...54bd43   esp32-csi-node.bin
15c263f6...02b32    esp32-csi-node-4mb.bin
7d2c7ac4...82c62f   ota_data_initial.bin
4c2cc4ff...d81f0    partition-table.bin
4c2cc4ff...d81f0    partition-table-4mb.bin

Who should upgrade

All users running multi-node ESP32-S3 deployments. Single-node users are unaffected but the upgrade is safe.

v0.7.0 — WiFlow Camera-Supervised Pose Model (92.9% PCK@20)

06 Apr 21:30
8dddbf9

Choose a tag to compare

WiFlow v1 — Camera-Supervised WiFi Pose Estimation

First WiFlow model trained on real ESP32 CSI + real camera ground truth.

Headline Result

Metric Value
PCK@20 92.9%
Eval loss 0.082
Bone constraint 0.008
Parameters 186,946
Model size 974 KB
Training time 19 minutes

What's New

Camera Ground-Truth Pipeline (ADR-079)

  • collect-ground-truth.py — MediaPipe webcam capture synced with CSI
  • align-ground-truth.js — Nanosecond time alignment
  • train-wiflow-supervised.js — 3-phase curriculum training
  • eval-wiflow.js — PCK/MPJPE evaluation
  • record-csi-udp.py — Lightweight ESP32 CSI recorder

ruvector Optimizations

  • O6: Subcarrier selection (70→35, 50% reduction)
  • O7: Attention-weighted subcarriers
  • O8: Stoer-Wagner min-cut person separation
  • O9: Multi-SPSA gradient estimation
  • O10: Scalable model (lite/small/medium/full)

Data Collection

  • ESP32-S3 CSI: 7,000 frames at 23fps (5 min)
  • Mac Mini M4 Pro camera: 6,470 frames via MediaPipe (5 min)
  • 345 time-aligned paired samples

Model Archive Contents

  • wiflow-v1.json — Trained model weights (974 KB)
  • training-log.json — Loss curves per phase
  • baseline-report.json — Pre-training baseline metrics
  • MODEL_CARD.md — Model documentation

How to Use

# Collect your own ground truth
python scripts/collect-ground-truth.py --duration 300 --preview
python scripts/record-csi-udp.py --duration 300

# Train
node scripts/train-wiflow-supervised.js --data data/paired/your-data.jsonl --scale lite

# Evaluate
node scripts/eval-wiflow.js --model models/wiflow-real/wiflow-v1.json --data data/paired/your-data.jsonl

Related

  • PR #363: Camera ground-truth training pipeline
  • ADR-079: Camera Ground-Truth Training Pipeline
  • ADR-072: WiFlow Architecture

v0.6.0 — Pre-Trained Models on HuggingFace + 17 Sensing Apps

03 Apr 14:08
aae01a2

Choose a tag to compare

Pre-trained weights: https://huggingface.co/ruv/ruview | mirror

0.008ms inference | 164K emb/s | 100% presence | 51.6% contrastive improvement | 8 KB model

Trained on 60,630 overnight samples. 17 sensing applications. 10 ADRs (069-078).

New: sleep monitor, apnea detector, stress monitor, gait analyzer, RF tomography, passive radar, material classifier, through-wall detector, device fingerprint.

PR #341 (Kalman tracker by @taylorjdawson) + PR #310 (security fix) merged.

HuggingFace | Cognitum.one | Tutorial

ESP32-S3 CSI Firmware v0.5.5 — Advanced Sensing + WiFlow + Camera-Free Training

03 Apr 12:13
4e9e92d

Choose a tag to compare

v0.5.5 — Advanced Sensing, WiFlow Architecture, Camera-Free Pose Training

TL;DR

Your $27 sensor kit now has spiking neural networks that learn your room in 30 seconds, min-cut person counting that actually works (fixes #348), CNN spectrogram embeddings for environment fingerprinting, multi-frequency mesh scanning across 6 WiFi channels, and the WiFlow SOTA architecture (1.8M params) for 17-keypoint pose estimation — all trainable without a camera.

What Changed (v0.5.4 → v0.5.5)

Feature v0.5.4 v0.5.5
Person counting Broken (always 4) MinCut: correct count (fixes #348)
WiFi channels 1 (ch 5 only) 6 channels (hopping 1/3/5/6/9/11)
Pose model Simple 8→64→128 encoder WiFlow: TCN + axial attention (1.8M params)
Pose keypoints 5 proxy → 17 interpolated 17 COCO keypoints (WiFlow decoder)
Online learning None SNN with STDP (adapts in <30s)
Environment fingerprint 8-dim features 128-dim CNN spectrogram
Multi-node fusion Average Graph transformer (GATv2 attention)
RF scanning None Live spectrum visualization
Neighbor WiFi Ignored Used as passive radar illuminators
Training pipeline ruvllm basic + camera-free + WiFlow + GCloud + Mac Mini
ADRs 069-071 069-076 (8 total)

New Capabilities

ADR-073: Multi-Frequency Mesh Scanning

ESP32 nodes hop across channels 1/3/5/6/9/11 at 200ms dwell. Neighbor WiFi networks (your printer, router, neighbors) become free RF illuminators. Null subcarriers dropped from 19% to 16%.

# Provision channel hopping
python firmware/esp32-csi-node/provision.py --port COM9 \
  --hop-channels "1,6,11" --hop-dwell 200

# Live RF scan
node scripts/rf-scan.js --port 5006 --duration 30

ADR-074: Spiking Neural Network

128→64→8 SNN with STDP unsupervised learning. Adapts to room in <30s without labels. 16-160x less compute than the FC encoder (event-driven, only processes changes).

node scripts/snn-csi-processor.js --port 5006

ADR-075: MinCut Person Separation (fixes #348)

Stoer-Wagner min-cut on subcarrier correlation graph. Correctly counts 1 person on all 24 test windows where old firmware showed 4. <5ms per window.

node scripts/mincut-person-counter.js --port 5006
# Or replay: node scripts/mincut-person-counter.js --replay data/recordings/*.csi.jsonl

ADR-076: CNN Spectrogram Embeddings + Graph Transformer

CSI 64×20 matrix → 224×224 grayscale → CNN → 128-dim embedding. Same-node similarity 0.95+. GATv2 multi-head attention fuses multi-node features.

node scripts/csi-spectrogram.js --replay data/recordings/*.csi.jsonl
node scripts/mesh-graph-transformer.js --port 5006

ADR-072: WiFlow SOTA Architecture

Full reimplementation of WiFlow (arXiv:2602.08661) in pure JS:

  • TCN temporal encoder (dilated causal conv, k=7)
  • Asymmetric spatial encoder (1×3 residual blocks)
  • Axial self-attention (8 heads, width + height)
  • Pose decoder → 17 COCO keypoints
  • SmoothL1 + bone constraint loss (14 skeleton connections)
  • 1.8M parameters (881 KB at 4-bit quantization)

Camera-Free Training (ADR-071 extended)

10 sensor signals replace cameras: PIR, BME280 temp/humidity, RSSI triangulation, subcarrier asymmetry, vibration, reed switch, kNN clusters, boundary fragility.

5-phase pipeline: multi-modal collection → weak labels → 5-keypoint proxy → 17-keypoint interpolation → self-refinement.

Validated Benchmarks

Metric Value
Rust tests 1,463 passed
Presence accuracy 100%
MinCut person count 24/24 correct (was 0/24)
Inference latency 0.012 ms (M4 Pro)
Throughput 171,472 emb/s
WiFlow PCK@20 2.5% (camera-free baseline)
WiFlow parameters 1,804,962
WiFlow model (4-bit) 881 KB
CNN spectrogram similarity 0.95+ (same-node)
SNN adaptation time <30s (STDP online)
Channel hopping 6 channels, 200ms dwell
Null reduction 19% → 16%

Flash Instructions

Same firmware binary as v0.5.4 (channel hopping is NVS-configured, no reflash needed for existing v0.5.4 users):

python -m esptool --chip esp32s3 --port COM9 --baud 460800 \
  write_flash --flash-mode dio --flash-size 8MB --flash-freq 80m \
  0x0 bootloader.bin 0x8000 partition-table.bin \
  0xf000 ota_data_initial.bin 0x20000 esp32-csi-node.bin

# Enable channel hopping (new in v0.5.5)
python firmware/esp32-csi-node/provision.py --port COM9 \
  --hop-channels "1,6,11" --hop-dwell 200

New Scripts (15+)

Script Purpose
rf-scan.js Live RF spectrum scanner
rf-scan-multifreq.js Multi-channel wideband view
snn-csi-processor.js Spiking neural network processor
mincut-person-counter.js Correct person counting
csi-graph-visualizer.js Correlation graph visualization
csi-spectrogram.js CNN spectrogram embeddings
mesh-graph-transformer.js GATv2 multi-node fusion
train-wiflow.js WiFlow SOTA training
train-camera-free.js Camera-free 17-keypoint training
train-ruvllm.js ruvllm contrastive + LoRA + TurboQuant
benchmark-ruvllm.js Model benchmarking
benchmark-wiflow.js WiFlow benchmarking
benchmark-rf-scan.js RF scan benchmarking
wiflow-model.js WiFlow architecture (pure JS)
seed_csi_bridge.py ESP32 → Cognitum Seed ingest

Learn more: Cognitum.one · Tutorial · User Guide

Full Changelog: v0.5.4-esp32...v0.5.5-esp32


Session Statistics

Metric Value
Commits 24
Files changed 74
Lines added 22,231
ADRs 8 (069-076)
Research docs 26
New scripts 20+
PRs merged 2 (#350, #352)
Issues addressed 4 (#348, #188, #190, #268)
Rust tests 1,463 passed
WiFlow PCK@20 2.5% (camera-free, improving with more data)
Overnight data 65,938+ frames collecting
Session cost ~$0.50 (Mac Mini electricity)

ESP32-S3 CSI Firmware v0.5.4 — Cognitum Seed Integration

02 Apr 23:56
7b12b36

Choose a tag to compare

ESP32-S3 CSI Firmware v0.5.4 — Cognitum Seed Integration

TL;DR

Your ESP32 can now remember what it senses. By connecting to a Cognitum Seed every presence detection, breathing measurement, and motion event gets stored as a searchable vector with cryptographic proof it happened.

What Changed (v0.5.3 → v0.5.4)

Feature v0.5.3 v0.5.4
CSI sensing ✅ Real-time only Real-time + persistent storage
Data retention ❌ Lost on reboot RVF vector store on Cognitum Seed
Similarity search ❌ None kNN queries ("find states like this one")
Data integrity ❌ None SHA-256 witness chain + Ed25519 signing
AI integration ❌ None 114-tool MCP proxy (Claude, GPT can query sensors)
Environmental sensors ❌ CSI only + BME280, PIR, vibration, ADC (via Seed)
Feature vectors ❌ Raw only 8-dim normalized @ 1 Hz (new packet 0xC5110003)
Security Basic Bearer tokens, TLS, source filtering, NaN rejection

New: 8-Dimension Feature Vector

Every second, the ESP32 sends a compact 48-byte packet summarizing what it sees:

Dim What it measures Example
0 Is someone there? (presence) 0.45 = maybe, 0.95 = definitely
1 Are they moving? (motion) 0.0 = still, 0.87 = active
2 Breathing rate 0.69 = 20.8 BPM (normal)
3 Heart rate 0.75 = 90 BPM (normal)
4 Signal quality (phase variance) Higher = more activity
5 How many people? 0.25 = 1 person, 0.50 = 2
6 Fall detected? 0.0 = no, 1.0 = yes
7 Signal strength (RSSI) 0.54 = -46 dBm (good)

These vectors are stored on the Cognitum Seed and can be searched: "Find the 10 most similar states to right now" — useful for anomaly detection, pattern recognition, and environment fingerprinting.

Architecture

ESP32-S3 ($9)  ──UDP──>  Your laptop  ──HTTPS──>  Cognitum Seed ($15)
  WiFi CSI capture          Bridge script            Stores vectors forever
  28 Hz raw frames          Batches & validates      kNN similarity search
  1 Hz feature vectors      NaN rejection            Witness chain (proof)
  1 Hz vital signs          Source filtering          114-tool AI proxy

How to Use

# 1. Flash firmware to ESP32-S3
python -m esptool --chip esp32s3 --port COM9 --baud 460800 \
  write_flash --flash-mode dio --flash-size 8MB --flash-freq 80m \
  0x0 bootloader.bin 0x8000 partition-table.bin \
  0xf000 ota_data_initial.bin 0x20000 esp32-csi-node.bin

# 2. Set WiFi + target (your laptop IP)
python firmware/esp32-csi-node/provision.py --port COM9 \
  --ssid "YourWiFi" --password "secret" \
  --target-ip 192.168.1.20 --target-port 5006

# 3. Pair with Cognitum Seed (plug in via USB first)
curl -sk -X POST https://169.254.42.1:8443/api/v1/pair/window
curl -sk -X POST https://169.254.42.1:8443/api/v1/pair \
  -H 'Content-Type: application/json' -d '{"client_name":"my-laptop"}'

# 4. Run the bridge
export SEED_TOKEN="<token-from-step-3>"
python scripts/seed_csi_bridge.py \
  --seed-url https://169.254.42.1:8443 --token "$SEED_TOKEN" --validate

# 5. Check what's stored
python scripts/seed_csi_bridge.py --token "$SEED_TOKEN" --stats

No Cognitum Seed? The ESP32 firmware works exactly as before — all existing features (CSI streaming, vitals, presence, fall detection, mesh TDM) are unchanged. The Seed integration is additive.

Learn more: Cognitum.one · ADR-069 · User Guide

Validation Results

Test Result
Rust workspace 1,463 passed, 0 failed
Python proof VERDICT: PASS
Firmware size 844 KB (55% flash free)
Feature vectors 1 Hz, 8-dim, all in [0.0, 1.0]
Vitals ↔ Features HR delta=0.0, BR delta=0.0
Seed ingest 941 vectors, 100% kNN match
Witness chain SHA-256 verified (1,325 entries)
Regression 6/6 PASSED — NO REGRESSIONS

Binary Hashes (SHA-256)

cf05de2b  esp32-csi-node.bin   (844 KB)
cbb8e3ba  bootloader.bin       (19 KB)
4c2cc4ff  partition-table.bin  (3 KB)
7d2c7ac4  ota_data_initial.bin (8 KB)

Full Changelog: v0.5.3-esp32...v0.5.4-esp32

ESP32-S3 CSI Firmware v0.5.3 — Cross-Node Fusion + DynamicMinCut

31 Mar 01:56
3733e54

Choose a tag to compare

What's Changed

Cross-Node Mesh Fusion

  • RSSI-weighted feature fusion across multiple ESP32 nodes — closer node gets higher weight
  • DynamicMinCut person separation via ruvector_mincut on subcarrier temporal correlation graph
  • RSSI-based skeleton position tracking — walk between nodes and the skeleton follows
  • Motion-responsive skeleton — arm swing (0-80px), leg kick (0-50px), walking bob, head nod all driven by real CSI data

Per-Node State (ADR-068)

  • Each ESP32 gets independent classification, vitals, person count
  • Stale node eviction after 60s inactivity
  • Multi-node aggregation: max(per_node_counts)

RuVector Signal Processing (Phases 1-3)

  • Subcarrier importance weighting via mincut partition
  • Temporal EMA keypoint smoothing with coherence gating
  • Skeleton kinematic constraints (Jakobsen relaxation, 12-bone COCO-17 tree)
  • Compressed pose history for trajectory matching

Smoothing & Quality

  • Client-side lerp interpolation (alpha=0.15) for fluid skeleton
  • Server EMA (alpha=0.15) for temporal blending
  • Dampened procedural animation, recalibrated for real ESP32 data
  • Vital sign filtering: larger median window (31), faster EMA, looser jump filter

Hardware Benchmarks (2 ESP32 nodes, 30s)

Metric v0.5.2 (baseline) v0.5.3 (fusion) Improvement
Keypoint jitter std=4.5px std=1.3px -72%
Feature noise 109.4 77.6 -29%
Feature stability std=154.1 std=105.4 -32%
Confidence 0.643 0.686 +7%
Presence accuracy 93.4% 94.6% +1.3pp

Bug Fixes

  • RSSI byte offset (#332), stack overflow, stale node leak, unsafe pointer removed
  • Person count: sum→max aggregation, recalibrated thresholds
  • Firmware CI: IDF v5.4, xxd→od

Binaries

File Flash Size Description
esp32-csi-node.bin 8MB Main firmware
esp32-csi-node-4mb.bin 4MB For 4MB flash boards
bootloader.bin Bootloader
partition-table.bin 8MB Partition table
partition-table-4mb.bin 4MB Partition table (4MB)
ota_data_initial.bin OTA data

Full Changelog: v0.5.2-esp32...v0.5.3-esp32

ESP32-S3 CSI Firmware v0.5.2 — RSSI Fix + Per-Node State

30 Mar 16:02
9814d2b

Choose a tag to compare

What's Changed

Bug Fixes

RSSI byte offset mismatch (#332)

  • Server was reading RSSI from byte 14 (sequence counter high byte) instead of byte 16 (actual RSSI)
  • Root cause: firmware packs n_subcarriers as u16 and freq_mhz as u32, but server assumed u8 and u16
  • Result: RSSI now shows correct negative dBm values (e.g., -46) instead of bogus positive values (+9)

Per-node state pipeline (#249, ADR-068)

  • Each ESP32 node now gets independent classification, person count, and vital sign tracking
  • Fixes the #1 user-reported issue: detection showing same output regardless of number of nodes/people
  • Scales to 256 nodes with <13 MB memory overhead

Firmware CI fixed (#327)

  • Upgraded from ESP-IDF v5.2 → v5.4, replaced xxd with od
  • Pre-compiled binaries now built and uploaded automatically

Sensing Server

Rebuild from source to get all fixes:

git pull origin main
cd rust-port/wifi-densepose-rs
cargo build --release -p wifi-densepose-sensing-server

Firmware

No firmware binary changes from v0.5.1 — the RSSI fix and per-node state are server-side only. If you already flashed v0.5.1, no reflash needed.

Full Changelog: v0.5.1-esp32...v0.5.2-esp32

ESP32-S3 CSI Firmware v0.5.1 — Watchdog Fix + Edge Detection

27 Mar 21:31
40f1962

Choose a tag to compare

What's Changed

Bug Fixes

Firmware: Watchdog crash on busy LANs (#321)

  • edge_dsp task now batch-limits to 4 frames before a 20ms yield
  • Fixed idle-path busy-spin where pdMS_TO_TICKS(5)==0 at 100Hz tick rate
  • Added ring buffer drop counter (drops=N in serial log) for diagnostics
  • QEMU validated: All 11 CI jobs pass (7 configs + fuzz + swarm + NVS + build)

Sensing Server: No detection from edge vitals (#323)

  • ESP32 nodes running Tier 2+ edge DSP now trigger full sensing_update in the UI
  • Previously, vitals packets (magic 0xC5110002) were broadcast but never generated person detection
  • Breathing animation now works from edge vitals (non-zero breathing_band_power)

Python Package: ModuleNotFoundError (#314)

  • Added wifi_densepose/ package with WiFiDensePose facade class
  • from wifi_densepose import WiFiDensePose now works as documented in README

CI Validation

Job Status
Build Espressif QEMU
NVS Matrix Generation
Fuzz Testing (ADR-061 Layer 6)
Swarm Test (ADR-062)
QEMU Test — default
QEMU Test — edge-tier0
QEMU Test — edge-tier1
QEMU Test — tdm-3node
QEMU Test — boundary-min
QEMU Test — boundary-max
QEMU Test — full-adr060

Upgrade Notes

  • Firmware: Reflash required for the watchdog fix. Build from source using ESP-IDF v5.4.
  • Sensing server: Rebuild from maincargo build --release -p wifi-densepose-sensing-server
  • Python: pip install -e . from repo root, or from wifi_densepose import WiFiDensePose

Full Changelog: v0.5.0-esp32...v0.5.1-esp32

ESP32-S3 CSI Firmware v0.5.0 — mmWave Sensor Fusion

15 Mar 20:15
66e2fa0

Choose a tag to compare

ESP32-S3 CSI Firmware v0.5.0 — mmWave Sensor Fusion (ADR-063/064)

What's New

60 GHz mmWave Radar Fusion — The firmware now auto-detects mmWave radar modules connected via UART and fuses their data with WiFi CSI for dramatically improved sensing.

Supported mmWave sensors:

Sensor Frequency Capabilities Cost
Seeed MR60BHA2 60 GHz Heart rate, breathing, presence, distance ~$15
HLK-LD2410 24 GHz Presence, distance (motion + static) ~$3

Auto-detection: The firmware probes UART1 (GPIO17/18) at boot — first at 115200 baud (MR60BHA2), then 256000 baud (LD2410). If a sensor is found, it registers capabilities and starts a background parsing task. No configuration needed.

48-byte fused vitals packet (magic 0xC5110004): When mmWave is active, vitals are fused using weighted Kalman averaging (mmWave 80% + CSI 20%). Falls back to the standard 32-byte CSI-only packet when no mmWave is detected — fully backward compatible.

Server-side fusion bridge (scripts/mmwave_fusion_bridge.py): For setups where the mmWave runs on a separate ESP32 (e.g., ESP32-C6 with ESPHome), this script reads both serial ports and fuses data in real-time.

Hardware Verified

Dual-sensor live capture (30 seconds, 2026-03-15):

  • COM7 (ESP32-S3): WiFi CSI on channel 5, RSSI -41 dBm
  • COM4 (ESP32-C6 + MR60BHA2): HR 75 bpm, BR 25/min, person at 52 cm
  • Both sensors feeding data concurrently

Also Includes (from v0.4.3.1)

  • Fall detection fix: threshold 15.0 rad/s², 3-frame debounce, 5s cooldown (#263)
  • Task watchdog fix: vTaskDelay after every frame (#266)
  • 4MB flash support (#265)
  • All 11 QEMU CI jobs green

Download Guide

File Flash Size
esp32-csi-node.bin 8MB 990 KB
bootloader.bin Both 18 KB
partition-table.bin 8MB 3 KB
ota_data_initial.bin Both 8 KB
esp32-csi-node-4mb.bin 4MB 773 KB
partition-table-4mb.bin 4MB 3 KB

Flash — 8MB:

python -m esptool --chip esp32s3 --port COM7 --baud 460800 \
  write_flash --flash_mode dio --flash_size 8MB --flash_freq 80m \
  0x0 bootloader.bin 0x8000 partition-table.bin \
  0xf000 ota_data_initial.bin 0x20000 esp32-csi-node.bin

Flash — 4MB:

python -m esptool --chip esp32s3 --port COM7 --baud 460800 \
  write_flash --flash_mode dio --flash_size 4MB --flash_freq 80m \
  0x0 bootloader.bin 0x8000 partition-table-4mb.bin \
  0xF000 ota_data_initial.bin 0x20000 esp32-csi-node-4mb.bin

Provision:

python firmware/esp32-csi-node/provision.py --port COM7 \
  --ssid "YourWiFi" --password "YourPassword" --target-ip 192.168.1.20

Full Changelog

See CHANGELOG.md

Closes #269