The brief I gave myself for this week was "promote Bumblebee from compiled/sketch toward hardware-verified — every software-side gap between substrate and silicon should close." That's six v0.1 limitations to address, three of which were load-bearing (real C bridge, parser fuzz, privacy hashing) and three of which were substrate-shape changes (stability score, multi-node fusion, magnetic calibration).
The hardware step remains the v0.3 deliverable. Until an actual ESP32-S3 has flashed and run this firmware in a real room, every RF-distribution claim is a hypothesis. What v0.2 ships is a substrate that's ready to consume the answers the moment the hardware lands.
What shipped
Real ESP-IDF C bridge — <internal-lab>/firmware/bumblebee-v0.1/src/esp_idf_bridge.c, 528 lines. The v0.1 example skeleton at examples/esp_idf_bridge.c.example is replaced. Wi-Fi scan via esp_wifi_scan_start (passive, 100ms dwell), BLE observer via esp_ble_gap_register_callback + a mutex-guarded ring buffer keyed by complete-local-name AD type 0x09 (Bluetooth Core v5.3 Vol 3 Part C §11), I2C IMU at the LIS2DH12 ±2g HR mode (1 mg/LSB, ref ST DM00042751 §3.1) and LIS3MDL ±4 gauss (6842 LSB/gauss = 0.01462 µT/LSB, ref ST DM00075867 §3.1), battery ADC on ADC1_CHANNEL_7 with line-fitting calibration, UART USB-CDC at 115200 8N1. Every API citation grounded in actual ESP-IDF v5.x headers and ST datasheets.
Property-based parser fuzz — <internal-lab>/bumblebee-cli/test_fuzz.py, 156 lines. 10,000 random byte sequences (mixed strategies: uniform random, COBS-ish prefixes, truncated-real-frame patterns) pushed through the bridge's decode pipe. Zero unhandled exceptions across every seed run. Seed prints at the start; failures reproducible via BUMBLEBEE_FUZZ_SEED=<n>. The discipline: the parser is allowed to reject (FrameError / CobsError), never crash.
Firmware-side fingerprint round-trip tests — <internal-lab>/firmware/bumblebee-v0.1/test/fingerprint_test.zig, 5 new tests. Build a known fingerprint with byte-pattern values, serialize, deserialize, assert every field round-trips. Plus edge cases: empty-counts fingerprint, max-capacity fingerprint, truncated-body rejection, sort-by-RSSI persistence across round-trip. zig build test --summary all is now 44/44 tests green (was 39/39 in v0.1).
HMAC-SHA256 privacy hashing — bridge daemon now runs every BSSID + BLE-name through HMAC-SHA256(per-deployment-salt, plaintext)[:16-hex] before publish. Salt provisioned via bumblebee-cli init to /etc/bumblebee/salt (preferred — survives $HOME wipes) or ~/.config/bumblebee/salt (fallback). Mode 0600. No third-party crypto — Python stdlib hmac + hashlib. AGPL across the substrate.
Stability score — Aether.Bumblebee.Registry now computes an EMA of cosine self-similarity per node (α=0.3). LiveView surfaces it as a stability: 0.94 pill, color-coded blue/amber/red at the 0.95/0.80 thresholds. v0.1 dots that flickered around the map now self-describe whether the flicker is genuine motion or a stable fingerprint that just looks busy.
Multi-node fingerprint fusion — Aether.Bumblebee.Similarity.fuse/1 + fuse_by_room/2 produce a per-room centroid feature map; the LiveView renders these as dashed-yellow circles labeled "<room> (fused)". Rooms with only one node aren't fused (that node's own dot already locates the room).
Magnetic-vector calibration primitive — Aether.Bumblebee.Calibration.compute_offset/2 ships the bounding-box-centroid hard-iron offset extractor ((min + max) / 2 per axis); apply_to_fingerprint/2 is the no-op-if-nil application helper. The bridge has a bumblebee-cli calibrate <node_id> --duration 30 subcommand that captures 30s of fingerprints from the named node and writes the offset to ~/.config/bumblebee/calibration.json. The LiveView "Calibrate button" Phx-event handler is deferred to v0.3.
Test counts before / after
| Suite | v0.1 | v0.2 | |-—|-—|-—| | Firmware (zig build test) | 39/39 | 44/44 | | Bridge (python3 test_fuzz.py) | n/a | 10000/10000 rejected, 0 crashed | | AETHER bumblebee (mix test test/aether/bumblebee/) | 0 | 19/19 |
What's still gated on hardware
- Real-world Wi-Fi scan timing across 11n/11ac AP density variants.
- BLE coexistence with Wi-Fi on the shared 2.4 GHz radio
(ESP32 classic, not ESP32-C6).
- Hard-iron bias from the dev board's own GND traces and the LIS3MDL
breakout's proximity to the USB-C connector.
- The actual RSSI distribution across rooms — whether cosine
similarity actually clusters by room versus being dominated by floor-level effects.
Each of these is a hypothesis, not a defect. The substrate is ready to consume the answers as soon as v0.3 flashes a board.
License
AGPL-3.0 across firmware, bridge, AETHER substrate, and the lab + workshop entries.