You will see lots of output lines:
GPSD,X=1252018312.141204,I=Generic NMEA
GPSD,W=1
GPSD,O=?
GPSD,Y=GSV 1252012212.000 10:3 30 168 0...
To stop, type W=0 and then ctrl-D (or just ctrl-D).
If you want to read "raw" (non-"cooked") NMEA data, just enter the R command. Entering the R command again will stop raw data output.
Now you can execute the cgps (console gps utility); press q to exit. On the left window there are position/speed/etc data (in case of poor GPS coverage, the horiz/vert/course errors will float even to 300 feet, but I think this is a problem of my GPS unit); the right window shows satellite list and information. Sadly, cgps only knows about mph and feet...
Now start gpsmon (another console gps utility); press ^C to exit. This contains far more information - everything gpsd can parse or predict: geoid, DOP/HDOP, magnetic variation, etc.
Now I can write a Ruby program (yes, I happen to love Ruby language; I don't like Python and Perl) to fetch the GPS date (which is always GMT) from gpsd, update it to GMT+1, and then issue the system date command to update it.
My GPS unit always reports date/time on its screen, but does not emit it if unable to read it via GPS. So gpsd won't give a date/time when the GPS receiver has poor GPS coverage. Also, it appears that soon after opening the socket, the date is not available (gpsd answers "D=?"); just wait a little and retry. I will loop waiting for either 4.0 seconds total pause, or a correct timestamp is received; any other error (timeouts on socket port, or invalid timestamp) will stop the program.
require 'socket'
GMT = +1.0 # local time here is GMT + 1 hour
gpsd = TCPSocket.open("localhost", 2947)
gdat = ""
trys = 4.0 # try for 4 seconds...
while trys >= 0.0
gpsd.puts "d" # request date from gpsd daemon
gdat = gpsd.gets.chomp # read response
break if gdat != "GPSD,D=?" && gdat != "GPSD"
sleep 0.2 # unknown date, sleep some time...
trys = trys -0.2 # ...and retry until timeout
end
# split "GPSD,D=2009-09-03T20:57:35.0Z" in date/time fields,
# then add GMT difference and finally issue a system set date
# using its weird syntax month/day/hour/min/year.seconds
system (Time.gm(*gdat.split(/[=Z]/)[1].split(/[-:T\.]/).
collect { |i| eval(i.gsub(/^0/,"")) }) + GMT*3600).
strftime("date --utc %m%d%H%M%Y.%S")
Once a GMT time is fetched via GPS, erase the header and footer part (delimited by "=" and "Z"), split the fields (separated by "-", ":", "T" or "."), collect their numeric values (erasing leading zeros), add the GMT difference (yes, you could set GMT=-9.5 to have GMT -09:30) and then build a date --utc command with reordered and striped parameters (don't complain about it: the date weird syntax dates back to 1969 or something like that...)
Yes, I happen to love Perl-style Chaotic Programming ;)
I placed it in /etc/gpsdate.rb and edited /etc/timezone to match my area (Europe/Rome). Then, if a date is available, ruby /etc/gpsdate.rb will set up the system date/time, else will fail with some error message; it won't loop forever.
Now, how to add it at the end of boot scripts?
To my surprise, there isn't any rc.local or boot.local - I had to add in mine.
I see that /etc/inittab at sysinit stage executes /etc/init.d/rcS - so I modified that rcS script to add a call to some /etc/rc.local created by me.
I see there a bug: it issues an exec (instead of a "call") to /etc/init.d/rc S (yes, "rc" script with "S" parameter - different from the above "rcS" script...) so the subsequent lines of the rcS won't be executed; I wiped out that "exec" and added soon after a call to /etc/rc.local - thus having this modified version:
# Call all parts in order.
/etc/init.d/rc S
#
# execute my local script
/etc/rc.local
#
# Finish setup if needed. The comment above about
# /sbin/unconfigured.sh applies here as well!
if [ -x /sbin/setup.sh ]
then
/sbin/setup.sh
fi
Then I created my /etc/rc.local script containing:
# to me: better having this static IP setup here:
ifconfig usb0 192.168.5.3
ruby /etc/gpsdate.rb &> /tmp/bootdate.txt
date >> /tmp/bootdate.txt
sync
Yes, I know some of you will complain, requiring me to use the standard init.d method, build start scripts, end scripts and so on... Sorry! When in a hurry, you sometimes forget the Elegant Solution Method, and prefer the Happy Tinkering Method...! :)
Now, after the reboot, I see that the /tmp/bootdate.txt contains the output of my gpsdate.rb (either a GMT date string or some error text, and then the "current" system date).
Let's write a Ruby script to make some GPS logging; instead of logging those weird NMEA strings, just log the gpsd parsed data:
require 'socket'
gpsd = TCPSocket.open("localhost", 2947)
gpsd.puts "W=1"
while a = gpsd.gets.chomp
puts a
end
It appears that it outputs some 140-150 lines per minute (up to 20 kilobytes per minute, or up to 1.2 megabytes per hours) can be written to disk. Mumble, mumble... I should mount Beagleboard + GPS on my bike and write a program that in real-time gives me statistics and GPS stuff and after a month gives me some large graphic diagram... = :) !!!