| 2026-07-09 |
Android Auto, field-validated — the full hands-free loop in a real truck — on an actual head unit, the in-car screen showed the live mesh map, and a message crossed the network to the truck, was read aloud, and the spoken reply traveled back over the mesh to the sender. The complete incoming + reply loop, validated in the field with the Google Play build — no developer mode, no cables. |
| 2026-07-09 |
Firmware release client-fw-2026.07.09 — road-test bug fixed the same night (#131) — the truck test flushed out a real reliability bug: on a busy cell, a node's peer-key table could fill up and silently block delivery confirmations — messages arrived fine, but senders burned their retries and saw "failed." Root-caused, fixed (larger table, least-recently-used eviction that never evicts active peers, and receipts that wait for keys instead of dropping), bench-validated end-to-end, and shipped to every board that night. Flash at flasher.loomwave.org. |
| 2026-07-09 |
The app is on Google Play (internal testing) — with an automated release pipeline — build, sign, upload, and release notes in one command via the Play Developer API. The Play build is what unlocks the complete Android Auto experience on real head units, and internal testers now get updates through the store instead of sideloading. Closed testing is next. |
| 2026-07-08 |
The mesh map is live — every opted-in node on a real map, from any node (#114) — nodes that turn on "share my location" now appear as pins on a street-map view in the app and on the Android Auto car screen. Positions relay cell-wide, so the map is complete no matter which node your phone connects through — including a headless Pi tower. Works offline too: with no internet the map stays pannable and pins render on a plain backdrop. Confirmed on the production tower and in the field. |
| 2026-07-07 |
Any two nodes can now message each other reliably (#120) — messaging between two client devices could silently fail in one direction — permanently — with a "no key" error, while the reverse direction worked fine. Two separate causes: a power-napping device only listened during part of each cycle and kept missing the moment the coordinator shared a particular peer's identity, and a long-settled device's cached identity quietly expired at the coordinator with nothing to refresh it. Both are fixed — devices now re-share their identity at a low background rate, and the coordinator varies the order it relays them — so every device learns every other device's key regardless of timing. Bench-proven on the pairs that used to fail. |
| 2026-07-07 |
Seeed T1000-E reception fixed — from ~⅓ of beacons missed to none — the LR1110-radio tracker was dropping 25–37% of the tower's beacons even at close range and bouncing between coordinators. The culprit was its own radio-stall recovery: it wasn't restoring the radio's high-sensitivity power mode after firing, and it was re-initializing the radio every healthy frame instead of only after a genuine miss. With both fixed, a bench T1000-E went from 5-of-8 beacons to 18-of-18 — zero misses. (This also retired the long-standing theory that power-napping caused the drops; the misses happened with napping fully off.) |
| 2026-07-06 |
On-node inbox — messages wait for your phone instead of getting lost (#127) — a message that arrived while your phone app was disconnected used to vanish: the node handed it to a Bluetooth link nobody was listening on. Now the node keeps a small on-device inbox of undelivered messages and replays them when the phone reconnects — and it survives a node reboot, since the buffer is persisted to the node's flash. The queue is bounded (newest messages win) and replayed gently so a backlog never stalls the radio schedule. A follow-up fix ensured the on-device drive-log can never crowd the inbox out of flash — verified end to end: messages injected, node hard-reset, both replayed on boot. |
| 2026-07-06 |
Companion app reliability pass — several quality fixes landed together: message threads are now scoped to the node you're connected through (and you can't message yourself); a delivered message (✓✓) can no longer flicker back to a single check when a late radio retransmit arrives; each node can be individually forgotten and display names are sanitized; and a small build-version footer makes it easy for testers to report exactly which build they're on. |
| 2026-07-04 |
In-car node map and mesh status — Android Auto screens verified; Play Store next (#78) — the companion app's in-car surface grew beyond hands-free messaging: a node map and a live mesh-status screen over Android Auto, validated on Google's head-unit emulator (one crash traced to a missing map-template permission and fixed). With a published privacy policy and upload signing in place, the app is headed to Play Store closed testing — so testers get the in-car screens without developer mode. Also new: a proper Loomwave launcher icon and a clear-node-list control. |
| 2026-07-03 |
Node positions, phase 1 — "you are here" with privacy by default (#114) — the phone now receives its own node's position over the wire: a compact GPS block (live fix, surveyed location, or none) shown as a "you are here" line in the app. Sharing location with the rest of the mesh is a separate, opt-in switch — default off, persisted on the node itself — decided as the privacy model before any position ever leaves the device. |
| 2026-07-03 |
Heltec V4 GPS — first confirmed fix on hardware — the original bring-up was driving the GPS module's reset line as "enable," holding it in reset forever, and listening on the wrong UART pin. A one-boot diagnostic pin sweep (kept in the firmware for future boards) measured the truth: enable, reset, and UART orientation all corrected, and the V4 went from GPS-dead to a live fix in under a minute. |
| 2026-07-03 |
Field usability: power-off, button wake, chirp de-spam, dead-battery guard — hold the button ~4 s for a power-off with an on-screen countdown (release to cancel); button presses now register instantly via interrupt instead of a 1 Hz poll that caught ~1 in 5 taps; join chirps now sound only on the first join after boot or on recovery from a real outage, instead of beeping on every rejoin; and a V3/V4 with a dead battery now sleeps and waits for charge instead of brownout boot-looping under radio-init load — a real field failure. |
| 2026-07-03 |
Roaming loyalty and eviction patience (#59, #112, #116) — a client between two comparable coordinators no longer ping-pongs: the incumbent gets a 6 dB hysteresis edge, and a transient beacon loss no longer blacklists it — a 10-second re-acquire grace stops the client from greedily grabbing whichever coordinator speaks first, so the incumbent's next beacon wins. This churn turned out to be the real source of tracker battery drain; bench-validated at zero coordinator changes in 150 s where before it flipped roughly every 25 s. On the coordinator side, small cells now require both missed roster turns and a real silence window before evicting, so a collision burst can't knock out a live member. |
| 2026-07-03 |
"Cell full" is gone — PACT-lite membership on the ESP32 coordinator and tower (#109) — membership is now a table row (up to 32 members) with a rotating per-frame telemetry roster, replacing the three standing slots that had a fleet of live clients playing musical chairs between coordinators all night. Ported byte-identical from the Rust coordinator to the ESP32 and hardware-validated with the live fleet: everyone seated, roster rotating, rows held. Beacon timing now uses the measured time-on-air instead of a stale constant (up to ~370 ms of error at worst case), and formerly silent receive drops now log with names. |
| 2026-07-03 |
Mesh-clock hardening — the schedule epoch always advances (#110) — on-air debugging traced a serving-cell collapse to a frozen schedule epoch: clients hash their contention-window picks from it, so a frozen value locked them into permanent collision patterns and the member table drained to zero. The epoch now always moves forward, converges to a pure UTC-derived value in steady state on time-anchored coordinators, and caps how long any single value can be re-served (encryption nonce safety). Clients also mix a per-beacon counter into their picks so a held epoch can never freeze them again. |
| 2026-07-03 |
Node identity from persisted hardware randomness (#94) — node addresses now derive from a persisted hardware TRNG seed instead of the radio's broadcast MAC, so identity survives reflashes and reboots and is no longer tied to a hardware identifier the radio announces to the world. The whole device fleet was rebuilt and published; a node updating from an older build gets a new address once, on first boot, by design. |
| 2026-07-03 |
Identity pins survive eviction (#112) — a member evicted for radio silence used to lose its pinned public key, so its next join stalled awaiting a fresh identity advert and, worse, its address was briefly open to being claimed under a different key — defeating first-writer-wins exactly when the rightful owner was knocked out. Trust-on-first-use pins, session keys, and replay history now persist through eviction, and the pin table is hard-capped so an attacker can never flood out an existing pin. |
| 2026-07-02 |
Live network telemetry over MQTT (#89) — infrastructure coordinators can now stream liveness, periodic metrics, and topology events (joins, evictions, backbone adjacency, routing forwards) to an MQTT broker — opt-in via a single environment variable, fully off when unset. The radio frame loop is never blocked: publishing rides a bounded queue in a dedicated thread, and the connection self-heals with backoff when the broker is down or slow. Groundwork for centralized live mesh mapping. |
| 2026-07-02 |
Coordinator hardening — nonce-reuse fix and hardware watchdog (#95, #104) — coordinators now persist an encryption-epoch high-water mark across reboots, closing a window where a rebooted coordinator re-used (epoch, sequence) pairs — two packets sealed under the same keystream is a serious AEAD break. Separately, a hardware watchdog self-resets a wedged coordinator, and radio-init failure now retries then hard-resets instead of hanging until a manual power cycle. Scoped to the ESP32 coordinator; the nRF52 watchdog stays off deliberately to protect the headless-reflash DFU window. |
| 2026-07-02 |
Android app — reliability and persistence (#99, #100) — message history, the learned peer directory, and the chosen connection now survive app restarts. Bluetooth auto-reconnects with exponential backoff after an unexpected drop (walking out of range, node reboot) instead of staying down until a manual tap. And a listener leak that made each reconnect show incoming messages an extra time is fixed, with incoming messages now deduplicated by ID. |
| 2026-07-02 |
Wired INFRA-to-INFRA backbone — hardware-validated over a real LAN (#64/#72) — the coordinator-to-coordinator backbone is now transport-agnostic: two distinct coordinators formed a signed-identity adjacency and exchanged bidirectional AEAD-sealed cross-cell frames over TCP, with none of the RF forwarding cap. A wired trunk can also be pinned to its designated partner tower (a peer-authorization ACL), so an open listener no longer trusts any node with a valid identity. |
| 2026-06-29 |
Firmware release client-fw-2026.06.29 — the reliable-delivery + automatic-retransmission build is now the published fleet release, and the platform roster grows to seven with the Seeed SenseCAP T1000-E (first LR11x0-radio client, with live GPS) and the Heltec WiFi LoRa 32 V4. Flash at flasher.loomwave.org. |
| 2026-06-29 |
Frame-integrity CRC16 — ghost-message bug fixed (#83) — first field test from a real masted site surfaced a confusing bug where garbled 'ghost' messages from phantom contacts appeared on the phone. Root cause: a dropped BLE notification desynced the phone↔node frame parser, which locked onto a stray byte and rendered a frame header as a message source. A trailing CRC16-CCITT on every BLE frame now lets both ends detect a false lock and resync cleanly. The whole device fleet plus the Android app were rebuilt to matched builds and published. |
| 2026-06-28 |
Hands-free in-car messaging — validated in an actual vehicle (Android Auto) — a message sent across the LoRa mesh was read aloud by Android Auto on the receiving phone, and a spoken voice-reply traveled back over the mesh to the sender. The full incoming + reply loop, no hands. |
| 2026-06-28 |
Opportunistic GPS time-sync — first coordinator adoption (#79) — foundation for network-wide time sync where any node with a GPS fix (client or coordinator) can anchor the whole mesh's clock. Bench-validated: a free-running coordinator adopted a Heltec T114 client's GPS-derived UTC over the air and re-derived its epoch around the better source. The first step toward seamless cross-cell message relay. |
| 2026-06-28 |
In-cell delivery reliability improvements — hardware-verified — two complementary fixes: the coordinator now TXes pending downlinks ahead of housekeeping traffic at each frame boundary (in-cell delivery jumped from 73% → 90%), and the client adds app-layer ARQ that resends an un-acked message every 45 s (up to four retries) so messages survive transient RF loss. Bench-validated end-to-end: a receiver reset mid-send still received the message at +64 s after rejoin. |
| 2026-06-28 |
LR1121 receive sensitivity recovered ~38 dB — the Nebra Duo's E80-900M2213S has its RF-switch DIOs wired opposite the LR1121 eval-board convention the driver assumed. Fixing the mapping (rx=DIO6) brought the mid-tower from −89 dBm to −51 dBm on the bench; distant nodes that were buried in the noise floor came back. TX was unaffected (both DIOs are HIGH on transmit, swap-immune), which is why the issue stayed hidden until receiving a distant signal. |
| 2026-06-24 |
RFC specification paper published — the full Loomwave design document is now online at loomwave.org/rfc/. Covers the complete stack: motivation, protocol, simulation results, and all hardware-verified results through Stage 6. |
| 2026-06-24 |
Boundary make-before-break handoff (#59) merged to main — when a peer coordinator's LSA confirms a client has roamed to it, the previous coordinator releases the slot immediately instead of waiting the ~50 s silence timeout. Eliminates wasted slots and stale LSAs at cell boundaries. Baked into the current field-test firmware; field verification planned June 27–28. |
| 2026-06-23 |
Dual-radio hub — two full cells on one node, hardware-verified — a single coordinator (Pi + Duo HAT) ran two independent cells simultaneously: SX1262 on channel A (915 MHz) and LR1121 on channel B (916 MHz). Heltec V3 joined cell A and V4 joined cell B, both streaming telemetry concurrently for 70+ frames, zero errors. Opens the capacity-layer path to N>1 cells per infrastructure node. |
| 2026-06-23 |
Per-link bandwidth — hardware-verified — each roster member now runs at its own (SF, BW) pair within the same frame. Bench-verified: SF7/BW500 for a strong member alongside SF9/BW125 for a marginal one in a single transmission, 13+18 positions, zero overruns. |
| 2026-06-23 |
Automatic (SF, BW) modulation selection — hardware-verified — the coordinator auto-selects the fastest bandwidth the cell can support, stepping up in hysteresis-respecting stages: SF9/BW125 → SF9/BW500 → SF7/BW500. Hardware-verified on the bench: member followed all steps (66 positions). SF7/BW500 delivers 4× the capacity of the SF7/BW125 floor that spreading-factor selection alone cannot reach. |