Continually Logging an iPhone’s Location
When I run or cycle I use apps like Strava or MapMyRun to log the route I take. These apps run on my iPhone and continually log my GPS coordinates. They are great for knowing where I ran and the pace I was doing. Apps like Strava also tell you if you run a particular route multiple times and provide a comparison between each particular run.
I thought it would be interesting to build on this and have a continual log of where I travel. I could use one of these tracking apps, but they aren’t really designed for continuous usage: the software is arranged around a particular route and activity (running or cycling) and continuously querying GPS for my current location will drain my iPhones battery very quickly.
I could have written my own native iPhone app to log the location at specific intervals. Unfortunately, you need to be a member of the Apple Developer program to deploy applications on to physical devices (and at £99, it isn’t really worth it for messing around). Instead I decided to build on the basic location querying provided by the Find My iPhone service that I had already investigated, to repeatedly log the location of my iPhone and plot the locations over time.
Other Implementations
As with all good ideas – someone else had already had this one first. A quick google search found a blog post on Tracking Your iPhone’s Location, which is essentially performing the same idea but using a Python script instead of Node. This post had details on the Find My iPhone library used and some information on how the tracking was actually performed and logged using Heroku. As part of my investigation in to learning Node, I decided to continue on my own.
Building a Node.js Tracking Service
To track the location of my iPhone, I built a service upon my Node implementation of Find My iPhone to handle the following tasks:
- Call findAllDevices() at a specified time interval to retrieve the latest location of my iPhone.
- Log the current location at every time interval to a database, so that the data can be used for something later.
1. Performing Tasks at Specified Intervals
The node-crontab library provides simple crontab-like tasks scheduling in Node. The library is very easy to use – the following code will call my trackPhone() method every 15 minutes:
var log_job = cron.scheduleJob('*/15 * * * *', function() {
trackPhone();
});
Those of you familiar with crontab will notice the first argument to scheduleJob() is the same format for specifying the time to run a cron job at. The second argument is the function to run at the specified time interval.
The trackPhone() method wraps the call to findAllDevices() with some logic to handle stale locations, do a bit of debug logging and ensure the location is stored in the database.
I have written a post on using node-crontab in your Node application if you want more information.
2. Logging Lightweight Data
There are many libraries that interact with databases in Node. For this web service I wanted a lightweight database that needed little configuration or maintenance. I could have used something like SQLite, but a search of NPM found many lightweight Node database implementations that simply stored data in a local flat JSON file.
There are many (many!) Node libraries that perform local super-lightweight JSON flat file database tasks. I decided to use Microdb for the simple reason that I found it, I tried the example, it worked. No need to look any further.
I decided to use a very simple database format:
{
device_name: 'My iPhone',
device_type: 'iPhone 6',
latitude: -3.12,
longitude: 55.011,
date: 1441044660734
}
The data field is calculated using the following code:
new Date().getTime();
Everytime trackPhone() from step 1 succeeds, a method to add the data to microdb is called.
I have written a post on using nodejs-microdb in your Node application if you want more information.
Mapping Visited Locations
Now that the location data is being retrieved and stored in a database, I needed to display it in a pretty way. I found the JavaScript library Leaflet that provided the means to draw a map on screen and annotate it with markers. It was very easy to use, as you can see from the following code.
To get a map on screen, load the OpenStreetMap tiles and centre the screen on Edinburgh:
<div id="map"></div> var map = L.map("map").setView([55.94785, -3.19462], 13); L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.your_access_token_here', { maxZoom: 18, id: 'mapbox.streets' } ).addTo(map);
To add a circle marker with a specified transparency:
L.circleMarker(
[-3.12, 55.011],
{ fillColor: "#800000", fillOpacity: 0.1, stroke:false}
).addTo(map);
I have written a post on using Leafletjs to display a map and plot locations if you want more information. (Coming soon).
View It In Action
This web service is live and continually running on OpenShift. You can see it working live and see the places I have been by visiting phone.ceejaycee.net/map.
Some interesting things to notice:
- Where I spent a lot of time (home and work) are clearly visible.
- I have one mountain biked in the Pentland Hills. You can view the route for that on Strava.
- I cycle and drive a variety of routes on my commute to work, which accounts for most of the single dot locations on roads in the city centre.
- You can see one road trip to Glencoe, in the highlands of Scotland.
Source Code
The entire source code for the service is available on GitHub. (Coming soon).
Downsides
- If I have no phone signal, there is no tracking. The Find My iPhone service requires a phone signal to query and return the location, so if I am in an area without reception the tracking will simply return the last known good location of my phone.
- The Find My iPhone API could change at any time and this service would stop working. Given that Apple would have to update it’s own apps to handle this, it shouldn’t be a problem for a wee while yet.
- Querying my iPhone’s location every 15 minutes might drain the battery. In a couple of weeks worth of testing, I haven’t seen any noticeable change in the battery usage. The battery usage is significantly less than using a tracking application, like Strava, and provides enough granularity for this project.
3 Responses
[…] I have been using nodejs-microdb with my iPhone tracking web application. […]
[…] I have written a Node.js application to poll the location of my iPhone at regular intervals and log the location. This application provides a historical trace of where I’ve been and shows the places I frequent most. You can read more about it here. […]
[…] OpenShift is a great Platform-as-a-Service provided by Red Hat to host web applications in a cloud environment. I use OpenShift to host a few services, such as my iPhone Tracking service (details here). […]