One device, several truths
An ESP32-C6 can observe BLE, parse Wi-Fi frames, drive a display, stream browser updates, and log to storage. The hard part is preventing each surface from inventing its own version of what the device is doing.
We treat detection as a stream of domain events, then reduce those events into a bounded state model. The LCD and browser render the same state; neither owns it.
Bounded by design
Unbounded contact history is a desktop assumption. Embedded state needs explicit capacity, expiry, and replacement rules.
ccontact_upsert(&(contact_update_t) {
.kind = CONTACT_REMOTE_ID,
.identity = frame->uas_id,
.rssi = frame->rssi,
.seen_at_ms = now_ms,
});
The reducer owns deduplication and expiry. Interfaces receive snapshots, which makes a 500 ms WebSocket push and a 30 Hz LCD refresh coexist without coupling the radio task to either one.
Instrument the quiet moments
Boot stages, scan health, storage state, GPS permissions, and stale contacts deserve the same attention as a positive detection. Useful firmware explains what it is waiting for.
- Use state names that describe operator meaning, not only driver state.
- Keep histories bounded and surface their expiry.
- Log transitions, not high-frequency noise.
- Design the recovery interaction with the failure path.
That discipline scales better than adding another status icon after every field report.