gps: modem GNSS -> gpsd -> OwnTracks/MQTT publisher

EC25-AF GNSS wiring (udev hotplug into gpsd) plus van-gps-owntracks, a
port of the wayback-era gps_to_owntracks.py: apt-only deps (python3-gps
instead of pip-only gpsdclient, paho 2.x callback API), broker secrets
moved out of the code into /etc/van-gps/config.json (0600, seeded from
a sanitized example), gpsd host now localhost. client_id is vanq-wan —
a legacy client still holds vanq on the broker and shared IDs get
kicked in a connect/disconnect loop. Exit-on-disconnect + systemd
Restart=always is the reconnect logic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Andreas Wrede
2026-07-14 22:03:40 -04:00
co-authored by Claude Fable 5
parent d2a2b19b85
commit 8d5415f326
7 changed files with 261 additions and 1 deletions
+38
View File
@@ -205,6 +205,44 @@ The `homeassistant` LAN name comes from `ap/van-ap-dnsmasq.conf` (`host-record`
support `--reset`; autoconnect reconnects), falling back to a USB unbind/bind of the
Quectel device (vendor `2c7c`) if ModemManager can't reach the modem.
### GPS (gpsd from the cellular modem)
The EC25-AF has a GNSS engine that streams NMEA on its USB interface 01 (`ttyUSB1`,
`gps` port in `mmcli`). Needs its own GPS antenna on the modem's GNSS connector for a fix.
- **One-time modem config** (persists in modem NV; survives reboot/replug/Restart):
GNSS auto-start via `AT+QGPSCFG="autogps",1` + `AT+QGPS=1`. ModemManager holds both
AT ports and swallows replies, so stop it first:
`systemctl stop ModemManager`, send the ATs on `/dev/ttyUSB3`, `systemctl start ModemManager`.
- **Host side** (deployed by deploy.sh, needs `apt install gpsd gpsd-clients`):
`gps/77-modem-gps.rules` udev rule matches the NMEA tty (2c7c:0125 if01), symlinks it
to `/dev/modem-gps`, and hot-adds it to gpsd via `gpsdctl@%k` — the same mechanism as
gpsd's own 60-gpsd.rules, so plug/unplug/renumbering just works. `gps/gpsd.default`
(`/etc/default/gpsd`) keeps `DEVICES` empty (hotplug does it) and runs gpsd with `-n`.
- Verify: `gpspipe -r -n 10` (raw NMEA), `cgps` (fix view), `systemctl status gpsdctl@ttyUSB1`.
- Don't enable MM location APIs (`mmcli --location-enable-gps-*`) at the same time —
MM would open the NMEA port and fight gpsd; `gps-unmanaged` is the only safe one.
### OwnTracks publisher (gpsd -> MQTT)
`gps/van-gps-owntracks` (service `van-gps-owntracks`) streams TPV fixes from local
gpsd and publishes OwnTracks location JSON to `owntracks/rv/gps` on home.wrede.ca
(tid `rv`) — at most every 10 min when parked, immediately after >250 m of movement.
Port of the wayback-era `gps_to_owntracks.py`, adapted to apt-only deps
(`python3-gps`, `python3-paho-mqtt` — the old `gpsdclient` is pip-only) and the
paho 2.x callback API.
- Broker credentials live only in `/etc/van-gps/config.json` (0600, seeded from
`gps/config.json.example` — edit after first deploy). All knobs (broker, topic,
intervals, gpsd host) live there too.
- **client_id must stay `vanq-wan` (or anything unique)**: some legacy client still
holds `vanq` on the broker (old copy on wayback?) and the broker kicks whoever
shares its ID — the symptom is connect/disconnect every few seconds.
- On MQTT disconnect the script exits and systemd restarts it (RestartSec=15);
that *is* the reconnect logic, so a red blip after a WAN failover is normal.
- Debug tracing: `kill -HUP` the process toggles per-fix logging to the journal.
- Verify: `journalctl -u van-gps-owntracks` shows `mqtt connect` and stays quiet;
a restart publishes the current fix immediately (first-message path), so
subscribing to `owntracks/rv/gps` while restarting shows a live message.
- Note: the broker holds an ancient *retained* message on this topic from a 2023
OwnTracks device (tid `RV`, Winegard SSID); our publishes are not retained.
### ZeroTier managed DNS
- `wrede.pvt` resolves over ZeroTier when off the home LAN. Mechanism: `allowDNS=1` (prereq) + `zerotier-systemd-manager` writes `99-ztuga7c2kh.network`, networkd applies it to resolved.
- Verify: `resolvectl status ztuga7c2kh` shows `DNS` scope + the two servers + `wrede.pvt`.