Every year thousands of hikers attempt long distance trails covering thousands of miles through wilderness over a span of months. During this time hikers are often without internet connection for weeks or more severely limiting their access to critical information. While hiking the 211 mile John Muir Trail, Ben often had difficulties obtaining information on current water levels, weather conditions, or the safety of campsites. To this end, we designed a specialized epidemic networking protocol (Trailmesh) that allows information to be disseminated along the trail corridor at remarkable speeds, ensuring hiker safety and a reasonable amount of comfort.

Inspiration

  • When designing Trailmesh we looked at BitTorrent and other peer-to-peer protocols for a model we found genuinely elegant. What makes a torrent powerful is that every peer who joins makes the network stronger. We set out to build a trail network that scales the same way. Every hiker who carries MiRIAD becomes another carrier, so messages, campsite reports, and last-known locations find more paths to their destination.
  • We approached MiRIAD hardware-first, because we wanted something that could scale affordably. MiRIAD tackles real trail problems (search and rescue, up-to-date campsite and water-source information, and off-grid communication) without robust infrastructure. There are no towers, gateways, or satellites: inexpensive off-the-shelf boards talk directly to each other on the license-free bands. Everything else can run on a phone, which most hikers already take with them.

What it does

MiRIAD turns every hiker's device into a mobile mini-server. Out past cell coverage, the data you carry (direct messages, campsite and water-source conditions, and the last-known locations of other hikers) spreads from person to person each time two MiRIAD users come within radio range. When anyone reconnects to the internet, everything they've collected flows up to the MiRIAD server and back out to everyone else.

It's a hybrid server–epidemic network: there's a master server to coordinate and synchronize the mesh with an epidemic protocol to support it in dead zones.

The Trail Ledger

  • Create an account while online. Names are unique, reserved by the server, and are how people address messages to each other.
  • Download provided trail ledgers in line with your planned expedition. These ledgers include the following "locale" information: detailed route data, water sources, campsites, and more. This way, once you're on the trail, you can reliably keep appraised of what's ahead even if networks are unreliable.
  • On every sync, the app checks the server to see if any "locales" have changed - each version carries a hash to prevent redundant re-downloads. Changes are a function of other hikers leaving comments on "locales". These can be vital when planning for resupply or sleeping accommodations.
  • In the Explore tab, you pick your trail; the app shows its route on its own offline map. From then on, the map, trail info, and walking distances along the trail to every locale all work with zero signal.

User Interactivity

  • Message anyone by name (including users you've never met) or broadcast to everyone (*) at once when in need.
  • Report conditions at locales (dead trees, bugs, exposure, bears…). Reports spread to every hiker downstream of you.
  • Passively record last-known locations of other hikers. Your position is saved once a minute and spreads hop by hop: if A meets B and later meets C, C learns where B was even though they never crossed paths, and since a LoRa contact means two hikers were within LoRa range (~3 miles), searchers get a bounded radius even when GPS is poor. If any hiker gets lost on the trail, MiRIAD ensures there is a solid last-known location where a search can begin.

Data Spread

Each hiker carries a Heltec WiFi LoRa 32 V3 (an ESP32-S3 microcontroller paired with a sub-GHz SX1262 LoRa transceiver), connected to their phone, laptop, or Raspberry Pi.

LoRa (915 MHz) ESP-NOW (2.4 GHz)
Job Find peers and shake hands; carry the exchange when hikers are far apart High-capacity exchange when hikers are close
Range Long (miles, per the hardware) Used within 60 m
Throughput ≈ 1.3 KB/s -> 0.47 KB/s ≈ 12 KB/s

Discovery and the handshake always go over LoRa. Each side's handshake includes its GPS position; if both hikers are within 60 m, the exchange switches to ESP-NOW automatically. The switch handoff ensures that if you're sharing a campsite with someone, you sync at full speed. Otherwise, the whole exchange stays on LoRa and sends positions first, the most useful data when you might only be in range briefly.

Everything MiRIAD sends is text, and each record is tiny compared with these rates, so a passing encounter is plenty of time to sync.

What is an epidemic protocol?

An epidemic protocol spreads data like a disease: every member of the network is simultaneously sender, receiver, and storage.

Example: Hiker A writes to Hiker C. The message waits on A's device until A meets Hiker B; their radios find each other, shake hands, and the message moves to B. Later B meets C, and the message is delivered. A and C never had to meet.

When two devices meet, they:

  1. Compare fingerprints. Beacons carry a manifest of everything each side holds; if the manifests match, they skip the exchange entirely.
  2. Agree on a cutoff (i.e. the older of their two last server syncs). Anything before it, both already have.
  3. Swap inventories of what each created or received after the cutoff (so data picked up offline keeps moving), then request only what's missing.
  4. Transfer by priority: over ESP-NOW, locale data first, then messages, positions, and tombstones; over LoRa, positions jump to the front. This way, if you walk out of range mid-transfer, the most important data has already arrived.

Tombstones (mesh congestion helpers)

  • When a message reaches its recipient, their device creates a delivered tombstone record, which spreads like any other record.
  • Relays (anyone who isn't the sender or receiver) delete the message on receipt of the tombstone but keep passing the tombstone along, so the cleanup spreads through the mesh.
  • When the tombstone reaches the sender, their message is marked received. Whoever reaches a server first uploads it, and the server forwards it to every device that syncs, short-circuiting the trip back.
  • Messages and tombstones both expire after 31 days, so stale data is culled, and no device or server is overburdened. If no tombstone comes back in that time, the sender considers the message lost. Broadcast messages are never tombstoned; they spread until they expire.

How we built it

We split the work into four tracks: 1) WebApp 2) Protocol 3) Database 4) Hardware

Hardware

The board (our Heltec device) does no meaningful computation on the data. The firmware (Arduino, Arduino-ESP32 core 3.3, RadioLib 7.8) never reads or changes what's inside a packet; all protocol logic is local to the host. But it still performs necessary transmission filtering:

  • Partner filtering on both radios: every frame begins with the sender's 4-byte device ID, and once a handshake starts, the board drops every frame not from that partner. That way, noise on the crowded 2.4 GHz band and other hikers' chatter never reach the host.
  • Listen-before-talk for LoRa: raw LoRa has none built in, so before each transmission the board checks whether a packet is already arriving. If one is, it waits a random backoff, all without leaving receive mode. Our first version used channel activity detection, but that cut off packets that had just started arriving whenever two boards transmitted close together.
  • Hardware-level rejection: a private sync word (0x24) makes the radio chip ignore LoRaWAN, Meshtastic, and other LoRa traffic, and packets that fail the radio's built-in error check are discarded.
  • A transmit queue and a small serial command set: send, receive, radio on/off, LoRa config, partner, and status (including dropped-packet, error, and airtime counters).

The Epidemic Protocol (Trailmesh)

Programmed using Python, managed by the host:

  • Duty-cycled discovery: devices wake for a 2 s window every 20 s of GPS-synced time and send beacons at random offsets. The lower device ID initiates the handshake.
  • A 12-byte frame header on every packet: sender_id | type | flags | session | seq.
  • Our own reliability layer: sequence numbers, cumulative + 32-bit selective ACKs, a 16-frame window, retransmission, and in-order delivery. LoRa uses delayed ACKs so a whole burst is confirmed at once.
  • Chunking for ESP-NOW's 250-byte limit: any record is split into ≤ 250-byte frames and reassembled by chunk index, then verified with a CRC32. A partial or corrupted record is never stored.
  • The 60 m radio switch: the responder compares both GPS positions and picks the radio (ESP32) for the exchange.

Server(s) Configuration

  • Each device keeps one SQLite database with four shared tables (locales, messages, geolocations, tombstones) plus private device info. The mesh carries the app's rows directly; there is no separate mesh store.
  • The master server (Flask + gunicorn) holds the master copy of everything. Devices push what arrived since their last push, pull what's new, and fetch global data and maps when their versions differ.
  • Devices find a server three ways: a public URL (via a Cloudflare tunnel), a LAN broadcast on the same Wi-Fi, or the radio mesh when there's nothing at all.

The Frontend

  • A Flask web app with Leaflet and Protomaps vector tiles, all vendored so it runs fully offline. Offline maps are cut to a corridor around each trail to stay small (the John Muir Trail's Yosemite Valley section is ~500 tiles).
  • Walking distances are measured along the actual trail network (shortest path), not as the crow flies.
  • It runs on a laptop, a Raspberry Pi serving a phone over Bluetooth, or directly on an Android phone in Termux, with the board plugged in over USB-C.
  • Demo data: the Gainesville–Hawthorne State Trail and the John Muir Trail's Yosemite Valley section, each with locale data.

Challenges we ran into

  • There were many challenges with running our project on mobile devices. Due to increased security concerns, most cellphones do not allow apps onto their public app stores without thorough verification which would not finish before the end of the challenge. In addition, we decided the development overhead of compiling an Android app and sideloading it via Android Studio would slow down testing substantially and would negatively impact our final product. Our final solution, which managed to maintain the python architecture while still supporting Android, was to install a terminal emulator. Termux, along with its accompanying API, is able to run python, host a web app, clone code from github, and interface with the USB transceiver, all locally. After learning what packages and libraries would include all the features we wanted, we created a streamlined process for updating the user interface entirely client-side after each modification to our project.
  • Getting anywhere near the upper limits of LoRa's and ESP-NOW's range proved difficult in practice. Obstructions like buildings and walls, combined with the limits of our compact dev boards and their small antennas, cut into how far we could reliably connect. We still demonstrated the full system working end to end, just not at the distances we'd hoped for. In a production version we'd expect much better results from stronger transceivers and better antennas.
  • Even though we laid out the entire protocol at the start, implementing it was not straightforward. Misunderstandings and a sprint-paced build left parts of the codebase working from completely different assumptions than the rest. Once we noticed the spec was being implemented inconsistently, we stepped back and reassessed MiRIAD as a team. We compared each person's understanding of the protocol, made edits and concessions where needed, and standardized the project.
  • Cleaning the database was messier than intended. Because of the nature of our protocol there is a high level of ‘trust’ between the master server and its nodes. When we tried purging the server’s data for a clean reset it immediately reset our changes once one of the nodes in the mesh resynced with the server. In order to address this “plague persistence issue” we had to shut off all nodes and the server, perform a clean deletion, and then resume the program as a fresh slate.

Accomplishments that we're proud of

  • We never had to make a disruptive pivot, and we credit the up-front planning for steering us around some early landmines. During planning, we realized ESP32s on their own couldn't reach much past ~60 meters, nowhere near enough for our vision of MiRIAD. Because we caught it before writing much code, we had time to order Heltec LoRa boards with overnight shipping and design the long-range LoRa layer from the start. That early catch shaped the final design and, in the end, our original idea was executed in full, and that's been deeply satisfying.
  • The same held for the protocol itself. The core of our design made it from spec to code essentially unchanged: agreeing on a sync cutoff, swapping inventories and requesting only what's missing, TCP-style acknowledgments, partner filtering, and tombstones. The changes we did make were refinements, not overhauls.
  • We made a project that is feasibly deployable and highly useful. With support from a land management organization it’s very easy to envision widespread use of MiRIAD providing a great amount of utility and safety to the outdoor community.

What we learned

"If I had more time, I would have written a shorter letter."
 — Mark Twain
  • In this hackathon, we went where nobody has gone before: emulating terminals on a phone instead of app development because we thought it would be easier. This was, to put it nicely, not the case. Combined with having hardware that refused to cooperate (Our ESP32’s decided that they would use different standards when connecting to USB) and having two types of device (laptops and phones), we ended up with a plethora of files and design overlap in order to make it work. In the future, it would be beneficial to figure out a single framework from the start instead of a mismatch of frameworks that integrated poorly; a shorter, cleaner letter would far better suffice.

  • An idea that fascinated us was that ‘wifi principles’ are just radio communication principles, and trying to apply them to different bands (i.e. the wifi band or the citizens band) is not an arcane process. This also showed us the benefit of our interdisciplinary team, where a computer scientist, computer engineer, electrical engineer, and physicist worked together to develop a highly integrated product.

What's next for MiRIAD

  • Right now, any relay can read what it carries, and a bad actor could use that to stalk or harass hikers. Two fixes come first:
  • Encrypted location pins. A hiker's GPS pins should be readable only by the agency or company hosting MiRIAD, not by every relay that carries them.
  • Encrypted direct messages. Only the sender and the intended receiver should be able to read a message, no matter how many hikers relay it. We also want to sign every record, so no one can impersonate another hiker or forge a delivery receipt to delete someone else's message.
  • Today anyone can broadcast to everyone, at any time. We'd reserve broadcasts for verified, privileged senders (park rangers, weather services, and other authorities) and for genuine emergencies. Hikers would get a confirmation step so they're sure before they broadcast, and the network would have anti-spam safeguards against anyone who abuses it.
  • In the future we would like to develop native mobile apps for the development of MiRIAD. This would allow for simpler deployment and a smoother user experience.
  • With collaboration from the managing organizations of these long trails we could create small portable MiRIAD enabled beacons that could be placed at various common gathering places (shelters, campsites, etc.) along the trail to significantly improve transmission rates.

Built With

Share this project:

Updates

Submission history