In The Wild with 39 Active Installs
FREE RAG Converter Online -- RAGconverter.com
rusty_esp_signal
Radios and sensing for the Janus ESP32 family: Wi-Fi station policy,
provisioning a device that has no network yet, a peer-to-peer link for chips
with no access point, long-range radio, presence from channel state, and a
millimetre-wave radar. Pure Rust, no C, no FFI, no_std by default.
- A device with no network can still be given one. A browser hands an
ESP32 its network over Bluetooth, on a page with no app and no server,
inside an encrypted session that a setup code unlocks (SPAKE2+, the device
proving its
did:mata): the passphrase never crosses the air in the clear and never reaches a server, a log, or a command line. Verified from Chrome on an ESP32-S3 and an ESP32-CAM: a whole session costs the device 0.27 s on the S3 and 0.82 s on the original ESP32, and the board joins in about a second. - Presence from the Wi-Fi channel itself, judged against a labelled public capture rather than our own recording: an empty room reads 17.4% occupancy and a walking person 86.1%, with a held-out pair at 60.8%.
- A link where there is no access point. Peer-to-peer framing sized to fit: 227 bytes of payload inside a 250-byte datagram, with hello, accept and confirm at 84, 100 and 18 bytes.
- The radar's own documentation is wrong, and the tests say where. Field offsets in the vendor datasheet do not match the vendor's tool; ours follow the wire.
What has run on hardware
| what | measured |
|---|---|
| the setup session over Bluetooth, from Chrome (XIAO ESP32-S3, trouble-host) | the device's time 0.27 s a session (Start 260 ms); joined in 995 ms, restarted without Bluetooth, the camera page on its token |
| the same on the ESP32-CAM (Bluedroid) | 0.82 s a session (Start 695-790 ms, the portable P-256 path); a mistyped passphrase offers setup again; the page 200 on its token, 403 without |
refusals, from an independent central (tools/setup_central.py) |
a wrong code, another device, a replayed session and a second writer refused; five wrong codes lock the window, and on the next power-on one more guess |
| provisioning over Bluetooth (the unencrypted version, now retired) | joined in 7.5 s; the reboot joins alone in 9.5 s with no Bluetooth |
| the identity behind it | the same did:mata held across six reflashes |
| the advertisement budget | 31 bytes, which is what forced the name and service layout |
| a failed join | must not spend the modem — a device that cannot join has to stay askable |
A known gap, stated plainly: channel-state presence and the peer-to-peer link are verified against captures and against the host, not yet on two chips talking to each other. Those rows need boards that are not on this bench, and the ledger says so rather than implying otherwise.
Every number, with the run that produced it:
docs/LEDGER.md.
Using it
use *;
use Env;
use Reset;
use ;
// The owner's settings, the identity store, randomness and the device key.
let env = Env ;
let mut provisioner = new?;
// A stored network is joined at once; without one, the setup window is open
// and the BLE backend routes the `setup` and `discover` characteristics here.
// A setup code unlocks the session; only then does a network go in.
if provisioner.boot.action == Connect
Two tracks
| track | what it is | this crate |
|---|---|---|
| A | std on ESP-IDF — Wi-Fi, Bluetooth provisioning, the radar's serial port |
rusty_esp_signal-esp --features esp-idf |
| B | no_std on esp-hal — the protocols, the detector, the framing |
rusty_esp_signal-core, default |
0.3.0 is a breaking release
The provisioning service carries the setup session (setup and discover);
the plaintext credentials write and the public scan are gone, and
Provisioner is the session's GATT router over the stores a platform lends it.
- let mut p: Provisioner = new;
- p.restore;
+ let env = Env ;
+ let mut p = new?;
+ p.boot;
A device takes a session once a setup code's verifier (setup.v) is in its
settings, written at flash time (espino's provision --setup-code-out, or the
portal). The page is docs/provision.html, its wasm rusty_esp_signal-web.
0.3.0 also carries the CSI work (breathing and a heart band, the presence
record at version 2, the CSI stream, a fall as a shape in the wander) and the
link's HMAC on the S3's SHA unit (sha-accel).
0.2.0 was a breaking release
EspNowLink no longer takes a lifetime parameter. esp-radio 1.0.0-beta.1
dropped it from EspNowSender and EspNowReceiver, and carrying one here
would have claimed a borrow the type does not hold — it owns the halves.
- let link: = new;
+ let link: EspNowLink = new;
The whole signal set moves to 0.2.0 together, the way it has always
published, even though only -esp broke.
The chip backends also move to the esp-hal 1.2 companion set, and the
library's dependency pins are ranges now rather than =: a firmware
must not mix companion sets, but it is the firmware that picks which, and an
= pin in a library took that choice away from every consumer at once.
S1, as a firmware you can run
firmware/c6-s1-link is the C6 ↔ C6 kill test, self-driving: one source,
two images, 1,000 authenticated ESP-NOW frames each way, loss / replay /
bad-tag counters straight from Session::counters(), and an unadopted
identity that must be refused.
It needs two boards, not three — what has to be turned away is an unadopted identity, not a third piece of silicon, so the initiator mints a second key and tries again. Same radio, same distance: a refusal cannot be blamed on range.
Part of Janus
Janus rebuilds the Espressif ESP32 and Arduino application portfolio as independent, memory-safe Rust packages — so a hardware maker can ship a device that the MATA home computer discovers, catalogs honestly, adopts under its own identity, and pays for. Ten packages, three layers, and the dependency direction never reverses.
| layer | packages |
|---|---|
| 0 — the vocabulary | rusty_esp_core · rusty_esp_dsp |
| 1 — the functions | rusty_esp_image · rusty_esp_video · rusty_esp_audio · rusty_esp_signal · rusty_esp_mid · rusty_esp_iroh |
| 2 — the surfaces | rusty_esp_arduino — the sketch facade · espino — the maker's CLI (not published) |
Every package is host-verified against an external oracle and keeps a ledger in which no number appears without the run that produced it. Five of seven device profiles have now run their kill tests on real silicon, three of them over a Wi-Fi network the board hosts itself.
Also check out the rest of Remade With Rust — including
rusty_alloc, the pure-Rust rebuild of
mimalloc that these firmwares run on, and
rusty_jpeg, the JPEG engine behind the
camera path — and our sister project
remade_ffmpeg_rs, a ground-up Rust rebuild of FFmpeg.
About Mata Network
Mata Network builds sovereign, self-hostable infrastructure. Remade With Rust is our open-source home for the permissively-licensed building blocks that work depends on.
License
MIT OR Apache-2.0, at your option. See LICENSE-MIT and LICENSE-APACHE.