Compare commits
8 Commits
173a440bd6
...
c56943e6e1
Author | SHA1 | Date | |
---|---|---|---|
c56943e6e1 | |||
b739d9a411 | |||
64789d1fe9 | |||
01e260e9aa | |||
0b91d4200f | |||
6ca0e77604 | |||
360c381b33 | |||
e5fdab4852 |
@ -2,7 +2,7 @@ FENNEL?=fennel
|
||||
PREFIX?=/usr/local
|
||||
NAME?=maps
|
||||
|
||||
MODULES=main.fnl
|
||||
MODULES=main.fnl tiles.fnl
|
||||
|
||||
%.lua : %.fnl
|
||||
$(FENNEL) --compile $< > $@
|
||||
@ -11,6 +11,12 @@ $(NAME): $(patsubst %.fnl,%.lua,$(MODULES)) Makefile
|
||||
(echo -e "#!/usr/bin/env lua\n" ; cat main.lua ) > $@
|
||||
chmod +x $@
|
||||
|
||||
run:
|
||||
fennel -e '((. (require :main) :run) "/tmp/gnss")'
|
||||
|
||||
test:
|
||||
fennel run-tests.fnl $(MODULES)
|
||||
|
||||
install:
|
||||
mkdir -p $(PREFIX)/bin $(PREFIX)/
|
||||
cp $(NAME) $(PREFIX)/bin
|
||||
|
@ -1,10 +1,72 @@
|
||||
(local { : sleep } (require :posix.unistd))
|
||||
(local { : sleep : close } (require :posix.unistd))
|
||||
(local sock (require :posix.sys.socket))
|
||||
(local poll (require :posix.poll))
|
||||
(local { : view } (require :fennel))
|
||||
|
||||
(fn handle-client [fd event]
|
||||
(case event
|
||||
{:HUP true}
|
||||
(do
|
||||
(print fd " disconnected")
|
||||
(close fd)
|
||||
(values fd nil))
|
||||
{:IN true}
|
||||
(do
|
||||
(sock.recv fd 1024) ; discard input and carry on
|
||||
nil)))
|
||||
|
||||
(fn accept-new-connection [server-sock event]
|
||||
(case event
|
||||
{:IN true}
|
||||
(do
|
||||
(print "new connection")
|
||||
(let [connected (sock.accept server-sock)]
|
||||
(print connected)
|
||||
(values connected handle-client)))
|
||||
{:HUP true}
|
||||
(do
|
||||
(print "HUP on server socket")
|
||||
(os.exit 1))
|
||||
_
|
||||
(values nil nil)))
|
||||
|
||||
(fn server-socket [path]
|
||||
(let [s (assert (sock.socket sock.AF_UNIX sock.SOCK_STREAM 0))
|
||||
sa { :family sock.AF_UNIX
|
||||
:path path
|
||||
}]
|
||||
(assert (sock.bind s sa))
|
||||
(assert (sock.listen s 10))
|
||||
s))
|
||||
|
||||
(fn read-with-rewind [handle]
|
||||
(let [(s err) (handle:read "L")]
|
||||
(if s
|
||||
s
|
||||
(if (and (not err) (handle:seek "set" 0)) ; eof
|
||||
(read-with-rewind handle)
|
||||
(error err)))))
|
||||
|
||||
(fn write-sentences [handle outputs]
|
||||
(var done false)
|
||||
(while (not done)
|
||||
(let [l (read-with-rewind handle)]
|
||||
(if (string.match l "GNS") (set done true))
|
||||
(each [fd action (pairs outputs)]
|
||||
(when (sock.getpeername fd) ; cheeky
|
||||
(sock.send fd l))))))
|
||||
|
||||
(let [[filename socketname] arg
|
||||
socket (io.popen (.. "socat - unix-listen:" socketname) :w)]
|
||||
server (server-socket socketname)
|
||||
fd-actions { server accept-new-connection }]
|
||||
(with-open [handle (io.open filename :r)]
|
||||
(each [l (handle:lines "L")]
|
||||
(if (string.match l "GNS") (sleep 1))
|
||||
(socket:write l)
|
||||
(socket:flush)
|
||||
)))
|
||||
(while true
|
||||
(let [poll-fds (collect [fd _ (pairs fd-actions)]
|
||||
(values fd {:events { :IN true } }))]
|
||||
(if (> (poll.poll poll-fds (* 1 1000)) 0)
|
||||
(each [fd v (pairs poll-fds)]
|
||||
(when (. v :revents)
|
||||
(print :polled fd (view v.revents))
|
||||
(let [(k v) ((. fd-actions fd) fd v.revents)]
|
||||
(and k (tset fd-actions k v)))))
|
||||
(write-sentences handle fd-actions))))))
|
||||
|
@ -2,6 +2,7 @@
|
||||
(local { : fdopen } (require :posix.stdio))
|
||||
(local ptime (require :posix.time))
|
||||
(local cqueues (require :cqueues))
|
||||
(local socket (require :cqueues.socket))
|
||||
|
||||
(local nmea (require :nmea))
|
||||
(local tiles (require :tiles))
|
||||
@ -86,6 +87,7 @@ label.readout {
|
||||
:lon 0
|
||||
:zoom 17
|
||||
:course 0 ; direction of travel
|
||||
:courses [0 0 0]
|
||||
:orientation-target 0 ; map rotation angle from north
|
||||
:orientation-actual 0 ; map rotation angle from north
|
||||
:tiles {}
|
||||
@ -140,6 +142,8 @@ label.readout {
|
||||
}
|
||||
}))
|
||||
|
||||
(define-tests
|
||||
:map-bounds-tile
|
||||
;; diagonal radius is 538 pixels, 2.1 tiles
|
||||
|
||||
(let [bounds (map-bounds-tile 65539.5 45014.5)]
|
||||
@ -151,7 +155,7 @@ label.readout {
|
||||
(expect= bounds.min {:x 65536 :y 45011})
|
||||
(expect= bounds.max {:x 65541 :y 45016})
|
||||
(expect= bounds.centre {:x 65539 :y 45014})
|
||||
)
|
||||
))
|
||||
|
||||
(fn map-bounds [lat lon zoom]
|
||||
(let [(tile-x tile-y) (tiles.latlon->tile app-state.lat app-state.lon app-state.zoom)]
|
||||
@ -279,7 +283,6 @@ label.readout {
|
||||
|
||||
|
||||
(when (not (= app-state.orientation-actual app-state.orientation-target))
|
||||
(print (- app-state.orientation-actual app-state.orientation-target))
|
||||
(g:translate (+ (/ viewport-width 2)) (+ (/ viewport-height 2)))
|
||||
(g:rotate (* (/ (- 360 (- app-state.orientation-actual app-state.orientation-target)) 180) math.pi))
|
||||
(g:translate (- (/ viewport-width 2)) (- (/ viewport-height 2))))
|
||||
@ -322,13 +325,13 @@ label.readout {
|
||||
h (// (- seconds-since-midnight (* m 60) s) 3600)]
|
||||
(string.format "%d:%02d:%02d" h m s)))
|
||||
|
||||
(expect= (hhmmss (+ 45 (* 60 12) (* 60 60 3))) "3:12:45")
|
||||
(define-tests
|
||||
:hhmmss
|
||||
(expect= (hhmmss (+ 45 (* 60 12) (* 60 60 3))) "3:12:45"))
|
||||
|
||||
(fn turn-smoothly [from to]
|
||||
(if (< (math.abs (- from to)) 10) to
|
||||
(+ from (* 0.05 (- to from)))))
|
||||
|
||||
|
||||
(if (< (math.abs (- from to)) 3) to
|
||||
(+ from (* 0.3 (- to from)))))
|
||||
|
||||
(fn update-app-state [new-vals]
|
||||
(let [old-state (merge {} app-state)
|
||||
@ -445,17 +448,12 @@ label.readout {
|
||||
}))))
|
||||
|
||||
|
||||
(local socket-path (or (. arg 1) "/var/run/gnss-share.sock"))
|
||||
(fn clamp [a b c]
|
||||
(if (< b a) a
|
||||
(> b c) c
|
||||
b))
|
||||
|
||||
(local gnss-socket
|
||||
(let [addr (Gio.UnixSocketAddress {
|
||||
:path socket-path
|
||||
})]
|
||||
(: (Gio.SocketClient) :connect addr nil)))
|
||||
|
||||
(fn read-gnss [socket]
|
||||
(each [l #(socket:read "l")]
|
||||
; (print "gnss" l)
|
||||
(fn read-gnss-sentence [l]
|
||||
(if (not (= l ""))
|
||||
(let [message (nmea.parse l)]
|
||||
(case message
|
||||
@ -470,18 +468,32 @@ label.readout {
|
||||
)
|
||||
{ : speed-knots }
|
||||
(update-app-state { :speed (* speed-knots knot-in-m-s) }))
|
||||
(if message.bearing-true
|
||||
(update-app-state { :course message.bearing-true }))
|
||||
)))
|
||||
true)
|
||||
(when message.bearing-true
|
||||
(let [c1 message.bearing-true
|
||||
c2 (. app-state.courses 1)
|
||||
c3 (. app-state.courses 2)]
|
||||
(update-app-state
|
||||
{ :course (clamp c1 c2 c3)
|
||||
:courses [c1 c2 c3]
|
||||
}))))))
|
||||
|
||||
(let [sock (gnss-socket:get_socket)
|
||||
fd (sock:get_fd)
|
||||
events [ GLib.IOCondition.IN GLib.IOCondition.HUP]
|
||||
channel (GLib.IOChannel.unix_new fd)
|
||||
handle (fdopen fd :r)]
|
||||
(GLib.io_add_watch channel 0 events #(read-gnss handle)))
|
||||
(fn collect-profile []
|
||||
(GLib.timeout_add
|
||||
GLib.PRIORITY_DEFAULT
|
||||
(* 60 1000) main-quit
|
||||
nil nil)
|
||||
(print "profiling for 60 seconds")
|
||||
(profile.start 0))
|
||||
|
||||
(fn watch-gnss-socket [socket-path]
|
||||
(let [sock (socket.connect { :path socket-path :unlink true })]
|
||||
(cq:wrap
|
||||
#(each [l (sock:lines "*L")]
|
||||
(read-gnss-sentence l)))))
|
||||
|
||||
|
||||
(fn run [gnss-socket]
|
||||
(watch-gnss-socket (or gnss-socket "/var/run/gnss-share.sock"))
|
||||
|
||||
(GLib.timeout_add
|
||||
GLib.PRIORITY_DEFAULT
|
||||
@ -495,15 +507,6 @@ label.readout {
|
||||
true)
|
||||
nil nil)
|
||||
|
||||
(fn collect-profile []
|
||||
(GLib.timeout_add
|
||||
GLib.PRIORITY_DEFAULT
|
||||
(* 60 1000) main-quit
|
||||
nil nil)
|
||||
(print "profiling for 60 seconds")
|
||||
(profile.start 0))
|
||||
|
||||
|
||||
(window:add
|
||||
(doto (Gtk.Overlay {})
|
||||
(: :add (osm-widget))
|
||||
@ -515,4 +518,6 @@ label.readout {
|
||||
(window:show_all)
|
||||
(styles)
|
||||
(when (os.getenv "MAP_PROFILE") (collect-profile))
|
||||
(Gtk:main)
|
||||
(Gtk:main))
|
||||
|
||||
{ : run }
|
||||
|
10
pkgs/maps/run-tests.fnl
Normal file
10
pkgs/maps/run-tests.fnl
Normal file
@ -0,0 +1,10 @@
|
||||
(local fennel (require :fennel))
|
||||
(local specials (require :fennel.specials))
|
||||
|
||||
(local compiler-env
|
||||
(doto (. (specials.make-compiler-env) :_G)
|
||||
(tset "RUNNING_TESTS" true)))
|
||||
|
||||
(each [_ f (ipairs arg)]
|
||||
(print :testing f)
|
||||
(fennel.dofile f { :correlate true :compilerEnv compiler-env }))
|
@ -10,7 +10,8 @@
|
||||
|
||||
(fn sinh [x] (/ (- 1 (math.exp (* -2 x))) (* 2 (math.exp (- x)))))
|
||||
|
||||
(expect (< (math.abs (- (sinh 2) 3.626860407847)) 0.001))
|
||||
(define-tests :sinh
|
||||
(expect (< (math.abs (- (sinh 2) 3.626860407847)) 0.001)))
|
||||
|
||||
(fn tile->latlon [xtile ytile zoom]
|
||||
(let [n (^ 2 zoom)
|
||||
@ -21,6 +22,8 @@
|
||||
|
||||
(values (/ (* lat-rad 180) math.pi) lon-deg)))
|
||||
|
||||
(define-tests
|
||||
:tile->latlon
|
||||
(let [(lat lon) (tile->latlon 0 0 0)]
|
||||
(expect= lon -180)
|
||||
(expect-near lat 85.05112877)
|
||||
@ -29,7 +32,7 @@
|
||||
(let [(lat lon) (tile->latlon 232798 103246 18)]
|
||||
(expect-near lon 139.699401855)
|
||||
(expect-near lat 35.6595278648)
|
||||
)
|
||||
))
|
||||
|
||||
(fn latlon->tile [lat lon zoom]
|
||||
(let [n (^ 2 zoom)
|
||||
@ -39,9 +42,10 @@
|
||||
y (* (- 1 (/ t math.pi)) (/ n 2))]
|
||||
(values x y)))
|
||||
|
||||
(define-tests :latlon->tile
|
||||
(let [(x y) (latlon->tile 52.1234 -0.53 17)]
|
||||
(expect= (math.floor x) 65343)
|
||||
(expect= (math.floor y) 43221))
|
||||
(expect= (math.floor y) 43221)))
|
||||
|
||||
|
||||
(fn overpass [lat lon zoom]
|
||||
|
Loading…
Reference in New Issue
Block a user