feat: build-time console baud, CSI source filtering, and esp-csi-rs 0.10.0 - #10
Merged
Merged
Conversation
`esp-csi-rs-core` replaced the ESP-NOW central/peripheral architecture with
two exhaustive roles — an emitter puts known RF energy into the channel and
never captures; a collector captures the channel's response — and removed the
ESP-NOW transport outright. This crate defines the `set-wifi --mode=`
vocabulary the whole host-side ecosystem parrots, so the rename has to land
here for the strings downstream to mean anything.
The ESP-NOW modes go with the transport rather than being deprecated in place:
they cannot work, so accepting them would only defer the failure to runtime.
Deliberately NO legacy aliases — an old string must fail loudly at the CLI
instead of silently drifting from what the firmware actually does. In exchange
the HT20/HT40 raw emitters, previously proprietary-only, are available here:
HT is plain 802.11n and core owns the emitter now.
`CollectionMode::{Collector,Listener}` is replaced by
`set-csi-output --enabled=`. Its two states were never independent of the role
(an emitter never collects; a collector that discards CSI does nothing useful),
and "collector" now names the RX role — keeping the flag would give one word
two meanings in every doc. What remains is a boolean: does CSI leave the device.
`--peer-mac` and `--ht40` survive by name but are retargeted to their only
remaining referents — the emitter's injection destination and the softAP's
secondary channel — matching what `esp-csi-cli-rs-pro` already exposes, so the
two firmwares keep one vocabulary. 40 MHz emission is selected by
`--mode=ht40-emitter`, not by `--ht40`. `--inject-period-ms` is new and is the
emitters' only rate control. `set-rate` becomes reporting-only: nothing applies
a PHY rate now that ESP-NOW is gone.
No HE20 anywhere: those modes stay `esp-csi-cli-rs-pro`-only. The C5/C6
`set-csi` acquisition flags are kept as-is — they are chip capability flags
(legacy / HT20 / HT40 / VHT20 / forced L-LTF), none of them HE — but the prose
calling them the "HE/STBC field set" was renamed, since it implied an HE
capability this firmware does not have, and `--csi-he-stbc` was dropped from
SPECS.md as a flag that never existed in the code.
`esp-csi-rs` / `esp-csi-rs-core` are patched to their `feat/emitter-collector`
branches until the role API is released; `CLI_PROTOCOL_VERSION` stays at 2
because the `info` grammar is unchanged.
Verified with the full CI matrix (both flavors, all five chips): esp32,
esp32s3, esp32c3, esp32c5, esp32c6 — no errors, no new warnings.
Refs #6
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pro firmware's `version` help already promised that "an open build answers `open <semver>` from the same command", but no such command existed here -- so the claim was false and host tooling had nothing positive to read from an open board. This matters beyond tidiness: csi-pipeline's selftest now prefers `version` over probing a proprietary-only mode string and inspecting the rejection, precisely because a positive statement survives mode renames. Without this the open case always fell through to the slower mode-probe fallback. Refs #6. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Refs #6. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Refs #6. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
EmitterConfig::with_ap_interface has always existed in the library but nothing exposed it, so an emitter could only ever inject on the STA interface. The driver accepts raw TX on both, but which one actually radiates turned out to be chip-dependent while investigating an S3 that accepts every injection and radiates none, so the choice belongs to the operator rather than being hard-coded. Refs #6. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On the C5 the station channel hint pins the radio band, and --set-channel is that hint. Its default is 149 (5 GHz) on that part, so associating to a 2.4 GHz AP without passing an explicit 2.4 GHz channel makes the AP invisible and reports only 'no access point found' -- with nothing pointing at the band as the cause. Cost me a wrong conclusion during hardware testing, so it is now stated in the help text with a worked example. Refs #6. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Four changes, all driven by the same reported problem: a collector delivering far
fewer CSI samples than the traffic rate configured for it.
**Console baud is a build-time setting.** `ESP_CSI_CLI_UART_BAUD` (default 115200),
read in `build.rs`, range-validated, passed to `Config::with_baudrate` at all three
`Uart::new` sites. Not a runtime command: one would have to change the rate of the
console carrying it, so the reply is either lost or sent at the old rate while the
host has already switched. The rate is instead immutable per image and declared —
`info` reports `baud=`, and `manifest.json` carries it per asset for tooling that
must choose a rate before the first byte. `CLI_PROTOCOL_VERSION` stays at 2: the
grammar is unchanged, host parsers end with `_ => {}`, and the host's check is exact
equality, so a bump would refuse otherwise-good boards at attach.
**`set-csi-filter --peer-mac= --min-phy=`.** A collector is promiscuous, so a
capture mixes the AP's beacons and ACKs and third-party devices in with the
configured traffic. Rejection happens in the Wi-Fi callback before the packet copy
and before formatting, so it also returns console bandwidth. Verified on hardware.
**ESP-NOW central/peripheral restored.** All four modes (`esp-now-central`,
`esp-now-peripheral`, `esp-now-fast-collector`, `esp-now-fast-source`) are exposed
again, alongside the HT emitters rather than instead of them — the engine kept both
families, and both are hardware-verified. `--peer-mac` is consequently read per
mode: the emitter's injection destination, or the explicit ESP-NOW peer. `--ht40`
likewise serves the softAP secondary channel or the per-peer HT40 TX PHY, and
`set-rate` applies to the central/peripheral pair rather than being reporting-only.
**Docs** across README, SPECS.md and WEBSERVER.md: the nine-mode vocabulary, a
Console throughput section with measured per-format/per-baud figures, a note that
there is deliberately no payload-truncation option (acquiring less via
`set-csi --htltf=off` measured *faster* than truncating to the same size, because
the radio does less work per frame), that `defmt` is not a throughput lever, and
that the rows at the head of a collection are real CSI from management and foreign
frames rather than dummy packets.
`esp-csi-rs` 0.10 absorbed the engine, so the requirement moves to `"0.10"` — at
`"0.9"` cargo could resolve 0.9.0, which has neither the engine nor
`set_csi_peer_filter`/`set_csi_min_sig_mode` — and the now-dead
`esp-csi-rs-core` patch line is removed.
The engine moved into `esp-csi-rs`, so the lock no longer carries an `esp-csi-rs-core` entry and pins the facade at 0.10.0 from the patched branch.
…ss-reference Three things in the unreleased entry were wrong or shouldn't have been there: - It announced that the ESP-NOW modes were removed. They were not — the engine retained them and all four are exposed, alongside the HT emitters rather than instead of them. `set-wifi --mode=` takes nine values. - `--peer-mac` and `--ht40` were described as retargeted to a single referent each. With both families supported they are read per mode, and `set-rate` is not reporting-only: the central/peripheral pair applies it as the per-peer TX PHY. - It referenced another firmware build that has no bearing on this repository. Removed; the emitter modes are simply described on their own terms. Dependency line updated for `esp-csi-rs 0.10`, which absorbed the engine.
`esp-csi-rs 0.10.0` is published, so the `[patch.crates-io]` redirect to the `feat/emitter-collector` branch is no longer needed — `esp-csi-rs = "0.10"` resolves from the registry. Drop the patch section and its now-stale comment, and re-lock onto the registry source. A clean clone of this repo now builds the firmware without any local checkout of the library, which was the point of holding the CLI release back until the library shipped. Verified against the registry-resolved crate: all five chip targets build (esp32, esp32c3, esp32c5, esp32c6, esp32s3), and on two classic ESP32 boards the 22-check console/filter suite and the 17-check ESP-NOW + emitter suite both pass in full. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This crate has never been on crates.io and should not be: its build product is an image flashed to an ESP32, so a registry consumer has nothing to depend on. It ships as source plus a git tag, and `esp-csi-rs` is the published artifact. `publish = false` makes that explicit and stops an accidental `cargo publish`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both Xtensa jobs failed, with and without `defmt`, before compiling a single
crate:
error: rustc 1.93.0-nightly is not supported by the following packages:
esp-metadata-generated@0.5.0 requires rustc 1.95.0
esp-rom-sys@0.1.5 requires rustc 1.95.0
That is dependency resolution refusing the toolchain, not a code or `defmt`
problem — which is why the four RISC-V jobs passed: they resolve against a
runner-provided toolchain that is already past the floor.
1.95.0.0 is the version this firmware is built and hardware-tested against
locally, and `cargo metadata` confirms 1.95.0 is the maximum `rust-version` in
the graph on all three targets (riscv32imac, xtensa-esp32, xtensa-esp32s3), so
it clears the floor exactly rather than by luck.
Kept pinned rather than floating so a toolchain release cannot break CI on its
own, with a comment recording that the pin tracks the `esp-hal` / `esp-radio`
bumps.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0.10.1 is published. Setting the floor there rather than leaving `"0.10"` is deliberate: `esp-csi-rs 0.10.0` fails to compile for `--features esp32,async-print` — `auto` is in its default set, so one added feature is enough — and `"0.10"` is `^0.10`, which would let cargo resolve 0.10.0 and leave that build broken from a clean checkout. `^0.10.1` still accepts every later 0.10.x, so this narrows nothing that matters. Verified: all five chip targets build, and `--features esp32,async-print`, the combination that failed against 0.10.0, now compiles. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.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.
Brings the CLI onto the released
esp-csi-rs 0.10.0and adds the console-throughput and CSIfiltering work that came out of investigating #7.
Depends on csi-rs/esp-csi-rs#29 for the library side;
0.10.0is already on crates.io, so thisbranch builds from a clean clone with no
[patch.crates-io]entry — which is why the CLI washeld back until the library shipped.
Console throughput
#7 reports a collector's sample rate collapsing. It is console-bandwidth-bound, not radio-bound —
the radio captures several times what the host receives, and the gap was invisible because the
statistics counters were being cleared by the end-of-run reset before anyone could read them.
The levers, measured on two classic ESP32 boards:
serializedlog modeset-csi --htltf=off(acquisition)defmtinstead ofprintlndefmtis included because it is the intuitive answer and it is wrong: a CSI line is alreadyformatted ASCII handed over as a single
{=str}argument, so there is nothing left to compress.ESP_CSI_CLI_UART_BAUD(default 115200, validated1..=5_000_000, withcargo:rerun-if-env-changed). Build-time rather than a runtime command:changing the baud of the link you are typing on cannot be done from the far end of that link
without a reconnect, and the value has to be known before the first byte of boot output.
infodeclares the baud so a host can confirm what it connected at.CLI_PROTOCOL_VERSIONstays at 2 — the grammar is unchanged.
CSI filtering —
set-csi-filterReduces what crosses the console at the source rather than truncating records:
--peer-macdelivers only frames from one transmitter. Several emitters can share one collector,so attribution belongs on the device.
--min-phydrops frames below a PHY floor, e.g. legacy beacons in an HT-only capture.Rejected frames count as RX drops, so the loss stays visible in
show-statsinstead of vanishing.ESP-NOW modes restored
esp-now-central,esp-now-peripheral,esp-now-fast-collectorandesp-now-fast-sourcesitalongside the HT20/HT40 emitters. Both families are needed: on chips whose MAC refuses a forced HT
rate, ESP-NOW is the emitter path that works.
Not included, deliberately
An earlier revision added
--max-samplesto truncate the emitted payload. It was withdrawn aftermeasurement:
set-csi --htltf=offreduces what the radio acquires and beat truncation on bothaxes — 23.92 vs 20.98 CSI/s and 506 vs 446 captured. Truncating output to go faster is the wrong
layer when the acquisition itself can be made smaller.
This crate is firmware
Marked
publish = false. The build product is an image flashed to an ESP32, so there is nothingfor a registry consumer to depend on; it ships as source plus a git tag, and
esp-csi-rsis thepublished artifact.
Verification
All five chip targets build against the registry-resolved crate. On two classic ESP32 boards:
22/22 console, statistics, acquisition and filter checks, and 17/17 ESP-NOW and emitter
checks. A 15-config matrix at 115200 and 8 at 921600, with one known pre-existing failure (an
AP/STA run followed by an ESP-NOW run yields nothing on the first ESP-NOW attempt and recovers on
the second — reproduced on a pre-merge image).
Relates to #7.