NTP ( the timekeeping daemon ) does not like devices that are not present at startup or go away on occasion like a detachable GPS device.
This is unix / _linux_ centric.
Your ntp configuration should contain something like:
# basic nmea source, mode: listen to GPRMC sentence, 9600baud ( in my case a sure electronics gps eval board ) : server 127.127.20.1 mode 17 fudge 127.127.20.1 flag1 0 flag2 0 flag3 0 flag4 0 time1 0.7800
with time1 being an adjustable value depending on what sentences the GPS outputs and your application specific delays.
All examples create a pty and link it to the expected gps device entry ( /dev/gps1 ) and handle disconnects / reconnects on that side gracefully.
The first script then just connects to a usb tty device and pushes selected sentences to the pty side, start this in boot up before rcntp runs:
#!/usr/bin/tclsh package require Expect package require udp set ::Stat(pty,spid) {} set ::Stat(gps,path) "/dev/gps1" proc respawn_pty {} { set spid $::Stat(pty,spid) if {$spid != "" } { close -i $spid -slave wait } catch { puts stderr exist:[file exists $::Stat(gps,path)] } catch { puts stderr type_:[file type $::Stat(gps,path)] } # if { [file exists $::Stat(gps,path)] } catch { if {[file type $::Stat(gps,path)] == "link" } { puts stderr "deleting existing link: $::Stat(gps,path)" file delete $::Stat(gps,path) } } cerr; puts stderr cerr:$cerr spawn -pty set ::Stat(pty,spid) [ set spid $spawn_id ] set ::Stat(pty,slave,name) $spawn_out(slave,name) set ::Stat(pty,slave,fd) $spawn_out(slave,fd) file link -symbolic $::Stat(gps,path) $::Stat(pty,slave,name) expect_background -i $::Stat(pty,spid) \ -re "AT.*?\[\r\n\]{1,2}" { exp_send -i $::Stat(pty,spid) "OK\r" puts stderr "AT sentence, OK sent" } \004 { puts stderr "$::Stat(pty,slave,name) ^D, reopen" # respawn_pty } eof { puts stderr "$::Stat(pty,slave,name) EOF, reopen" # respawn_pty } puts stderr "$::Stat(pty,slave,name) linked to $$::Stat(gps,path), open" parray ::Stat return $::Stat(pty,slave,name) } respawn_pty set fd [ open /dev/ttyUSB0 {RDWR NONBLOCK} ] fconfigure $fd \ -encoding binary -translation binary \ -mode 9600,n,8,1 -handshake none spawn -open $fd set gps_spid $spawn_id log_user 0 expect -i $gps_spid \ -re {(\$GPGGA.*?)\[\r\]} { set sentence $expect_out(1,string) exp_send -i $::Stat(pty,spid) $sentence\r puts stderr 1:$sentence exp_continue } -re {(\$GPGGA.*?\*[[:xdigit:]]{2})[\r]} { set sentence $expect_out(1,string) exp_send -i $::Stat(pty,spid) $sentence\r puts stderr 2:$sentence exp_continue } timeout { puts stderr timeout exp_continue } eof { puts stderr "EOF on GPSside" } puts end # vwait forever
The second example sets up a udp gateway to ntp, receiving udp packets on a select port and piping that down into the pty/tty device opened by ntpd, start this in boot up before rcntp runs:
#!/usr/bin/tclsh # $Id: gpsplug.tcl,v 1.3 2011/05/16 07:05:45 uwe Exp uwe $ # cprt: C2011 Uwe Klein Habertwedt # what: plugin for ntpd to allow a nmea source to # what: be remote or intermittently available. # what: provides a tty(pty) for ntp to attach to # what: while listening on udp:61161 for incoming # what: nmea GPRMC messages ( intp:mode:0=1 ~= listen to RMC ) # what: ntp.conf: # basic nmea source, mode: listen to GPRMC sentence, 9600baud: # what: ntp.conf: server 127.127.20.1 mode 17 # what: ntp.conf: fudge 127.127.20.1 flag1 0 flag2 0 flag3 0 flag4 0 time1 0.7800 # use_: start before ntpd at boot time. package require Expect package require udp set ::Stat(pty,spid) {} set ::Stat(gps,path) "/dev/gps1" set ::Stat(udp,port) 61161 proc respawn_pty {} { set spid $::Stat(pty,spid) if {$spid != "" } { close -i $spid -slave wait } catch { puts stderr exist:[file exists $::Stat(gps,path)] } catch { puts stderr type_:[file type $::Stat(gps,path)] } catch { if {[file type $::Stat(gps,path)] == "link" } { puts stderr "deleting existing link: $::Stat(gps,path)" file delete $::Stat(gps,path) } } cerr; puts stderr cerr:$cerr spawn -pty set ::Stat(pty,spid) [ set spid $spawn_id ] set ::Stat(pty,slave,name) $spawn_out(slave,name) set ::Stat(pty,slave,fd) $spawn_out(slave,fd) file link -symbolic $::Stat(gps,path) $::Stat(pty,slave,name) expect_background -i $::Stat(pty,spid) \ -re "AT.*?\[\r\n\]{1,2}" { exp_send -i $::Stat(pty,spid) "OK\r" puts stderr "AT sentence, OK sent" } \004 { puts stderr "$::Stat(pty,slave,name) ^D, reopen" # respawn_pty } eof { puts stderr "$::Stat(pty,slave,name) EOF, reopen" # respawn_pty } puts stderr "$::Stat(pty,slave,name) linked to $$::Stat(gps,path), open" parray ::Stat return $::Stat(pty,slave,name) } respawn_pty proc udpEventHandler {sock} { set sentence [read $sock] set peer [fconfigure $sock -peer] puts stderr "$peer: [string length $sentence] {$sentence}" exp_send -i $::Stat(pty,spid) $sentence\r return } proc udp_listen {port} { set srv [udp_open $port] fconfigure $srv -buffering none -translation binary fileevent $srv readable [list ::udpEventHandler $srv] puts "Listening on udp port: [fconfigure $srv -myport]" return $srv } set gpssock [ udp_listen $::Stat(udp,port) ] vwait forever #end
The next script provides the nmea server:
#!/usr/bin/tclsh package require Expect package require udp set ::Stat(pty,spid) {} set ::Stat(gps,path) "/dev/gps1" set ::Stat(udp,sock) [ udp_open 616162 ] udp_conf $::Stat(udp,sock) localhost 616161 set fd [ open /dev/ttyUSB0 {RDWR NONBLOCK} ] fconfigure $fd \ -encoding binary -translation binary \ -mode 9600,n,8,1 -handshake none spawn -open $fd set gps_spid $spawn_id log_user 0 expect -i $gps_spid \ -re {(\$GPRMC.*?\*[[:xdigit:]]{2})[\r]} { set sentence $expect_out(1,string) puts -nonewline $::Stat(udp,sock) $sentence flush $::Stat(udp,sock) puts stderr 1:$sentence exp_continue } -re {(\$GPGGA.*?\*[[:xdigit:]]{2})[\r]} { set sentence $expect_out(1,string) # puts -nonewline $::Stat(udp,sock) $sentence # flush $::Stat(udp,sock) puts stderr 2:$sentence exp_continue } timeout { puts stderr timeout exp_continue } eof { puts stderr "EOF on GPSside" } puts end # vwait forever