From 68068d73d8f362de807afd023f00e4d0b7f2def0 Mon Sep 17 00:00:00 2001 From: arsen Date: Sun, 17 May 2026 12:04:11 +0700 Subject: [PATCH] =?UTF-8?q?feat(adr-106):=20server-side=20=C2=B5s=20timest?= =?UTF-8?q?amp=20on=20raw-CSI=20ingest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the first ADR-106 open item without an FW change. On every raw-CSI frame we now stamp `ns.latest_timestamp_us` with SystemTime::now() in µs since UNIX epoch. NodeInfo.timestamp_us surfaces it on WS via the already-wired skip_serializing_if guard. Accuracy is wall-clock + Mac monotonic + LAN jitter ≈ ~1 ms. Verified cross-node skew ts(node1) - ts(node2) = 1556 µs in a single test, well within the 5-10 ms tolerance needed for FFT-based vital-signs correlation across sensors. Sensor-side ESP-IDF rx_ctrl.timestamp (true RX-time µs) is still better and remains on the open list for a future FW header bump (reserved bytes [18..19] are only 2 of the 4 we'd need — header extension required, opt-in via new magic). --- v2/crates/wifi-densepose-sensing-server/src/main.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/v2/crates/wifi-densepose-sensing-server/src/main.rs b/v2/crates/wifi-densepose-sensing-server/src/main.rs index f978e054..722ab4fd 100644 --- a/v2/crates/wifi-densepose-sensing-server/src/main.rs +++ b/v2/crates/wifi-densepose-sensing-server/src/main.rs @@ -4909,6 +4909,18 @@ async fn udp_receiver_task(state: SharedState, udp_port: u16) { } ns.latest_noise_floor = frame.noise_floor; ns.latest_n_antennas = frame.n_antennas; + // ADR-106 follow-up: server-side receive timestamp + // in µs since UNIX epoch. Not as precise as + // sensor-side `info->rx_ctrl.timestamp` would be, + // but good enough for cross-node alignment within + // ~1 ms (Mac monotonic + LAN jitter). Sensor-side + // timestamp deferred to a future FW change that + // extends the 0xC511_0001 header — see ADR-106 + // Open Items. + ns.latest_timestamp_us = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .map(|d| d.as_micros() as u64) + .unwrap_or(0); let sample_rate_hz = 1000.0 / 500.0_f64; let (features, mut classification, breathing_rate_hz, sub_variances, raw_motion) =