A few years ago I came across Umbrella Today. The site had a simple function, providing a weather forecast with only one variable: is it going to rain today? Enter your zip code and you get a Yes-No answer to the question. The simplicity of this appealed to me. Although it was featured on LifeHacker in 2008 the site has since gone offline. Anyway, I don’t live in the USA and therefore didn’t have a zip code.
It thought it would be fun to set up a similar system using a Raspberry Pi, an RGB LED, and the Weather Underground API. When rain is forecast the LED is blue, otherwise it’s green. The final product is shown below.
To built your own Umbrella Advisement Notification Device, you will need:
- Raspberry Pi (with network connection)
- RGB LED (either common anode or cathode)
- 3x 220Ω resistors
- Breadboard
- Breadboard jumper wires
The components should be assembled following the schematic below. 3 of the pins on the LED correspond to the red, green and blue LEDs inside. The longest pin on the LED should be connected to 3v3 (if common anode) or ground (if common cathode). The value of the resistors can be adjusted to preference, with larger values resulting in less brightness. For more information, see the Adafruit tutorial on RGB LEDs.
Now that the hardware is set up we need to write some software to control the LED.
All of the code in this post is available on GitHub: https://github.com/snorfalorpagus/umbrella_today_rpi
If you haven’t already, install the RPi.GPIO
and requests
modules:
sudo pip install RPi.GPIO
sudo pip install requests
You will need to update the APIKEY
and LOCATION
variables. An API
key can be requested from the Weather Underground developer
site. At the time of
writing, free access allows 500 queries per day. That’s enough for us!
You can get the location code by copy and pasting the URL from the
standard website. The example below is for Oxford,
England.
The module below uses the
requests module to query
the Weather Underground API. The forecast for the current date is
retrieved in JSON (or tomorrow, if it’s after 5pm). The umbrella_today
function returns True
if it forecasts greater than or equal to 1
millimetre of rainfall during the day.
"""
umbrella.py
Is it going to rain today (or tomorrow)?
Requires an API key for Weather Underground:
https://www.wunderground.com/weather/api/
"""
import requests
from datetime import datetime, timedelta
APIKEY = "YOUR API KEY HERE"
LOCATION = "gb/benson/zmw:00000.19.03658"
URL_TEMPLATE = "http://api.wunderground.com/api/{APIKEY}/forecast/q/{LOCATION}.json"
def umbrella_today():
# get the current date
date = datetime.now()
# if the current time is after 5pm, use tomorrow instead
if date.hour >= 5:
date += timedelta(1)
date_tuple = (date.year, date.month, date.day)
# download forecast from weather underground
url = URL_TEMPLATE.format(APIKEY=APIKEY, LOCATION=LOCATION)
r = requests.get(url)
if not r.status_code == 200:
raise RuntimeError("Request returned status code: {}".format(r.status_code))
data = r.json()
# order forecasts into dictionary {date: forecast}
records = {}
for record in data['forecast']['simpleforecast']['forecastday']:
year = record['date']['year']
month = record['date']['month']
day = record['date']['day']
records[(year, month, day)] = record
# get forecast rainfall in millimetres
forecast = records[date_tuple]
rainfall_mm = forecast['qpf_day']['mm']
if rainfall_mm is not None and rainfall_mm >= 1:
return True
else:
return False
We can test that everything is working using the Python console:
>>> from umbrella import umbrella_today
>>> umbrella_today()
True
Uh oh! Looks like we’ll need to take a raincoat.
Next we need something to control the color of the LED. The module below
uses the RPi.GPIO
module to control a common anode LED. For a common
cathode, you’ll need to swap the order of GPIO.HIGH
and GPIO.LOW
in
the call to GPIO.output()
.
"""
led.py
This module allows the color of a common anode LED to be set by name: RED,
GREEN or BLUE.
For pin numbering on the Raspberry Pi, see:
https://www.raspberrypi.org/documentation/usage/gpio/
"""
import RPi.GPIO as GPIO
import atexit
PINS = [15, 13, 11] # red, green, blue
colors = {
'RED': (1,0,0),
'GREEN': (0,1,0),
'BLUE': (0,0,1),
None: (0,0,0),
}
def setup():
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
for PIN in PINS:
GPIO.setup(PIN, GPIO.OUT)
setup()
def set_color(name):
"""Set the color of the LED"""
rgb = colors[name]
for PIN, val in zip(PINS, rgb):
GPIO.output(PIN, [GPIO.HIGH, GPIO.LOW][val])
# ensure the LED is turned off when the program exits
atexit.register(lambda: set_color(None))
You can use the module above to test your hardware setup. The two lines
below import the set_color
function, then set the color of the LED to
blue.
>>> from led import set_color
>>> set_color('BLUE')
Finally, a short script to link the modules together. Every 30 minutes the weather forecast is checked and the color of the LED is updated accordingly.
"""
main.py
Update the forecast LED every 30 minutes
"""
from led import set_color
from umbrella import umbrella_today
from time import sleep
while True:
if umbrella_today():
set_color('BLUE')
else:
set_color('GREEN')
sleep(60 * 30) # 30 minutes
The RPi.GPIO
module requires root privilege to function, so call it
with sudo
. If you want to leave this running you could call it using
screen
, or with something more complicated (+ robust).
sudo python main.py
The Raspberry Pi, Python and the requests module were all used for convenience and also due to my RPi being in prominent view in my living room. The same result could be achieved using an ESP8266 and C++ without too much difficulty, even with the limited GPIO of the ESP-01. To avoid the burden of having to parse JSON on an IC the heavy living could be offloaded to script on a webserver which just returned a True/False response.