Files

7.2 KiB
Raw Permalink Blame History

Macker

Two processes: the client reads GPS fixes from gpsd in the car, and the VPS server receives them and serves a live location page. Requires Go 1.27 and a running gpsd on the car.

From this repository on the VPS:

go build -o /tmp/macker-server ./server
/tmp/macker-server -ingest :2948 -http :8080

On the car, from this repository:

go build -o /tmp/macker-client ./client
/tmp/macker-client -addr YOUR_VPS_HOST -port 2948 -interval 5s -batch 25

Open http://YOUR_VPS_HOST:8080. Allow the car to reach TCP port 2948 and the browser to reach the web port. For operation across the public internet, use a private tunnel (such as WireGuard) between car and VPS and bind -ingest to the VPS tunnel address. Put the web listener behind an HTTPS reverse proxy with authentication if the location should be private. The application's TCP ingestion and web endpoints have no built-in authentication or encryption.

The browser polls every two seconds. Speed comes from gpsd in metres per second and is shown in mph and km/h. The current gpsd dependency represents omitted speed as zero, so a GPS report without speed can appear stationary. Reports without a position fix are ignored. “Last update” uses the GPS fix time, falling back to server receipt time when absent. After 30 seconds, the page marks the fix stale and hides current speed. Delayed timestamped fixes cannot replace newer fixes.

The map shades an estimated GPS uncertainty circle around each fix. Its radius is hypot(LatErr, LongErr) in metres, enclosing the reported north–south and east–west error ranges. The circle moves and resizes with each fix and is hidden when either estimate is missing, zero, negative, or non-finite. A stale fix retains its last reported circle; it does not predict movement since the fix. This is an estimate, not a guaranteed confidence boundary: gpsd notes that error confidence varies by receiver.

The server retains only the latest fix in memory; a restart clears it. There is no route history or durable client queue. The client compresses each JSON batch into an in-memory ZIP containing points.json, then sends the ZIP bytes inside the existing gob framing. The server unzips in memory, validates the archive and checksum, and accepts at most 4 MiB compressed and 16 MiB expanded. No temporary files are created. Upgrade the server first: it also accepts legacy uncompressed JSON batches. Then rebuild and restart the client to enable compression. Browser access to unpkg.com and tile.openstreetmap.org is required for the map. Map integration follows the Leaflet quick start; OpenStreetMap attribution is included.

Checks:

go test -race ./client/... ./server/... ./datapoint/...

Free local address lookup: Jackson to the Mississippi coast

Address lookup runs on the VPS using a local index of OpenStreetMap addresses. There are no API keys, subscriptions, or per-request fees, and GPS coordinates are not sent to an address service. The full Mississippi extract covers the operating area from Jackson south to the coast without guessing a route boundary.

Install curl, Go, and Osmium Tool on the machine preparing the data (osmium-tool on Debian/Ubuntu; osmium on Arch). From the repository root:

./scripts/prepare-addresses.sh

go build -o /tmp/macker-server ./server
/tmp/macker-server -addresses data/mississippi-addresses.json -ingest :2948 -http :8080

The preparation script downloads the free Mississippi OSM extract from Geofabrik, retains address nodes and ways together with their referenced nodes using Osmium tags-filter, and builds data/mississippi-addresses.json. Temporary source files are removed. Allow disk space for the roughly 90 MB PBF download and its filtered XML, plus memory for importing the referenced coordinates. Actual resource usage depends on the current extract.

Preparation can run on a different machine: copy the resulting JSON file to the VPS. The running server needs only its binary and this index; it does not need Osmium, a Nominatim server, or a database service. By default it looks for data/mississippi-addresses.json relative to its working directory; use an absolute -addresses path in a systemd service. If the file is missing, GPS and mapping still work, with address lookup shown as unconfigured.

The page displays the nearest mapped address within 5 km and its approximate straight-line distance. Address nodes use their recorded coordinates. Addressed building ways use the mean of their vertices, so distance is to an approximate building location, not an entrance, boundary, or driving route. Ways missing referenced coordinates are skipped. Only objects with a house number and street/place are indexed; relation-only addresses, address interpolation, and unmapped houses are not synthesized. OSM address coverage varies, especially in rural areas. If no mapped address is within range, the page says no nearby mapped address is available.

The in-memory spatial index searches locally on every location API request, without the hosted geocoder's 30-second throttle or its 25-metre reuse window. Stale GPS fixes label the distance as belonging to the last known fix. Local data takes precedence over any previously configured geocoder endpoint. The map tiles still load from OpenStreetMap as before.

To refresh, rerun the preparation script and restart the server. Imports replace the JSON file atomically after successful parsing, preserving an existing file if import fails. The generated data is derived from OpenStreetMap and is covered by ODbL; attribution is displayed in the address card. Keep that attribution and license when sharing the dataset.

If you already have filtered OSM XML, import it directly with no download:

go run ./server -import-osm addresses.osm -addresses data/mississippi-addresses.json

Free aerial imagery

Use the Street / Aerial layer control on the map. Street uses OpenStreetMap; Aerial uses the public-domain USDA NAIP imagery exposed by the USGS National Map imagery service. No Google services, accounts, API keys, subscriptions, or paid SDKs are required. The GPS marker and uncertainty circle remain above either background.

The browser loads aerial images directly from imagery.nationalmap.gov on demand, limited to Mississippi's bounding box. This is an online government-hosted imagery layer, not a self-hosted/offline collection. No imagery archive is downloaded to the VPS. The ImageServer's exportImage operation is used with matching Web Mercator tile bounds, natural-color rendering, and attribution. Imagery acquisition dates vary; the photographs are not live. If an aerial image fails to load, the page switches back to Street and offers retry by selecting Aerial again. The map initially opens over southern Mississippi until the first car fix arrives.

Rebuild and restart the server to include the updated embedded page, then reload the browser. The car client needs no changes.