../

Weatherpaper: Weatherforecast on a RPi Zero with E-Paper Display


Intro

Using a Raspberry Pi Zero W and a 2.13“ e-paper hat one can create a quite decent weatherstation with a few lines of python code. As source for weatherinformation the ASCII based weather-api wttr.in which can be easily used via http requests. The API follows the pattern https://wttr.in/<location>. The help-page can be found at wttr.in/:help. To query, for example, the weatherinformation for Berlin one can use curl:

curl https://wttr.in/Berlin
Example weather request for Berlin.

Since there won’t be much space on the e-paper display we won’t use the query displayed above, but just the current weather:

curl https://wttr.in/Berlin?0T
Weather report: Berlin

        \   /     Clear
         .-.      +1(-3) °C
      (   ) ―   ↘ 15 km/h
         `-’      10 km
        /   \     0.0 mm

Prerequisites

The documentation for the e-paper display can be found on the Waveshare website. It also contains example code on how to use the display with other boards than the Raspberry Pi.

Setup

Waveshare provides a library to interact with the display using python at github.com/waveshareteam/e-Paper. Easiest is to clone this repository, but before one should create a python virtual environment to not steer up any other installed packages.

1# Creating a directory for this project
2mkdir weatherpaper
3cd weatherpaper
4# Creating the python virtualenv
5virtualenv .venv
6# Cloning the waveshare/e-paper repository
7git clone https://github.com/waveshareteam/e-Paper.git

Next one can activate the virtualenv just created and install waveshare’s python library using pip.

1# Activating the virtualenv
2source .venv/bin/activate
3# Changing directory to the library
4cd e-Paper/RaspberryPi_JetsonNano/python
5# Installing the waveshare library
6pip install .
7# Installing the requests library
8pip install requests

The font used to display the weatherforecast information will be Fira Code. This font can be found on github as well at github.com/tonsky/FiraCode. For the weatherpaper script the .ttf font file is required in a directory called ttf within the same path as the script itself. To set this up the following commands can be used.

1cd weatherpaper
2# Downloading the zip file using curl. Github redirects, thus -L is required.
3curl -L --output Fira_Code_v6.2.zip https://github.com/tonsky/FiraCode/releases/download/6.2/Fira_Code_v6.2.zip
4# Since we only need a single ttf file, we only extract the one needed.
5unzip Fira_Code_v6.2.zip "ttf/FiraCode-Regular.ttf" -d "."
6# Remove the unneeded zip file
7rm Fira_Code_v6.2.zip

Now, everything is prepared for the weatherpaper python script.

The Weatherpaper Script

The script itself is quite compact. The code can also be found at github.com/derfalx/scripts.

Lines 1 to 8 contain any import needed, as well as the basic log configuration. The main function of the script is weatherpaper. It takes three parameter: location, language and minutes. The first parameter, location contains the location name to be queried. The language to be used for the output of wttr.in is set using language and the waiting time in minutes between two updates of the weatherinformation is passed using minutes.

Preparation and initialization is done in line 17 to 26. First, the e-paper driver is initialized and the display is cleared. Next, the font to be used is loaded and an initial image is created, containing only white (= no content). For updates of the display epd.FULL_UPDATE is used. This way, the display is fully refreshed each time a image is drawn. It would also be possible to do a full update only once a while, but this could lead to a “dirty display” which shows previous content as background shadow.

Fetching and displaying weather information is done in the while(True) loop. It should only stop in case of an keyboard interrupt (or a major exception/error). To fetch the weather information python’s request library is used. The returned content is properly decoded (line 34) and set as text on a new image (line 36 to 38). The image is then rotated by 180° to match the orientation of the display (line 41). In case one does not rotate the display, this line can be omitted. Finally, the image is displayed (line42). This code block is enclosed in a try-except block in case an exception is raised while fetching / processing the request to wttr.in.

Once a request was done - regardless if it was successful or not - the script sleeps for the previously defined amount of minutes.

1import logging
2logging.basicConfig(level=logging.DEBUG)
3import os
4from waveshare_epd import epd2in13_V2
5import time
6from PIL import Image, ImageDraw, ImageFont
7import requests
8import sys
9
10
11def weatherpaper(location, language, minutes):
12 # Main try-except is used to intercept keyboardinterrupts to properly
13 # shut down the script.
14 try:
15 logging.info("== weatherpaper ==")
16 # Preparing and cleaning the Display
17 epd = epd2in13_V2.EPD()
18 epd.init(epd.FULL_UPDATE)
19 epd.Clear(0xFF)
20 # Loading the font and creating an initial, empty screen.
21 fontpath = os.path.join(os.path.dirname(os.path.realpath(__file__)))
22 font = ImageFont.truetype(os.path.join(fontpath, 'ttf/FiraCode-Regular.ttf'), 13)
23 image = Image.new('1', (epd.height, epd.width), 255)
24 draw = ImageDraw.Draw(image)
25 # Everytime an update is done, it will be a full (instead of a partial) update.
26 epd.init(epd.FULL_UPDATE)
27
28 while(True):
29 try:
30 r = requests.get(f'https://wttr.in/{location}?0T&lang={language}')
31 # In case r.status_code is not a successful status, raise an exception
32 r.raise_for_status()
33 # Setting proper encoding, so the text can be display correct
34 r.encoding = 'utf-8'
35 logging.info(r.text)
36 image = Image.new('1', (epd.height, epd.width), 255)
37 draw = ImageDraw.Draw(image)
38 draw.text((0,0), r.text, font=font, fill=0)
39 # Rotating the image is needed in my case, since I use the display bottom up.
40 # In case you use it the other way round, remove this line.
41 image = image.rotate(180)
42 epd.display(epd.getbuffer(image))
43 except requests.exceptions.RequestException as e:
44 logging.warn(f'An exception occurred while requesting wttr.in. Maybe it returned != 200. Skipping update.')
45
46 time.sleep(60 * minutes)
47 except KeyboardInterrupt:
48 epd2in13_V2.epdconfig.module_exit()
49 exit()
50
51
52if __name__ == '__main__':
53 if len(sys.argv) != 4:
54 print("usage: python weatherpaper.py <location> <language> <minutes>")
55 exit()
56
57 weatherpaper(sys.argv[1], sys.argv[2], int(sys.argv[3]))
58

Running the Script in Background

To run the weatherpaper script in background one can use the follow bash script:

1#! /bin/bash
2source ./weatherpaper/.venv/bin/activate
3nohup python ./weatherpaper/weatherpaper.py "<location>" "<language>" <minutes> &

Simply set location, language, minutes and make the script executable using chmod u+x <scriptname>.

There you go!

Kategorien: #/Raspberry Pi/; #/Python/

Tags: #/raspberry pi zero/; #/e-paper display/; #/weatherstation/