Skip to content

Instantly share code, notes, and snippets.

@yath

yath/gpssim.tcl

Created Oct 26, 2019
Embed
What would you like to do?
#!/usr/bin/tclsh
# IV-11 doesn’t know about time zones, so doesn’t know about DST, so it’s set
# to a UTC offset of 0 and this script sends the local time (as defined by $TZ
# or $TCL_TZ, cf. https://www.tcl.tk/man/tcl8.6/TclCmd/clock.htm#M21).
package require Tcl 8.5
package require nmea
# formats a number decimally as ddd.fff with zero-padding. Basically [format "%0[d].[f]f"].
proc decfmt {num d f} {
set numi [expr {entier($num)}]
set ret [format "%0${d}d" $numi]
if {$f > 0} {
set numf [expr {$num-$numi}]
set fi [expr {entier($numf * pow(10, $f))}]
set ret "$ret.$fi"
}
return $ret
}
# converts a decimal, signed coordinate into DEGMM.MMM,[NE] format.
proc coord {dec islat} {
set dir [expr { ($dec < 0) ? ($islat ? "S" : "E") : ($islat ? "N" : "W") }]
set degs [expr { int(abs($dec)) }]
set mins [expr { (abs($dec) - $degs) * 60 }]
set intwidth [expr {$islat ? 4 : 5}]
return "[decfmt [expr { $degs*100 + $mins }] $intwidth 3],$dir"
}
# converts a decimal latitude with coord.
proc lat {dec} {
return [coord $dec 1]
}
# converts a decimal longitude with coord.
proc lon {dec} {
return [coord $dec 0]
}
# converts a timestamp in milliseconds from epoch into local HHMMSS.mmm
proc localtime {ms} {
set ts [expr {$ms/1000}]
set micros [decfmt [expr {$ms%1000}] 3 0]
return [clock format $ts -format "%H%M%S.$micros"]
}
# converts a timestamp in milliseconds from epoch into UTC HHMMSS.mmm
proc unused_utctime {ms} {
set ts [expr {$ms/1000}]
set micros [decfmt [expr {$ms%1000}] 3 0]
return [clock format $ts -format "%H%M%S.$micros" -timezone :UTC]
}
# formats a decimal number as meters.
proc meters {dec} {
return [format {%.1f,M} $dec]
}
# returns the arguments joined by comma, surrounded with $ and * and the checksum.
proc gpsmsg args {
set msg [join $args ","]
return "\$$msg*[::nmea::checksum $msg]"
}
# returns a Recommended Minimum Sentence C record (https://www.gpsinformation.org/dale/nmea.htm#RMC).
proc gprmc {ts lat lon {speed 0} {angle 0} {magvar 003.1,W}} {
set utcdate [clock format $ts -format %d%m%y -timezone :UTC]
return [gpsmsg GPRMC [localtime $ts] A [lat $lat] [lon $lon] $speed $angle $utcdate $magvar]
}
# returns a GPS Fix Data record (https://www.gpsinformation.org/dale/nmea.htm#GGA).
proc gpgga {ts lat lon {alt 100} {geoid 50} {quality 1} {nsats 8} {hdop 0.9}} {
return [gpsmsg GPGGA [localtime $ts] [lat $lat] [lon $lon] $quality [format %02d $nsats] [format %.1f $hdop] [meters $alt] [meters $geoid] "" ""]
}
# returns a Geograpgic Latitude and Longitude record (https://www.gpsinformation.org/dale/nmea.htm#GLL).
proc gpgll {ts lat lon} {
return [gpsmsg GPGLL [lat $lat] [lon $lon] [localtime $ts] A]
}
# returns a DOP and Active Satellites record (https://www.gpsinformation.org/dale/nmea.htm#GSA).
proc gpgsa {pdop hdop vdop {sats {}}} {
while {[llength $sats] < 12} {
lappend sats ""
}
return [gpsmsg GPGSA A 3 [join $sats ","] $pdop $hdop $vdop]
}
set lat 48.0569522
set lon 11.4810454
set dop 1.5
while 1 {
set now [expr {[clock milliseconds]-6}]
puts [gprmc $now $lat $lon]
puts [gpgga $now $lat $lon]
puts [gpgll $now $lat $lon]
puts [gpgsa $dop $dop $dop]
after [expr 30*1000]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.