A cross-platform browser console for the SeaTrac SP-48 ASV, hull SN-25. Live map, telemetry, manual RC, waypoint missions, power-board control and camera views — from any Mac, Linux box or tablet browser.
SeaTrac's own Dashboard is Windows-only. This is a small, self-contained replacement for the operations we need day to day, speaking the same documented SP-48 protocol.
Scope: built and tested against SN-25 specifically. Link ports, the power-output names and the tag calibrations are SN-25's. It is not a generalised product.
📖 docs/ARCHITECTURE.md — how it talks to the boat, end to end. Read that before changing anything.
| Python 3.9+ | required | Runs the server. No pip packages — standard library only. |
| ffmpeg | optional | Decodes the boat's H.264 camera frames. Everything except the camera view works without it. |
sn25client.pem + .key |
required for the cloud link | Authenticates you to the SeaTrac server. See keys/README.md. |
There is no requirements.txt and no virtualenv, on purpose: the fewer moving
parts on a boat deployment, the better.
git clone <this-repo> sn25-webgui
cd sn25-webgui
bash setup-macos.shsetup-macos.sh checks Python, offers to install ffmpeg, verifies your
certificate is in place, and runs the backend self-test. It is safe to re-run.
macOS does not always ship a usable python3. Check first:
python3 --versionIf that fails, pick one of these:
(a) Apple's Command Line Tools — no admin rights needed
xcode-select --installAccept the dialog and wait for it to finish. This is the least invasive option and gives you a Python that runs this project fine.
(b) Homebrew — if you already use brew, or want a newer Python
brew install python(c) The official graphical installer — no terminal required Download the macOS 64-bit universal2 installer from https://www.python.org/downloads/macos/ and run it.
Then re-run bash setup-macos.sh.
If macOS says "python3: command not found" and pops up a developer-tools dialog, that is option (a) — click Install.
Copy the pair from the SeaTrac Dashboard installation:
keys/sn25client.pem
keys/sn25client.key
These are secrets — anyone with them can command the boat. .gitignore
already excludes them.
Double-click start.command in Finder. It launches the server on Cell1 and
opens your browser. Leave the Terminal window open; Ctrl-C stops it.
First time, macOS may block it as an unidentified developer. Right-click → Open → Open once, and it will run normally from then on.
Run from the repo root:
python3 webgui/server.py --server seatracserver.com:41024 --cert keys/sn25client.pem --key keys/sn25client.key --legacy-tls --insecureThen open http://localhost:8080.
python3 webgui/server.py --boat 10.1.20.88Plain UDP to the SP-48 on port 62001. No certificate needed.
Advanced: through your own relay (CGNAT workaround)
If the boat is behind carrier NAT and you run the companion relay on a public VPS:
python3 webgui/server.py --relay relay.example.com:7777 --token SECRETRequires relay/relay_server.py on the VPS and relay/boat_agent.py on the
payload PC (not included here — see the autonomy repo).
| Flag | Default | Notes |
|---|---|---|
--server HOST:PORT |
— | SeaTrac cloud link. Port selects the radio (see below). |
--boat IP |
— | On-LAN UDP mode. |
--camera-port N |
43024 |
Link carrying video. 48124 = PCStarlink (more bandwidth). |
--http-port N |
8080 |
Change if 8080 is taken. |
--legacy-tls |
off | Lowers OpenSSL's security level for SeaTrac's older certs. |
--insecure |
off | Skips server cert verification. Your client cert still authenticates you. |
--arrival-m N |
15 |
Waypoint arrival radius, metres. |
| Link | Port | Character |
|---|---|---|
| Cell1 | 41024 | Always on, low bandwidth. Telemetry only — no video. |
| Cell2 | 42124 | High bandwidth. Needs the Router (24V#1) powered. |
| Certus | 42224 | Iridium, global, slow and metered. Control only. |
| Starlink | 42324 | High bandwidth, needs VBat#4 powered. |
| PCCell2 | 43024 | Payload computer via Cell2 — this is where video lives. |
| PCStarlink | 48124 | Payload computer via Starlink — fastest video. |
Only Cell1 (41024) is vendor-confirmed for SN-25; the rest follow the documented pattern. You can switch links live from the dropdown in the GUI — no restart needed.
Without a boat — exercises the whole backend against a simulated SP-48:
cd webgui && python3 gui_test.pyExpect seven OK lines (SSE stream, AIS, command POST, power feedback,
vendored Leaflet, tile cache, mission event).
With the boat — press Check now in the GUI. A green connected pill plus a firmware version means the round trip works.
Map tiles are cached to webgui/tilecache/ as you pan, so previously-viewed
areas keep working with no internet. Leaflet itself is vendored in
webgui/vendor/, so the GUI loads with no CDN.
To pre-load an operating area before going out:
python3 webgui/prefetch_tiles.py --helpThe cache is not committed (it grows to hundreds of MB).
| Symptom | Cause / fix |
|---|---|
python3: command not found |
See If the Mac has no Python above. |
ffmpeg not installed on the GUI host in the camera panel |
brew install ffmpeg. Everything else still works. |
--server requires --cert and --key |
Certificate missing — see keys/README.md. |
| TLS handshake fails | Add --legacy-tls --insecure. If it persists, your .pem/.key may have expired. |
Address already in use |
Another copy is running: pkill -f webgui/server.py, or use --http-port 8090. |
| Camera panel blank / stalls | Needs 24V#2 Cameras and the Router powered, on a PC link (43024/48124). Cell1 cannot carry video. |
| Telemetry frozen, boat reachable | Boat may be in storage mode (reports every ~5 min). Switch Reports/Timing to Mission rates in Dashboard. |
| Mission starts then "ENDED (not all reached)" | Usually slow telemetry versus the comms watchdog — use Cell2/Starlink, not Cell1. |
| Map grey outside cached areas | No internet and no cached tiles. Pre-load with prefetch_tiles.py. |
This software moves a 380 kg vehicle. The interlocks are deliberate:
- ⛔ EMERGENCY STOP commands
all_stopand kills the RC loop first. - Manual RC requires confirmation, and resends throttle/rudder at 3 Hz so the boat's own watchdog stops the motors if the GUI or link dies.
- Comm/Motor board off requires typing
CONFIRM. Turning the comm board off cannot be undone remotely — it is the thing that receives your commands. - Commands are refused while the link is down (except Abort).
- Mission legs are driven one go-to-and-hold at a time, with a stale-telemetry watchdog that parks the boat.
Keep a human watching the boat and a hand on E-Stop. Nothing here is a substitute for that.
webgui/
server.py backend: transports, HTTP/SSE, camera pipeline, missions
index.html the entire frontend (no build step, no framework)
prefetch_tiles.py bulk-download map tiles for offline use
gui_test.py offline end-to-end backend test (simulated boat)
tls_gui_test.py TLS transport test against a local loopback server
vendor/ Leaflet js+css, vendored so the map works offline
seatrac/ SP-48 protocol: framing, decode, command builders, transports
autonomy/mission.py waypoint mission runner with safety watchdogs
relay/ client side of the optional VPS relay
keys/ your certificate goes here (gitignored)
docs/ARCHITECTURE.md how it all fits together