use cqueues for gnss socket

This is to avoid a weird bug in the previous glib iochannel
implementation, where the socket was randomly being closed
after about a minute run time. But it's also less code, so
that's OK
This commit is contained in:
Daniel Barlow 2025-06-30 20:30:23 +01:00
parent b739d9a411
commit c56943e6e1
2 changed files with 29 additions and 37 deletions

View File

@ -12,7 +12,7 @@ $(NAME): $(patsubst %.fnl,%.lua,$(MODULES)) Makefile
chmod +x $@ chmod +x $@
run: run:
( fennel fake-nmea.fnl commute.nmea /tmp/gnss & ) ; sleep 1; fennel -e '((. (require :main) :run) "/tmp/gnss")' fennel -e '((. (require :main) :run) "/tmp/gnss")'
test: test:
fennel run-tests.fnl $(MODULES) fennel run-tests.fnl $(MODULES)

View File

@ -2,6 +2,7 @@
(local { : fdopen } (require :posix.stdio)) (local { : fdopen } (require :posix.stdio))
(local ptime (require :posix.time)) (local ptime (require :posix.time))
(local cqueues (require :cqueues)) (local cqueues (require :cqueues))
(local socket (require :cqueues.socket))
(local nmea (require :nmea)) (local nmea (require :nmea))
(local tiles (require :tiles)) (local tiles (require :tiles))
@ -452,32 +453,29 @@ label.readout {
(> b c) c (> b c) c
b)) b))
(fn read-gnss [socket] (fn read-gnss-sentence [l]
(each [l #(socket:read "l")] (if (not (= l ""))
; (print "gnss" l) (let [message (nmea.parse l)]
(if (not (= l "")) (case message
(let [message (nmea.parse l)] { : lat : lon : utc}
(case message (update-app-state
{ : lat : lon : utc} {
: lat : lon
:time-of-day
(let [(h m s) (string.match utc "(..)(..)(..)")]
(+ s (* m 60) (* h 60 60)))
}
)
{ : speed-knots }
(update-app-state { :speed (* speed-knots knot-in-m-s) }))
(when message.bearing-true
(let [c1 message.bearing-true
c2 (. app-state.courses 1)
c3 (. app-state.courses 2)]
(update-app-state (update-app-state
{ { :course (clamp c1 c2 c3)
: lat : lon :courses [c1 c2 c3]
:time-of-day }))))))
(let [(h m s) (string.match utc "(..)(..)(..)")]
(+ s (* m 60) (* h 60 60)))
}
)
{ : speed-knots }
(update-app-state { :speed (* speed-knots knot-in-m-s) }))
(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]
}))))))
true)
(fn collect-profile [] (fn collect-profile []
(GLib.timeout_add (GLib.timeout_add
@ -488,17 +486,11 @@ label.readout {
(profile.start 0)) (profile.start 0))
(fn watch-gnss-socket [socket-path] (fn watch-gnss-socket [socket-path]
(let [gnss-socket (let [sock (socket.connect { :path socket-path :unlink true })]
(let [addr (Gio.UnixSocketAddress { (cq:wrap
:path socket-path #(each [l (sock:lines "*L")]
})] (read-gnss-sentence l)))))
(: (Gio.SocketClient) :connect addr nil))
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 run [gnss-socket] (fn run [gnss-socket]
(watch-gnss-socket (or gnss-socket "/var/run/gnss-share.sock")) (watch-gnss-socket (or gnss-socket "/var/run/gnss-share.sock"))