feat(wire): carry transmitter and transmission identity in the CSI frame - #1805
Open
clonea1 wants to merge 1 commit into
Open
feat(wire): carry transmitter and transmission identity in the CSI frame#1805clonea1 wants to merge 1 commit into
clonea1 wants to merge 1 commit into
Conversation
A sink receiving CSI from several nodes currently cannot tell whether two
frames describe the same packet in the air or two unrelated ones. Node ids
differ, arrival timestamps differ, and the `sequence` field at bytes 12..15 is
each node's OWN counter -- nothing in a v1 frame links them.
Wire v3 adds the two fields that do:
[20..25] transmitter MAC (802.11 addr2)
[26..27] rx_seq of the overheard frame (LE u16)
[28..] I/Q data
rx_seq is assigned by the transmitter, so every receiver of one packet reports
the same value. `(addr2, rx_seq)` is therefore a receiver-independent name for
a single transmission -- no clocks, no synchronisation and no guard interval,
because the frames are literally the same emission arriving nanoseconds apart.
New magic (0xC511000A) rather than a silent layout change, so a sink that does
not know v3 rejects the frame instead of misreading the payload: the I/Q offset
moves 20 -> 28 and a v1 reader would shift every sample. 0xC5110002..0009 are
already taken by the vitals, feature and other edge packets, so v3 claims the
next free value; adjacency is not assumed anywhere.
Also adds `rx_seq` to the test stub's `wifi_csi_info_t`. The fuzz target
compiles the REAL csi_collector.c, so the stub has to carry the fields the
serializer reads or the harness silently stops matching the firmware -- and in
this case stops building. Mirrors IDF's esp_wifi_types_native.h.
Scoped deliberately to the CSI frame. An earlier version of this branch also
carried a sync-packet v1->v2 bump and node health fields (heap, reset reason,
thermal state), which pulled in esp_system.h, esp_heap_caps.h and thermal.h and
broke the fuzz build. Those belong with the sync-packet and thermal work, not
here.
Co-Authored-By: claude-flow <ruv@ruv.net>
clonea1
force-pushed
the
contrib/csi-wire-v3
branch
from
September 4, 2026 19:14
4adb7e8 to
de3f996
Compare
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.
Wire v1 identifies neither which transmitter a frame came from nor which
transmission it was. Both are needed before frames from different nodes can be
related to each other.
v2 appends the 802.11 addr2 (transmitter MAC) at bytes 20..25. A node in
promiscuous MGMT+DATA mode with no filter produces CSI for every transmitter
on the channel -- measured 2026-08-28 at ~75% non-AP in a normal home. Each
frame is a valid measurement of a DIFFERENT link, and without the transmitter
on the wire the sink interleaves them into one history with mixed geometry.
v3 appends the 802.11 receive sequence number. v2 makes a frame attributable
to a link; v3 makes it attributable to a transmission. The existing byte 12..15
carries a counter private to each node, so two nodes that captured the same
packet off the air report unrelated numbers and the sink cannot tell it was one
event observed twice. Arrival timestamps do not substitute -- the sink sees
network jitter, not the moment of capture.
This answers the blocker stated in ADR-138 (LinkGroup / ArrayCoordinator),
which is Accepted-partial with integration glue pending because the
mesh_aligned_us plumbing exists today only in the sensing server, not in a
shared FrameMeta. Per-frame identity on the wire is that missing piece.
Sequencing note: a receiver must accept v2 and v3 before a sender emits them,
so the server-side parser should land first.
Stacked on the thermal change: the ESP-NOW sync packet carries die
temperature, thermal state and TX dBm in bytes 29..31, so this file depends on
thermal.h.
Rebased onto current
mainbefore opening: staged before today's seven merges, so it needed replaying to avoid reading as a revert of them. Clean rebase, no files deleted.