Files
maptool/docs/development.adoc
T
randy 87df90f75c Redesign UI as an OsmAnd-style sidebar, add live GNSS position via gpsd
Restructure the map controls from MapLibre corner buttons into a left
sidebar of icons with flyouts/panels (radar, GPX, GNSS), matching
OsmAnd's layout more closely:

- Base map and GPX selection are now full-height side panels docked
  next to the sidebar (not small dropdown flyouts or a right-docked
  panel), opening/closing exclusively via a small shared event bus
  (panels.js) so only one is ever open at a time.
- The GPX panel's upload/new-folder controls are now icon buttons in
  the header instead of an always-visible dropzone and form; dragging
  a GPX file onto the tree, a specific folder, or straight onto the
  map itself all upload it.
- New: Maptool::GpsdClient (lib/maptool/gpsd_client.rb) streams live
  GNSS fixes from a local gpsd daemon over Server-Sent Events
  (/api/gnss/stream) to a marker on the map (public/js/gnss.js) — one
  background gpsd connection shared by every browser tab.
- The online map style (public/js/osmand-style.js) is now styled to
  resemble OsmAnd's own rendering, applied to both the online and
  offline (PMTiles) styles.

Also adds a GeolocateControl (browser geolocation) next to the zoom
controls.
2026-08-25 19:39:13 +02:00

2.8 KiB
Raw Blame History

Development guide

Web app only

bundle install
bundle exec puma -C config/puma.rb

Open http://127.0.0.1:4567. For auto-reload during development, run via the rerun gem instead:

bundle exec rerun -- bundle exec puma -C config/puma.rb
Tip
Browsers apply heuristic caching to static files even without explicit cache headers, so an edit to public/ (or views/) can appear not to have taken effect on the next reload. Force a real reload (e.g. Ctrl/Cmd+Shift+R) if that happens.

Offline map data

To enable the offline style, place a PMTiles file at data/offline.pmtiles (see docs/architecture.adoc for how it is served and styled). It is not part of the repository — obtain or build one locally:

  • The simplest source is a pre-built extract from protomaps.com’s extract builder — pick a region and download it as .pmtiles. Its schema is what protomaps-themes-base (the styling library used for the offline style) expects.

  • To convert some other vector tile source (e.g. an .mbtiles file) into PMTiles, use the go-pmtiles CLI: pmtiles convert in.mbtiles data/offline.pmtiles.

Once the file is in place, GET /api/offline-tiles reports available: true and the map defaults to the offline style.

GNSS position (gpsd)

The "GNSS" control needs gpsd running and pointed at a receiver (gpsd /dev/ttyUSB0, or whatever device the receiver shows up as). On openSUSE, gpsd is a package with systemd units (gpsd.service / gpsd.socket); on other distributions, check your package manager. No app-side configuration is needed — it just connects to 127.0.0.1:2947, gpsd’s default port.

To test without hardware, feed gpsd a fake NMEA stream over TCP instead of a real serial device — gpsd accepts a tcp://host:port source:

# terminal 1: a TCP server repeating one NMEA GGA/RMC sentence pair
python3 - <<'PY' 5001
import socket, sys, time

def checksum(s):
    cs = 0
    for ch in s:
        cs ^= ord(ch)
    return f"{cs:02X}"

def sentence(body):
    return f"${body}*{checksum(body)}\r\n"

port = int(sys.argv[1])
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("127.0.0.1", port))
srv.listen(1)
conn, _ = srv.accept()
gga = "GPGGA,123519,4808.916,N,01706.462,E,1,08,0.9,140.4,M,46.9,M,,"
rmc = "GPRMC,123519,A,4808.916,N,01706.462,E,000.5,084.4,230824,003.1,W"
while True:
    conn.sendall((sentence(gga) + sentence(rmc)).encode())
    time.sleep(1)
PY

# terminal 2: point gpsd at it instead of a real device
gpsd -N -n tcp://127.0.0.1:5001

GET /api/gnss/position should then report the fake fix (Bratislava Castle, in the sentences above) within a couple of seconds.