I wanted to make a little news feed reader for the Raspberry Pi Pico W, a cheap microcontroller with wifi capabilities, and display the results on a Pimoroni Pico Inky Pack e-ink display using Micropython.
I flashed the Pico with the Pimoroni Micropython bundle. Unfortunately the Micropython libraries do not appear to include an XML parser, so I had to use regex calls to extract the headlines and the dates from the RSS feed. The regex functions are a subset of those available in Python 3.7+ and I was only able to grab three items with a single pattern before running out of memory.
The reader uses the three buttons (A, B, C) on the Inky display to select between the three items and display each. It gets the RSS feed every ten minutes and checks to see if the title of the first item has changed from the previous fetch, refreshing the display if this is true.
I’m using the ABC Australia latest news RSS feed as the source: https://www.abc.net.au/news/feed/51120/rss.xml
Three files are used.
WIFI_CONFIG.py
SSID = 'your-network-ssid'
PSK = 'your-network-password'
network_connect.py
import time
import network
import WIFI_CONFIG
wlan = network.WLAN(network.STA_IF)
def connect_to_network():
wlan.active(True)
wlan.config(pm = 0xa11140) # Disable power-save mode
wlan.connect(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK)
max_wait = 10
while max_wait > 0:
if wlan.status() < 0 or wlan.status() >= 3:
break
max_wait -= 1
print('waiting for connection...')
time.sleep(1)
if wlan.status() !=3:
raise RuntimeError('network connection failed')
else:
print('connected')
status = wlan.ifconfig()
print('ip = ' + status[0])
main.py
# Get the ABC Australia news feed and display on Pimoroni Inky
import network_connect
import time
import urequests
import re
from pimoroni import Button
from picographics import PicoGraphics, DISPLAY_INKY_PACK, PEN_1BIT
network_connect.connect_to_network()
# ABC News Feed
feed_address = "http://www.abc.net.au/news/feed/51120/rss.xml"
feed_title = "ABC News"
feed_instructions = "Press A, B or C to display the 3 latest items."
feed_items = {}
old_title = ""
# Function to get feed
def get_feed():
titles = {}
dates = {}
r = urequests.get(feed_address)
item_pattern = '<item>\s*<title>(.*?)</title>.*?</description>\s*<pubDate>(.*?)\+'
pattern = item_pattern + '.*?' + item_pattern + '.*?' + item_pattern
items = re.search(pattern, r.content)
j = 1
for i in range(3):
titles[i] = items.group(j).decode('utf-8')
dates[i] = items.group(j+1).decode('utf-8')
j = j + 2
r.close()
return titles, dates
# We're only using a few colours so we can use a 4 bit/16 colour palette and save RAM!
display = PicoGraphics(display=DISPLAY_INKY_PACK, pen_type=PEN_1BIT, rotate=0)
display.set_backlight(0.5)
display.set_font("bitmap8")
button_a = Button(12)
button_b = Button(13)
button_c = Button(14)
WHITE = 15
BLACK = 0
# sets up a handy function we can call to clear the screen
def clear():
display.set_pen(WHITE)
display.clear()
display.update()
# Display feed item
def display_item(i = 0):
clear() # clear to black
display.set_pen(BLACK) # change the pen colour
display.text(feed_title, 10, 5, 240, 3)
display.line(10, 30, 286, 30) # draw a line beneath the title
display.text('Item ' + str(i + 1) + ': ' + feed_items[1][i], 10, 35, 240, 1) # display the date and item nunber
display.text(feed_items[0][i], 10, 45, 240, 2) # display the title
display.line(10, 115, 286, 115) # draw a line above the instructions
display.text(feed_instructions, 10, 118, 240, 1) # display feed instructions
display.update()
# set up
clear()
feed_items = get_feed()
old_title = feed_items[0][0]
display_item(0)
ftimer = 0
while True:
if ftimer > 600: # update every 10 minutes
feed_items = get_feed()
if feed_items[0][0] != old_title: # feed contains updated items
old_title = feed_items[0][0]
display_item(0)
ftimer = 0
if button_a.read(): # if a button press is detected then...
display_item(0)
elif button_b.read():
display_item(1)
elif button_c.read():
display_item(2)
time.sleep(0.1) # this number is how frequently the Pico checks for button presses
ftimer = ftimer + 1
I’m just learning Python and the Pico, so there are probably better ways of doing some of the above.
It does appear to run out of memory or crash when independently powered, so I’m looking into that. Use the above code at your own risk.
Future Enhancements
Instead of getting three items from a single news feed I’m thinking of using the buttons to switch between three different feeds. More error checking is also required.