Since the PyPortal came out, there have been many examples written which take advantage of the CircuitPython displayio graphics system. We have been working on writing a version of displayio that runs on Blinka, the CircuitPython compatibility layer for Python 3 on single board computers. With Blinka, you can run your favorite CircuitPython displayio applications and games on boards such as the Raspberry Pi or even the FT232H.

To make things even easier, we also wrote a version of the PyPortal library that runs on Blinka to make it even easier to get up and running. The Raspberry Pi is already connected to the internet, so we decided to take advantage of this and removed much of the code that handled managing the connections and replaced it with the Linux equivalents.

The Blinka PyPortal library is a port of the original PyPortal library that is intended to be run in CPython.  It leverages the Blinka Displayio library, which is a port of the original CircuitPython displayio library and is built on top of Adafruit Blinka and the Python Imaging Library. The idea behind the PyPortal library is to be able to run many of the examples that are currently available for the PyPortal with minimal changes.

Parts

To run the examples, you'll need a Raspberry Pi or FT232H. If you are going the Raspberry Pi route, a Raspberry Pi 4 is preferred due to its processing speed:

The Raspberry Pi 4 Model B is the newest Raspberry Pi computer made, and the Pi Foundation knows you can always make a good thing better! And what could make the Pi 4 better...
Out of Stock

For the Raspberry Pi, you will also need a PiTFT such as the 3.2" TFT:

Is this not the cutest little display for the Raspberry Pi? It features a 3.2" display with 320x240 16-bit color pixels and a resistive touch overlay. The plate uses the high...
Out of Stock

If you would like to play sound, one of the easiest ways is to connect an amplified speaker to the Raspberry Pi such as the Monoprice 5-watt amp:

Always be ready rock out or record with this 5-watt Guitar Amplifier, Portable Recorder, and USB Audio Interface from Monoprice.This handheld 5-watt amp...
Out of Stock

If you would prefer to run it directly from your computer, you could use an FT232H:

Wouldn't it be cool to drive a tiny OLED display, read a
$14.95
In Stock

For the FT232H, you will need a Breakout TFT such as the 2.8" TFT Breakout:

Add some jazz & pizazz to your project with a color touchscreen LCD. This TFT display is big (2.8" diagonal) bright (4 white-LED backlight) and colorful! 240x320 pixels with...
$29.95
In Stock

Setting up the Raspberry Pi is easy. Since the PiTFT comes preassembled, all you need to do is place it onto the GPIO pins.

Since there are dozens of Linux computers/boards you can use we will show wiring for Raspberry Pi. For other platforms, please visit the guide for CircuitPython on Linux to see whether your platform is supported

Connect the display as shown below to your Raspberry Pi.

Additional Parts

If you don't already have a 3.5mm cable, you'll want to grab one of those:

This basic cable comes with two 3.5mm (1/8" headphone jack size) stereo connectors. It's fairly straight forward, you'll commonly need these to connect two audio devices...
$2.95
In Stock

If you are using a Raspberry Pi 4 and have some active cooling on it such as the Pimoroni Fan Shim or Heatsink Case, you may want to attach a 40-pin stacking header so that the pins on the PiTFT don't interfere:

Stack multiple plates, breakouts etc onto your Raspberry Pi Model B+ with this custom-made extra-tall and extra-long 2x20 female header. The female header part has extra spaces to...
$2.95
In Stock
Note this is not a kernel driver that will let you have the console appear on the TFT. However, this is handy when you can't install an fbtft driver, and want to use the TFT purely from 'user Python' code!

Software Setup

You'll need to install the Adafruit_Blinka library that provides the CircuitPython support in Python. This may also require enabling SPI on your platform and verifying you are running Python 3. Since each platform is a little different, and Linux changes often, please visit the CircuitPython on Linux guide to get your computer ready!

If you have already installed the kernel module, you will need to remove it by running the installer and choosing uninstall.

Pillow Library

We also need PIL, the Python Imaging Library, to allow graphics and using text with custom fonts. There are several system libraries that PIL relies on, so installing via a package manager is the easiest way to bring in everything:

  • sudo apt-get install python3-pil

NumPy Library

A recent improvement of the RGB_Display library makes use of NumPy for additional speed. This can be installed with the following command:

  • sudo apt-get install python3-numpy

Install the PyPortal Library

You'll next want to install the Blinka PyPortal library. Installing this library will also install all of the dependencies, so it's really easy to setup. Just run the following command:

pip3 install adafruit-blinka-pyportal

Using a 3.5" PiTFT

If you want to use a 3.5" PiTFT, then you will need to do a little extra work. First, you'll need to install the HX8357 library. You can do that by using the following comand:

pip3 install adafruit-circuitpython-hx8357

Next you'll need to initialize the display at the beginning of the example and pass it into the initializer. We'll go over that on the Running Examples page.

If you are using the 3.5" PiTFT, keep in mind that the display's resolution is higher than what examples were written for, so things may appear a little off.

Connecting More Sensors

Most of the PiTFT hats either have a 40-pin or a 26-pin connector on the back that allows you to connect more sensors. We also conveniently have both 40-pin and 26-pin versions of the Pi cobbler that will connect to the back of the panel so that you can hook up more sensors.

This is the assembled version of the Pi T-Cobbler Plus.  It only works with the Raspberry Pi Model Zero, A+, B+, Pi 2, Pi 3 & Pi 4! (Any Pi with 2x20...
$7.95
In Stock
Now that you've finally got your hands on a Raspberry Pi® , you're probably itching to make some fun embedded computer projects...
$6.95
In Stock

Using the FT232H for running the PyPortal examples will require 3 main components. You will need the FT232H itself and a TFT display such as the 2.8" ILI9341 touchscreen breakout.

The first thing you will need to do is be sure the solderable jumpers on the back of the TFT breakout is setup to use SPI. By default, all of these breakouts are configured to use 8-bit data mode and some soldering will be required.

Wouldn't it be cool to drive a tiny OLED display, read a
$14.95
In Stock

Wiring

The pinouts for each of the TFT display breakouts is about the same, so you can use this diagram for all of them.
  • 5V on the FT232H connects to Vin on the TFT
  • GND on the FT232H connects to GND on the TFT
  • D0 on the FT232H connects to CLK on the TFT
  • D1 on the FT232H connects to MOSI on the TFT
  • D4 on the FT232H connects to CS on the TFT
  • D5 on the FT232H connects to D/C on the TFT
  • D6 on the FT232H connects to RST on the TFT

Software Setup

To run the Examples off your Mac, Windows, or Linux computer, first you'll need to be sure that you have your computer set up to run Blinka. You can find more information on getting your computer set up in our CircuitPython Libraries on any Computer with FT232H guide.

Additionally, you will also need PIL and NumPy. Since the installation procedure can vary from system to system, we linked to each package's installation instructions.

Pillow/PIL

This is the Python Imaging Library which is used to render the plots onto bitmaps that can be sent to the TFT display. Install instructions are here:

NumPy

This is the Numerical Python library and is an open source Python library that’s the universal standard for working with numerical data in Python, and it’s at the core of the scientific Python and PyData ecosystems. This is used to quickly process graphical data so that it can be sent to the display efficiently.

Install the PyPortal Library

You'll next want to install the Blinka PyPortal library. Installing this library will also install all of the dependencies, so it's really easy to setup. Just run the following command:

pip3 install adafruit-blinka-pyportal

Before running these examples, be sure your Single Board Computer is connected to the internet, since a connection is required.

The included examples are all ports from previous projects for the PyPortal with associated learn guides. To use each of the examples, you will want to either go to the original Learn Guide click Download Project Zip or go to the original Project Files on GitHub.

While there are other examples besides the ones listed on this page, some of them make use of the some of the onboard sensors such as the light or temperature sensor, which is not present by default on the Pi. However, if you have a PiTFT with additional pins on the back, you could use a 26-pin or 40-pin Pi-Cobbler and connect additional sensors too.

If you are using an FT232H, you could may wire up some additional sensors to this board on some unused GPIO pins, though since the I2C pins are shared with the SPI pins, you won't be able to run and use I2C devices at the same time.

The following examples have been modified to work with the Raspberry Pi, which has a Linux Operating System and no built-in NeoPixel.

Secrets File

To run the examples, you will need to setup a secrets.py file in your script folder. You can copy it below if you don't already have one. Note that unlike the original PyPortal secrets file, you don't need to add your WiFi connection information because your board should already be on the internet.

# This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it

secrets = {
    'timezone' : "America/New_York", # http://worldtimeapi.org/timezones
    'github_token' : 'fawfj23rakjnfawiefa',
    'hackaday_token' : 'h4xx0rs3kret',
    'openweather_token' : 'xxxxxxxxxxxxxxxxxxxxxxxx',
    }

PyPortal Startup Image and Sound

The PyPortal library looks to see if the PyPortal Startup Image and Wav file are in the folder that you are running the example from and plays them if they are there. You can download those here if you don't already have a copy. Be sure they are named pyportal_startup.bmp and pyportal_startup.wav.

When you start up each example, you should see the startup image displayed briefly and a hear sound played:

If you are using the 3.5" PiTFT, keep in mind that the display's resolution is higher than what examples were written for, so things may appear a little off.

Script changes for the 3.5" HX8357 TFT Display

To use the HX8357 display, we'll need to declare the display object in the example and pass it in since there's no way to detect which display is being used. In fact, it's likely that without modifying the code, the example would still run in a portion of the display with the unused part appearing as random noise.

The first thing you will need to add is some code to setup the display.

# Setup the Display
import board
import displayio
import adafruit_hx8357
displayio.release_displays()
spi = board.SPI()
tft_cs = board.CE0
tft_dc = board.D25

display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs)
display = adafruit_hx8357.HX8357(display_bus, width=480, height=320, backlight_pin=board.D18)

The other thing you will need to change is to pass in the already initialized display as an additional parameter to the PyPortal Initialization Function. So we will change this line:

pyportal = PyPortal(

to this:

pyportal = PyPortal(
    display=display,
If you see "AttributeError: module 'board' has no attribute 'NEOPIXEL'", make sure you are using the examples below rather than the original examples from the guides.

Bitcoin Example

The first example is the Bitcoin Price Display. This gets the current bitcoin value and displays it on the screen. You can get the resources for this example from the original PyPortal Bitcoin Example or from the original Learn Guide.

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
"""
This example will access the coindesk API, grab a number like bitcoin value in
USD and display it on a screen
If you can find something that spits out JSON data, we can display it!

You can find any resources in the associated Learn Guide at:
https://learn.adafruit.com/pyportal-bitcoin-value-display

Note: This library is designed to run on CPython and not CircuitPython.
"""
import os
import time
from adafruit_pyportal import PyPortal

# You can display in 'GBP', 'EUR' or 'USD'
CURRENCY = "USD"
# Set up where we'll be fetching data from
DATA_SOURCE = "https://api.coindesk.com/v1/bpi/currentprice.json"
DATA_LOCATION = ["bpi", CURRENCY, "rate_float"]


def text_transform(val):
    if CURRENCY == "USD":
        return "$%d" % val
    if CURRENCY == "EUR":
        return "‎€%d" % val
    if CURRENCY == "GBP":
        return "£%d" % val
    return "%d" % val


# the current working directory (where this file is)
try:
    cwd = os.path.dirname(os.path.realpath(__file__))
except AttributeError:
    cwd = ("/" + __file__).rsplit("/", 1)[0]

pyportal = PyPortal(
    url=DATA_SOURCE,
    json_path=DATA_LOCATION,
    default_bg=cwd + "/bitcoin_background.bmp",
    text_font=cwd + "/fonts/Arial-Bold-24-Complete.bdf",
    text_position=(195, 130),
    text_color=0x0,
    text_transform=text_transform,
)
pyportal.preload_font(b"$012345789")  # preload numbers
pyportal.preload_font((0x00A3, 0x20AC))  # preload gbp/euro symbol

while True:
    try:
        value = pyportal.fetch()
        print("Response is", value)
    except (ValueError, RuntimeError) as e:
        print("Some error occured, retrying! -", e)

    time.sleep(3 * 60)  # wait 3 minutes

Upload the secrets file, background image, font folder and the above example code to your Pi. If you are using a 3.5" display, be sure to make the necessary changes as well. After that, run the code:

python3 adafruit_blinka_pyportal_bitcoin.py

You should see something similar to the following:

NASA Image Example

The next example is the Image of the Day from NASA. This will get the current NASA image URL, download the image, resize it, and display it on the screen. You can get the resources for this example from the original PyPortal NASA Example or from the original Learn Guide.

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
"""
You can find any resources in the associated Learn Guide at:
https://learn.adafruit.com/pyportal-nasa-image-of-the-day-viewer

Note: This library is designed to run on CPython and not CircuitPython.
"""
import os
import time
from adafruit_pyportal import PyPortal

# Set up where we'll be fetching data from
DATA_SOURCE = "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"
# There's a few different places we look for data in the photo of the day
IMAGE_LOCATION = ["url"]
TITLE_LOCATION = ["title"]
DATE_LOCATION = ["date"]

# the current working directory (where this file is)
try:
    cwd = os.path.dirname(os.path.realpath(__file__))
except AttributeError:
    cwd = ("/" + __file__).rsplit("/", 1)[0]

pyportal = PyPortal(
    url=DATA_SOURCE,
    json_path=(TITLE_LOCATION, DATE_LOCATION),
    default_bg=cwd + "/nasa_background.bmp",
    text_font=cwd + "/fonts/Arial-12.bdf",
    text_position=((5, 220), (5, 200)),
    text_color=(0xFFFFFF, 0xFFFFFF),
    text_maxlen=(50, 50),  # cut off characters
    image_json_path=IMAGE_LOCATION,
    image_resize=(320, 240),
    image_position=(0, 0),
    debug=True,
)

while True:
    response = None
    try:
        response = pyportal.fetch()
        print("Response is", response)
    except RuntimeError as e:
        print("Some error occured, retrying! -", e)

    time.sleep(30 * 60)  # 30 minutes till next check

Upload the secrets file, background image, font folder and the above example code to your Pi. If you are using a 3.5" display, be sure to make the necessary changes as well. After that, run the code:

python3 adafruit_blinka_pyportal_nasa.py

You should see the following background appear first:

Following that, it should download and display an image similar to this:

Quote Example

The next example is the Adafruit Quote display. This will go out and fetch a random quote from the Adafruit website and display it on the screen. You can get the resources for this example from the original PyPortal Quote Example or from the original Learn Guide.

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
"""
You can find any resources in the associated Learn Guide at:
https://learn.adafruit.com/pyportal-adafruit-quote-board

Note: This library is designed to run on CPython and not CircuitPython.
"""
import os
import time
from adafruit_pyportal import PyPortal

# Set up where we'll be fetching data from
DATA_SOURCE = "https://www.adafruit.com/api/quotes.php"
QUOTE_LOCATION = [0, "text"]
AUTHOR_LOCATION = [0, "author"]

# the current working directory (where this file is)
try:
    cwd = os.path.dirname(os.path.realpath(__file__))
except AttributeError:
    cwd = ("/" + __file__).rsplit("/", 1)[0]

pyportal = PyPortal(
    url=DATA_SOURCE,
    json_path=(QUOTE_LOCATION, AUTHOR_LOCATION),
    default_bg=cwd + "/quote_background.bmp",
    text_font=cwd + "/fonts/Arial-ItalicMT-17.bdf",
    text_position=((20, 120), (5, 210)),  # quote location  # author location
    text_color=(0xFFFFFF, 0x8080FF),  # quote text color  # author text color
    text_wrap=(35, 0),  # characters to wrap for quote  # no wrap for author
    text_maxlen=(180, 30),  # max text size for quote & author
)

# speed up projects with lots of text by preloading the font!
pyportal.preload_font()

while True:
    try:
        value = pyportal.fetch()
        print("Response is", value)
    except (ValueError, RuntimeError) as e:
        print("Some error occured, retrying! -", e)
    time.sleep(60)

Upload the secrets file, background image, font folder and the above example code to your Pi. If you are using a 3.5" display, be sure to make the necessary changes as well. After that, run the code:

python3 adafruit_blinka_pyportal_quote.py

You should see something similar to the following:

Discord Counter Example

The next example is the Adafruit Discord Online Counter display. This will go out and find the number of people currently online using the Adafruit Discord Server and display it on the screen. You can get the resources for this example from the original PyPortal Discord Example or from the original Learn Guide.

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
"""
This example will access shields.io API, grab the SVG graphic and then use
regular expression search to locate the number of online discord users, then
display it on a screen.
If you can find something that spits out text, we can display it!

You can find any resources in the associated Learn Guide at:
https://learn.adafruit.com/pyportal-discord-online-count

Note: This library is designed to run on CPython and not CircuitPython.
"""
import os
import time
from adafruit_pyportal import PyPortal

# Set up where we'll be fetching data from
DATA_SOURCE = "https://img.shields.io/discord/327254708534116352.svg"
# a regular expression for finding the data within the SVG xml text!
DATA_LOCATION = [r">([0-9]+ online)<"]

try:
    cwd = os.path.dirname(os.path.realpath(__file__))
except AttributeError:
    cwd = ("/" + __file__).rsplit("/", 1)[0]

pyportal = PyPortal(
    url=DATA_SOURCE,
    regexp_path=DATA_LOCATION,
    default_bg=cwd + "/discord_background.bmp",
    text_font=cwd + "/fonts/Collegiate-50.bdf",
    text_position=(70, 216),
    text_color=0x000000,
)

while True:
    try:
        value = pyportal.fetch()
        print("Response is", value)
    except RuntimeError as e:
        print("Some error occured, retrying! -", e)
    time.sleep(60)

Upload the secrets file, background image, font folder and the above example code to your Pi. If you are using a 3.5" display, be sure to make the necessary changes as well. After that, run the code:

python3 adafruit_blinka_pyportal_discord.py

You should see something similar to the following:

Open Weather Example

The last example is the Open Weather display. This will go out and find the weather conditions for the location that you have set and display it on the screen. This example is a little bit more complicated than the other examples. You can get the resources for this example from the original PyPortal Open Weather Example or from the original Learn Guide.

For this example, you will need to go to this link and register for a free account. Once registered, you'll get an email containing your API key, also known as the "openweather token". Edit your secrets.py file and add the token into there.

Look for this line and be sure to change the LOCATION variable to your location:

# Use cityname, country code where countrycode is ISO3166 format.
# E.g. "New York, US" or "London, GB"
LOCATION = "Manhattan, US"

For this example, you will need 2 files. The main file:

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
"""
This example queries the Open Weather Maps site API to find out the current
weather for your location... and display it on a screen!
if you can find something that spits out JSON data, we can display it

You can find any resources in the associated Learn Guide at:
https://learn.adafruit.com/pyportal-weather-station

Note: This library is designed to run on CPython and not CircuitPython.
"""
import os
import sys
import time
import adafruit_blinka_pyportal_openweather_graphics as openweather_graphics
from adafruit_pyportal import PyPortal

# the current working directory (where this file is)
try:
    cwd = os.path.dirname(os.path.realpath(__file__))
except AttributeError:
    cwd = ("/" + __file__).rsplit("/", 1)[0]

sys.path.append(cwd)

# Get wifi details and more from a secrets.py file
try:
    from secrets import secrets
except ImportError:
    print("WiFi secrets are kept in secrets.py, please add them there!")
    raise

# Use cityname, country code where countrycode is ISO3166 format.
# E.g. "New York, US" or "London, GB"
LOCATION = "Manhattan, US"

# Set up where we'll be fetching data from
DATA_SOURCE = "http://api.openweathermap.org/data/2.5/weather?q=" + LOCATION
DATA_SOURCE += "&appid=" + secrets["openweather_token"]
# You'll need to get a token from openweather.org, looks like 'b6907d289e10d714a6e88b30761fae22'
DATA_LOCATION = []


# Initialize the pyportal object and let us know what data to fetch and where
# to display it
pyportal = PyPortal(url=DATA_SOURCE, json_path=DATA_LOCATION, default_bg=0x000000)

gfx = openweather_graphics.OpenWeather_Graphics(
    pyportal.splash, am_pm=True, celsius=False
)

localtile_refresh = None
weather_refresh = None
while True:
    # only query the online time once per hour (and on first run)
    if (not localtile_refresh) or (time.monotonic() - localtile_refresh) > 3600:
        try:
            print("Getting time from internet!")
            pyportal.get_local_time()
            localtile_refresh = time.monotonic()
        except RuntimeError as e:
            print("Some error occured, retrying! -", e)
            continue

    # only query the weather every 10 minutes (and on first run)
    if (not weather_refresh) or (time.monotonic() - weather_refresh) > 600:
        try:
            value = pyportal.fetch()
            print("Response is", value)
            gfx.display_weather(value)
            weather_refresh = time.monotonic()
        except RuntimeError as e:
            print("Some error occured, retrying! -", e)
            continue

    gfx.update_time()
    time.sleep(30)  # wait 30 seconds before updating anything again

And the Graphics handling file:

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
"""
This is a dependency of adafruit_blinka_pyportal_openweather.py and
should not be run directly.

Note: This library is designed to run on CPython and not CircuitPython.
"""

import os
import time
import json
import displayio
from adafruit_display_text.label import Label
from adafruit_bitmap_font import bitmap_font

try:
    cwd = os.path.dirname(os.path.realpath(__file__))
except AttributeError:
    cwd = ("/" + __file__).rsplit("/", 1)[0]

small_font = cwd + "/fonts/Arial-12.bdf"
medium_font = cwd + "/fonts/Arial-16.bdf"
large_font = cwd + "/fonts/Arial-Bold-24.bdf"

# pylint: disable=too-many-instance-attributes
class OpenWeather_Graphics(displayio.Group):
    def __init__(self, root_group, *, am_pm=True, celsius=True):
        super().__init__(max_size=2)
        self.am_pm = am_pm
        self.celsius = celsius

        root_group.append(self)
        self._icon_group = displayio.Group(max_size=1)
        self.append(self._icon_group)
        self._text_group = displayio.Group(max_size=5)
        self.append(self._text_group)

        self._icon_sprite = None
        self.set_icon(cwd + "/weather_background.bmp")

        self.small_font = bitmap_font.load_font(small_font)
        self.medium_font = bitmap_font.load_font(medium_font)
        self.large_font = bitmap_font.load_font(large_font)
        glyphs = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.: "
        self.small_font.load_glyphs(glyphs)
        self.medium_font.load_glyphs(glyphs)
        self.large_font.load_glyphs(glyphs)
        self.large_font.load_glyphs(("°",))  # a non-ascii character we need for sure
        self.city_text = None

        self.time_text = Label(self.medium_font, max_glyphs=8)
        self.time_text.x = 200
        self.time_text.y = 12
        self.time_text.color = 0xFFFFFF
        self._text_group.append(self.time_text)

        self.temp_text = Label(self.large_font, max_glyphs=6)
        self.temp_text.x = 200
        self.temp_text.y = 195
        self.temp_text.color = 0xFFFFFF
        self._text_group.append(self.temp_text)

        self.main_text = Label(self.large_font, max_glyphs=20)
        self.main_text.x = 10
        self.main_text.y = 195
        self.main_text.color = 0xFFFFFF
        self._text_group.append(self.main_text)

        self.description_text = Label(self.small_font, max_glyphs=60)
        self.description_text.x = 10
        self.description_text.y = 225
        self.description_text.color = 0xFFFFFF
        self._text_group.append(self.description_text)

    def display_weather(self, weather):
        weather = json.loads(weather)

        # set the icon/background
        weather_icon = weather["weather"][0]["icon"]
        self.set_icon(cwd + "/icons/" + weather_icon + ".bmp")

        city_name = weather["name"] + ", " + weather["sys"]["country"]
        print(city_name)
        if not self.city_text:
            self.city_text = Label(self.medium_font, text=city_name)
            self.city_text.x = 10
            self.city_text.y = 12
            self.city_text.color = 0xFFFFFF
            self._text_group.append(self.city_text)

        self.update_time()

        main_text = weather["weather"][0]["main"]
        print(main_text)
        self.main_text.text = main_text

        temperature = weather["main"]["temp"] - 273.15  # its...in kelvin
        print(temperature)
        if self.celsius:
            self.temp_text.text = "%d °C" % temperature
        else:
            self.temp_text.text = "%d °F" % ((temperature * 9 / 5) + 32)

        description = weather["weather"][0]["description"]
        description = description[0].upper() + description[1:]
        print(description)
        self.description_text.text = description
        # "thunderstorm with heavy drizzle"

    def update_time(self):
        """Fetch the time.localtime(), parse it out and update the display text"""
        now = time.localtime()
        hour = now[3]
        minute = now[4]
        format_str = "%d:%02d"
        if self.am_pm:
            if hour >= 12:
                hour -= 12
                format_str = format_str + " PM"
            else:
                format_str = format_str + " AM"
            if hour == 0:
                hour = 12
        time_str = format_str % (hour, minute)
        print(time_str)
        self.time_text.text = time_str

    def set_icon(self, filename):
        """The background image to a bitmap file.

        :param filename: The filename of the chosen icon

        """
        print("Set icon to ", filename)
        if self._icon_group:
            self._icon_group.pop()

        if not filename:
            return  # we're done, no icon desired
        with open(filename, "rb") as icon_file:
            icon = displayio.OnDiskBitmap(icon_file)
            self._icon_sprite = displayio.TileGrid(
                icon, pixel_shader=displayio.ColorConverter()
            )
            self._icon_group.append(self._icon_sprite)

Upload the updated secrets file, background image, font folder, icons folder and the above example files to your Pi. If you are using a 3.5" display, be sure to make the necessary changes as well. After that, run the code:

python3 adafruit_blinka_pyportal_openweather.py

You should see something similar to the following:

This guide was first published on Jul 09, 2020. It was last updated on Jul 09, 2020.