| 2026-09-10 |
Two ways a healthy node could walk away from a working tower — both fixed on main, neither in a build you can flash yet — who this affects, first: it takes a node running in coordinator-free direct mode and a working cell on the same channel within radio earshot of it. If every node you own is joined to one cell, or your direct-mode nodes are off on their own, nothing here reaches you, and the image the installer serves is unchanged either way. What we found, chasing a cell that kept losing beacons on the bench. A node talking directly has no coordinator to take its turns from, so it transmits on a schedule of its own and does not listen before it does — and in every one of the seven collisions we measured, it was the direct-mode node that started first — around half a second to a bit over a second before the beacon — wrecking both transmissions. Six of nine beacons went missing in thirty-three minutes that way. Behind it sat a second fault that turned each lost beacon into something worse: a node abandoned its coordinator after a fixed twelve seconds without hearing one, a threshold set when cells ran fast frames. On a slower cell — the kind a tower-synchronised network uses — twelve seconds is not even two beacons apart, so one collision was enough to make a node at point-blank range give up, rescan and re-register. Four such abandons in fourteen minutes, each of them exactly twelve seconds after the last beacon it heard. Both fixes are merged. The first has the direct-mode node learn the rhythm of the beacons it can hear, predict when the next one is due, and keep quiet across that window and the busy stretch after it — with a floor that guarantees a fifth of every cycle stays open, so nothing it wanted to send can be starved out, and with emergency alerts deliberately exempt: an SOS never yields to a beacon. The second reads the cell's own pace out of the beacon and waits proportionally — at least twelve seconds, and at least two and a half beacons — and re-arms the receiver first, something only one of the seven boards used to do. In a thirty-minute acceptance run the fixed build rode out silences of 13.8 and 15.8 seconds and stayed with its coordinator five separate times; the old build could not have occupied any of those states. Status, plainly: the beacon-timing fix has passed that run, the collision fix is merged and live on a single bench node but not yet proven at scale, and neither is in the image at flasher.loomwave.org. They ride out with the next build, and this page will say when that is. |
| 2026-09-10 |
A message with no tower behind it can now travel further than one radio hop — when there is no coordinator in range, Loomwave nodes talk to each other directly. Until now that was strictly what you could hear: if a node was not in earshot of the sender, the message did not reach it, and the phrase we used on this page for coordinator-free mode was "no tower to relay". That changes. Nodes now pass a coordinator-free channel message along for each other — each node repeating what it heard, unchanged, exactly once, with a hop budget that runs out so nothing can circle forever, and only after checking the sender's signature, so a node never repeats something it cannot verify. To keep a crowd from all shouting the same thing, a node that hears two of its neighbours already repeat a message stays quiet — with one deliberate exception that turned out to matter: a node that heard the message only faintly repeats it regardless. That node is usually the one at the edge, the only link to whoever is further out, and staying quiet is exactly the wrong instinct for it. In the network model we test these designs against, that single exception is the difference between half the nodes receiving a message and all of them, and it costs nothing extra among nodes that could already hear each other. Two honest limits. This is direct messages' quieter sibling — it carries channel and broadcast traffic, not one-to-one messages, which still travel only as far as the sender's own radio. And it is merged source with simulation and test-bench results behind it, not a shipped feature: it has not been proven on the air, no installable image carries it, and the nodes you can flash today still relay nothing when they are on their own. It goes out with the same build as the fixes above. |
| 2026-09-06 |
A fresh ESP32 node could refuse to be paired, forever — fixed on main, and never in a build you can flash — the reassuring half first, because it decides whether this is your problem: the image the web installer serves is the 2026-08-28 build, it predates this bug entirely, and it is unaffected. If you flash from flasher.loomwave.org, you were never exposed and there is nothing to do. What broke, and for whom: a node keeps a small record of who owns it, written the first time an owner claims it. On the three ESP32 boards — Heltec V3, Heltec V4, Station G2 — the firmware opened that record read-only before it existed, and the chip's answer for "no such record yet" came back indistinguishable from "the record is damaged". The node then did the careful thing for the wrong reason: it declared its owner store unreadable and refused every pairing claim rather than risk overwriting a real owner. Nothing was actually wrong with the node, and no amount of retrying, rebooting or resetting helped — a board that had never been claimed could never be claimed. The fix probes for the record before reading it, so absent now means new and claimable, while a genuinely faulty store still fails closed and refuses the claim. Verified on hardware both directions: a fresh board becomes claimable, an already-paired board stays paired. The exposure window is narrow and it is developers-only: every build from main between 2026-08-28 and the fix carried it, and no released image ever did. The four nRF52840 boards — T114, XiaoGator, RAK4631, T1000-E — were never affected; they store that record as a file, and a missing file already read as new. When the next installer build ships, it will carry the fix from the start. |
| 2026-09-04 |
The band survey is already on a build you can flash — on exactly one board, and not on a masted relay yet — this one has been shipping quietly since the 2026-08-28 image, and we had it listed as still-in-development. Correcting that, with the limits attached. A Station G2 flashed as a coordinator with WiFi can survey the radio band it lives in: open the node's own web page and it steps across fourteen channels spanning 902–928 MHz, sitting about three seconds on each — half a second measuring the noise floor, then a listening pass — and reports what it found per channel: the floor, the loudest thing it saw, and what fraction of the time that channel was busy. A couple of minutes end to end. It measures energy, not traffic: it can tell you a channel is loud, never who is talking on it. It is a diagnostic and it came out of one — we built it while chasing a real reception problem, because guessing at what the air looked like was not working. Two limits are worth more than the feature. First, one target only: the Station G2 coordinator-with-WiFi image. The other installer builds do not carry the page, and the UF2 boards — T114, XiaoGator, RAK4631, T1000-E — have no WiFi to serve it from. Second, and this is the one to read twice: on a node relaying under a tower, a sweep in the currently published build can knock it off that tower. Going off-channel to listen collides with the tower's beacon, and partway through the sweep the node gives up on the tower and falls back to standing on its own. The repair — the survey now waits for the tower's beacon to pass before it listens, and refuses outright rather than return a survey it had to cut short — is merged, but it is not in the image the installer serves, and it has not yet been confirmed on the air. So on a masted relay, treat a sweep as something that will interrupt that node's mesh duty; run it on a bench node, or on one you can afford to have step out for a couple of minutes. On a node already claimed by an owner, starting a sweep takes that node's OTA password. One sweep per five minutes. |
| 2026-08-31 |
A drive test caught the cross-cell delivery bug red-handed — and this one is still open — messages sent between two mesh cells were received and decrypted at the backbone relay, and then went nowhere: seven forwards in, zero out, and no error recorded anywhere. We now have the mechanism rather than the symptom. The relay held no current route to the destination cell — that cell's coordinator had stopped announcing its roster after a restart — and a message with no route simply vanishes instead of reporting a failure. Behind it sits a second finding that explains the first: a coordinator can boot into a broken state at random. The same board, power-cycled twice fifteen minutes apart, once came up announcing its cell normally and once came up silent — never announcing, sealing frames the backbone could not read. That boot-time coin flip is the precondition for the silent drop, and it reproduces on the bench with nothing but a power cycle. Neither is fixed yet, and we would rather say so plainly: until the fixes land, a message crossing between cells can fail without telling you. The hop between cells is where it is lost. The first thing to land is the instrument — a stay-at-home cross-cell smoke test (#330) that puts this entire scenario on the bench, no truck required. |
| 2026-08-30 |
Emergency SOS has landed in the firmware — and it is not on a build you can flash yet — read the second half of that first, because it is the half that matters today: this is merged source code, not a release. Nodes in the field do not have SOS, and five taps on one of them do nothing. The installer still serves the 2026-08-28 build, which predates the feature by hours. What is written, reviewed and merged: five deliberate taps on the node's own button — or the app, or the serial console — raise an alert that rides airtime the node already owns, so it outranks that node's own chat traffic without taking anything extra from the channel. It carries the sender's position, and it repeats until it is stood down, or until it lapses on its own after thirty minutes. Nodes that hear an alert re-broadcast it under a strict rate bound, so a stranger's distress call gets relayed while nobody can turn the mesh into their personal transmitter. One deliberate exception is worth knowing before you would ever need it: raising an SOS sends your position even if your standing “share my location” setting is off — an alert without a position is close to useless, so triggering one is an explicit decision to be found, and the app says exactly that on the screen where you trigger it. The raise-and-cancel gesture was verified on real hardware; an adversarial review of the result then found three ways an armed alert could fail silently, and all three fixes are merged (#314, #316, #317), alongside a reworked on-device screen that makes a node claim only what is true at each stage. A fourth came later and from a different direction — bench testing found it and the source confirmed it: on a node that already had an owner, an SOS raised over Bluetooth by a phone that was not that owner never reached the alert code at all; a list of what an unclaimed connection is allowed to ask for had simply never had the SOS request added to it. That silence was the opposite of the intent. A stranger being able to raise an alert through a node they do not own — rate-limited, and with none of the other privileges the owner has — is deliberate, and it is much of what makes an SOS worth carrying in the first place. Fixed (#396), with that list now pinned by tests, so it can neither quietly narrow again nor quietly widen. Next is validating the whole alert path on the air, and then a flasher build that actually puts SOS on nodes. This page will say so when that build exists. |
| 2026-08-28 |
If you run a Heltec V4 or a Seeed T1000-E, reflash it — those two images were built far below full transmit power — a single build setting fixes a node's transmit power at compile time, and every board image sets it explicitly. Two did not: the Heltec V4 and the Seeed T1000-E fell through to a bench default of −9 dBm instead of the 22 dBm the rest of the fleet uses. Nothing about it was visible from the outside — no warning, no log line, no setting you could check on the node — which is exactly why it survived. That 31 dB gap is measured at the radio chip, not at the antenna: the V4 has an amplifier in front of its antenna that absorbs some of the shortfall, and we have not yet measured how much, so we are not going to attach a range figure to it. What is certain is that a V4 or a T1000-E flashed from the installer before 2026-08-28 has been transmitting far more quietly than it was meant to, and that the 2026-08-28 build fixes it. Reflash from flasher.loomwave.org — it keeps the node's identity, channels and owner binding. The other five platforms were always correct and need nothing. The setting can no longer go missing: a check now fails the build if any board image leaves it unset, and it runs on the path that actually publishes the installer, not only on the one that doesn't. |
| 2026-08-28 |
Messaging with no tower at all — coordinator-free operation is now a first-class tier — Loomwave has always said it needs no infrastructure, and the coordinator-free mode behind that promise has always existed. It was a survival mode, though, and it behaved like one: a direct message from a peer nearby could vanish into a 45-second gap while the node was still working out that its coordinator had gone; channel traffic heard before joining a cell was dropped outright; retries kept the slow pace built for a schedule that was no longer running; and a stalled message blamed a network registration that, with no coordinator anywhere, could not have been the problem. All four are fixed in this build. Nodes out of reach of any coordinator now carry direct messages and channel traffic between themselves, advertise their names to each other so peers show up as names rather than addresses, and retry at a pace suited to talking directly — about 9 seconds rather than 45. The node-side behaviour is in the firmware you can flash today; the matching app changes — a Direct status with a live count of the neighbours in earshot, and a stalled message that says "no peers nearby" instead of blaming an uplink that isn't there — are merged and ride out with the next app build. It is a smaller network while you are in it: whoever is in radio range, no tower to relay, no delivery across cells. But it is a working one, and it now tells you the truth about which one you are on. |
| 2026-08-28 |
The next-generation radio left the bench — and the first field result is mostly a measurement of where we put the receiver (#170) — the LR2021 evaluation hardware got its first real-world link test: one board carried on foot along a walked route, the other left stationary as the receiver, running 2.4 GHz LoRa at 2.450 GHz, SF9, BW 500 kHz and +22 dBm with the stock whip antennas on both ends. From fixed stops, every frame arrived out to 218 m — 50 of 50 at each stop but one. Walking, the link was clean to about 150 m, had lost half its frames by 270 m and was effectively dead past 300 m, though a handful still made it in from 436 m. The number that matters most, though, is one that has nothing to do with distance: at the very first stop, 7 m apart, the link was already spending about 26 dB more than free space alone can explain. The receiver was indoors, unelevated, in a recessed spot with no gain antenna, and that placement dominates every row of the results — it is several times larger than the roughly 8.7 dB the 2.4 GHz band itself costs against 900 MHz. So the honest conclusion is that this run measured a poor receive location, and the band's actual reach is still unmeasured; it is not a fair comparison against our 900 MHz drive test, which had a mast and an external antenna behind it. One genuine radio result did come out of it: frames decoded at −15 dB signal-to-noise, roughly 3 dB better than the nominal figure for this spreading factor. This is one run, one route and one receiver placement, with approximate distances — a data point, not a coverage curve. The rerun that answers the real question puts the receiver outdoors and up high. Full write-up, plot and data: loomwave.org/rfc/24ghz-per-test-1-result.html. This remains evaluation, not a shipping feature. |
| 2026-08-18 |
Reinstalling from the web installer no longer wipes your node (#216) — every install served from the browser flasher used to erase the patch of flash where an ESP32 node keeps its settings, even though the installer declared it would leave that area alone. A node came back from a routine reinstall with a brand-new address that every peer had to learn all over again, and with its WiFi setup, saved position, channel subscriptions and owner binding gone. The installer now writes the firmware as two pieces that step around that area, so reflashing to pick up a fix keeps a node's identity, its channels and its owner. This covers the browser-flashed boards — Heltec V3, Heltec V4, and Station G2 as client or coordinator; the nRF52840 boards you flash by drag-and-drop were never affected. Wiping a node on purpose is still there as an explicit factory reset. Any installer build dated 2026-08-18 or later has the fix — the date is shown next to each board at flasher.loomwave.org. |
| 2026-08-05 |
The compact tower antenna, simulated whole: two targets clear, one the model cannot resolve — earlier simulations described a board outline the design had since outgrown, so the whole antenna — radiator, printed balun, matching section, ground pour and reflector — was re-simulated as one structure at the as-cut 104 × 200 mm outline, driven at the real connector. Return loss comes out at −11.6 dB or better across the whole 902–928 MHz band and realized gain at 6.9 dBi — both comfortably inside target, and both still inside it when the simulation's own settings are varied. Front-to-back is the one that will not settle: moving the simulated boundary further from the antenna, with the geometry untouched, shifts that number by more than a decibel, and moving it further still shifts it back the other way. There is no setting the result converges on, so the model cannot resolve front-to-back against its target — a statement about the simulation, not a verdict on the antenna. Establishing that cost a run 6.5× the size of the original, and it is why nothing has been sent for fabrication: a real front-to-back figure for this design needs a measurement the simulation cannot stand in for. This remains exploratory design work. |
| 2026-08-02 |
The published specification now matches what the fleet actually runs — the packet-format reference was brought up to the shipped wire version, including the membership-scaling beacon that lets a single coordinator serve a dense hub and its downlink-pending signaling. A new reliable-messaging chapter documents confirmed delivery end to end: the sealed message envelope the infrastructure can't open, the automatic retransmission that survives a dropped packet, and the short receive-window timing rule that makes downlinks land. The whole specification is self-contained and browsable at loomwave.org/rfc/. |
| 2026-07-31 |
Next-generation radio evaluation begins — LR2021 on the bench — Semtech's new dual-band transceiver came up on the bench and linked to itself cleanly: 25 of 25 packets at 915 MHz, then a first 2.4 GHz LoRa link (8 of 8 at SF9/BW500) and a 2.6 Mb/s FLRC link at 2.45 GHz. This is evaluation, not a shipping feature — but if it delivers, future towers could carry backbone traffic on a separate band, freeing up airtime where everyday messages live. |
| 2026-07-30 |
A compact 4-channel tower antenna, designed before anything was fabricated — a printed-circuit radiator with its impedance-matching network etched onto the board, designed end to end in open-source electromagnetic simulation (openEMS) and taken to a fabrication package. The automated fab gate passed that package; a human review then caught fabrication-killing defects the gate had missed — copper printed outside the board outline — which is what drove the new outline and hole-overlap checks the gate now runs. The full-structure simulation of that board followed on 2026-08-05 — see above. |
| 2026-07-25 |
Firmware release client-fw-2026.07.25 — message the mesh from any web browser (#153) — coordinators with WiFi now host a chat page: join the coordinator's network, open /chat, and you're talking on the mesh with no app to install (iPhones included). Validated over real radio in both directions on the bench. The web page talks on the built-in #Public channel, which is open by design — see below. Also in this build: a fix for nodes that hadn't finished joining a cell silently ignoring channel traffic, battery voltage reported on the air, and a lower-idle-power mode for WiFi coordinators. Flash at flasher.loomwave.org. |
| 2026-07-25 |
Battery telemetry and early warning — the first piece of fleet energy monitoring (#152) — nodes now report battery voltage as part of their normal telemetry, and infrastructure keeps a solar-aware trend fit over it, so a node heading for a flat battery can be flagged days out instead of simply going quiet. Alongside it, a staged-rollout system for firmware updates landed in dry-run form — canary nodes, automated health checks against live telemetry, and halt-or-rollback rules — groundwork for safe fleet-wide updates. |
| 2026-07-24 |
Smarter cross-cell routing, live on the production tower (#145) — cross-cell delivery now prefers the cell that actually owns the recipient and forgets stale routes learned from elsewhere, fixing two delivery bugs reported from the field. The routing decision was pulled out into a pure, unit-tested function first, so the behaviour that fixed them is now pinned by tests rather than by hope. |
| 2026-07-24 |
Infrastructure relays now sip power (#146) — the WiFi-connected coordinator build idles about 30% lower — 0.17 A down to 0.12 A at 5 V, measured at the bench meter on a freshly booted node. It is on by default in the shipped WiFi coordinator firmware. That figure is the combined effect of three settings measured together, not one: a slower CPU clock, deeper WiFi sleep between beacons, and trimmed WiFi transmit power. The deeper sleep is the one that trades against how quickly the node answers an incoming connection — a balance we are still tuning. |
| 2026-07-13 |
One-click WiFi setup for a masted coordinator (#136, #137) — the phone now hands a coordinator its WiFi credentials in a single tap using Wi-Fi Easy Connect, instead of typing a password into a tiny screen or baking credentials into a build. It is now the default WiFi coordinator firmware for the Station G2. One caveat if you plan to update that node over the air later: a coordinator set up this way generates its own update password, and that password never reaches the phone — so a node provisioned entirely by one tap will refuse over-the-air updates. Until the app can retrieve it for you, set that node up from its built-in setup page instead of using the one tap, where you choose that password yourself. Do it in that order: a node that has already been set up by one tap can't have its update password changed from the setup page afterwards — it has to be factory-reset from the app first, which also gives it a new node address and unpairs it from its owner. Nothing else about the one-tap path changes. |
| 2026-07-12 |
Your node answers to you — owner binding, read receipts, and a new home screen (#130, #133) — a node can now be claimed by its owner through a challenge-response, with display boards showing a passcode on their own screen, so a stranger in range can't quietly pair with your node; an unauthenticated connection times out rather than squatting the slot, and a node can be unpaired again on the owner's say-so. Messages gained a third receipt state — sent, delivered, and read — and the app moved to a three-tab shell: Chats, Channels, Node. |
| 2026-07-11 |
Channels in the app — join, create, and catch up (#132) — the phone app can join or create a channel, generate a strong random channel key in one tap, share an invite by QR code or link, and read the channel thread alongside direct messages. History missed while your phone was away syncs when you reconnect, and it survives leaving and re-entering a channel. |
| 2026-07-11 |
Group channels are live on the mesh — send once, reach everyone (#132) — send to a named channel and every subscriber's node receives it, across cells. A channel message crosses a whole cell in two radio transmissions rather than having every node repeat it, and it travels only toward cells that actually have a subscriber, so a channel costs airtime where it is wanted and nothing where it isn't. Coordinators keep a per-channel history that survives reboots and updates, so a node that was powered off catches up on exactly the messages it missed when it returns — proven by powering a node down, sending messages, and watching them replay on its return. Validated over real RF between two towers. Every channel message carries its sender's signature, so you can tell who really sent it. |
| 2026-07-11 |
What a channel key does and doesn't hide — worth being precise about, since we ship both. A channel you create carries a key you chose and shared yourself; the infrastructure holds no channel key material at all, so coordinators forward those messages by channel identifier alone and cannot read the contents. The built-in #Public channel is the deliberate exception: its key is compiled into every node's firmware, so every node — and every coordinator — derives the same one. Anything on #Public is readable by anyone in radio range, joined or not. That is not a gap, it's the point: it's what lets a coordinator serve the browser chat page above with no app, no account, and no join. Use a channel of your own for anything you wouldn't say out loud. |
| 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. |