Should I cycle: on hold for now

I started building a prototype for Should I cycle on iOS 8 and pretty early on I’ve hit a roadblock. What I wanted was a daily scheduled notification to popup telling me whether conditions were right for cycling or not.

I wanted to use iOS’s local notifications to do this – but I don’t think it can be done. Sure, you can schedule a local notification to popup at say 7:30am, but what’s displayed on the notification has to be set at the time the notification is scheduled. What this means is let’s say at 9pm at night I schedule a notification for 7:30am the next day. And at 9pm the sky is clear and conditions are fine. Then at 7:30am the next day it’s raining. Well, the 7:30am notification popup is going to say “Sky is clear” because that’s what the conditions were like when the notification was scheduled.

So that’s annoying.

What I want to do can be done via remote notifications – i.e. the I would have to schedule on a web server a push notification out to the mobile at 7:30am the next day. But that would be pretty complicated to setup for a prototype.

So I decided I would give up on the push notification for now and instead just check the current weather / cycling conditions whenever the app is started.

But then another thing happened – I gave up cycling to work for various reasons. So for now I have no motivation to work on this app. Maybe one day I’ll pick it up again.

Should I cycle: designing the UI

This is the sixth post in my series on building a mobile app, “should I cycle”.

Now that I’ve got my API implemented I’m ready to build the client app.

For my initial prototype I don’t really need any UI at all – I can get away with hard-coding the values I want for my should I cycle alerts particular to my route – e.g. 8am, London, no rain, not easterly winds over 10 mph. However, I haven’t gotten around to implementing that yet for one reason – I can’t decide whether to implement an iPhone or Android (or even Windows Phone) version first. See, I currently have a 2 year old iPhone 5 which is working fine. Just last week the new iPhone 6 was released and I was a bit underwhelmed, so I probably won’t be buying one. So right now I can’t decide whether to stick to my iPhone 5 or jump over to Android and get myself a OnePlus One phone which my flatmate owns and looks pretty good.

In the meantime I started thinking about what the UI for a first version of Should I cycle could look like, and came up with these mockups (using Balsamiq). As you can see I’ve taken iOS’s Alarm app as inspiration and copied much of its UI.

01 Home

02 add alert

03 repeat

04 label

05 city

06 Pollution

07 weather

08 wind direction

09 wind speed

Hmm I guess right now I should just get on with a prototype (with no UI) on iOS for my iPhone 5!

Should I cycle: implementing the API using Node.js

Now that I have my API defined, and it is pretty darn simple, it’s time to implement it.

During my day job I write ASP.NET MVC websites and Web APIs, but part of the reason for doing a side project such as this is the chance to dabble in different technologies.

Since my API is so simple I thought I’d give it a go using Node.js.

I found this nice tutorial which got me started.

As per my API documentation, my endpoint will look like this:

/v1/cycle?location=London,uk&airquality=wa7,wa9

My API is going to:

  1. Take two arguments
    1. weather location
    2. air quality monitoring locations (a list)
  2. Call an external API for each of those arguments
  3. Parse the results from those external APIs into a result and return it.

Since Node is all about doing stuff in a non-blocking parallel way, I have to make each of the external API calls in parallel. And since the air quality argument is actually a list of locations, I can call each one of them in parallel too. I came across the async library and a helpful post by Sebastian Seilund on how to use it. Basically, I can use async.parallel to start two tasks – one which looks up the weather, and the other which calls async.forEach to lookup the air quality (also in parallel!).

The results of each of these are collated into an object named shouldicycle and returned via JSON.

router.get('/v1/cycle', function(req, res, next) {
    var location = req.query.location;
    var airQualities = req.query.airquality;
    var shouldicycle = {};
    shouldicycle.pollution = [];

    async.parallel([
        // Get weather
        function(callback) {
            if (location) {
                weather.lookupCurrentWeather(location, shouldicycle, callback);
            }
            else {
                callback();
            }
        },
        // Get airquality
        function(callback) {
            if (airQualities) {
                var airQualityArray = airQualities.split(',');
                async.forEach(airQualityArray, function(airQuality, airQualityCallback) {
                    weather.lookupAirQuality(airQuality, shouldicycle, airQualityCallback);
                }, callback);
            }
            else {
                callback();
            }
        }
    ],
    // This is called when weather and airquality are done
    function(err) {
        if (err) return next(err);
        res.json(shouldicycle);
    });
});

Anyway, that’s enough source code for one blog posting.
The entire source is in github over here. All of the logic lives in server.js and weather.js. Code reviews are welcome, this is my first node app :-)

Debugging node

I developed the shouldicycle API on a mixture of Mac and Windows machines, but when it came to debugging I found good old Visual Studio 2013 with Node.js Tools for Visual Studio to be perfect for the job. Not sure what I would do if I had to debug my node app on my Mac.

Deploying it to Heroku

Since I am in Node land I decided to deploy it to Heroku. I could have deployed it to Azure, but since deploying to Azure is part of my day job I thought I’d see how Heroku works.

I found this helpful guide on deploying a node app to Heroku.

So yay, my minimum viable product API is up!

http://ancient-beyond-7553.herokuapp.com/api

Here’s a sample query for London:

http://ancient-beyond-7553.herokuapp.com/api/v1/cycle?location=london,uk&airquality=WA7,WA9

Todo

There’s still plenty to be done on that API. A bit of validation and checking on the input parameters for a start. And to implement caching too, both of my results and also of the results I retrieve from the weather and pollution APIs. But what I’ve done so far is enough for a minimum viable product, so now I can move on and get started with the iOS / Android app.

Should I cycle: designing my API

Once I had determined I was going to use London Air API and OpenWeatherMap’s API it made it easy to design my own API.

I find that documenting this process is essential as otherwise I would forget the decisions I’d made during planning and investigation when it came time to actually write the code.

Should I Cycle API

Document version

Date Version Author Comments
25 August 2014 0.1 Matt Frear Initial version

Cycle endpoint

GET

/v1/cycle?location=London,uk&airquality=wa7,wa9

Arguments

Name Type Required Description
location string 1 The location for weather results.

e.g. London,uk

We will call OpenWeatherMap’s forecast service with this info http://api.openweathermap.org/data/2.5/forecast?
q=London,uk&units=metric

airquality string 0..n A site code to check for pollution.

This parameter can be passed as a comma-separated list to check multiple sites, e.g.

/v1/cycle?location=london&airquality=wa7,wa6
We will call London Air’s API for each location.

A list of available locations is at:

http://api.erg.kcl.ac.uk/AirQuality/Information/Monito
ringSites/GroupName=London/Json
e.g. Putney’s is WA7.

We will call:

http://api.erg.kcl.ac.uk/AirQuality/Hourly/
MonitoringIndex/SiteCode=WA7/Json

Response

The response format will be JSON.

Name Type Description
city string The name of the City
temp int Temperature in degrees Celcius
symbol int OpenWeatherMap’s symbol for the current condition
windDegree int The wind direction in degrees from 0 to 359
windDirection string The 3 digit code for the wind direction, e.g. ENE
windSpeed int The wind speed in m/s
windStrength string A text description for the wind speed, e.g. “Moderate breeze”
pollution [] An array of pollution readings for each sensor requested

A pollution reading looks like

Name Type Description
name string The Sitecode requested, e.g. WA7
speciesCode string The type of reading, e.g. NO2
airQualityIndex int The level of pollution, where 1 = low and 10 = high

The API document is hosted in Google Docs over here: Should I Cycle API.

Should I cycle: choosing APIs

Since I’m going to have to build an API for my app before I write any code I’m going to think about what my API should look like.

To do this I’m going to do some investigation of what APIs are out there which my API will call.

For air quality I found the London Air API. It looks pretty good, easy to use with good documentation. I can get the current air quality for Putney by calling: http://api.erg.kcl.ac.uk/AirQuality/Hourly/MonitoringIndex/SiteCode=WA7/Json

Which Weather API to use?

Yahoo

Choosing a weather API was more difficult. I was originally going to use Yahoo’s weather API, I can get London’s weather like so: http://weather.yahooapis.com/forecastrss?w=44418&u=c

But I couldn’t see any “chance of rain in the next hour” metric in the results. Which is annoying, because Yahoo’s own iOS weather app has that information nicely presented. Using Charles proxy I could see that Yahoo’s iOS app uses https://mobileweather.yql.yahooapis.com and not their own public weather API. Its query for London looks like “select * from yahoo.media.weather.oauth where flickrGroup=’1463451@N25′ AND hourly=’TRUE’ AND hours=’23’ AND days=’10’ AND pw=’1316′ AND ph=’1316′ AND uv=’TRUE’ AND unit=’C’ AND mp=’true’ AND lang=’en’ AND woeid in (44418)”

Anyway, without the “chance of rain in next hour” metric I started looking elsewhere.

Forecast.io

I took a look at Forecast.io’s API and their API looked great – easy to use and it has the hourly forecast which is what I want. But when I tested its results for London a couple of things bothered me. 1. it’s in imperial only, not metric. OK that’s not a showstopper, I can do conversions to metric in my API. But the wind direction was plain incorrect. The weather was blowing an easterly but their API was saying it’s a southerly. Bad data = showstopper.

OpenWeatherMap

I had a quick look at OpenWeatherMap’s API and their API has super easy documentation (London current conditions here and 3 hour forecast here) but I couldn’t see hourly data there either.

Met Office

The UK’s own Met Office has numerous APIs over at http://www.metoffice.gov.uk/datapoint.

But bloody hell, it’s hard work trying to figure out which API call to use and how to call it. The “UK daily site specific forecast” was one option – here’s its results for Wandsworth. But that only has the forecast conditions at noon and midnight. All I want to know is what the conditions are now. Where’s that? Ah let’s try the “UK 3-hourly site-specific forecast” (Wandsworth here). Again, it’s 3 hour forecast feed. All I want to know is the conditions right now and for the next hour. I guess that’s as close as I’m going to get though.

Conclusion

I couldn’t find the perfect weather API – only Forecast.IO had a rain prediction for the next hour but their wind direction was incorrect. OpenWeatherMap and Met Office both had 3 hour predictions, but OpenWeatherMap’s documentation is better, their Free account has better terms, and they work worldwide and not UK only so I’m gonna use them.

Winner: OpenWeatherMap

 

Should I cycle: System design

I spent some time on the weekend thinking about Should I Cycle, the app I want to build. There’s two ways I could do it:

  • standalone iPhone app

or

  • build an API
  • iPhone app will call the API

Given the terms of use of most of the weather APIs out there, I wouldn’t be able to call them directly from my iPhone app. So I should build my own API which the iPhone app will call. OK then.

What should my API look like and what will it do? It’ll be pretty simple – when invoked, all it will do is call the other web services it’ll use – weather, air quality, pollen levels, convert the results into a succinct format, and probably cache the results.

Here’s a simple diagram (created using draw.io):

Should I cycle (1)

App idea: Should I Cycle?

I’ve come up with an idea for an iPhone app which I’m going to implement if I have time. I don’t expect to make any money off this app, and I’m only going to build it for an audience of one – me! But if it works well I’ll see if I can be bothered putting it on the app store.

The app is pretty simple – at a set time each day (i.e. in the morning) it should send me an alert (i.e. a push notification) as to whether I should cycle to work or not.

As a fair weather cyclist, the criteria on whether I should cycle to work or not are:

  • Weather – likelihood of rain in the next hour
  • Weather – wind direction
  • Air quality – pollution levels
  • Air quality – pollen count

additional criteria in the future could be:

  • Traffic conditions (doesn’t really bother me)
  • Tube conditions (i.e. if there’s tube or train delays then you should probably cycle)

Anyway, here’s a mockup of what I want the app to do (using creately.com):

Screen Shot 2014-08-25 at 17.43.15