Location based services needs to be switched on

Location based services needs to be switched on

Inspired by the question in the http://fanbóys.org/ podcast, I will write down, what I have up and running for over two years now.

Goal: Have a background method running, which collects your location during the day and displays it on a map and has some export functionality.

Ingredients: An Apple iPhone, an Apple ID, activated Find My iPhone, a LAMP system and additional Google Maps.

And here is how we going to do this.

If you have an Apple iPhone and have activated the Find My iPhone service, your iPhone will send its location to Apple every time it does get a Push Messages or sth like this. You can get the location of your iPhone by using the Find My iPhone App on any other iPhone or on the MobileMewebsite. All you need is to enter your Apple ID and your password and you are able to locate the iPhone.

Activate the Find My iPhone service

Activate the Find My iPhone service

Yes, your iPhone isn’t you, but usually you are not far away from it.

Cool, we have a service, which gets location updates and we can see it on a webpage. But only there, and only the last location… We want more.

Here comes a PHP class in to the arena, which scrapes the MobileMe webpage and does retrieve the latest location. So if we do this regularly (eg. every 5 min) we get a log, of where we have been. This PHP class is provided by clickontyler and is named sosumi – A MobileMe Scraper, the source code is on github.

So after downloading and unpacking the tar ball you can write a small php script to get your latest position.

<?php
  require 'class.sosumi.scraper.php';
  Header('Content-type: text/plain');
  $ssm = new Sosumi('YOUR_APPLE_ID', 'YOUR_PASSWORD');
        try {
                print_r($ssm);
        } catch (Exception $e) {
                echo "$e->getMessage\n";
        }
?>

And this is what you get back:

Sosumi Object
(
    [devices] => Array
        (
            [0] => SosumiDevice Object
                (
                    [isLocating] =>
                    [locationTimestamp] => 2011-10-03 21:02:18
                    [locationType] => Wifi
                    [horizontalAccuracy] => 86.487785814542
                    [locationFinished] =>
                    [longitude] => 11.478...88
                    [latitude] => 48.155...96
                    [deviceModel] => FourthGen
                    [deviceStatus] => 200
                    [id] => QVBT...~
                    [name] => Titanic
                    [deviceClass] => iPhone
                    [chargingStatus] => NotCharging
                    [batteryLevel] => 0.5317959
                    [locationOld] =>
                )

        )

    [debug] =>
    [username:Sosumi:private] => YOUR_APPLE_ID
    [password:Sosumi:private] => YOUR_PASSWORD
    [inactiveTime:Sosumi:private] => 120000
    [nextPollTime:Sosumi:private] => 1317668527
    [lastStatus:Sosumi:private] => 200
    [lastURL:Sosumi:private] => https://p04-fmipweb.me.com/fmipservice/client/refreshClient
    [cookieFile:Sosumi:private] => /tmp/sosumimrXk1w
    [clientContext] => Array
        (
            [appName] => MobileMe Find (Web)
            [appVersion] => 1.0
        )

    [lsc] => Array
        (
        )

    [authenticated] =>
    [partition] => p04
    [serverContext] => stdClass Object
        (
            [prefsUpdateTime] => 1312812264416
            [maxDeviceLoadTime] => 60000
            [authToken] =>
            [classicUser] => 1
            [sessionLifespan] => 900000
            [imageBaseUrl] => https://statici.icloud.com
            [deviceLoadStatus] => 200
            [clientId] => Y2xp...a
            [lastSessionExtensionTime] =>
            [preferredLanguage] => en-us
            [timezone] => stdClass Object
                (
                    [tzCurrentName] => Central European Summer Time
                    [previousTransition] => 1301187599999
                    [previousOffset] => 3600000
                    [currentOffset] => 7200000
                    [tzName] => Europe/Berlin
                )

            [callbackIntervalInMS] => 10000
            [cloudUser] =>
            [validRegion] => 1
            [maxLocatingTime] => 90000
            [hasDevices] => 1
            [prsId] => 200333247
            [macCount] => 0
        )

    [timezoneSource] => Europe/Berlin
    [timezoneDestination] => Europe/Berlin
    [isc] => AQA...~
)

Pretty much information returned, we are interested in the following:

  • locationTimestamp = 2011-10-03 21:02:18
  • horizontalAccuracy = 86.487785814542 (in meters)
  • longitude = 11.478…88
  • latitude = 48.155…96

But sosumi has another class call which hands back the necessary information much easier:

<?php
  $ssm = new Sosumi('YOUR_APPLE_ID', 'YOUR_PASSWORD');
        try {
                $loc = $ssm->locate();
                print_r($loc);
        } catch (Exception $e) {
                exit(0);
        }
?>

This array is your return values:

Array
(
    [latitude] => 48.155...71
    [longitude] => 11.478...08
    [accuracy] => 65
    [timestamp] => 2011-10-03 21:04:16
)

So we need to put this into a MySQL database, remember to create the database and its structure prior to usage:

#!/usr/bin/php
<?PHP
  // This is a simple cron script you can use to track
  // your location over time. It uses the MySQL schema
  // pasted below.
  //
  // CREATE TABLE `history` (
  //   `dt` datetime NOT NULL,
  //   `lat` decimal(10,6) NOT NULL,
  //   `lng` decimal(10,6) NOT NULL,
  //   `acc` decimal(10,6) NOT NULL,
  //   `user` varchar(32) NOT NULL,
  //   UNIQUE KEY `dtuser` (`user`,`dt`)
  // )

  require 'class.sosumi.scraper.php';

  $ssm = new Sosumi('YOUR_APPLE_ID', 'YOUR_PASSWORD');
        try {
                $loc = $ssm->locate();
        } catch (Exception $e) {
                exit(0);
        }

  if(strlen($loc['latitude']))
  {
    $db = mysql_connect('MYSQL_HOST', 'MYSQL_USER', 'MYSQL_PASS');
    mysql_select_db('MYSQL_TABLE', $db) or die(mysql_error());

    $dt = date('Y-m-d H:i:s');
    $lat = mysql_real_escape_string($loc['latitude'], $db);
    $lng = mysql_real_escape_string($loc['longitude'], $db);
    $acc = mysql_real_escape_string($loc['accuracy'], $db);

    $query = "INSERT INTO history (`dt`, `lat`, `lng`, `user`, `acc`) VALUES ('$dt', '$lat', '$lng', 'MY_NAME', '$acc')";
    mysql_query($query, $db) or die(mysql_error());
  }
?>

So if you run this command via cron, you’ll keep track of yourself.

More in part 2 – Displaying the location data