I'll be watching you: Stalk me in real time via the web
Friday, November 8, 2013
Author's note: Google took down Google Latitude and Locality is no longer online. But my code is still around, and I'll leave this up in case anyone finds anything of use!
I've always been fascinated by the idea of real-time location data. The first Google Glass video showed a person checking where his friend was with a real-time location service. I always liked the idea of the Weasley family clock from Harry Potter, which the mother of the large Weasley family used to keep tabs on her kids and husband. So I tried to build a Weasley clock of my own with HTML, CSS, and a little JavaScript magic.
I named my web application Locality. Check it out right now, and read on to find out how it works.
locality
Noun
The position or site of something.
An area or neighborhood, esp. as regarded as a place occupied by certain people or as the scene of particular activities.
Step one is figuring out where I am at any given time. The easiest way to get my own real-time location data is with an Android smartphone that I already have. It's got GPS and 4G, so it'll try to sync my location to Google Latitude whenever I move around.
Getting the data out of Google Latitude is slightly tricky. Latitude offers "site badges", HTML drop-ins that put a little map and an icon on the map to show people where you are. But I want the coordinates, and Latitude offers a JSON feed to get that data out too. The URL for any given user's JSON feed is https://latitude.google.com/latitude/apps/badge/api?user=YOUR_USER_ID_HERE&type=json
.
If you've ever worked with JSON before, you know that making a JSON request from one domain to another is likely to fail because of HTTP access control (CORS). So I used Yahoo's YQL to import a JSON feed, read the data, and spit it back out as JSONP -- which isn't governed by CORS.
// URL for Latitude data in JSON form var latitudeUrl = 'https://latitude.google.com/latitude/apps/badge/api?user=MY_USER_ID&type=json'; // use Yahoo YQL to proxy the JSON into JSONP var yahooYqlUrl = 'http://query.yahooapis.com/v1/public/yql?callback=?'
$.getJSON(yahooYqlUrl, { q: ‘select * from json where url=”’ + latitudeUrl + ’”’, format: ‘json’ }, function(response) { var data = response.query.results.json; // do something with data here });
It's a bit of a hacky solution but it works very well. Credit where credit is due to Stack Overflow user hippietrail. Apparently there's also a cool little service called jsonp.ru that does the same thing, but I trust Yahoo more with my data.
Once I've got the Matt coordinates, I need to figure out where Matt is. I started by constructing a list of location objects with data on each location of which I wanted to keep track. I grabbed the coordinates from Google Maps by using the "right-click to drop coordinates" Labs addon and manually typing the coordinates for each location into my code.
var locations = [
{
name: "Stadium View",
coordinates: {
latitude: 44.971599,
longitude: -93.221807
}
},
{
name: "Kenneth H. Keller Hall",
coordinates: {
latitude: 44.974650,
longitude: -93.232460
}
},
// ... put more locations here
]
Okay, so now I have the coordinates of locations and the coordinates for myself. I need to be able to tell how far away I am from each location. It turns out this is a reasonably well-solved problem -- I found some fantastic scripts from Chris Veness at movable-type.co.uk that do just what I want: simple, accurate calculation of distances between two latitude/longitude pairs.
I wrote a little function that uses LatLon.js
to calculate the distance in miles between two pairs of coordinates:
function distMiLatLon(lat1, lon1, lat2, lon2) {
var rMi = 3963.1676; // earth's radius in miles
var p1 = new LatLon(lat1, lon1, rMi);
var p2 = new LatLon(lat2, lon2, rMi);
return p1.distanceTo(p2); // in miles
}
For my application, I decided if I was within 500 feet of a known location, I should be checked in. 500 feet == .094697 miles, so I set var maxDistToValidateLoc = .094697
in my code. After Locality gets the coordinates for locations and for me, it iterates down the list of locations and calculates a distance to each one. If a distance is less than .094697 miles, it registers me as being present at that location. Otherwise, it puts me in the "no man's land" category of "somewhere else".
That's the JavaScript and data handling side covered. I'll write more about the HTML/CSS layout in another post. For now, check out the app at mplewis.com/locality and tell me what you think!
I'd love to hear what you think about this post. Email me or @ me on Bluesky!