How to build a #TfL bus arrivals board/weather display with a #RaspberryPi and #unicorn hat.

I live on a bus route, not far from a stop. I hate waiting outside for the bus. I use Citymapper on my smartphone to minimise waiting outside by leaving just in time for a bus.  I also check on that phone what the weather is and what it will be for the rest of the day.

Checking the phone works fine, but with a Raspberry Pi and superbright blinky lights everything is so much cooler!

Browsing around I came across this excellent page by Daniel Forsyth that inspired me to use a Raspberry Pi A+ in a Coupé Royale case from Pimoroni and a Unicorn-hat to display when the next bus is leaving. Actually, I wanted to see not only the next bus, but also all the busses after that one and the same for the stop across the street. And I wanted to see a brief weather prediction for the day.  And all of that on the Unicorn hat display.

Thanks to Richard Hayler, who made a scrolling text on the Unicorn hat possible and shared it on GitHub, Transport for London who has open data of real time information on busses and the pywapi (Python weather API) it wasn’t too hard.

The code:

import requests
from UHScroll import *
import pywapi
import unicornhat as unicorn

#### This function is originally built by Daniel Forsyth 
#### (http://danielforsyth.me/catching-the-bus-to-class-with-python/
#### I just slightly changed a bit. Thanks Daniel!!
def nextBus(stop):
    stop = str(stop)
    r = requests.get('http://countdown.tfl.gov.uk/stopBoard/'+stop)
    json_result = r.json()
    all_stops = json_result['arrivals']
    my_stops = []
    for x in all_stops:
        if x['isRealTime']== True and x['isCancelled'] == False and x['routeName']=="245":
            x = str(x['estimatedWait'][:-4])
            if x == '':
                x = '0'
            my_stops.append(x)
    return  my_stops
####
####
####

while True:
    try:
#### The '<<<<' and '>>>>>' are to indicate the direction in which the bus is going. 😉
        b = nextBus(58175)
        b = '>>>>> '+','.join(b)
        a = nextBus(58990)
        a ='<<<<< '+ ','.join(a)
    except:
#### Sometimes the service is a bit slow,(we're all human after all) and I don't want this to crash the script.
        a = 'Tfl error'
        b = 'Tfl error'

    try:
        weather_com_result = pywapi.get_weather_from_weather_com('UKXX1158')
        weather = ("It is " + weather_com_result['current_conditions']['text'].lower() + " and " + weather_com_result['current_conditions']['temperature'] + "C. Feels like "+ weather_com_result['current_conditions']['feels_like'] + " C. Forecast: " + weather_com_result['forecasts'][0]['day']['text'] + ". Min " + weather_com_result['forecasts'][0]['low'] + ". Max " + weather_com_result['forecasts'][0]['high'])
    except:
        weather = 'Error retrieving weather'

#### This bit rotates the info on the Pi for about a minute, until it is about time to fetch fresh new info
    for i in range (0,3):
        unicorn_scroll(b,'green',255,0.04)
        unicorn_scroll(a,'red',255,0.04)
        unicorn_scroll(weather, 'white', 128, 0.04)

After this I updated crontab so the script runs once at boot-up in the background.

Now it is happy and brightly blinking away by the front door.

Video!

PS: at night, from the outside it looks like some crazy alarm has gone off in our hallway, it may even keep burglars away! 🙂