learnings, nerdisms, bicycles
TLDR: I built e-ink firmware, a web dashboard, and a snapshot service for driving my display. You can see the source code @e-ink-dashboard.
Early version of e-ink web dashboardI want an e-ink display to show me cool-stuff™ when I'm walking around my house.
More specifically, throughout the day, I want to see:
I find myself walking by the kitchen refridgerator reguarly during the workday, thus, it's a great spot to mount my display.
First thing first! We gotta pick the display hardware. There's far more options on the market now than there was a few years ago.
Geeze--I already have an unused e-ink display--an Amazon kindle! Kindles are awesome. They have a sleek thin profile, run some sort of linux variant, and can be meddled with. After hacking a few kindles, I recommend to any interested party to not persue this route. Kindle hacking is doable, but the hardware fights you along the way. The hacks are not always reliable, different f/w versions behave differently, mine had unsolvable problems with its RTC. I've always had success jailbreaking it and getting it to paint stuff on screen, but it's a system that simply doesn't want to be programmed against. Amazon doesn't want you doing this, and their softwares may periodically unjailbreak you. I do not condone or recommend using kindles. Yes, you can do it. However, it can be very frustrating--death by 1000 cuts--trying to build robust software on this platform.
Waveshare has a bunch of displays and associated controller modules ready to hack, off-the-shelf!
Honestly, this is a great option. Consider it! However, I found the following compelling...
Here's an excellent turn-key product, ready to program with almost nil effort.
I picked the Inkplate 10 - https://soldered.com/product/inkplate-10-9-7-e-paper-board-copy/.
I spent around USD$220 for my Inkplate 10. I want a big display! It took <5 minutes after unboxing it to have meaningful content rendered on the screen. Incredible!
I forgot to buy the option with a battery, but I found a compatible battery on Amazon. Soldered does sell a battery, and I recommend buying that. The battery from Amazon is cheaper and works fine, but the terminals need to be flipped.
Wonderfully, the 3d printed case that I bought from Soldered also has a little slot to locate and fix the battery into position, which is pretty slick. It has a home and wont rattle around. Even cooler--it has a charging circuit already dialed in.
Finally, because I want my e-ink to live on the fridge for weeks at a time without charging, I really wanted to truly go low power. That means that I need to send the device into deep sleep, and have it wake on a timer. For this, you'll need a CR2032 battery, for which the Inkplate board already has a receptacle for. Now, the RTC clock and waking features become available to you!
Full Bill of Materials (BOM):
I already have web-based visuals on my home network for my airquality monitors. See cdaringe/freshawair. Getting these charts onto my display is my primary objective.
Err uhh hmm uhhhhhhh. Seems silly to have great visuals already on the web and rebuild them in C. Further, my data is in postgres, which freshawair's grafana instance already integrates with. To rebuild my core visuals would be to re-invent the wheel.
No thanks.
Well hey, if my UI is already avaible in grafana, why not just capture that?
This almost meets my needs! However, Grafana has some shortcomings. You cannot change very simple UI things--like axis font sizes or chart title font properties. Further, I don't want most of the grafana GUI aspects, just specifically some charts in my dashboards.
Further, if I want other content interspersed on my e-ink dashboard, using Grafana alone doesn't allow for any customizations.
This option takes the approach of having the dashboard be a simple screenshot of a webapp. This option gives me great flexibility at the cost of complexity. The complexity is that I need more systems--a webapp, a means to serve that webapp, and a screenshotter workflow. This webapp:
A downside to this approach is that every UI change means a web request. I don't care! My objective is genrally static content. I would like some interactivity, but I'll cross that bridge when I really need it!
How can I get device data onto the screen if I'm just using screenshots? I'd have to screenshot in realtime if using Option 3 alone.
Screeshotting is slow. You have to launch a browser, wait for network settling and web content to load, run a screenshot routine, then post-process an image. That's not viable for real-time.
My solution for this is to make my host server an API, and allow adding overlay images onto the screenshots. While I could again use the C arduino API to render some content onto the screen with e-ink partial rendering, I want a more powerful option, and I want to keep the firmware simple-stupid.
This solution adds ?searchParam
style options to image downloads, a
la GET /dashboard/image.png?batteryoverlay=85,500,1140
. Decoded, 85
means
the battery is at 85%
capacity, and the following digits are offsets from the top-left corner of the display.
During processing of image.png
, overlays are detected, and ImageMagick
convert ...
commands composite images and text over the base image and serve the resultant image up.
convert
is plenty fast.
With this capability, screenshots drive the primary dashboard, while allowing some
realtime capabilities onto the maybe-stale screenshot.
This is ultimately the solution I chose. You can see the implementation here: e-ink-dashboard.
It's all bundled up in a docker container, making deployment easy-ish.
e-ink backplateNow that I'm done, how do I sincerely feel about it? I do a lot of stupid projects. Sometimes I finish them and am simply not impressed with my work. Most of the time, I start a bigger project, get bored, and end up leaving it unfinished.
Not this time! I am absolutely delighted with this project!
Final e-ink dashboardThere's more I want to do with it:
puppeteer
and friends are much better than other tools in other stacks. This is part of the reason I run the snapshotting workflow in a child process.Let me know what you think over in GitHub issues.