Use GPS to make maps of cell-tower locations and start building cheap location-based services.
Ever wanted to figure out where you are from the signals received by your mobile phone? The telecommunications companies, the emergency service providers, and, by extension, many "authorities" have access to this map of where mobile phone users are, where they have been, and where they are likely to be heading. Now you can build such a map for yourself and your friends!
From most Nokia phones, including older models, you can get the cell ID of the base tower you are connected to. Earlier models had a "monitor" mode that could scan for all available cell towers and their respective signal strengths; on later models, this has been locked down.
Fortunately, we can still get the current cell tower ID and signal strength from the phone, via Bluetooth or a serial cable, using an extended version of plain old AT modem commands! We used a Perl script to connect to the phone at intervalsevery seven seconds, though we were bicycling and could have set the interval as short as once per secondand ask it for its cell ID metadata, which includes a Location Area Code (LAC), and a Cell ID (CID). Taken together, the LAC and CID form a unique identifier for any cell in a wireless provider's national network.
The script, which we'll call cellstumbler.pl, uses an interface to the gpsd daemon to correlate mobile phone cell IDs with GPS coordinates. By running gpsd instead of connecting to the GPS directly from our script, we were able to use Kismet to talk to gpsd as well, to correlate Wi-Fi traces with GPS coordinates at the same time. See [Hack #57] for detailed instructions on running gpsd.
Also, you'll need the Device::Modem module from the CPAN to run this code. You can obtain it by running perl -MCPAN -e 'install Device::Modem' as root on your Linux system.
5.17.1. The Code
Here is the code contained in cellstumbler.pl:
#!/usr/bin/perl use 5.6.1; use IO::Socket; use Device::Modem; use Getopt::Std; use strict; use warnings; BEGIN { $|++ }; # autoflush STDOUT. # Read command line options. my %opt; getopt('gpr', \%opt); # Set parameters based on command line options, with defaults. my $GPSD = $opt{g} || "localhost:2947"; my $GSM_Port = $opt{p} || "/dev/ttyS0"; my $GSM_Baud = $opt{b} || 115_200; my $Rate = $opt{r} || 1; # Connect to gpsd. my $gps = IO::Socket::INET->new($GPSD) or die "Can't connect to gpsd at $GPSD: $! "; # Connect to the cell phone. my $gsm = Device::Modem->new( port => $GSM_Port ); $gsm->connect( baudrate => $GSM_Baud ) or die "Can't connect to modem on $GSM_Port: $! "; # Tell the cell phone we want all the network registration data it has. $gsm->reset; $gsm->atsend( "AT+CREG=2 " ); die "AT+CREG not recognized by modem on $GSM_Port" unless $gsm->answer eq "OK"; while (1) { # Tell gpsd we want position, date, and status. $gps->print("pds "); # Parse out the response. If the date is blank, gpsd needs a second to catch up. my $location = <$gps>; my ($lat, $long, $date, $status) = ($location =~ /P=(.+?) (.+?),D=(.+?),S=(.+?)/gos); next unless $date; # Turn the date into an RFC 2445 ICal date string. my ($mo, $d, $y, $h, $m, $s) = split /[ /:]/o, $date; $date = "${y}${mo}${d}T${h}${m}${s}Z"; # Query cell ID and location area code. $gsm->atsend( "AT+CREG? " ); my ($cid, $lac) = ($gsm->answer =~ /"([dA-F]{4})"/gios); # Query signal strength. $gsm->atsend( "AT+CSQ " ); my ($signal) = ($gsm->answer =~ /(d+)/gos); $signal = -113 + $signal * 2; # Print a line of data and wait. print join(",", $date, $status, $lat, $long, hex($cid), hex($lac), $signal), " "; sleep( $Rate ); }
5.17.2. Running the Code
As mentioned earlier, you need to have gpsd running before starting cellstumbler.pl. We used a Bluetooth RFCOMM serial connection to talk to a Nokia 3650, so we had to bind an RFCOMM port first, using the six-part Bluetooth ID of the phone. You can use hcitool scan in Linux to search for the Bluetooth ID of your phone. If your phone doesn't have Bluetooth, then you'll need a serial cable, but you can skip the whole RFCOMM bit. You may need to use a terminal program like minicom to poke around your system's serial ports to figure out which the phone is accessible on. You'll know it's working when you type AT into the terminal program, and get an OK from the phone in response.
Finally, assuming cellstumbler.pl is in the current directory and marked as executable, you can start it like this, where xx:xx etc is the Bluetooth ID of your phone:
$ rfcomm bind /dev/rfcomm0 xx:xx:xx:xx:xx:xx $ ./cellstumbler.pl -p /dev/rfcomm0 -r 5 > cell_data.txt
In this particular case, we're telling cellstumbler.pl to talk to the phone on the /dev/rfcomm0 serial port with the -p option and to collect a sample every five seconds with the -r option. There's a -b option available in case you need to explicitly set the baud rate on the serial line to the phone, and a -g option, just in case you're running gpsd on a different port (or different machine!) than the default.
If you want to see the cell ID data go by as you collect it, you can use the very handy tee shell command:
$ ./cellstumbler.pl -p /dev/rfcomm0 | tee cell_data.txt
The standard output of cellstumbler.pl contains one sample per line, with seven comma-separated fields. In order, they are:
timestamp (in iCal format)
GPS status
latitude
longitude
CID (in hexadecimal)
LAC (in hexadecimal)
signal strength (measured in dBm)
The value in the GPS status field is returned directly from gpsd, which will be 0 if the GPS has no satellite lock, 1 if it has a satellite lock, and 2 if the location reading is differentially corrected (e,g,, via a WAAS signal).
5.17.3. Evaluating the Data
Given a set of readings of the ID of some radio frequency beacon and its signal strength, and the latitude and longitude and time at which the measurement was taken, how can we figure out where the radio antennas are? We could start with a naive interpolation technique that doesn't even make use of the signal strength data.
First, we convert the latitude and longitude from the GPS readings into UTM, to make Cartesian calculations easier. (See [Hack #26] for more details on this process.) We take the numerical average of all the GPS points collected for the same cell-ID reading, and call this the "center" of the cell. We take the distance from the center of the cell to the matching point farthest away and make that the radius of the circle. It's a quick-and-dirty technique, but it will give approximate "good-enough" measurements for many kinds of spatial navigation in urban areas: a map of a surrounding 500m radius, or interesting places less than half a mile's walk away.
We can get better results based on signal strength and by using more interesting algorithms, such as inverse distance weighting and particle filters. We also have to be aware of problems or flaws in different radio technologies. Buildings and trees block lines of sight and dampen or divert radio waves; our perfect circles are more likely to be distended blobs. Intel's PlaceLab project implements some of these more advanced techniques; you can find PlaceLab's source code at http://placelab.org.
These same techniques are equally viable for making RF frequency maps for other channels and protocols, particularly 802.11 wireless. As mentioned previously, while cellstumbling for mobile phone base stations, we also used Kismet to talk to gpsd and collect readings for 802.11 access points, including information about whether they provide open service and offer DHCP addresses.
Now that we've gathered all this data, we might want to submit it to a repository, to make it useful for other applications or to visualize it. Figure 5-37 shows part of a simple map we made with the support of RIXC, a Latvian cultural organization (http://rixc.lv), showing cellular reception in central Riga. The map, made in SVG, depicts a circle representing each centroid, with a label for each cell ID. An obvious next step for this "bubble diagram" would be to plot it over a base map of the area to provide context.
Figure 5-37. Part of an SVG bubble diagram of Riga's cellular network
Envision the possibilities that can blossom when individuals go out, collect cell ID samples, and compile them together in a collaborative database. Suddenly, applications can be written for smart phones, like those running the Symbian OS, which can look up a user's location in a database simply by examining the current cell ID, with no need for a GPS on the phone. You can explore this idea further at http://mappinghacks.com/cell/, where we provide a demo of a small web service that allows people to upload files full of points or post individual points in real time. The full sources of the various scripts described herefor calculating centroids, generating SVG bubble diagrams, and so onare available on the site as well.
5.17.4. See Also:
Mapping Your Life
Mapping Your Neighborhood
Mapping Your World
Mapping (on) the Web
Mapping with Gadgets
Mapping on Your Desktop
Names and Places
Building the Geospatial Web
Mapping with Other People