fix(scripts): emit the ADR-018 header layout in synth-csi-udp.py - #1953
Open
buraga-kyo wants to merge 1 commit into
Open
buraga-kyo wants to merge 1 commit into
buraga-kyo wants to merge 1 commit into
Conversation
The emitter was written alongside the first calibrate.rs parser (ruvnet#838), which read n_subcarriers as a u8 at offset 6 and freq_mhz as a u16 at offset 8. That parser was aligned with the firmware layout in ruvnet#1005 (d0e27e6); the script kept the old struct string. Decoded by the firmware layout (csi_collector.c), every emitted frame carried freq_mhz=461164, sequence=0xA1C90000 (constant: the rssi and noise bytes landing in the sequence slot) and rssi=0. `wifi-densepose calibrate` kept working by coincidence: the I/Q block starts at offset 20 in both layouts, n_subcarriers=52 decodes the same because the old reserved byte was zero, and the baseline ignores sequence/rssi/freq (baselines differ only in captured_at). The sensing-server calibration does not: it admits one observation per forward sequence, so with a constant sequence every frame after the first is a Duplicate. Measured over 12 s at 20 Hz: frame_count=1 before, 239 after; frames_per_second 0.08 before, 19.9 after. The header now matches firmware/esp32-csi-node/main/csi_collector.c and the three Rust readers (esp32_parser.rs, calibrate.rs, sensing-server csi.rs): n_subcarriers u16 @6, freq_mhz u32 @8, sequence u32 @12, rssi i8 @16, noise_floor i8 @17, ppdu_type @18, flags @19. Amplitude and phase synthesis are unchanged. Feito por buraga-kyo <sprtj@protonmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
scripts/synth-csi-udp.pypacks the 20-byte header as<I B B B B H I b b I— n_subcarriers u8 @6, freq u16 @8, sequence @10, rssi @14. That is the layout of the firstcalibrate.rsparser (#838). The parser was aligned with the firmware in #1005 (d0e27e65); the script was not.csi_collector.cand all three Rust readers (esp32_parser.rs,calibrate.rs, sensing-servercsi.rs) read n_subcarriers u16 @6, freq u32 @8, sequence @12, rssi @16, ppdu_type @18, flags @19.One struct string and its field comments change. Amplitude/phase synthesis, rate, and CLI flags are untouched.
Effect — MEASURED
Decoding one emitted frame with the firmware layout (
struct.unpack_from('<IBBHIIbbBB', pkt)):0xA1C90000= the rssi and noise bytes)wifi-densepose calibrate(the script's stated target) is unaffected by coincidence: the I/Q block starts at offset 20 in both layouts, the old reserved byte was zero so n_subcarriers decodes as 52 either way, and the baseline ignores sequence/rssi/freq. Baselines produced with both versions are byte-identical apart fromcaptured_at.The sensing-server calibration is broken by the constant sequence — it admits one observation per forward node sequence (
calibration_sequence_order,Duplicatewhendelta == 0).POST /api/v1/calibration/start?source_node_id=42, emitter at 20 Hz, status read after 12 s:frame_countframes_per_secondlast_sequence_by_node["42"]grid_binding.statusstale/api/v1/nodesalso reportedrssi_dbm: 0.0for the node before the change.Reproduce
Header decode, no server needed:
python3 -c "import struct, importlib.util as u; s=u.spec_from_file_location('m','scripts/synth-csi-udp.py'); m=u.module_from_spec(s); s.loader.exec_module(m); p=m.build_packet(42,7,2412,-55,[40.0]*52,[0.0]*52); print(struct.unpack_from('<IBBHIIbbBB',p))"Scope
One file, header struct only. Synthetic emitter; no CSI or person data.
scripts/csi-data-policy-check.sh --stagedpasses. No other file in the tree references the script.Out of scope, noted for a separate look:
scripts/collect-training-data.pylabels a 16-byte<IBBHbbBxIheader "ADR-018 raw CSI frame"; I did not verify whether that reader is intentional legacy or a similar drift.Test plan
python3 -m py_compile scripts/synth-csi-udp.pyaggregator --bind 127.0.0.1:5005showsseq:0..159 rssi=-55(wasseq:2714304512 rssi=0)wifi-densepose calibrate --min-frames 100succeeds with both versions; baselines differ only atcaptured_atframe_count1 → 239 over 12 s at 20 Hzbash scripts/csi-data-policy-check.sh --staged→ OK