Hack 57. Connect to Your GPS from Multiple Applications
In Linux, BSD, and OS X, you can get live GPS data across different processesand even different computerssimultaneously.
While almost miraculous in their basic operation, your average GPS receiver lacks much in the way of wits all on its own. Even the fanciest of them can do little more than plot your location on a map, and maybe give directions to a destination. Once combined with a computer, though, that same GPS receiver can power a wide range of new and different applications, from auto navigation systems like gpsdrive [Hack #63] to network sensing tools like Kismet and Macstumbler [Hack #17] . However, the very nature of the serial connection linking the twobe it RS-232, USB, or Bluetoothlimits the GPS to talking to one application at a time. As soon as you want to do more than one thing at a time with the data you're getting from that GPS receiver, you will find yourself in a world of sadness and regret.
Fortunately, there is a way around this tragic outcome! For salvation, you can turn to gpsd, a GPS data multiplexer, which runs as a daemon on *NIX operating systems, including OS X. gpsd handles the nitty-gritty details of listening to the GPS receiver and then rebroadcasts the information it receives to other applications over a TCP/IP socket, using a simple text-based protocol. This arrangement allows applications that know how to talk to gpsd to avoid the hassle of needing permissions to set up the serial port or dealing with the specific details of different GPS receivers. Furthermore, since gpsd uses TCP to relay GPS data, a client application can talk to it across a networkor even across the Internet!
5.13.1. Installing gpsd
You can get the source code to gpsd from http://www.pygps.org/gpsd/downloads/. The source code unpacks and builds in the usual way. Use the following commands, in which x.xx is the latest revision of gpsd:
$ tar xvfz gpsd-x.xx.tar.gz $ cd gpsd-x.xx $ ./configure $ make $ make install
You may get an error something like the following when you run make:
In file included from netlib.c:12: .../include/varargs.h:4:2: #error "GCC no longer implements ." .../include/varargs.h:5:2: #error "Revise your code to use ."
If this happens, it's because gpsd was written against gcc headers that your particular system no longer supports. Fortunately, this is easy to fix. Run the following bit of perl, and then run make again. Everything should build just fine:
$ perl -pi -e 's/varargs.h/stdarg.h/g' *.c $ make
5.13.2. Running gpsd
First, you'll need to make sure your GPS receiver is on and properly connected to your computer (see [Hack #50] if your computer doesn't have a serial port). Next, you'll want to be sure your GPS receiver is configured to output NMEA-0183. Chances are good that the GPS receiver has an option for this in a setup menu, but check your owner's manual to be sure. Several new models of Garmin GPS units no longer speak NMEA. There is discussion of extending gpsd to support the proprietary Garmin protocol, but if you are in the market for a new GPS, you may want to add standards compliance to your list of purchase requirements!
|
Starting gpsd is pretty straightforward. If you've already symlinked /dev/gps to the serial device to which your GPS receiver is typically connected, just enter:
$ /usr/local/sbin/gpsd
However, if you need to explicitly set the serial port or baud rate, you can do that as well:
$ /usr/local/sbin/gpsd -p /dev/ttyS1 -s 4800
Users with a DeLorme EarthMate USB GPS receiver will need to set special options for the EarthMate:
$ /usr/local/sbin/gpsd -Te -s 9600
Once running, gpsd listens on TCP port 2947 for incoming connections. You can test it out by using telnet to type commands directly to gpsd:
$ telnet localhost 2947 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. s GPSD,S=0 s GPSD,S=1 p GPSD,P=37.739000 -122.419000
Commands to gpsd take the form of one or more letters, followed by a new line. Each letter is a single command. The s command, for example, requests the status of the GPS connection, returning a 1 if the GPS is connected, and a 0 if it's not. This can be useful for testing purposes, but, as you can see, gpsd doesn't always return a successful status on the first try, so give it a couple tries before deciding that you need to troubleshoot the connection. As you can see, the p command requests the current position. Another useful command for debugging is r, which requests a raw dump of the NMEA data:
r GPSD,R=1 $GPRMC,085400,A,3744.0000,N,12225.0000,W,0.0,359.6,060804,15.1,E,A*39 $GPRMB,A,9.99,R,,Exit 192,4402.6514,N,12302.9773,W,379.131,355.9,,V,A*42 $GPGGA,085400,3744.3751,N,12225.1963,W,1,05,2.5,81.1,M,-28.1,M,,*4A r GPSD,R=0
Pretty ugly, huh? A second r command terminates the raw dump. Control-] followed by quit gets you out of telnet. Table 5-1 lists some other gpsd commands.
Command |
Description |
---|---|
p |
Latitude/longitude, in decimal degrees. |
d |
Date/time, in MM/DD/YYYY HH:MM:SS format. |
a |
Altitude, in meters. |
v |
Current speed, in knots. |
s |
GPS status (0 = Disconnected; 1 = No GPS Fix; 2 = 2-D Fix; 3 = 3-D Fix) |
m |
Operating mode (0 = Disconnected; 1 = GPS; 2 = DGPS / WAAS) |
5.13.3. Visualizing the Output of gpsd
Another useful tool that ships with gpsd is called, simply, gps, and it's an X11 program for visualizing gpsd output. You start it by running /usr/local/bin/gps. Figure 5-29 shows a typical gps display, including the nifty satellite visibility chart.
Figure 5-29. A typical gps display
What's particularly cool about this screenshot is that it was taken on a different machine than the one the GPS was connected to; the two computers were connected via a wireless network, with gpsd running on the one with the serial link to the GPS. We then ran gps -p x.x.x.x:2947 on the other laptop, where x.x.x.x was the IP address of the gpsd machine, and voilà!
5.13.4. Hacking the Hack
At this point, you should be ready to run kismet [Hack #17] or gpsdrive [Hack #63], or kismet and gpsdrive together, or, indeed, your choice of GPS-using *NIX applications. The nice thing about gpsd is that once you've got it running, you can kind of forget about it. So we'd like to share with you just one more thing you can do with gpsd, which is to set up a little CGI application on the Web that shows your current location in real time:
#!/usr/bin/perl use CGI; use CGI::Carp 'fatalsToBrowser'; use IO::Socket::INET; use strict; my $GPSD_Server = "yourhostname.here:2947"; my $Map_Width = 0.25; # degrees my $Map_Pixels = 320; ###### my $gpsd = IO::Socket::INET->new( $GPSD_Server ) or die "Couldn't connect to GPS server. "; my $data = <$gpsd>; my ($lat, $lon) = ($data =~ /(-?d+.d+) (-?d+.d+)/gos); my $map = "http://tiger.census.gov/cgi-bin/mapgen?" . "lon=$lon&lat=$lat&wid=$Map_Width&ht=$Map_Width" . "&iht=$Map_Pixels&iwd=$Map_Pixels" . "&mark=$lon,$lat,redpin"; print CGI->header, <Where am I?
Where am I?
($lat, $lon)
End
This CGI script connects to a gpsd running on the server specified by $GPSD_Server, fetches the current latitude and longitude, and shows the location on a TIGER Map Server map [Hack #14] . If you have a *NIX laptop running gpsd, and a Net connection with some kind of dynamic DNS alias, this script could live on a web server on the Internet and connect to your laptop on demand to give others a general idea of your whereabouts. Assuming you were somewhere in the U.S. at the time, interested parties would see something like Figure 5-30.
Figure 5-30. Where am I? Live, thanks to gpsd
Although this example is a bit contrived (and does almost no error checking to speak of), it demonstrates the simplicity and power of gpsd. You can find out more about gpsd at http://gpsd.berlios.de.
5.13.5. See Also
- [Hack #50]
- [Hack #58]
- [Hack #14]
- [Hack #17]
- [Hack #63]