In this blog post, I will share a project that I worked on during the X-mas break. The project involves a Raspberry Pi, an e-ink display, the SAP Community RSS (Really Simple Syndication) feed (https://blogs.sap.com/feed/), some python 🐍, and even a 3D printer.

SAP Community blog posts feed in e-ink display
I personally love RSS. For me, there isn't a better way to be informed of what's going on on my preferred websites/blogs than by reading the RSS entries on my favourite feed reader -
Miniflux (of course
self-hosted :-).
RSS (RDF Site Summary or Really Simple Syndication) is a web feed that allows users and applications to access updates to websites in a standardized, computer-readable format. Subscribing to RSS feeds can allow a user to keep track of many different websites in a single news aggregator, which constantly monitor sites for new content, removing the need for the user to manually check them. Source: Wikipedia.
I remember fondly the days when every single website published an RSS feed and it was simple to subscribe to them.
Google Reader was the most popular feed reader at that time until big G decided
to kill the product. A sad day, if you ask me. Unfortunately, RSS lost some momentum when this happened and its adoption slowed down significantly. That said, there are still many websites that publish an RSS feed. In some websites, you'll find a link/icon to the RSS feed visible in the UI but I would say that most have it somewhat hidden/not that accessible. I found myself going to the source of the web page (
Right click > Web Page source) to find a link to the RSS feed. You'll normally find it in the head section of the HTML.

SAP Community - RSS feed link
As you can imagine, I'm subscribed to the SAP Community blogs section RSS feed. This is to learn from what other members of the community share/write about. Now, whenever I want to know what's happening in SAP Community, I go to my feed reader and select the SAP Community feed and I can see all the blog posts published since the last time I checked my feed.
There is a lot going on in SAP Community and it is possible to filter your feed by you favourite tag, e.g. SAP Buiness Technology Platform - https://content.services.sap.com/feed?type=blogpost&tags=8077228b-f0b1-4176-ad1b-61a78d61a847&title=.... To get a topic feed go to to https://blogs.sap.com, select a tag you are interested and copy the link from the RSS link that's in the header.
I'm able to read the entries on Miniflux but I was thinking if there was a way to consume the feed in a passive way and not have to go and check a website. Enter an e-ink display.
e-ink display

Prototype - Raspberry Pi inside the cardboard box
I do most of my reading on an e-ink device (Kindle). I've had a couple and have always enjoy the experience of reading on an e-ink display. Unfortunately, there is no SDK for the device so it is not possible to create an app/program to extend its capabilities. That said, I've always wanted to play with an e-ink display but I just never had a nice little project to justify buying one.
Given my new "want" to check the feed in a passive way, I thought it will be cool to use an e-ink display to keep me informed of what's going on in SAP Community. Obviously, some coding is required to display something on the display which add to the fun of the project.
The e-ink display that I got for my project is a Waveshare -
7.5inch E-Paper E-Ink Display Module (B) for Raspberry Pi Pico, 800×480, Red / Black / White. Its size is similar to a photo frame, so it will easily be on my desk (yes, I also have a photo of my family on my desk
❤️). Waveshare has a library that allows you to interact with the display from different programming languages. This is available on their public repo,
waveshare / e-Paper, and it contains many examples of how you can use the display. Let's look at some code now.
Script
After testing the display and making sure I was able to communicate with the display from the Raspberry Pi, I developed a python script that gets the SAP Community blogs feed and shows the latest entries on the display. The display will only refresh if there is a new entry. If there aren't new entries there's no need to refresh what's on display.
I refer to the script below as the
skills script. Any new functionality I want to add to the program, e.g. display a dashboard, the status of a device, a quote, a message, etc., will be a new "skill" in the script, which can be triggered on demand if needed.
import logging
import os
import sys
import textwrap
from PIL import Image, ImageDraw, ImageFont
import epaper
import feedparser
PIC_DIR = os.path.join(os.getcwd(), 'pic')
FONTS_DIR = os.path.join(os.getcwd(), 'fonts')
LIB_DIR = os.path.join(os.getcwd(), 'lib')
if os.path.exists(LIB_DIR):
sys.path.append(LIB_DIR)
logging.basicConfig(level=logging.DEBUG)
# e-Paper instance
epd = epaper.epaper('epd7in5b_V2').EPD()
# e-Paper dimensions
EPAPER_WIDTH = epd.width
EPAPER_HEIGHT = epd.height
LAST_FEED_ITEM = ""
def poll_sap_community_rss():
black_image = Image.open(os.path.join(PIC_DIR, 'sap-community-classic.png'))
red_image = Image.new('1', (EPAPER_WIDTH, EPAPER_HEIGHT), 255)
font_title = ImageFont.truetype(
os.path.join(FONTS_DIR, 'BentonSans-Bold.ttf'), 18)
font_additional_text = ImageFont.truetype(
os.path.join(FONTS_DIR, 'BentonSans-RegularItalic.ttf'), 14)
draw_black = ImageDraw.Draw(black_image)
draw_red = ImageDraw.Draw(red_image)
blogs_url = "https://blogs.sap.com/feed/"
parsed_feed = feedparser.parse(blogs_url)
# Position where text rendering will start
y = 100
global LAST_FEED_ITEM
# Check that there are new feeds
if parsed_feed.entries[0].id != LAST_FEED_ITEM:
LAST_FEED_ITEM = parsed_feed.entries[0].id
for entry in parsed_feed.entries:
print(entry.title)
draw_black.text((20, y), entry.title, font=font_title, fill=0)
draw_red.text((EPAPER_WIDTH - 160, y + 25), entry.category,
font=font_additional_text, align='right', fill=0)
draw_black.text((20, y + 25), entry.author,
font=font_additional_text, fill=0)
y += 60
if y > 440:
break
black_image.save("Sample.png")
logging.debug("EPD init")
epd.init()
logging.info("Render RSS details")
epd.display(epd.getbuffer(black_image), epd.getbuffer(red_image))
logging.debug("EPD sleep")
epd.sleep()
def init_screen():
logging.info("Initialising...")
logging.info("init")
epd.init()
logging.info("clear")
epd.Clear()
Of course, I wasn't satisfied with just having a program running and displaying the latest feed entries. I want to be able to show different things on the display, at different times of the day..... enter APScheduler and its API
🙂
Flask and the Advanced Python Scheduler (APScheduler)
With
APScheduler I'm able to schedule different tasks on my program. In my case, checking for new feed entries in the SAP Community blogs feed happens every 5 minutes. The API is provided by the
Flask-APScheduler package.
Via the API I can control the scheduler, e.g. start/stop jobs, trigger functionality on demand, etc.
Having an API and a scheduler gives the device a lot of flexibility. Meaning, I can use it for a lot of different purposes,e.g. display an inspirational quote, show me how I'm doing on my habit tracker at a particular point in time or enable it so that my family can send me an important message straight to the display.
#!/usr/bin/env python3
import time
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from flask import Flask
from flask_apscheduler import APScheduler
from skills import init_screen, poll_sap_community_rss
class Config:
"""App configuration."""
JOBS = [
{
"id": "sap_community_rss",
"func": "skills:poll_sap_community_rss",
"trigger": "interval",
"replace_existing": True,
"seconds": 300
}
]
SCHEDULER_JOBSTORES = {
"default": SQLAlchemyJobStore(url="sqlite:///jobs.db")}
SCHEDULER_EXECUTORS = {"default": {
"type": "threadpool", "max_workers": 20}}
SCHEDULER_JOB_DEFAULTS = {"coalesce": False, "max_instances": 3}
SCHEDULER_API_ENABLED = True
if __name__ == "__main__":
app = Flask(__name__)
app.config.from_object(Config())
scheduler = APScheduler()
scheduler.init_app(app)
print("Init screen")
init_screen()
time.sleep(1)
print("SAP Community RSS")
poll_sap_community_rss()
time.sleep(5)
# Start scheduler
scheduler.start()
app.run(host="0.0.0.0")
Running as a service
It is likely that I will need to unplug the Raspberry Pi but whenever I turn it on again I want my program to refresh the display with new data. For this, I created a simple service that will start whenever the Raspberry Pi reboots. See the sample
e-ink-display.service below.
[Unit]
Description=e-Ink Display
After=multi-user.target
[Service]
WorkingDirectory=/home/pi/repos/github.com/sap-community-e-ink-rss/
ExecStart=/usr/bin/python3 /home/pi/repos/github.com/sap-community-e-ink-rss/scheduler.py
User=pi
[Install]
WantedBy=multi-user.target
For more details on how do create a service like the one above in a Raspberry Pi, check out this blog post - How to create a systemd service in Linux.
3D printing
Ok, so I got an e-ink display working, the code is running fine but, as shown in the "prototype" photo above, the Raspberry Pi is in a cardboard box and nothing protects the delicate e-ink display. I wanted a case for it so that it will look nice on my desk but there is nothing available to purchase online. Fortunately, there is a massive 3D printing community and I was able to find a
"thing" in
Thingiverse that could help get me started with the case needed for this project.
I don't have a 3D printer, at least not yet, but I do know someone who has one (Thanks
Pablo!). He was kind enough to help with some adjustments required in the STL (
Standard
Triangle
Language) as the original design is for an LCD display, which has different dimensions, and the e-ink display is a bit thinner and smaller.
If you are into 3D printing, stop motion or playmobil, I highly recommend checking out Pablo's posts.
After a few hours of 3D printing, sanding down some screws, and a bit of glue.... Check out how the case with the display and Raspberry Pi looks like in the photos below.
I think the device looks amazing on my desk. I'm now able to passively read what's going on in SAP Community by just checking out the display. It's what's normally on the display but I also have some other "skills" that display information on it.

3D printed frame on my desk
I'm quite happy with the current state of this little project. The display now sits next to my home office display and I'm able to passively know if there is something happening in the SAP Community. Let me know what you think of the project in the comments below and please share some ideas with me on other cool skills that I can code on this thing. Thanks for reading!