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.
This commit is contained in:
1 parent
008e034932
commit
87df90f75c
14 files changed
+939
-200
No files matched your search
@@ -42,3 +42,51 @@ build one locally:
|
||||
|
||||
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 https://gpsd.io[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:
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
# 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.
|
||||
Reference in new issue
Block a user