Kindle 4 eink dashboard

I’ve jailbroken my old Kindle 4 non touch so that it shows a lovelace panel. The panel is rendered on a server every minute and the kindle polls it every minute and displays it.

I’ve published of a guide here, if you want to build it yourself: https://github.com/sibbl/hass-lovelace-kindle-4

The device is always powered, but I also set the update frequency to 15 minutes in the past and the battery lasts quite some weeks. Using a CDN and using a different schedule each night extended it to almost one month.

Also, the Kindle 4 NT is quite hard to set up as it has no rtcwake and it’s not straight forward to start scripts after booting. The whole thing might be easier to build with newer Paperwhite models…

11 Likes

Hi sibbl,

Thanks for sharing your project! Looks really nice :slight_smile:

I’m trying to replicate it but I get this log output when running the container in portainer:

> [email protected] start /app
> node index.js
Starting browser...
Adding authentication entry to browser's local storage...
Starting rendering cronjob...
Server is running at 5000
Rendering http://192.168.178.50:8123/lovelace/casa?kiosk to image...
Failed to render TimeoutError: Navigation timeout of 10000 ms exceeded
    at /app/node_modules/puppeteer/lib/cjs/puppeteer/common/LifecycleWatcher.js:106:111
Converting rendered screenshot of http://192.168.178.50:8123/lovelace/casa?kiosk to grayscale png...
(node:17) UnhandledPromiseRejectionWarning: Error: Command failed: convert: unable to open image '/output/screen.png.temp': No such file or directory @ error/blob.c/OpenBlob/3496.
convert: no decode delegate for this image format `TEMP' @ error/constitute.c/ReadImage/562.
convert: no images defined `/output/screen.png' @ error/convert.c/ConvertImageCommand/3273.
    at ChildProcess.onExit (/app/node_modules/gm/lib/command.js:301:17)
    at ChildProcess.emit (events.js:314:20)
    at maybeClose (internal/child_process.js:1022:16)
    at Socket.<anonymous> (internal/child_process.js:444:11)
    at Socket.emit (events.js:314:20)
    at Pipe.<anonymous> (net.js:675:12)
(node:17) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:17) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

My Environment variables are as follows:

ENV
PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NODE_VERSION 12.20.1
YARN_VERSION 1.22.5
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
PUPPETEER_EXECUTABLE_PATH /usr/bin/chromium-browser
USE_IMAGE_MAGICK true
HA_ACCESS_TOKEN eyJ0e…
HA_BASE_URL http://192.168.178.50:8123
HA_SCREENSHOT_URL /lovelace/casa?kiosk
LANGUAGE en
CRON_JOB * * * * *
RENDERING_TIMEOUT 10000
RENDERING_DELAY 0
RENDERING_SCREEN_HEIGHT 800
RENDERING_SCREEN_WIDTH 600
ROTATION 0
SCALING 1
GRAYSCALE_DEPTH 8
OUTPUT_PATH /output/screen.png
PORT 5000

Can you give a me hint what could be going wrong?

Thanks a lot in advance.

It pretty much looks like the Home Assistant view cannot be opened within 10 seconds.

I’d recommend increasing RENDERING_TIMEOUT to i.e. 30000 (=30 sec) to give it more time.

1 Like

Thanks for your reply, I actually managed to make it work exactly as you suggest.

I’m not running Homeassistant in a docker environment but instead the easy install method using Hass OS. So in order to install your rendering software I have used the portainer add-on in homeassistant and successfully made it run - I see the png file gets created in the container. Now the issue is accessing it. I know I need to create a Volume in order to access the data inside the container. But at which URL is it than available? Can you post as an example which URL you use in your kindle?

The docker container exposes a single HTTP port. Any GET request to it will return the image.

So if your HA has the IP “192.168.0.100” and you’ve mapped the container’s port to 5000 (which is the default port) via portainer, then it’s available at http://192.168.0.100:5000 :wink:

Thanks, I ended up understanding what to do and it runs now. Since I can’t use docker compose in my setup, all those steps have to be done “by hand”.

Since my Wlan is automatically off for some hours every night I realized the Kindle actually doesn’t manage to reconnect once the Wlan is available again. After searching a bit, I tried the following solution and it seems to work:

script.sh

wait_wlan() {
    $(/usr/bin/wpa_cli -i wlan0 reconnect)
    return $(lipc-get-prop com.lab126.wifid cmState | grep CONNECTED | wc -l)
}

Thanks for your response and the code snipped.

The code was supposed to call this reconnect command after failing to get wifi for 5 times (which means a delay of 5+4+3+2+1 = 15 seconds): see the code.

However there was a small bug in the utils.sh which was recently fixed by this PR. It caused the script to never go into this if condition and call the reconnect command.

So anyone who has the same problems: the code in the GitHub repo should be in a better state by now :slight_smile:

Every now and then the tool stops working with this output:

Rendering http://192.168.178.50:8123/lovelace-kindle/0?kiosk to image...
Converting rendered screenshot of http://192.168.178.50:8123/lovelace-kindle/0?kiosk to grayscale png...
Finished http://192.168.178.50:8123/lovelace-kindle/0?kiosk
> [email protected] start /app
> node index.js
Starting browser...
Adding authentication entry to browser's local storage...
(node:18) UnhandledPromiseRejectionWarning: Error: net::ERR_CONNECTION_REFUSED at http://192.168.178.50:8123
at navigate (/app/node_modules/puppeteer/lib/cjs/puppeteer/common/FrameManager.js:115:23)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async FrameManager.navigateFrame (/app/node_modules/puppeteer/lib/cjs/puppeteer/common/FrameManager.js:90:21)
at async Frame.goto (/app/node_modules/puppeteer/lib/cjs/puppeteer/common/FrameManager.js:417:16)
at async Page.goto (/app/node_modules/puppeteer/lib/cjs/puppeteer/common/Page.js:784:16)
at async /app/index.js:31:3
(node:18) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:18) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Once again, can you give a me hint what could be going wrong?

Thanks a lot in advance.

This indicates that the machine (or Docker container) cannot reach 192.168.178.50. Hard to tell what’s the exact problem without knowing your (network) setup.

@sibbl I got this same error as above mentioned and the fix with RENDERING_TIMEOUT=30000 works, maybe add this to a new FAQ section on your github page.