MeshCore POTA gateway
A Heltec V3, V4, V4 R8, or XIAO ESP32-S3 + SX1262 running MeshCore room-server firmware, plus a small gateway module. Published firmware is v1.17.1+. Field operators log into the room over LoRa and post a SPOT line. The room HTTPS-POSTs that to api.pota.app on Wi-Fi. TLS runs on a background task so the LoRa stack keeps running. The XIAO build has no OLED; status is the serial pota command.
Utility page (flash, zip, first spot): MeshCore POTA gateway
It is not a group chat named #pota. MeshCore rooms are a BBS: add the room as a contact, log in, post text. Optional prefix #pota SPOT … is accepted in that post body.
Not affiliated with Parks on the Air or MeshCore. Independent tool from KB3CMT. Confirm spots on pota.app. Gateway / firmware bugs: Report a bug. General contact: kb3cmt@gmail.com.
What stays stock MeshCore
src/(Dispatcher, BaseChatMesh, Mesh) is unmodified.simple_repeateris unmodified. Do not flash this build onto a node that must remain a repeater.- Room BBS, login, ACL, adverts, and post sync are stock.
SPOTlines are also stored as normal room posts, then queued for HTTP. - Default
set repeat off. This node is a destination + internet edge, not a flood repeater. Existing repeaters keep carrying daily traffic. - The gateway environments are
Heltec_v3_room_server_pota,heltec_v4_room_server_pota,heltec_v4_r8_room_server_pota, andXiao_S3_WIO_room_server_pota. The matching room-server environment without_potastays a plain room server.
One live gateway
A room post is encrypted to one room identity. A second board on the same frequency cannot decrypt it. Two live gateways only double-spot if someone logs into both and posts twice. Run one named room (example BSR-POTA); keep a second board as a spare.
Flash
- USB, then the browser flasher. Pick Heltec V3, V4, V4 R8, or XIAO ESP32-S3 + SX1262. Chrome or Edge. The image is
v1.17.1+. Other roles in the same tree are on the test builds page. - Or PlatformIO from the
build/pota-allbranch:
pio run -e Heltec_v3_room_server_pota -t upload -t monitor
pio run -e heltec_v4_room_server_pota -t upload -t monitor
pio run -e heltec_v4_r8_room_server_pota -t upload -t monitor
pio run -e Xiao_S3_WIO_room_server_pota -t upload -t monitor
- Serial (115200) should show a Room ID and
[POTA] Wi-Fi STA starting.
Firmware compile default radio in upstream MeshCore is often EU (869.618 / BW 62.5 / SF 8). A US club mesh will not hear the room until you copy get radio from a working node and set radio <freq>,<bw>,<sf>,<cr> then reboot.
Room setup (once)
| Command | Purpose |
|---|---|
get radio / set radio … | Match the mesh, then reboot |
set name BSR-POTA | Advertised name |
set guest.password … | Room login (default compiled hello) |
password … | Admin CLI (default compiled password) |
get repeat | Must stay off |
advert | Flood advert so clients can find the room |
pota | Wi-Fi / queue / pnp=on or pnp=off / blk= |
pota block CALL | Admin: refuse that callsign (also /P and PREFIX/CALL) |
pota unblock CALL | Admin: remove one block-list entry |
pota blocks | Admin: list the block list |
room.post SPOT … | USB dry-run, no second node |
Change the default passwords before the room is public.
Wi-Fi
Radio comes up first. Saved credentials get about 25 seconds. If none, AP MeshCore-POTA-Gateway at http://192.168.4.1. Phone hotspot is fine (iPhone 172.20.10.x is normal). After you save, leave that AP so the board can join the hotspot. Cellular data must be on.
Once STA is up, a Heltec OLED shows the DHCP address and serial prints [PNP] portal http://<ip>/. The XIAO has no screen, so read the address from serial pota. Open http://<that-ip>/ on the same Wi-Fi to set ParksnPeaks (this does not reconnect Wi-Fi). WWFF/SOTA spotting stays off until both validate. Enter OFF in the key field to clear. Blank key on save keeps the stored key.
pota on serial includes pnp=on or pnp=off.
First spot
From a MeshCore client (login with the room password, not admin):
SPOT W1AW US-1234 14.285 SSB Test Activation
K-1234 becomes US-1234. Frequency may be MHz or kHz. USB dry-run:
room.post SPOT KB3CMT US-0001 14235 SSB Testing MeshCore Gateway
Serial: [POTA] Queued then [POTA] OK HTTP 200. Then check pota.app.
WWFF / SOTA (ParksnPeaks, only with a valid portal API key):
SPOT WWFF W1AW KFF-0001 7.144 SSB CQ WWFF
SPOT SOTA W1AW/P W1/GM-001 14.285 SSB CQ SOTA
Daily mesh
Phones and companions still use existing repeaters. This board advertises as a room. Login and posts are peer datagrams to its public key — same as any MeshCore room. Extra RF is one short post per spot plus the usual room advert schedule. Leave repeat off. Park the gateway at the internet edge (vehicle hotspot, EOC, house Wi-Fi), not as the only RF hop in the middle of the mesh.
Wi-Fi TX on these ESP32-S3 boards can slightly desense the SX1262. That is hardware coexistence, not a MeshCore bug.
Gateway operator card
When and why to stand up a node, how to name it, and how to shut it down cleanly. Flash and first-spot steps stay on the utility page and earlier sections of this guide. Independent tool from KB3CMT / Get On The Air — not affiliated with Parks on the Air or MeshCore. Confirm spots on pota.app. Passwords stay off public pages.
When to stand up a node
| Stand up when… | Skip or defer when… |
|---|---|
| Activators are in RF range of a mesh but no cell at parks you care about | Cell + pota.app (or APSPOT / SOTAMAT) already works reliably |
| Club / ARES / EOC wants a fixed internet-edge room for field weekends | You would place it as the only RF hop in the middle of a busy mesh |
| Event / multi-activator weekend with a known LoRa footprint | You cannot change default passwords or supervise the room |
| Personal field kit: vehicle hotspot + board as your edge (not a public club room) | A second live room on the same mesh with no clear “which room for spots” rule |
Rule of thumb: one named live gateway per mesh; spare powered off; park at the internet edge; leave repeat off.
When not to
- You only want a normal MeshCore repeater or plain room — flash the matching non-
_potaimage instead. - You cannot rotate credentials or watch for bogus spots from your room.
- Someone else already runs a live
…-POTAroom on that mesh and ops know which one to use. - You are tempted to publish the room password on a public web page, Discord, or social post — don’t. Share out-of-band to trusted ops only.
Naming
- Advertised room name: unique and obvious, e.g.
CLUB-POTA,W3ABC-POTA,BSR-POTA. - Spare board (powered off):
CLUB-POTA-SPARE(or similar) so it is never confused with the live room if briefly powered for maintenance. - Avoid names that look like an open public channel or imply official POTA endorsement.
Before first advert (change defaults)
Compile defaults exist so the board boots; treat them as change-me, not club secrets.
- Match radio to the mesh (
get radioon a working node →set radio …→ reboot). set name …to your…-POTAname.- Change room (guest) password — this is what field ops use to post.
- Change admin password — CLI only; never share with field ops.
- Confirm
get repeatis off. advert, then USB dry-run:room.post SPOT …and check serial / pota.app.
Placement — internet edge
- Prefer house Wi-Fi, EOC LAN, or a vehicle phone hotspot where the board can reach the internet.
- Do not rely on this board as the only LoRa hop in the middle of the mesh. Existing repeaters carry daily traffic; this node is a destination + internet edge.
- SoftAP (
MeshCore-POTA-Gateway) is for first setup — do not leave it unattended on a public LAN longer than needed.
Repeat off · one live · spare cold
| Practice | Why |
|---|---|
| Repeat off | Room + gateway, not a flood repeater. Turning repeat on adds airtime on meshes that already have repeaters. |
| One live gateway | One named room identity. Two live rooms only double-spot if someone logs into both and posts twice. |
| Spare powered off | Keep a flashed spare for swap; power it only for maintenance or failover. |
Rotate, revoke, shut down
| Action | How (high level) |
|---|---|
| Rotate room password | Change guest password → advert → tell trusted ops the new password out-of-band. |
| Rotate admin | Change admin password; do not share it. |
| Revoke access | New room password is the revoke. Compromised ParksnPeaks key → clear via local portal (OFF) and re-issue at ParksnPeaks. |
| Temporary shutdown | Power off or disconnect Wi-Fi so spots cannot leave; room posts without internet will queue one-deep only while powered. |
| Retire / re-role | Re-flash with erase when changing role (repeater ↔ room ↔ gateway). Re-do radio, name, passwords, repeat, advert. |
RF / legal (high-level — not legal advice)
- Amateur band, power, and identification rules apply when you operate a node as a Part 97 amateur station. Running the default Part 15 mesh does not make the node an amateur station.
- Do not advertise commercial web URLs over RF (site Part 97 posture).
- Gateway Wi-Fi is Part 15. The LoRa mesh (902–928 MHz in the US) normally runs under Part 15 too, and that traffic is not amateur traffic. A node is a Part 97 amateur station only when a licensed ham runs it as one: unencrypted and identified with a call sign. Room posts are encrypted, so they can't go out as amateur traffic. See Part 15 vs Part 97.
- Confirm real activations and spots yourself; this tool does not grant any POTA rights or affiliation.
Who should run one
A licensed amateur willing to keep firmware updated, rotate credentials, watch for abuse, and own the Wi-Fi/backhaul. Club-branded rooms: get trustee / ARES EC buy-in first.
Anti-abuse
Anti-abuse is in the gateway firmware and runs before a spot is queued for HTTPS. A SPOT line still lands in the room log; it is forwarded only if all checks pass. Rejection is logged on serial as [POTA] rejected … and does not count against the limits below. The room password is still who may post.
| Check | What is forwarded |
|---|---|
| Callsign | 3–15 characters, letters and digits, up to two /, with at least one letter and one digit |
| POTA reference | US-1234 shape: 1–3 letters, hyphen, 4 or 5 digits. K-1234 → US-1234 |
| WWFF reference | KFF-0001 / VKFF-1234 |
| SOTA reference | W1/GM-001 |
| Frequency | Decimal = MHz (14.285, 146.52); bare integer = kHz. Kept range 100 kHz–1300 MHz |
| Mode | 2–8 letters or digits (SSB, CW, FT8) |
| Duplicate | Same program + callsign + reference + frequency + mode within 5 minutes |
| Per callsign | 3 queued spots / 10 minutes for the activator callsign in the SPOT line |
| Whole gateway | 20 queued spots / hour (POTA + WWFF + SOTA share the cap) |
| Block list | Up to 16 callsigns, persist across reboot. Admin: pota block CALL, pota unblock CALL, pota blocks. W1AW also matches W1AW/P and KH6/W1AW. Serial pota shows blk=. The open Wi-Fi page cannot edit this list |
One park (reference) per line. A comma-separated 2-fer fails the reference check; post each park on its own line.
Caveat: one room login can rotate callsigns until the gateway hits the 20 / hour global cap. The room password still gates who may post.
The browser flasher is build/pota-all at a852559f (v1.17.1+). That image includes these checks.
Change the default passwords before you advert. Share the room password out-of-band. Rotate it to revoke. Run one live …-POTA room per mesh, keep the spare cold, and watch pota.app for spots you do not recognize.
The spotter still POSTs without a POTA session JWT. If api.pota.app/spot starts returning 401, operators will need a portal session field in a later build. Until then, confirm on pota.app.
Related
- Gateway operator card — when to stand up, naming, rotate/shutdown
- MeshCore POTA gateway utility — zip, flash, checklist
- MeshCore test builds — the same
v1.17.1+tree, including repeaters and companions - Report a bug (GitHub Issues) — MeshCore POTA gateway / firmware issues
- Dead cell / rover QRT
- Activate
- POTAPlus
Notes & edits
Comments and proposed markdown sit in a queue. Nothing is public until it is reviewed. How this works.