Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.altnautica.com/llms.txt

Use this file to discover all available pages before exploring further.

Receiver Mode

A receiver is the hub of a distributed-receive deployment. It listens to the drone with its own RTL8812EU, accepts forwarded fragments from every paired relay over the local mesh, runs WFB-ng’s native FEC combine across the merged stream, and republishes the clean video to the same downstream pipeline a single-node Ground Agent uses. There is exactly one receiver per deployment. Every other mesh node is a relay.

What you need

ItemNotes
Ground Agent SBCPi 4B is the bench reference
RTL8812EU USB WiFi adapter (primary)Drone-facing radio. Same as a single-node setup.
Second RTL8812EU USB adapter (default mesh carrier)Same chip as the primary for inventory simplicity and matched 29 dBm TX power. Any 802.11s-capable USB WiFi dongle also works; MT7612U and MT7921AU are common alternatives when mainline kernel coverage is preferred on the mesh side.
Antennas5 GHz omni on each radio. Primary on UNII-3 (channel 149 or 153), mesh on UNII-1 (channel 36 or 40). Keep 30 cm minimum between antennas on the same chassis.
OLED + 4 buttonsFor the Accept window during pairing
Power, case, cablingSame shape as a relay

Install

Same as any ground-station install. Mesh dependencies are always pulled on this profile; no flag is required.
sudo ./install.sh
This installs batctl, avahi-daemon, wpasupplicant, creates /etc/ados/mesh/, and lays down the three role-gated systemd units. profile_detect scans for the second USB WiFi adapter at boot and sets mesh_capable: true in /etc/ados/profile.conf when present.

Switch the role to receiver

Unlike relay, receiver does not require prior pairing. A fresh receiver can come up cold; it generates its own mesh identity (mesh_id and psk.key) on first boot of mesh_manager. OLED: Mesh menu -> Set role -> select receiver with B1/B2 -> confirm with B3. Setup webapp: Ground Station -> Role -> Receiver. REST:
curl -X PUT http://localhost:8080/api/v1/ground-station/role \
  -H "Content-Type: application/json" \
  -d '{"role": "receiver"}'
The transition masks the direct-mode ados-wfb-rx.service, masks ados-wfb-relay.service, unmasks ados-batman.service and ados-wfb-receiver.service, writes receiver to /etc/ados/mesh/role, and starts the mesh + aggregator units.

Verify

Open the setup webapp Ground Station page or Mission Control Hardware tab. The role should show receiver, mesh should be up, and the relay list should be empty until a relay joins. The mesh is up. There are no peers yet because no relay has joined.

Open the Accept window for pairing

To accept a relay, the receiver must open a 60 second Accept window: OLED: Mesh menu -> Accept relay. The screen shows a countdown and an empty pending-relay list. Setup webapp: Ground Station -> Pair relay -> Accept for 60 seconds. REST:
curl -X POST http://localhost:8080/api/v1/ground-station/pair/accept \
  -H "Content-Type: application/json" \
  -d '{"duration_s": 60}'
The receiver binds a UDP listener on bat0:5801. When a relay sends a join request over the mesh, it appears in the pending list on the OLED, setup webapp, and GCS Hardware tab. To approve a pending relay: OLED: highlight the relay with B2/B3, press B1 to approve. Setup webapp or GCS: approve the pending relay by device id. REST:
curl -X POST http://localhost:8080/api/v1/ground-station/pair/approve/<device_id>
The receiver assembles an invite bundle (mesh ID, mesh PSK, drone WFB key, receiver mDNS name + port), encrypts it with Curve25519 ECDH + ChaCha20-Poly1305 keyed off the relay’s ephemeral public key, and sends it back over UDP. The blob is sent twice 100 ms apart to survive a single dropped packet on the lossy mesh. Full pairing protocol details

What runs on the box

After role=receiver:
UnitWhat it does
ados-batman.servicebatman-adv on the second USB dongle. Same module as a relay uses.
ados-wfb-receiver.serviceRuns wfb_rx -a <listen_port> (default port 5800). Accepts UDP forwards from relays. With accept_local_nic: true (default), also reads the local RTL8812EU directly.
ados-mediamtx-gs.serviceRepublishes the clean stream as WHEP. Unchanged from a single-node setup.
The receiver also publishes _ados-receiver._tcp on the mesh interface via mDNS so relays can resolve it without manual configuration.

FEC combine

WFB-ng’s native Reed-Solomon FEC runs at the receiver. The WfbConfig defaults are fec_k = 8 (data fragments per block) and fec_n = 12 (total fragments per block, so 4 parity). This means the receiver can recover the original block as long as it has any 8 of the 12 fragments, regardless of which radio (local or any relay) saw which fragment. The combine stats land in /run/ados/wfb-receiver.json. Surface them via:
curl http://localhost:8080/api/v1/ground-station/wfb/receiver/combined
Fields: fragments_after_dedup, fec_repaired, output_kbps, up. The receiver runs batman-adv in gw client mode by default. If any node on the mesh (a relay or the receiver itself) advertises a cloud gateway via gw server (because it has 4G, Ethernet, or a WiFi client connection), the receiver picks the best one by TQ and routes cloud-bound traffic over it. When a gateway dies, batman-adv evicts it and the receiver picks the next best automatically. No operator action needed. You can pin a specific gateway from the GCS Hardware tab’s Mesh sub-view, or:
curl -X PUT http://localhost:8080/api/v1/ground-station/mesh/gateway_preference \
  -H "Content-Type: application/json" \
  -d '{"mode": "pinned", "pinned_mac": "AA:BB:CC:DD:EE:01"}'
Set mode: auto to release the pin.

Where to monitor

  • OLED: the status header shows Rx<id> as the role badge. Mesh -> Neighbors lists every paired relay with TQ. The Accept window screen shows pending relays during pairing.
  • GCS Mission Control: Hardware tab -> Distributed RX renders a RelayCard for each paired relay with fragment counts, plus a CombinedStreamStats card showing FEC-repaired fragments and output kbps. Mesh tab shows MeshHealthCard, MeshNeighborsTable, MeshGatewaysTable.
  • Setup webapp: Ground Station and System pages show role, mesh health, neighbors, gateways, relays, and combined stream stats.
  • REST API: /api/v1/ground-station/wfb/receiver/relays and /api/v1/ground-station/wfb/receiver/combined.

Decommissioning a relay

To revoke a relay so it can no longer rejoin without re-pairing: GCS: Hardware tab -> Distributed RX -> RelayCard -> Revoke. Type the relay’s device id to confirm. Setup webapp: Ground Station -> Relays -> Revoke. The device id goes into /etc/ados/mesh/revocations.json (mode 0600). On any future pair attempt from this device, the receiver drops the join request silently and the GCS surfaces a relay_revoked toast.

Where to next