- Published on
E-ink domotics dashboard using Home Assistant, puppet and FBInk on a Kobo Clara
- Authors

- Name
- Peter Peerdeman
- @peterpeerdeman
An always-on dashboard in the house has been on my wishlist for quite a while. Somehow, I never really went for it before. Recently I saw a live PV / Grid consume / Grid delivery panel at a friends house, and with the recent pv solar wifi stick mod in place, it was about time for a first prototype of this solution.
as I don't want another device emitting light drawing our gaze and messing with our natural sleep rhythm, the solution had to be E-ink. There are some off the shelf products available, such as the proprietary TRMNL and the diy Inkplate, but I had a Kobo e-reader that is seeing some idle time recently, and that turned out to be a perfectly capable platform for the first prototype.

screenshots instead of a browser
The lazy plan would be to point the Kobo's built-in browser at a home assistant dashboard in a sort of kiosk mode and call it a day. Unfortunately, that does not work as the experimental browser cant run the home assistant dashboard without javascript.
The approach that some had used online is to take screenshots with a headless browser, and render the images to the Kobo screen.
For this rendering I use balloob's puppet add-on, a headless Chrome that screenshots any home assistant view. Home Assistant was already running in a docker-compose, so we only had to add the extra container. Requesting a URL and get a grayscale PNG back:
http://<puppet-host>:10000/<token>/kobo-dashboard/0?viewport=1448x1072&zoom=1.76
rooting and rendering on the kobo
The Kobo needed three pieces to work:
- KFMon -> inserting a launcher button to run your own scripts
- FBInk -> drawing a PNG straight to the e-ink framebuffer
- a bash script that fetches the image from puppet and draws it with FBInk
kfmon
The documentation and the forum thread about this are all over the place. In the end, i used the one click kobo install packages to get KOreader started, from which you can enable a SSH server to get a root shell on the device.
To turn the reader into a dashboard the script kills nickel, the Kobo UI, and also hindenburg, the watchdog that otherwise brings nickel back a minute later.
fbink
FBInk is the app that is used to draw to the screen. The version of FBInk is important here, the latest release on github (1.25.0 from 2022) does not support the latest kobo devices, while the latest master branch does. To get one of the latest compiled versions, you can peek into the fbink workflows and grab a binary from one of the recent builds there, and install it to the kobo via SSH.
the script
The launcher script got tweaked a couple of times, starting off as a simple drawing to the screen loop and ending up with a couple of extra features:
- I tried finding a balance between a nice refresh time to make it feel real-time, but not draw too much power. Achieved through faster refresh rate during breakfast time and dinner time
- deghost, by only clearing the screen every x refreshes
- adding SSH dropbear to provide a way back in without resetting the device
- adding support for refresh and reboot commands via writing files through ssh
#!/bin/sh
# ---------- config ----------
BASE_URL="http://puppetserver:10000/kobo-dashboard/0"
QUERY="viewport=1448x1072&colors=000000%2C242424%2C494949%2C6D6D6D%2C929292%2CB6B6B6%2CDBDBDB%2CFFFFFF&lang=en&rotate=90&zoom=1.76&wait=5000"
URL="${BASE_URL}?${QUERY}"
FBINK=fbink # full-path it if KFMon can't find it on PATH
IMG=/tmp/dash.png
CTRL=/mnt/onboard/.dash # drop control files here
INTERVAL_NORMAL=120 # seconds between refreshes (normal)
INTERVAL_MORNING=30 # seconds between refreshes in the morning window
MORNING_START=6 # 06:00
MORNING_END=10 # up to (not incl.) 10:00
TICK=5 # how often to check control files, seconds
DEGHOST_EVERY=10 # do a full flashing refresh every Nth draw
# ----------------------------
mkdir -p "$CTRL"
# take over the screen (kill UI + the watchdog that respawns it)
killall -q -TERM nickel hindenburg sickel fickel 2>/dev/null
# guarantee an SSH way back in; dropbear survives nickel being gone.
pidof dropbear >/dev/null 2>&1 || dropbear -R >/dev/null 2>&1 &
# draw [flash]
# no arg -> fast, no-flash update (no flicker, but ghosts over time)
# "flash" -> full flashing refresh (brief flash, clears ghosting)
draw() {
wget -q -O "$IMG" "$URL" || return 1
if [ "$1" = "flash" ]; then
"$FBINK" -q -f -g file="$IMG"
else
"$FBINK" -q -g file="$IMG"
fi
}
count=0
draw flash # clean first paint
while true; do
H=$(date +%H); H=${H#0} # strip leading zero to avoid octal (08/09)
if [ "${H:-0}" -ge "$MORNING_START" ] && [ "${H:-0}" -lt "$MORNING_END" ]; then
INTERVAL=$INTERVAL_MORNING
else
INTERVAL=$INTERVAL_NORMAL
fi
# wait out the interval in small ticks so control files act within ~5s
waited=0
forced=0
while [ "$waited" -lt "$INTERVAL" ]; do
[ -f "$CTRL/reboot" ] && { rm -f "$CTRL/reboot"; reboot; }
[ -f "$CTRL/refresh" ] && { rm -f "$CTRL/refresh"; forced=1; break; }
sleep "$TICK"
waited=$((waited + TICK))
done
# flash on a manual refresh or every DEGHOST_EVERY draws; otherwise silent
count=$((count + 1))
if [ "$forced" -eq 1 ] || [ "$count" -ge "$DEGHOST_EVERY" ]; then
draw flash
count=0
else
draw
fi
done
Now the fun part began, which was deciding which widgets to show on the screen. I found the markdown tile very useful to print data in a little bigger font, and avoided to customise the styling of the tiles. The historic bar charts and line charts render quite well, and using emoji's helps to create some visual support between all of the stats.
Putting the kobo in landscape mode on an ikea tablet stand, and wiring it to a big 20.000mA battery pack makes it a nice portable prototype to experience live stats from the dinner table. Maybe we will bolt it to the wall at some point, but let's see if we still enjoy the stats after a couple weeks first.