Compare commits
5 Commits
bf7eac5fac
...
21471654cb
Author | SHA1 | Date | |
---|---|---|---|
21471654cb | |||
e49173cfdd | |||
36b1284996 | |||
015caf45c6 | |||
97440603f3 |
10
pkgs/maps/fake-nmea.fnl
Normal file
10
pkgs/maps/fake-nmea.fnl
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
(local { : sleep } (require :posix.unistd))
|
||||||
|
|
||||||
|
(let [[filename socketname] arg
|
||||||
|
socket (io.popen (.. "socat - unix-listen:" socketname) :w)]
|
||||||
|
(with-open [handle (io.open filename :r)]
|
||||||
|
(each [l (handle:lines "L")]
|
||||||
|
(if (string.match l "GNS") (sleep 1))
|
||||||
|
(socket:write l)
|
||||||
|
(socket:flush)
|
||||||
|
)))
|
@ -2,6 +2,8 @@
|
|||||||
(local { : fdopen } (require :posix.stdio))
|
(local { : fdopen } (require :posix.stdio))
|
||||||
(local nmea (require :nmea))
|
(local nmea (require :nmea))
|
||||||
|
|
||||||
|
(import-macros { : define-tests : expect : expect= } :assert)
|
||||||
|
|
||||||
(local {
|
(local {
|
||||||
: Gtk
|
: Gtk
|
||||||
: OsmGpsMap
|
: OsmGpsMap
|
||||||
@ -20,6 +22,16 @@ label.readout {
|
|||||||
}
|
}
|
||||||
")
|
")
|
||||||
|
|
||||||
|
(local utc-offset
|
||||||
|
(let [now (os.time)
|
||||||
|
localt (os.date "*t" now)
|
||||||
|
utct (os.date "!*t" now)]
|
||||||
|
(tset localt :isdst false)
|
||||||
|
(os.difftime (os.time localt) (os.time utct))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(fn styles []
|
(fn styles []
|
||||||
(let [style_provider (Gtk.CssProvider)]
|
(let [style_provider (Gtk.CssProvider)]
|
||||||
(Gtk.StyleContext.add_provider_for_screen
|
(Gtk.StyleContext.add_provider_for_screen
|
||||||
@ -38,20 +50,73 @@ label.readout {
|
|||||||
:on_destroy Gtk.main_quit
|
:on_destroy Gtk.main_quit
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(fn osm-widget []
|
(local state-widgets { })
|
||||||
(doto (OsmGpsMap.Map {})
|
|
||||||
(tset :map-source OsmGpsMap.MapSource_t.OPENSTREETMAP)
|
(fn osm-widget []
|
||||||
(: :set_center_and_zoom 52.595 -0.1 14)
|
(let [w
|
||||||
(: :layer_add (OsmGpsMap.MapOsd {
|
(doto (OsmGpsMap.Map {})
|
||||||
:show_copyright true
|
(tset :map-source OsmGpsMap.MapSource_t.OPENSTREETMAP)
|
||||||
; :show_coordinates true
|
(: :set_center_and_zoom 52.595 -0.1 17)
|
||||||
:show_scale true
|
(: :layer_add (OsmGpsMap.MapOsd {
|
||||||
}))
|
:show_copyright true
|
||||||
))
|
; :show_coordinates true
|
||||||
|
:show_scale true
|
||||||
|
}))
|
||||||
|
)]
|
||||||
|
(tset state-widgets :osm w)
|
||||||
|
w))
|
||||||
|
|
||||||
|
|
||||||
|
(fn readout [name text]
|
||||||
|
(let [w
|
||||||
|
(doto (Gtk.Label {:label text : name})
|
||||||
|
(-> (: :get_style_context)
|
||||||
|
(: :add_class :readout)))]
|
||||||
|
(tset state-widgets name w)
|
||||||
|
w))
|
||||||
|
|
||||||
|
(local knot-in-m-s
|
||||||
|
(/ 1852 ; metres in nautical mile
|
||||||
|
3600 ; seconds in an hour
|
||||||
|
))
|
||||||
|
|
||||||
|
(fn hhmmss [seconds-since-midnight]
|
||||||
|
(let [s (% seconds-since-midnight 60)
|
||||||
|
m (% (// (- seconds-since-midnight s) 60) 60)
|
||||||
|
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")
|
||||||
|
|
||||||
|
|
||||||
|
(local
|
||||||
|
app-state {
|
||||||
|
:time-of-day 0
|
||||||
|
:elapsed-time 0
|
||||||
|
:speed 14
|
||||||
|
:lat 49
|
||||||
|
:lon 0
|
||||||
|
:course 22
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
(fn merge [table1 table2]
|
||||||
|
(collect [k v (pairs table2) &into table1]
|
||||||
|
k v))
|
||||||
|
|
||||||
|
|
||||||
|
(fn update-app-state [new-vals]
|
||||||
|
(merge app-state new-vals)
|
||||||
|
(each [name widget (pairs state-widgets)]
|
||||||
|
(case name
|
||||||
|
:speed (widget:set_label
|
||||||
|
(string.format "%.1f km/h" (* app-state.speed 3.6)))
|
||||||
|
:osm (widget:set_center app-state.lat app-state.lon)
|
||||||
|
:time (widget:set_label
|
||||||
|
(hhmmss (+ utc-offset app-state.time-of-day)))
|
||||||
|
)))
|
||||||
|
|
||||||
(fn readout [text]
|
|
||||||
(doto (Gtk.Label {:label text})
|
|
||||||
(-> (: :get_style_context) (: :add_class :readout))))
|
|
||||||
|
|
||||||
(fn readouts []
|
(fn readouts []
|
||||||
(doto (Gtk.Box
|
(doto (Gtk.Box
|
||||||
@ -60,13 +125,37 @@ label.readout {
|
|||||||
:halign Gtk.Align.END
|
:halign Gtk.Align.END
|
||||||
})
|
})
|
||||||
(-> (: :get_style_context) (: :add_class :readouts))
|
(-> (: :get_style_context) (: :add_class :readouts))
|
||||||
(: :add (readout "21:05:00"))
|
(: :add (readout :time ""))
|
||||||
(: :add (readout "00:00"))
|
(: :add (readout :elapsed-time ""))
|
||||||
(: :add (readout "25 km/h"))))
|
(: :add (readout :speed "0"))))
|
||||||
|
|
||||||
|
(fn arrow []
|
||||||
|
(let [height 40
|
||||||
|
w (Gtk.Label {
|
||||||
|
:halign Gtk.Align.CENTER
|
||||||
|
:valign Gtk.Align.CENTER
|
||||||
|
:width height :height height
|
||||||
|
:on_draw
|
||||||
|
(fn [self g]
|
||||||
|
(g:set_source_rgb 0.4 0.0 0.1)
|
||||||
|
(g:translate (// height 2) (// height 2))
|
||||||
|
(g:rotate (/ (* -2 app-state.course math.pi) 360) )
|
||||||
|
(g:translate (// height -2) (// height -2))
|
||||||
|
(g:set_line_width 4)
|
||||||
|
(g:move_to 10 height)
|
||||||
|
(g:line_to (// height 2) 0)
|
||||||
|
(g:line_to (- height 10) height)
|
||||||
|
(g:fill)
|
||||||
|
true)
|
||||||
|
})]
|
||||||
|
w))
|
||||||
|
|
||||||
|
|
||||||
|
(local socket-path (or (. arg 1) "/var/run/gnss-share.sock"))
|
||||||
|
|
||||||
(local gnss-socket
|
(local gnss-socket
|
||||||
(let [addr (Gio.UnixSocketAddress {
|
(let [addr (Gio.UnixSocketAddress {
|
||||||
:path "/var/run/gnss-share.sock"
|
:path socket-path
|
||||||
})]
|
})]
|
||||||
(: (Gio.SocketClient) :connect addr nil)))
|
(: (Gio.SocketClient) :connect addr nil)))
|
||||||
|
|
||||||
@ -74,8 +163,22 @@ label.readout {
|
|||||||
(each [l #(socket:read "l")]
|
(each [l #(socket:read "l")]
|
||||||
; (print "gnss" l)
|
; (print "gnss" l)
|
||||||
(if (not (= l ""))
|
(if (not (= l ""))
|
||||||
(print (view (nmea.parse l)))))
|
(let [message (nmea.parse l)]
|
||||||
|
(case message
|
||||||
|
{ : lat : lon : utc}
|
||||||
|
(update-app-state
|
||||||
|
{
|
||||||
|
: 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) }))
|
||||||
|
(if message.bearing-true
|
||||||
|
(update-app-state { :course message.bearing-true }))
|
||||||
|
)))
|
||||||
true)
|
true)
|
||||||
|
|
||||||
(let [sock (gnss-socket:get_socket)
|
(let [sock (gnss-socket:get_socket)
|
||||||
@ -90,6 +193,7 @@ label.readout {
|
|||||||
(doto (Gtk.Overlay {})
|
(doto (Gtk.Overlay {})
|
||||||
(: :add (osm-widget))
|
(: :add (osm-widget))
|
||||||
(: :add_overlay (readouts))
|
(: :add_overlay (readouts))
|
||||||
|
(: :add_overlay (arrow))
|
||||||
))
|
))
|
||||||
|
|
||||||
(window:show_all)
|
(window:show_all)
|
||||||
|
@ -54,6 +54,15 @@
|
|||||||
nil
|
nil
|
||||||
(tonumber s)))
|
(tonumber s)))
|
||||||
|
|
||||||
|
(fn parse-coordinate [value sign]
|
||||||
|
(if (= value "")
|
||||||
|
nil
|
||||||
|
(let [(deg min) (string.match value "(..)(.+)")]
|
||||||
|
(*
|
||||||
|
(+ (tonumber deg)
|
||||||
|
(/ (tonumber min) 60))
|
||||||
|
(case sign :N 1 :E 1 :S -1 :W -1)))))
|
||||||
|
|
||||||
(local
|
(local
|
||||||
msg-types
|
msg-types
|
||||||
{
|
{
|
||||||
@ -66,14 +75,9 @@
|
|||||||
altitude _
|
altitude _
|
||||||
geoidal-separation _
|
geoidal-separation _
|
||||||
_ _ ] fields
|
_ _ ] fields
|
||||||
latf (if (= lat "")
|
]
|
||||||
nil
|
{ :lat (parse-coordinate lat latsign)
|
||||||
(* (tonumber lat) 0.01 (case latsign :N 1 :S -1)))
|
:lon (parse-coordinate lon lonsign)
|
||||||
lonf (if (= lon "")
|
|
||||||
nil
|
|
||||||
(* (tonumber lon) 0.01 (case lonsign :E 1 :W -1)))]
|
|
||||||
{ :lat latf
|
|
||||||
:lon lonf
|
|
||||||
: fix-quality
|
: fix-quality
|
||||||
:total-space-vehicles (try-number total-space-vehicles)
|
:total-space-vehicles (try-number total-space-vehicles)
|
||||||
:hdop (try-number hdop)
|
:hdop (try-number hdop)
|
||||||
@ -86,39 +90,27 @@
|
|||||||
knots bearing-true date
|
knots bearing-true date
|
||||||
magn-var magn-var-sign
|
magn-var magn-var-sign
|
||||||
mode nav-status &as fields]]
|
mode nav-status &as fields]]
|
||||||
(let [latf (if (= lat "")
|
(let [magnetic-variation (if (= magn-var "")
|
||||||
nil
|
|
||||||
(* (tonumber lat) 0.01 (case latsign :N 1 :S -1)))
|
|
||||||
lonf (if (= lon "")
|
|
||||||
nil
|
|
||||||
(* (tonumber lon) 0.01 (case lonsign :E 1 :W -1)))
|
|
||||||
magnetic-variation (if (= magn-var "")
|
|
||||||
nil
|
nil
|
||||||
(* (tonumber magn-var)
|
(* (tonumber magn-var)
|
||||||
(case magn-var-sign :E 1 :W -1)))]
|
(case magn-var-sign :E 1 :W -1)))]
|
||||||
{ : utc
|
{ : utc
|
||||||
: valid
|
: valid
|
||||||
:lat latf
|
:lat (parse-coordinate lat latsign)
|
||||||
:lon lonf
|
:lon (parse-coordinate lon lonsign)
|
||||||
:speed-knots (try-number knots)
|
:speed-knots (try-number knots)
|
||||||
:bearing-true (try-number bearing-true)
|
:bearing-true (try-number bearing-true)
|
||||||
: date
|
: date
|
||||||
: magnetic-variation
|
: magnetic-variation ;;; XXX probably wrong
|
||||||
: mode
|
: mode
|
||||||
}))
|
}))
|
||||||
|
|
||||||
:GNS
|
:GNS
|
||||||
(fn [fields]
|
(fn [fields]
|
||||||
(let [[utc lat latsign lon lonsign mode total-space-vehicles
|
(let [[utc lat latsign lon lonsign mode total-space-vehicles
|
||||||
hdop altitude geoidal-separation _ _ nav-status] fields
|
hdop altitude geoidal-separation _ _ nav-status] fields]
|
||||||
latf (if (= lat "")
|
{ :lat (parse-coordinate lat latsign)
|
||||||
nil
|
:lon (parse-coordinate lon lonsign)
|
||||||
(* (tonumber lat) 0.01 (case latsign :N 1 :S -1)))
|
|
||||||
lonf (if (= lon "")
|
|
||||||
nil
|
|
||||||
(* (tonumber lon) 0.01 (case lonsign :E 1 :W -1)))]
|
|
||||||
{ :lat latf
|
|
||||||
:lon lonf
|
|
||||||
: mode
|
: mode
|
||||||
:total-space-vehicles (try-number total-space-vehicles)
|
:total-space-vehicles (try-number total-space-vehicles)
|
||||||
:hdop (try-number hdop)
|
:hdop (try-number hdop)
|
||||||
@ -150,14 +142,16 @@
|
|||||||
(tset :talker talker))
|
(tset :talker talker))
|
||||||
split)))
|
split)))
|
||||||
|
|
||||||
|
;; XXX this is wrong. 5131.348976 is 51 degrees 31.348976 minutes
|
||||||
|
|
||||||
(expect=
|
(expect=
|
||||||
(parse-line
|
(parse-line
|
||||||
"$GNGNS,111134.00,5131.348976,N,00005.551003,W,AAAANN,19,0.7,20.3,47.0,,,V*0C\n")
|
"$GNGNS,111134.00,5131.348976,N,00005.551003,W,AAAANN,19,0.7,20.3,47.0,,,V*0C\n")
|
||||||
{:altitude 20.3
|
{:altitude 20.3
|
||||||
:geoidal-separation 47
|
:geoidal-separation 47
|
||||||
:hdop 0.7
|
:hdop 0.7
|
||||||
:lat 51.31348976
|
:lat 51.522482933333
|
||||||
:lon -0.05551003
|
:lon -0.092516716666667
|
||||||
:message-type "GNS"
|
:message-type "GNS"
|
||||||
:mode "AAAANN"
|
:mode "AAAANN"
|
||||||
:nav-status "V"
|
:nav-status "V"
|
||||||
|
Loading…
Reference in New Issue
Block a user