Inspiration

Off-grid LoRa mesh networks like Meshtastic are a lifeline when cell towers and the internet are gone — disaster zones, backcountry rescue, remote industrial sites. But they were built for tiny text telemetry, not media. LoRa's "Long Fast" preset runs at ~1.07 kbps, one ~200-byte packet takes ~1.5 seconds on air, and RF links drop packets constantly. So a normal photo (hundreds of KB) or voice clip (tens of KB) simply can't get through, and every client — Apple, Android, Meshtastic Web — is stuck doing text and position only. We wanted to know: what would it actually take to move real media through that pipe, honestly, and prove it on screen?

What it does

FARCAST is a live, self-contained web demo that sends a real image, a real Codec2-rate voice note, and real text both ways across a 5-node partial-mesh LoRa network with per-link packet loss and a hop limit of 3. It proves three things in real time: how much media gets through per byte, how well delivery recovers from loss, and how honest the delivery status is.

Everything the bytes touch is real code on real bytes: compress → encrypt (AES-256-GCM) → fragment into ~200-byte packets → LT fountain-code → relay hop-by-hop → reassemble → decrypt → SHA-256 verify → render the image / play the audio / show the text. The only simulated layer is the physical radio (links, per-link loss, flooding, hop limit, airtime) — the one part you want to simulate so loss and recovery are visible and controllable live. You can move loss faders, kill a relay mid-flight and watch alternate-path recovery, and flip Fountain ↔ naive ARQ to watch one deliver the photo while the other stalls.

How we built it

  • Source compression — image downscaled to 64×64 and quantized with a hand-rolled median-cut palette codec (16 colours, 4-bit indices) → ~2 KB; voice as real IMA ADPCM on real PCM; text as UTF-8 through the same pipeline.
  • Security — the whole payload is sealed once with AES-256-GCM, then fragmented, so relays only ever carry ciphertext; every fragment carries a truncated HMAC-SHA-256 tag so tampered fragments are dropped before they poison the decoder.
  • The hero — LT fountain code — a rateless erasure code where each symbol is the XOR of a random subset of source blocks, its neighbour set derived from a 32-bit seed via a Robust Soliton degree distribution (so the neighbour list is never transmitted), decoded by belief-propagation peeling. The receiver rebuilds the file from any sufficiently large subset of symbols — no ACKs, no targeted retransmits.
  • The baseline — naive ARQ — stop-and-wait where every fragment must be ACKed across the same lossy mesh, so dropped ACKs trigger the classic retransmit storm.
  • The radio — managed flooding (rebroadcast-once, hop limit 3) with every link transmission an independent Bernoulli trial, airtime from real Meshtastic preset data rates, and a seeded PRNG so every run is deterministic and reproducible.
  • Honesty — DELIVERED flips true only when SHA-256 of the reconstruction matches the original, then we actually render/play it.

Stack: React + Vite + TypeScript + Tailwind v4, WebCrypto, SVG + Canvas + Web Audio, zero heavy dependencies — the fountain code, codecs, and radio sim are all hand-rolled. The core engine is pure, DOM-free, deterministic, and unit-tested.

Challenges we ran into

  • Hand-rolling an LT fountain code — getting the Robust Soliton distribution, seed-derived neighbour sets, and peeling decoder correct with no library, while keeping decode overhead under ~2× K symbols.
  • Making the comparison fair, not rigged — modelling ARQ's ACKs crossing the same lossy mesh so the retransmit storm emerges honestly rather than being hand-waved.
  • Resisting the urge to fake it — forcing ourselves to run real AES, real HMAC, real SHA-256, and a real compression pipeline on real bytes, so "delivered" is backed by proof, never a cosmetic green check.
  • Being honest about the hard parts — we don't run actual Codec2 (too heavy for a clean build), so we report the true ADPCM bitrate openly instead of overclaiming.

Accomplishments that we're proud of

  • A measured, head-to-head result: averaged over 8 seeds, at 40% link loss the fountain code delivers 88% of the time while ARQ delivers only 25% — a ~3.5× reliability gap — at 1.27× the goodput and zero targeted retransmits vs ARQ's ~161.
  • Zero false deliveries at any loss level: beyond ~50% loss the mesh is simply below capacity and neither scheme can deliver — and FARCAST says so, with a truthful FAILED — need N more fragments.
  • A genuinely functional demo, not a mockup — the whole media pipeline is real code, with 11 unit tests across it.
  • A full product/business framing: the three technical axes recast as value props, form factors (SDK / monitoring SaaS / hardware bundles), and six credible buyer segments.

What we learned

  • Feedback is the enemy on a lossy link. ARQ's retransmits explode with loss (10 → 29 → 79 → 161 → 232+) because the ACKs themselves drop. A rateless erasure code sidesteps the entire feedback loop — "just emit a few more symbols" beats "ask again" every time the back-channel is unreliable.
  • Honesty is a feature. Refusing to show a green check without a SHA-256 proof made the demo more compelling, not less — the honest-failure beat at 90% loss lands harder than any inflated success.
  • Realism anchors matter. Keeping 200-byte fragments, hop limit 3, real preset data rates, and real airtime kept the whole thing grounded in what an actual radio does.

What's next for get-hired-hack-chrp-off-grid

  1. Real Codec2 via WASM — swap the ADPCM model for genuine 1.2–3.2 kbps Codec2 so the voice is intelligible at a true Codec2 rate.
  2. Progressive / partial-decode image — render a coarse preview as fragments arrive and sharpen it, visually dramatizing "any sufficient subset."
  3. Adaptive FEC — auto-tune fountain overhead to the measured link loss and show the chosen overhead live.
  4. Unequal error protection — protect image palette/voice-energy bits more heavily for graceful degradation in the 45–60% band.
  5. Live tamper demo — a "flip a bit" button that corrupts a fragment and shows the receiver reject it on its HMAC tag.
  6. Energy / battery model — convert airtime to mAh and show "messages per charge" for off-grid buyers.
  7. Duty-cycle enforcement, topology editor + scale, shareable runs/CSV export, and a latency dimension.

Built With

Share this project:

Updates

Submission history