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?
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 ) 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.
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):
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.
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.
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.
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.
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.
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