mirror of
https://github.com/ruvnet/RuView
synced 2026-08-08 20:11:43 +00:00
004a63e82d
- Upgrade openssl to 0.10.78 (CVE-2026-41676), jsonwebtoken to 9.4 - Suppress unmaintained-only/no-CVE advisories in .cargo/audit.toml with per-entry rationale - Fix all `cargo clippy --all-targets -- -D warnings` errors across 35 crates: derivable_impls, needless_range_loop, map_or→is_some_and/ is_none_or, await_holding_lock (drop MutexGuard before .await), ptr_arg (&mut Vec→&mut [T]), useless_conversion, approximate_constant (2.718→E, 3.14→PI), field_reassign_with_default, manual_inspect, useless_vec, lines_filter_map_ok, print_literal, dead_code - Apply `cargo fmt --all` - Pre-existing test failure in wifi-densepose-signal (test_estimate_occupancy_noise_only) is not introduced by this PR
88 lines
2.5 KiB
Rust
88 lines
2.5 KiB
Rust
//! UDP aggregator CLI for receiving ESP32 CSI frames (ADR-018).
|
|
//!
|
|
//! Listens for ADR-018 binary CSI frames on a UDP socket, parses each
|
|
//! packet, and prints a one-line summary to stdout.
|
|
//!
|
|
//! Usage:
|
|
//! cargo run -p wifi-densepose-hardware --bin aggregator -- --bind 0.0.0.0:5005
|
|
|
|
use std::net::UdpSocket;
|
|
use std::process;
|
|
|
|
use clap::Parser;
|
|
use wifi_densepose_hardware::{Esp32CsiParser, ParseError};
|
|
|
|
/// UDP aggregator for ESP32 CSI nodes (ADR-018).
|
|
#[derive(Parser)]
|
|
#[command(
|
|
name = "aggregator",
|
|
about = "Receive and display live CSI frames from ESP32 nodes"
|
|
)]
|
|
struct Cli {
|
|
/// Address:port to bind the UDP listener to.
|
|
#[arg(long, default_value = "0.0.0.0:5005")]
|
|
bind: String,
|
|
|
|
/// Print raw hex dump alongside parsed output.
|
|
#[arg(long, short)]
|
|
verbose: bool,
|
|
}
|
|
|
|
fn main() {
|
|
let cli = Cli::parse();
|
|
|
|
let socket = match UdpSocket::bind(&cli.bind) {
|
|
Ok(s) => s,
|
|
Err(e) => {
|
|
eprintln!("Error: cannot bind to {}: {}", cli.bind, e);
|
|
process::exit(1);
|
|
}
|
|
};
|
|
|
|
eprintln!("Listening on {}...", cli.bind);
|
|
|
|
let mut buf = [0u8; 2048];
|
|
|
|
loop {
|
|
let (n, src) = match socket.recv_from(&mut buf) {
|
|
Ok(r) => r,
|
|
Err(e) => {
|
|
eprintln!("recv error: {}", e);
|
|
continue;
|
|
}
|
|
};
|
|
|
|
if cli.verbose {
|
|
eprintln!(" [{} bytes from {}]", n, src);
|
|
}
|
|
|
|
match Esp32CsiParser::parse_frame(&buf[..n]) {
|
|
Ok((frame, _consumed)) => {
|
|
let mean_amp = frame.mean_amplitude();
|
|
println!(
|
|
"[node:{} seq:{}] sc={} rssi={} amp={:.1}",
|
|
frame.metadata.node_id,
|
|
frame.metadata.sequence,
|
|
frame.subcarrier_count(),
|
|
frame.metadata.rssi_dbm,
|
|
mean_amp,
|
|
);
|
|
}
|
|
// The firmware sends several packet types on this UDP port
|
|
// (ADR-039 vitals, ADR-081 feature state, ADR-095 temporal, …)
|
|
// alongside ADR-018 CSI frames. Those are expected, not errors —
|
|
// this CSI-only aggregator just skips them. (RuView#517)
|
|
Err(ParseError::NonCsiPacket { kind, .. }) => {
|
|
if cli.verbose {
|
|
eprintln!(" [skipped {} packet — not a CSI frame]", kind);
|
|
}
|
|
}
|
|
Err(e) => {
|
|
if cli.verbose {
|
|
eprintln!(" parse error: {}", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|