wifi-densepose/v2/crates/rvcsi-node
Claude b116a99481
feat(rvcsi): real nexmon_csi UDP/PCAP fidelity — chanspec decode, libpcap reader, NexmonPcapAdapter
Raises the Nexmon path from a normalized record format to parsing what the
patched Broadcom firmware actually emits, end to end.

napi-c shim (ABI 1.0 -> 1.1, additive):
- rvcsi_nx_csi_udp_header / rvcsi_nx_csi_udp_decode — parse the real nexmon_csi
  UDP payload: the 18-byte header (magic 0x1111, rssi int8, fctl, src_mac[6],
  seq_cnt, core/spatial-stream, Broadcom chanspec, chip_ver) + nsub complex CSI
  samples (modern int16 LE I/Q export — what CSIKit/csireader.py read for the
  BCM43455c0 / 4358 / 4366c0; nsub = (len-18)/4). rvcsi_nx_csi_udp_write to
  synthesize payloads for tests. rvcsi_nx_decode_chanspec — d11ac chanspec ->
  channel (chanspec & 0xff) / bandwidth (bits [13:11], cross-checked against the
  FFT size) / band (bits [15:14], cross-checked against the channel number).
  Still allocation-free, bounds-checked, structured errors, never panics.
- ffi.rs wraps it: decode_chanspec / parse_nexmon_udp_header / decode_nexmon_udp
  / encode_nexmon_udp + DecodedChanspec / NexmonCsiHeader; every unsafe block
  documented; the ABI guard now expects 1.1.

rvcsi-adapter-nexmon:
- pcap.rs — a dependency-free classic-libpcap reader (all four byte-order /
  timestamp-resolution magics; Ethernet / raw-IPv4 / Linux-SLL link types;
  tolerates a truncated final record; pcapng is a follow-up) + extract_udp_payload
  + a synthetic_udp_pcap / synthetic_nexmon_pcap test/example generator.
- NexmonPcapAdapter (a CsiSource) — reads the CSI UDP packets out of a
  `tcpdump -i wlan0 dst port 5500 -w csi.pcap` capture, decodes each via the C
  shim, stamps the frame timestamp from the pcap packet time; non-CSI packets
  counted as "skipped" in health.

rvcsi-runtime: decode_nexmon_pcap, summarize_nexmon_pcap (+ NexmonPcapSummary:
link type, CSI frame count, channels, bandwidths, subcarrier counts, chip
versions, RSSI range, time span), CaptureRuntime::open_nexmon_pcap[_bytes].

rvcsi-node (napi-rs): nexmonDecodePcap, inspectNexmonPcap, decodeChanspec,
RvcsiRuntime.openNexmonPcap. @ruv/rvcsi SDK + .d.ts updated (NexmonPcapSummary,
DecodedChanspec). rvcsi-cli: `record --source nexmon-pcap`, `inspect-nexmon`,
`decode-chanspec`.

161 rvcsi tests pass (adapter-nexmon 9->22), 0 failures, clippy-clean.
ADR-096 §2.2/§2.3/§5, CHANGELOG, CLAUDE.md updated.

https://claude.ai/code/session_01CdYAPvRTjcch6YrYf42n1z
2026-05-13 01:15:22 +00:00
..
__test__ feat(rvcsi): real nexmon_csi UDP/PCAP fidelity — chanspec decode, libpcap reader, NexmonPcapAdapter 2026-05-13 01:15:22 +00:00
src feat(rvcsi): real nexmon_csi UDP/PCAP fidelity — chanspec decode, libpcap reader, NexmonPcapAdapter 2026-05-13 01:15:22 +00:00
Cargo.toml feat(rvcsi): real nexmon_csi UDP/PCAP fidelity — chanspec decode, libpcap reader, NexmonPcapAdapter 2026-05-13 01:15:22 +00:00
README.md feat(rvcsi): rvcsi-runtime composition + rvcsi-node (napi-rs) + rvcsi-cli + @ruv/rvcsi TS SDK 2026-05-13 00:17:45 +00:00
build.rs feat(rvcsi): rvcsi-core + napi-c Nexmon shim + crate skeletons (ADR-095/096) 2026-05-12 23:49:58 +00:00
index.d.ts feat(rvcsi): real nexmon_csi UDP/PCAP fidelity — chanspec decode, libpcap reader, NexmonPcapAdapter 2026-05-13 01:15:22 +00:00
index.js feat(rvcsi): real nexmon_csi UDP/PCAP fidelity — chanspec decode, libpcap reader, NexmonPcapAdapter 2026-05-13 01:15:22 +00:00
package.json feat(rvcsi): rvcsi-runtime composition + rvcsi-node (napi-rs) + rvcsi-cli + @ruv/rvcsi TS SDK 2026-05-13 00:17:45 +00:00

README.md

@ruv/rvcsi

Node.js bindings (napi-rs) for rvCSI — the edge RF sensing runtime: ingest WiFi CSI from files / Nexmon dumps, validate and normalize it, run reusable DSP, emit typed presence / motion / quality / anomaly events, and export temporal embeddings to an RF-memory store. See ADR-095 and ADR-096.

This package wraps the Rust crates in v2/crates/rvcsi-*. The Rust side does all the work (parsing, validation, DSP, events, embeddings); this is a thin, safe JS surface — nothing crosses the boundary except validated/normalized objects (delivered as JSON the SDK parses for you).

Build

The native addon is produced from the rvcsi-node Rust crate:

# from v2/crates/rvcsi-node
npm install              # installs @napi-rs/cli
npm run build            # -> rvcsi-node.<triple>.node + binding.js + binding.d.ts

(cargo build -p rvcsi-node also compiles the addon as a cdylib; napi build additionally emits the platform loader and .d.ts.)

Usage

const { RvCsi, inspectCaptureFile, eventsFromCaptureFile, nexmonDecodeRecords } = require('@ruv/rvcsi');

// One-shot: summarize a capture
const summary = inspectCaptureFile('lab.rvcsi');
console.log(summary.frame_count, summary.channels, summary.mean_quality);

// One-shot: replay a capture into events
for (const e of eventsFromCaptureFile('lab.rvcsi')) {
  console.log(e.kind, e.timestamp_ns, e.confidence);
}

// Streaming
const rt = RvCsi.openCaptureFile('lab.rvcsi');
let frame;
while ((frame = rt.nextCleanFrame()) !== null) {
  // frame.validation is 'Accepted' | 'Degraded' | 'Recovered' — never 'Pending'/'Rejected'
  if (frame.quality_score > 0.5) { /* ... */ }
}
const events = rt.drainEvents();
console.log(rt.health());

// Decode raw Nexmon records (the napi-c shim format) straight from a Buffer
const fs = require('fs');
const frames = nexmonDecodeRecords(fs.readFileSync('nexmon.bin'), 'wlan0', 1);

TypeScript types ship in index.d.ts (CsiFrame, CsiWindow, CsiEvent, SourceHealth, CaptureSummary, ValidationStatus, CsiEventKind, ...).

What's here vs. not (yet)

Implemented: file/replay + Nexmon sources, the validation pipeline, the DSP stages, window aggregation + the event state machines, RuVector-style RF-memory export. Not yet wired into this addon: live radio capture, the WebSocket daemon, and the MCP tool server — those come with rvcsi-daemon / rvcsi-mcp.