feat(adr-018): ESP32-S3 firmware, Rust aggregator, and live CSI pipeline

Complete end-to-end WiFi CSI capture pipeline verified on real hardware:

- ESP32-S3 firmware: WiFi STA + promiscuous mode CSI collection,
  ADR-018 binary serialization, UDP streaming at ~20 Hz
- Rust aggregator CLI binary (clap): receives UDP frames, parses with
  Esp32CsiParser, prints per-frame summary (node, seq, rssi, amp)
- UDP aggregator module with per-node sequence tracking and drop detection
- CsiFrame bridge to detection pipeline (amplitude/phase/SNR conversion)
- Python ESP32 binary parser with UDP reader
- Presence detection confirmed: motion score 10/10 from live CSI variance

Hardware verified: ESP32-S3-DevKitC-1 (CP2102, MAC 3C:0F:02:EC:C2:28),
Docker ESP-IDF v5.2 build, esptool 5.1.0 flash, 20 Rust + 6 Python tests pass.

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
rUv
2026-02-28 13:22:04 -05:00
parent 885627b0a4
commit 92a5182dc3
22 changed files with 1786 additions and 169 deletions

View File

@@ -3,11 +3,9 @@
//! This crate provides platform-agnostic types and parsers for WiFi CSI data
//! from various hardware sources:
//!
//! - **ESP32/ESP32-S3**: Parses binary CSI frames from ESP-IDF `wifi_csi_info_t`
//! streamed over serial (UART) or UDP
//! - **Intel 5300**: Parses CSI log files from the Linux CSI Tool
//! - **Linux WiFi**: Reads RSSI/signal info from standard Linux wireless interfaces
//! for commodity sensing (ADR-013)
//! - **ESP32/ESP32-S3**: Parses ADR-018 binary CSI frames streamed over UDP
//! - **UDP Aggregator**: Receives frames from multiple ESP32 nodes (ADR-018 Layer 2)
//! - **Bridge**: Converts CsiFrame → CsiData for the detection pipeline (ADR-018 Layer 3)
//!
//! # Design Principles
//!
@@ -21,8 +19,8 @@
//! ```rust
//! use wifi_densepose_hardware::{CsiFrame, Esp32CsiParser, ParseError};
//!
//! // Parse ESP32 CSI data from serial bytes
//! let raw_bytes: &[u8] = &[/* ESP32 CSI binary frame */];
//! // Parse ESP32 CSI data from UDP bytes
//! let raw_bytes: &[u8] = &[/* ADR-018 binary frame */];
//! match Esp32CsiParser::parse_frame(raw_bytes) {
//! Ok((frame, consumed)) => {
//! println!("Parsed {} subcarriers ({} bytes)", frame.subcarrier_count(), consumed);
@@ -39,7 +37,10 @@
mod csi_frame;
mod error;
mod esp32_parser;
pub mod aggregator;
mod bridge;
pub use csi_frame::{CsiFrame, CsiMetadata, SubcarrierData, Bandwidth, AntennaConfig};
pub use error::ParseError;
pub use esp32_parser::Esp32CsiParser;
pub use bridge::CsiData;