Home Assistant dashboard on Kindle

Hi folks,

I want to use an old Kindle to display a HA dashboard, similar to this, but with arbitrary data from HA. I do not want to click anything, I just want to show the status.

The general idea:

  • I configure a HA dashboard with the elements I want to have
  • using puppeteer I render the web page and save it to a png file.
  • Node.js serves the png file via HTTP.
  • the Kindle downloads the png file using kite and shows it as screen saver.

My problem right now is authenticating on the Web interface using puppeteer. It looks like the bearer tokens only work for the REST API and logging in via username/password does not work, as puppeteer does not support filling in forms with shadow root elements.

Any ideas on taking automatic screenshots from the Web UI and saving them to png files?
Or on bypassing the HA authentication screen?

Best,
Christian

Hi, here you have another aproximations: (Very) Basic Homeassistant dashboard for E-ink devices and Kiosk apps

And if you like to capture web into PNG you can use Selenium library, some example: https://pythonspot.com/selenium-take-screenshot/

But my approximation to Kindle (4th generation, near 2011/2012) device used during last 3 years or more.
My approximation was use the “especial browser” inside Kindle. And small python script (outside of Kindle :smile: ) doing the function of web server (the authentication was done here), but I had next problems:

  • I’m created a web template filled with data from HA. The data needs to refresh, and you can only use pure javascript, not another libs (like JQuery).
  • If you always are refreshing webpage (every 1 minute for example), you drain your battery. For this refreshing time, you can “slow” down the time refresh, if you are not in home or during night.
  • Some encoding are not allow for use.
  • You need to take care to not allow to access all your devices, or only like a viewer (not allow any action or only a few).

And with this problems, (and continuous powered device) still running. Hope this helps.

Another ideas are welcome. :smiley:

Hey @ChristianKuehnel,

I just bought a $20 kindle paperwhite and also want to make a visual home assistant dashboard. It seems like there are a lot of old projects all based on the idea of having a server generate an image and using a kindle jailbreak tweak to display this image on the device as a screensaver.

My device isn’t here yet, but I think these are the most promising options (that both require a jailbroken device):

  1. This is the most recently updated project that mentions using the long lived token in home assistant and not the old depreciated API password. Unfortunately, it is just a docker container. It’d love to see someone (maybe I’ll try and take this action item on after I get my device) and convert this to a home assistant addon so users could easily add it to their instance. Also the docker container is just hosting a react website, so it might be easy to add additional sensors on the image.
  1. This project doesn’t interact with home assistant but is a standalone weather dashboard:
    https://github.com/x-magic/kindle-weather-stand-alone

Let me know which options you’ve explored!

1 Like

This all sounds overly complicated and inflexible.
You could try a waveshare 7.5“ e-ink display that comes with an esp32 capable of running esphome. There you can use all your home assistant sensors and display whatever you want.

I agree that it does seem overly complicated. I’ve currently got a Kindle Paperwhite 1 running an AppDaemons Dashboard via Alpine Linux and it seems to be very responsive, updates quick and loads the dashboard in a webbrowser requiring no image capturing fun at all. I’ve written up my complete (painful) journey here https://thomaspreece.com/blog/2019/12/10/home-assistant-kindle-dashboard/ which should point you in the right direction to get a Alpine running on the PW1/PW2 and a suitable AppDaemon dashboard to go along with it. Just a shame the in build browser on the Kindle sucks and doesn’t support long connections.

2 Likes

Thanks for mentioning my project :slight_smile:

My two cents on your feedback:

  1. I’ve also explored creating a HA addon. However, having a Puppeteer Chrome instance running the whole time on slower machines like the Raspberry Pi just makes no sense, I’m afraid.
  2. There’s a newer project which renders a Lovelace panel instead of a custom React page, which makes it way more customizable:
  3. Based on this new container, I’ve also built a Kindle 4 photo frame, which I’ve posted here
1 Like

All,

I try to tun the container in portainer. Its starts, but gives the following log

,
> [email protected] start /app,
> node index.js,
,
Starting browser...,
Adding authentication entry to browser's local storage...,
(node:25) UnhandledPromiseRejectionWarning: Error: net::ERR_SSL_PROTOCOL_ERROR at https://10.0.10.8: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:25) 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:25) [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.,

I can log into the docker and there is no file in the output directory.

These are my ENV variables

HA_BASE_URL https://10.0.10.8:8123
HA_SCREENSHOT_URL /lovelace?kiosk
HA_ACCESS_TOKEN eyJ0eXAiO…
CRON_JOB * * * * *
RENDERING_TIMEOUT 30000
RENDERING_DELAY 5
RENDERING_SCREEN_HEIGHT 800
RENDERING_SCREEN_WIDTH 600
GRAYSCALE_DEPTH 8
OUTPUT_PATH /output/cover.png
LANGUAGE de
ROTATION 0
SCALING 1
PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NODE_VERSION 12.20.0
YARN_VERSION 1.22.5
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
PUPPETEER_EXECUTABLE_PATH /usr/bin/chromium-browser
USE_IMAGE_MAGICK true

I would appretiate some help in trouble shooting ,-). Thanks

Found it. HTTP instead of HTTPS worked like a charm.

Can you run this project if you do not have containers?

Unfortunately not at the current state. Generally, each hass.io addon runs in a container so using the current Nodejs base app, a new hassio addon could be created. However, this is still an open issue.

2 Likes

Thanks!

I am just after the function of getting an automated print screen of a HA dashboard, would that be hard to build myself? I also have a synology NAS.

Lol, I spent like 8 hours to make onlinescreensaver working on K4 just to find that I am unable to install your docker add-on (because i don’t have containers). I will check out now and then to see if there is any update. Thanks anyway for your work

as always, i’m late for the party.
Here is my working pupeteer script.
if you normally have SSL errors because for example you use the IP instead of the URL set ignoreHTTPSErrors to true.

const puppeteer = require('puppeteer');

// either change the settings here or run node with variables e.g. 
// login_page="https://homeassistant.underknowledge.cc/" login_username="root" login_password="un52SDvVfVOscyRVKi0D46p4NPbd8GXrDXFtHSd" node ha_test.js
const login_page = process.env.login_page || "https://homeassistant.underknowledge.cc/";
const login_username = process.env.login_username || "root";
const login_password = process.env.login_password || "un52SDvVfVOscyRVKi0D46p4NPbd8GXrDXFtHSd";


function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

(async () => {
  const browser = await puppeteer.launch({
  headless: false,
  defaultViewport:{width:1366,height:768},
  ignoreHTTPSErrors: false,
  });
  const page = await browser.newPage();
  await page.goto(login_page, { waitUntil: 'networkidle0' });

  // find shadow elements by js selector
  const username = await page.evaluateHandle(`document.querySelector("body > div > ha-authorize").shadowRoot.querySelector("ha-auth-flow").shadowRoot.querySelector("form > ha-form").shadowRoot.querySelector("div > ha-form-string:nth-child(1)").shadowRoot.querySelector("mwc-textfield").shadowRoot.querySelector("label > input")`);
  await username.type(login_username);

  const password = await page.evaluateHandle(`document.querySelector("body > div > ha-authorize").shadowRoot.querySelector("ha-auth-flow").shadowRoot.querySelector("form > ha-form").shadowRoot.querySelector("div > ha-form-string:nth-child(2)").shadowRoot.querySelector("mwc-textfield").shadowRoot.querySelector("label > input")`);
  await password.type(login_password);

  const loginHandle = await page.evaluateHandle(`document.querySelector("body > div > ha-authorize").shadowRoot.querySelector("ha-auth-flow").shadowRoot.querySelector("form > div > mwc-button")`);
  await loginHandle.click();
  
  await sleep(1000); // my lovelace has to load a lot of pictures

  const sidebarHandle = await page.evaluateHandle(`document.querySelector("body > home-assistant").shadowRoot.querySelector("home-assistant-main").shadowRoot.querySelector("#drawer > ha-sidebar").shadowRoot.querySelector("div.menu > ha-icon-button").shadowRoot.querySelector("mwc-icon-button > ha-svg-icon")`);
  await sidebarHandle.click();
  await sleep(4500); // I guess the page resize does not render this fast
  // 
  // fullscreen screenshot, see https://pptr.dev/#?product=Puppeteer&version=v13.0.1&show=api-pagescreenshotoptions for further options
  screenshot = await page.screenshot({path: 'home_assistant.png', fullPage: true});

//   // partial, play around yourself dont ignore the const browser settings above
//   await page.screenshot({
//     path: 'home_assistant.jpg',
//     type: 'jpeg',
//     quality: 80,
//     clip: { x: 60, y: 145, width: 1010, height: 1150 }
//     });

  await browser.close();
})();

Now I want to learn how I can write an add-on to have pupeteer right with HA


Edit:

2 Likes