Ever since I saw this project (http://digitalfantastico.blogspot.co.uk/2013/01/a-big-bite-of-raspberry-pi-having.html) by Gareth James at Brighton Hackspace, I’ve wanted to make my own display like it. It’s a display that shows when the next trains are from his local station to get into Brighton.
I need to get from Beeston to Nottingham, where I have more choices than just one train. There are two different bus stops (both with different routes) and a train station I could use. Working out which one I should use at a particular time requires looking at three different webpages, which is a bit of a faff.
The basic principle of the display is to scrape website(s) for the relevant information and display it in a easy-to-glance-at format. Gareth’s display used a RaspberryPI to perform the scraping and a TFT screen for the display.
Since I have an HP Touchpad that I barely used, I decide it was finally time to put Android on it (Cyanogenmod), and get into the world of app development. Android devices have a “Daydream” mode (a bit like a screensaver) that can come on when charging. To my (limited) knowledge, they’re just applications that declare themselves as daydreams. This was what I chose to write, since I could put the tablet on its wireless charger and automatically display the application, and then just pick it up when I need to use it normally.
The website I chose to scrape for the bus information is http://www.nextbuses.mobi. For trains I used http://www.traintimes.org. The “Terms” page asks you kindly not to use it for apps, but I hope that my one-request-every-10-minutes-or-so-on-just-my-tablet application won’t cause an issue.
When the application level update manager decides it needs to perform an update, the data flow from website to the screen is:
- An asynchronous URL thread is started that pulls the raw HTML.
- The HTML data is passed to a class that uses TagSoup to scrape it and produce strings containing the pertinent information.
- The strings are passed to a handler class that produces a list of individual journey objects.
- The journey objects are passed to a manager that collates all the journeys from each website and sorts into time order.
- The application requests journeys from the manager and decides which ones to display (based on user-configurable time and display settings).
- The display is dynamically re-generated if the number of displayed rows needs changing.
Every 30 seconds, the screen is updated with how much time is remaining for each journey.
This 30-second tick also allows the journey manager to discard old journeys and to decide when to make a request for new website data.
A new request is made each time an item is removed from the list or when 15 minutes has elapsed since the last update. This means that most of the time a lot of data is pulled for journeys already in the list. The reason for doing it this way it means the data is “more live” – in case of delays/cancellations/breakdowns to services.
The application all runs off a state machine (I love state machines. They make things sane.) using stateless4j (https://code.google.com/p/stateless4j/), a Java port of the C# “stateless” project (https://code.google.com/p/stateless/).
The 30-second tick is kicked off by a handler registered with the Android API. The tick itself just passes an “update display” request into the state machine, or starts an update if the update manager decides that one is required.
Here’s what the screen looks like on a typical weekday morning:
The screen displays eight items, each with an icon showing the transport type (the British Rail symbol for trains, the relevant bus route logo for the four different buses I can take) and the time the service departs. The time is in “minutes remaining” format for journeys in the next 20 minutes, and the departure time for journeys further in the future.
It takes me about 5 minutes to walk to the stops, so the time turns red with 10 minutes to go. The journey is removed from the screen with 4 minutes remaining, since I certainly won’t make it after that.
Most of the numbers (number of journeys to display, update times, journey discard and highlight times) are user-configurable with a Settings activity.