simon-dreher.de

Probably in every nerdy household, old hardware lies in drawers and gathers dust. Since getting a Tolino ebook reader, this also happened to my old Kindle. EInk displays are actually quite nice to display information without too much energy consumption and are easy to read even in bright light. So why not recycle the Kindle and use it to display useful information in the hallway?

There are already some similar projects:

Jailbreaking the Kindle

The first step on my journey was to get some more access to the Kindle than just downloading ebooks and opening them.

Luckily there are several tutorials for jailbreaking. As I had a Kindle 4, I could follow the instructions in mobileread wiki, a pretty nice gist and a blogpost on Kindle jailbreak. They all cover more or less the same steps, but it helped me to read multiple of them to make some things clearer to me. For example I skipped to execute the installer of USBNetwork before editing etc files. If you have another model, you will need to use a different jailbreak.

After this you can add your public ssh key and can ssh into your Kindle the same as every other linux machine.

Proof of concept

Before diving into technical implementation, I tried out available tools on the Kindle and what could be sensibly fit onto the screen.

The screen uses a resolution of 600x800px, so the first prototype was just some SVG of that size that I did with inkscape. Then converted this to a PNG with the required color mode:

inkscape display.svg -o display.png --export-png-color-mode=Gray_8 --export-background=ffffffff

To display this on the Kindle I scped it and drew it using eips -g display.png. (The mobileread wiki also has documentation on eips)

Proof of concept with some ideas

Running Go on Kindle

The biggest technical challenge was to get a Go binary running on the Kindle.

The other similar projects (metnioned in introduction) used a server component to generate the image and then only download and display the image on the Kindle. I didn't want to maintain another service and additionally I want to keep me the option to also fetch data from the local network.

Cross-compiling for the Kindle was pretty easy: env GOOS=linux GOARCH=arm GOARM=5 go build. However I then ran into the problem that the binary always panicked with runtime: epollwait on fd 3 failed with 38. I first thought, this would be related to my network calls, but it even happened with code that just contained sleeps. Apparently Gos garbage collector or something was the issue, as Go requires a Linux kernel >= 2.6.32 since Go 1.18. You already guessed it: the Kindle uses a kernel version of 2.6.31. So close ...

The solution is simply to use Go 1.17. It doesn't suffice to just set the toolchain in go.mod to 1.17, also the go build needs to be of that version. I used docker/podman to do this:

podman run --rm -v "${PWD}":/app -it docker.io/golang:1.17.13 bash -c "cd /app &&  env GOOS=linux GOARCH=arm GOARM=5 go build"

As Go has an image module in the standard module, I just used that to write a PNG and display it with eips.

Tadaa: we can run a single binary and it paints to the display. Now what should we show there?

Modules

Did separate "modules" that you can theoretically extend and combine as you like.

Weather

The very first idea was to display the current weather and weather forecast. It turns out that the german "Deutsche Wetterdienst" has a public API under https://dwd.api.bund.dev. The documentation could be better, but with comparing to what is shown in the app, you can determine the units (mostly tenth of normal units, e.g. 0.1°C or 0.1mm).

Most difficulties I had with finding the station ID. In the end using the mosmix list and trying to find the nearest city was working best for me. The API then returns current values or forecasts (and maxints for past values), depending on the type of the station. I think the stations from the mosmix list all return forecasts, but not sure. The app also shows values like wind over time, which is not returned in this API.

Apart from showing the numbers, I also had fun to visualize the weather using a penguin. Depending on rain, sun and temperature he wears a scarf, sunglasses, carries an umbrella etc. Implementation wasn't actually that complicated: in a SVG I drew the penguin and its accessoires in multiple layers. Every layer is then exported to one PNG each and simply printed over each other if e.g. it is cold.

The diagram will probably be extended to also have sunrise and sunset as well as wind.

Tram departures

The trams in Karlsruhe are operated by KVV and luckily they do have a public API. In fact they don't have one API: they have several. The most comfortable KVV API was shut down, but in the thread another API under https://projekte.kvv-efa.de is mentioned. To find the station ID you can use

https://www.kvv.de/tunnelEfaDirect.php?action=XSLT_STOPFINDER_REQUEST&coordOutputFormat=WGS84[dd.ddddd]&name_sf=Karlsruhe%20Europaplatz&language=de&outputFormat=JSON&type_sf=stop

(replacing Karlsruhe%20Europaplatz with your station name). The same APIs are used by github.com/harbaum/kvv, which uses an Arduino to show departures on an epaper display.

Word clock

Also wanted to show the current time and to make it a bit more interesting, it describes the time like "just before quarter past eight".

Further ideas

There are a lot of further ideas:

Run

To run the binary every minute, I currently simply use cron as described by Matt Healy.

mntroot rw
cp display /mnt/us/display
nano /etc/crontab/root
* * * * * /mnt/us/display
/etc/init.d/cron restart

In the future, I would like to do that more sophisticated, e.g. to not poll the weather API every minute.

Frame

The info dashboard also should get a nice frame and of course a place where it can be seen.

Using a normal picture frame is tricky, as the screen is 9x12.2cm and fotos are normally 9x13cm. So all normal foto frames and passepartouts are too high and at the same time a bit tight when using the USB jack. Also with the Kindle border and buttons there is quite some gap between the screen and frame. I think I'll try to print a passepartout with cutouts for the buttons. But I first need to model it and have it printed by some colleague or so. Will update this article when I've done that.

Finish

The code was published to github.com/Semoar/display. Feel free to open issues there. Or contact me as usual :)

The finished info dashboard Kindle without frame