get unstuck, in time

21 August 2008

Location tracking using Relocatable

"Relocatable" is the location-gathering daemon add-on to "Locatable" (currently they're bundled together for distribution purposes on Cydia; an AppStore version will only contain Locatable as it's not permissible to install daemon processes through the official program). Relocatable is set up to run at 10-minute intervals and gather location data in the background. This means location data is typically available to the browser on a jailbroken phone without having to launch the Locatable app proper. Several of you have asked if there's a way to do a scheduled publish of your location to a destination server of your choice based on the data that Relocatable collects. The answer is a definite yes, and Mike Carambat emailed me the following solution:
Requirements 1. Jailbroken iPhone 2. Install "Locatable" from Cydia 3. Make sure you have "SQLLite" from Cydia 4. Make sure you have "cURL" from Cydia 5. A server based facility to store the data captured from your phone Concept Basically, "Locatable" is a springboard app which uses Core Location to capture GPS coordinates. The cool thing about it, is that it stores them in a SQLite database which is then easily accessible. You query this database via the sqlite3 command and pipe its results to cURL which forwards the data to your server. Instructions 1. Create a shell script called "pushgps" on your iphone which you will invoke on a periodic basis. Put it in the /usr/bin/ on your iphone. This shell script looks like this: ---------- start ---------- #! /bin/sh curl -d POS="`sqlite3 /var/mobile/Library/WebKit/Databases/http_lbs.tralfamadore.com_0/*.db 'select latitude, longitude from location where tag = "Current"'`" ----------- end ----------- (replace the "yourserverhere" and "path_to_gps_recorder" with YOUR server and recording software. (see below for ideas on doing this) Don't forget to: chmod 755 pushgps 2. Next, create a plist file /System/Library/LaunchDaemons/com.whatever.pushgps.plist which contains: ---------- start ---------- <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ""> <plist version="1.0"> <dict> <key>Label</key> <string>com.whatever.pushgps</string> <key>ProgramArguments</key> <array> <string>/usr/bin/pushgps</string> </array> <key>StartInterval</key> <integer>600</integer> </dict> </plist> ----------- end ----------- (replace the "whatever"s with your name, company name, domain, or whatever. This is just an identifier. the 600 refers to every 10 minutes. change if needed. Locatable's interval defaults to 10 minutes, but can be changed as well in its plist file (same directory)) 3. Create software to record the GPS data You'll need to post the coordinate data to *somewhere* online. No, I'm not gonna do it for you. Get your own server ;) Maybe the folks at would be open at some point to do this for us. I wrote a simple perl script called which runs on my server which simply records and time/date stamps the data. Something like this: ---------- start ----------
#!/usr/bin/perl # GPS Recorder $maxhistory=1000; # Total number of locations to store if ($ENV{"REQUEST_METHOD"} eq 'GET') {$buffer=$ENV{"QUERY_STRING"};} else {read (STDIN, $buffer, $ENV{"CONTENT_LENGTH"});} @vars=split(/&/,$buffer); foreach $var (@vars) { ($name, $value)=split (/=/,$var); $name =~ tr/+/ /; $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; chomp($name); chomp($value); $stuff{$name}=$value; } if (exists ($stuff{'POS'})) { ($lat,$long)=split(/\|/,$stuff{'POS'}); chomp($lat); chomp($long); &GetDateTime; open (STUFF, "gpslocation.txt"); @lines=; close (STUFF); $numlines=@lines; $sp=0; if (($numlines-$maxhistory)>-1) { $sp=$numlines-$maxhistory; } open (STUFF, ">gpslocation.txt"); for ($i=$sp; $i<$numlines; $i++) { chomp($lines[$i]);
print STUFF "$lines[$i]\n";
} print STUFF "$date\t$time\t$lat\t$long\n"; close (STUFF); print "Content-type: text/plain\n\n"; print "Latitude: $lat\n"; print "Longitude: $long\n"; exit(0); } print "Content-type: text/plain\n\n"; print "ERROR"; exit(0); sub GetDateTime { ($second, $minute, $hour, $dayofmonth, $month, $year, $weekday, $dayofyear, $isdst) = localtime(time); $year=($year+1900); $month++; $date=sprintf("%02D",$month)."/".sprintf("%02D",$dayofmonth)."/".sprintf("%04D",$year); $time=sprintf("%02D",$hour).":".sprintf("%02D",$minute).":".sprintf("%02D",$second); }
----------- end -----------
Thanks Mike! Update (1 Sep 08): While this method still works (and it provides a good example of a server-side script to handle the data), as of version 0.3 Relocatable allows you to specify a command to execute each time a location fix is acquired, so there's no need to use the pushgps part. See this post for details.

Labels: , , , , ,

Copyright (C) 2001-2008