Chicago Bus App

Chicago Bus App

Chicago is a Big Data city.

https://data.cityofchicago.org serves 914 distinct, publicly accessible data sets including Beach Water Quality, Rat Infestations, Employee names and salaries. Chicago is “dedicated to promoting access to government data and encouraging the development of creative tools to engage and serve Chicago’s diverse community”. They have a Github site, video tutorials and sample API code. It is an immense data store!

It is a terrific strategy. For example: building a city bus smartphone app. Design, support, customer service, bug fixes, inaccuracies – all cost time and money. Chicago has chosen to make data they already collect as part of operations publicly available. They’ve equipped independent developer citizens with the data necessary to build the best bus application they can, in a competitive marketplace, resulting in a dozen bus apps at zero cost to the city in time, money or other resources. Not to mention a community of invested citizens. Brilliant.

Then again, maybe not. The marketplace is competitive but the rewards are minimal, driven by the rush-to-the-bottom dynamic of the smartphone app ecosystem. The available apps are flexible, feature-filled, and some (very few) are even aesthetically well-designed and stable. They’re also all terrible. Every app required 3-6 clicks and 30+ seconds of interaction to get the bus information I want, even though that request never changes. I need to go to work and back every day, at the same time, from the same place, on the same route. I don’t need to know anything else 95% of the time.

Which brings us to the second beauty of a public API: I can personally access it with minimal hassle. A quick web page, with the apple-mobile-web-app-capable set to yes, and an app designed for me, by me is only a couple hours away. A web app requires no developer agreements, sidesteps the App Store, can be updated in real time, and can be private.

So here’s my “app”: it displays the time until the next 5 buses on my route arrive at my stop. You can’t change the routes, you can’t change the stops. There is zero flexibility and there is one feature: I open the app and it displays the minutes until the bus leaves. It refreshes every 30 seconds or when I click anywhere. All it required is a very, very simple PHP script (if you try with Javascript you will run into the cross-domain request limitation) which dynamically renders a Bootstrap based web page.

First we grab the XML Bus feeds from the API. Get your own key to follow along:

 //Current time according to the bus system
 $timeNowURL = 'http://www.ctabustracker.com/bustime/api/v1/gettime?key=MYKEY';
 $timenowxml = simplexml_load_file($timeNowURL) or die("feed not loading");
 $busCurrentTime = strtotime($timenowxml->tm);
 //Next buses available from my stop IDs and routes.
 $nextBus = 'http://www.ctabustracker.com/bustime/api/v1/getpredictions?key=MYKEY&stpid=STPID,STPID2&rt=RTID';
 $nextbusxml = simplexml_load_file($nextBus) or die("feed not loading");
 $buses = $busxml->children();

I grab the bus system’s current time because it can differ from the actual time by over a minute. I also grab the two routes I’m interested in. PHP’s simplexmp_load_file takes care of calling the request and parsing the result. strtotime() works wonders on every date string I’ve ever thrown at it (much, much better than the javascript version, which required parsing character by character to get a Date object).

I then prepare the recieved data for display:

foreach($busses as $a)
 {
      if ($a->rtdir == "Westbound") { //separate into east and westbound data
         $predictedTime = strtotime($a->prdtm); //get the predicted time
         $minutesUntil = floor(($predictedTime - $busCurrentTime)/60); //calculate minutes until and round up (to not provide false data and give a small cushion)
         $westCounter++; // this counter is used for simplification purposes.
         $predWest[$westCounter] = $minutesUntil; //add the prediction to an array.
        } else if ($a->rtdir == "Eastbound") { //repeat for eastbound
         $predictedTime = strtotime($a->prdtm);
         $minutesUntil = floor(($predictedTime - $busCurrentTime)/60);
         $eastCounter++;
         $predEast[$eastCounter] = $minutesUntil; 
        }
 }

There is more data available, including approximate feet to the next stop, but it isn’t necessary.
To render the HTML I brute force a few calls like this inside my HTML template:

if ($westCounter >= 1) { echo $predWest[1]; } else { echo"-"; }

“if there is a value then use it, or display a placeholder.”


Bus App main screen

Maybe in the future I could add features like user configurable routes or stops, but I don’t need that. Anyone can customize those in the code and then leave it static. I still have a Chicago Bus app on my phone for those rare times when I need a different route. Google is pretty good too.

But in the mornings, I open this app with one touch and let it sit on the counter, refreshing every 30 seconds, until I’m ready to leave – at which point I can see, with zero interaction, how many minutes until the next bus.

Leave a Reply

Your email address will not be published. Required fields are marked *