Skip to content

Transforming my old Kindle DX into a smart(ish) e-ink clock

License

Notifications You must be signed in to change notification settings

quelcom/homeink

Repository files navigation

Homeink

Transforming my old Kindle DX into a smart(ish) e-ink clock 🕙

Homeink v1

Intro

Back in 2010 I bought an Amazon Kindle DX, thinking that the large screen would be ideal for reading technical books in PDF format. Even though reading such books was doable overall, it required few compromises. In some cases, PDF books required a bit of preprocessing in order to crop empty margins. Despite that, PDFs with condensed charts or images were still difficult to interpret, and the zooming and navigation capabilities of the device were a bit underwhelming, especially with heavy files. In the end, I used the Kindle DX for reading mostly sci-fi books, and for that it was perfect. Especially when I learned how to hack the device and install KOReader. That lasted for years until the battery started to give up due to its age. In 2021 I bought a Kobo Libra 2 and the Kindle went right into a drawer. I refused the idea of considering the Kindle e-waste and that I should just get rid of it, so it went to a drawer waiting for a new opportunity.

And the opportunity came: I was looking to buy a large (around 10" or 12") display in order to display a Home Assistant dashboard and I suddenly remembered I still had my old Kindle. The major blocker is that the Kindle DX does not have any ethernet or wi-fi connectivity (only networking available is the built-in 3G radio for Amazon Whispernet, which has been defunct for years). On the other hand, a Raspberry Pi Zero 2 W has all the networking I need and is tiny. Considering I already hacked the Kindle back in the days, I started to explore the idea of coupling them and see if I could control the Kindle display from the Pi Zero.

Preparations

Kindle

I installed the latest version of the USBNetwork hack from this post in Mobileread. Installation is straight-forward, just following the instractions and making sure I am getting the correct .bin file for the DX model.

I also installed FBInk to control the e-ink display, which is a great alternative to the default eips command.

Pi Zero

I installed DietPi because I had an unused 2 GB micro SD card and I didn't want to buy a new one. I roll with the defaults, but I added a new network interface in order to being able to SSH to the Kindle over RNDIS:

dietpi@DietPi:~$ cat /etc/network/interfaces.d/usb0
auto usb0
iface usb0 inet static
address 192.168.2.1
netmask 255.255.255.0

I also adjusted the cpu governor to powersave and few tweaks here and there, but nothing important other than adding the new network interface.

Frame

I bought a 3d picture frame that was big enough to hold the kindle and handcrafted a passepartout with thick cardstock paper to hide the Kindle frame and keyboard. I secured the Pi Zero with kapton tape, drilled some holes in the back for ventilation and added a bit of foam to make sure the Kindle does not move inside the frame.

Inside the frame

Homeink inside

Back cover

Homeink back cover

Software

Homeink

The main software is called Homeink and is a Go application that gets installed in the Pi Zero device. In a nutshell:

  • It provides a small wrapper to the FBInk tool, and it runs fbink commands over SSH thanks to the goph library.
  • It is also a small HTTP server that currently exposes two endpoints available in the local network. At the moment there are two endpoints:
    • /api/v1/screenshot that accepts an image to be rendered in the display. Used to render local weather forecasts from Supersää.
    • /api/v1/water, that is used to show the daily water consumption in our home.

The HTTP server also exposes a Swagger UI under /swagger/index.html, which is useful to test the endpoints, especially the screenshot endpoint because it is a multipart request.

Oh, and of course it shows the current time! 😅

Also it shows the cpu temperature of the Pi Zero, which is something I want to keep an eye as the Zero is confined in a tight place. In the future, I might end up using Telegram bot notifications instead.

Supersää screenshots

Code is under the docker-supersaa-screenshots directory. It is a separated Go application, but it lives in the same repository for simplicity. The application uses chromedp to periodically take screenshots of specific components of Supersää, it converts the screenshots to 16-bit grayscale (which is what the Kindle DX display can handle) and calls the /api/v1/screenshot from Homeink. There is a very rudimentary caching in place, so I do not need to send and re-render the same images over and over again, albeit the hourly forecast are updated several times per hour.

Chromedp and the Go application are bundled into a single docker image, and the container runs on my home server within my home network. My main motivation was to reduce as much as possible the processing work required by the Pi Zero.

Water usage

Not exactly an application, but listing here for documenting purposes. At home I monitor our water consumption with a great ESPHome device from smart-stuff.nl. I am not extremely interested in tracking the liters or cost, but with two young kids I wanted to have Home Assistant automations that would warn me if the water consumption goes above some thresholds based on our usual water usage patterns (more than 30 liters in the last 15 minutes, more than 60 liters in the last hour, etc).

In Home Assistant, I use the RESTFul Command integration and created two services in configuration.yaml, one for the Pi Zero device and another for my local computer for testing:

[core-ssh ~]$ cat homeassistant/configuration.yaml
...
rest_command:
  liters_request_dev:
    url: http://dietpi.lan:3000/api/v1/water
    method: POST
    headers:
      accept: "application/json"
    payload: '{"liters": {{ liters_placeholder }}}'
  liters_request:
    url: http://mbm3pro.lan:3000/api/v1/water
    method: POST
    headers:
      accept: "application/json"
    payload: '{"liters": {{ liters_placeholder }}}'

Then I added a new automation that is triggered every two minutes, but it only calls the /api/v1/water endpoint if the water sensor has been recently updated:

[core-ssh automations]$ cat water_report_kindle.yaml
- alias: Water report to kindle
  trigger:
      - platform: time_pattern
        minutes: "/2"
  condition:
    - condition: template
      value_template: '{{ as_timestamp(now()) - as_timestamp(states.sensor.watermeter_daily.last_updated) < 150 }}'
  action:
    - service: rest_command.liters_request
      data:
        liters_placeholder: >-
          {{ states('sensor.watermeter_daily')|int }}

Future

Besides monitoring/visualizing the Homeink endpoint calls in my local Grafana, there is screen space still available in bottom-right which I am planning to use it for more Home Assistant stuff: doors being opened, showing the temperature of different rooms, etc.

Considering how invested I am with Home Assistant already, another possibility is to crreate 16-bit grayscale screenshots of a custom dashboard, and render it every minute.

About

Transforming my old Kindle DX into a smart(ish) e-ink clock

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published