Skip to content

Waypoint

An open, community-governed host system and UI for MMDVM digital voice hotspots.

Waypoint is a ground-up hotspot host system for amateur radio digital voice — DMR, YSF, D-Star, P25, NXDN, POCSAG and beyond — built on the public g4klx GPL stack and the new MQTT data plane of MMDVM-Host.

The Waypoint settings UI: station identity, frequencies and modem on one page

It exists because the amateur community deserves a hotspot platform that is:

  • Lossless — configuration is a schema-versioned store; applying a change never destroys another setting. Gateway INI files are generated artifacts, not the source of truth.
  • Honest about status — the dashboard consumes structured MQTT/JSON events. No log scraping, no "shows Not Linked while linked."
  • Secure by default — no default credentials, HTTPS out of the box, a real security-reporting channel.
  • Safe to update — updates are atomic or they don't happen, and your local customizations live in a documented override layer that survives every one.
  • Usable from your phone — responsive to 360 px, dark-default with a real light theme, and a first-run claim you can complete one-handed.
  • Governed to outlive any one person — public repos, public CI, a review SLA, and a written no-telemetry policy. See GOVERNANCE.md.

Quick start

The easiest way to run Waypoint is the ready-to-flash SD-card image (Raspberry Pi OS Lite Bookworm + the full stack):

  1. Download waypoint-<version>-bookworm-<arch>.img.xz and SHA256SUMS from the latest release, and verify them: sha256sum -c SHA256SUMS and minisign -Vm SHA256SUMS -P <release key>.
  2. Flash it with Raspberry Pi Imager (Use custom → the .img.xz), balenaEtcher or dd. Nothing needs configuring at flash time — the image ships no login of any kind and sets itself up on first boot.
  3. Power it up and join the Waypoint-Setup-XXXX network it raises, or reach it over Ethernet at https://raspberrypi.local/. The wizard asks for a hostname, a recovery account and your Wi-Fi, then locks root.
  4. Browse to https://<your-hostname>.local/ and complete the one-time claim to set your Waypoint admin account.

Pick arm64 on a Pi 3/4, armhf for a Pi Zero 2 W / 2 / 3 (32-bit). Pi Zero W and Pi 1 are not supported. Full flashing and first-boot walk-through: docs/image.md.

Locked out? A Waypoint password cannot be recovered — it is stored only as a hash — but you can take a node back with a shell on it (sudo waypointd reset-claim) or with its SD card in a reader. Both routes are in docs/recovery.md, and on the node's own login screen, which is where you will be when you need them.

What it does

The highlights. The complete inventory, with design records and issue links, is in docs/features.md.

Your settings are a store, not a pile of INI files

A schema-versioned store is authoritative and every gateway's .ini is a compiled output of it, so changing one thing cannot silently drop another. Hand-edits belong in an override layer that merges last and survives updates. Save a whole setup as a named profile and switch between them in a click, or import an existing Pi-Star or WPSD card and keep what's on it.

Cross-mode buses, not a grid of bridges

A bus is a named object you attach modes to. Voice entering from any attached mode is converted and emitted to every other, with IDs, callsigns and talkgroups translated per destination — one bus instead of a matrix of YSF2DMR/DMR2YSF daemons. A bus can also span more than one Waypoint node on your LAN over a mutually-authenticated link, so the garage YSF node and the shack DMR node work as one without touching a reflector or the internet.

Text messages, sent by the node itself

Send a DMR text message to a radio over your own RF — no BrandMeister, no reflector. Messages crossing the node either way are recorded and served over an authenticated API, and are never published. A sent message reads sent, not delivered, because unconfirmed DMR data carries no acknowledgement. Off by default, since it puts Waypoint in the path of every DMR frame. Your radio's channel needs M-SMS format with APRS Receive off — see docs/messages-api.md.

The dashboard tells the truth

Status is folded server-side from the host stack's structured MQTT events into one authoritative value, streamed to the browser and republished for Home Assistant with zero YAML. A stranded transmission expires on a watchdog and a killed gateway shows down within about a second, so nothing latches stale. Every event is persisted, so history is the same in every browser regardless of when it connected.

The node handles its own hardware

Modem detection: the board's own identity string, and what the node is configured for

Waypoint asks the modem what it is instead of guessing from the port it appeared on, and tells you when a correctly fitted hat is mute because Bluetooth owns the UART. It flashes firmware on GPIO hats from a button — no SSH, no stm32flash, and an interrupted flash is recoverable by retry. And it calibrates itself: press start, key your radio when asked, and watch the bit error rate fall as the node sweeps its own reference oscillator and keeps the offset that won. Nothing else automates that.

An optional public page for your node

The public node page: reach card, live status and a map

Publish a read-only page saying how to actually work your node — frequencies, colour code, timeslots, grid, nets, links — plus recent callsigns, a JSON API and a drop-in <iframe> widget for a club website. It is off by default and every route answers 404 until you turn it on, and it publishes callsigns and nothing else: no duration, BER, talkgroup for a heard station, version string, IP, or location finer than a 6-character grid square. Those fields do not exist in the responses. See docs/public-api.md.

Updates that complete or don't happen

Releases are signed (minisign/Ed25519) and verified before they are applied. The new binary is staged and atomically swapped with the old one kept as a rollback, then health-gated — if it doesn't come up healthy it reverts itself, including after a power cut mid-update. The same confirm-or-revert discipline covers the mode daemons, which arrive as signed apt packages. HTTPS is on from first boot with a per-device certificate, so your claim password never crosses the network in the clear.

Status

Active development. The config core, the full mode stack, cross-mode buses, LAN peering, host networking, modem detection, firmware flashing, guided calibration, DMR text messaging and the public page are in place, with per-mode, two-node and on-hardware runs validated on the bench — against a real radio, and written up including what did not go as planned. All eight mode daemons are built, signed, published and — as of the POCSAG close-out (#33) — delivered: installed over apt by Waypoint's own updater on a real node, which is a different claim from "the package exists" and is the one that had never been tested.

The first flashable SD-card image ships as v1-initialimg, built end-to-end by public CI for arm64 and armhf. The requirements register is imported — every item carries provenance back to the community complaint or upstream issue that motivated it — and everything is public from the first commit.

Still ahead: the cross-codec bus path (the AMBE+2 reframe envelope ships, so DMR/YSF-DN/NXDN interoperate, but a vocoder-crossing attachment is refused outright rather than half-working); carrying text across a bus — the DMR text plane exists now, but bridging it to a mesh radio or a second node, and the local map that goes with it, do not (#85); the full-size MMDVM (#25) and DVMega (#26) board tiers; flashing USB stick boards, which is designed but deliberately unbuilt because they are the only boards a flash can brick and none has reached a bench yet (RFC-0020); and a read-only root with A/B slots and automatic rollback (RFC-0017, design).

Caveats, stated plainly:

  • Peering is LAN-only by design — no WAN/Internet mesh, no owner failover.
  • v1-initialimg is an initial image: flashable and complete, but early. Treat it as a beta while it takes on hardware miles.
  • Open defects the bench found and we have not yet fixed are worth knowing before you lean on a mode: no YSF startup reflector links, because the picker stores a name YSFGateway cannot resolve (#146); a DMR transmission to a secondary network kills the next one to the primary (#144); and an unset frequency crash-loops YSFGateway and MMDVM-Host with no visible cause instead of being refused up front (#145, #215, #216).
  • Accessibility is a merge gate, and it passes — 294 pages across three themes and both light and dark, zero violations (#121 cleared a backlog of 98). That is a floor, not a certificate: no automated scan substitutes for using the thing with a screen reader.

Reference bench hardware: MMDVM_HS_Dual_Hat (STM32F103, dual ADF7021) on a Raspberry Pi 3, running Waypoint's own MMDVM_HS firmware build, plus full-size MMDVM (STM32F4/F7) targets.

Architecture (short version)

Radio (MMDVM_HS / MMDVM firmware)
  ↕ serial
g4klx host stack (MMDVM-Host + mode gateways, unmodified)
  ↕ MQTT (mosquitto, JSON events)
waypointd — Go core daemon
  · schema-versioned config store (SQLite in /var/lib/waypoint); INIs are compiled outputs
  · service supervisor (mode gateways + per-bus hub daemons) with reconnect policies
  · hardware ops: board detect, firmware flash (GPIO hats), guided calibration
  · DMR text messages: a codec, and (opt-in) a relay on the MMDVM-Host ↔ DMRGateway
    loopback so the node can originate a data burst of its own
  · REST + WebSocket API (the dashboard is just the first client)
  ↕ HTTPS
Web UI — responsive SPA, embedded in the daemon binary

Full detail: docs/architecture.md.

Contributing

Start with CONTRIBUTING.md. The short version: every PR gets a human response within 14 days — even if it's "no, and here's why." Every behaviour change ships with tests, and any check that tells an operator something is wrong cites the upstream line or field width it rests on. Requirement issues labeled good-first-issue are curated for newcomers. Feature-scale changes start as an issue — the RFC process is dormant until v1, because a comment period needs a community to comment.

This project also runs AI-assisted triage (Claude): new issues and PRs get an initial technical read within minutes, and you can mention @claude in any thread for interactive help. AI never merges; maintainers do.

License

GPL-3.0. The bundled g4klx components are GPL-2.0-or-later. Documentation is CC-BY-SA-4.0.


Waypoint is an independent community project. It reuses no code from Pi-Star or WPSD and is not affiliated with either; we're grateful to both for years of service to the hobby, and to Jonathan Naylor G4KLX, whose stack makes all of this possible.

About

Waypoint — open, community-governed host system and UI for MMDVM digital voice hotspots

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages