GopherCal: Experiments with eInk

I have to admit, last year, I got fascinated by eink. It's through a few hackernews posts and I loved the following projects: https://www.invisible-computers.com/, and https://gregraiz.com/posts/i-made-an-eink-newspaper/ and I wanted something similar but with a Todoist integration.

Also, it had been a while since I wrote some code, and I was looking for some side projects to tinker with. And a DIY eInk calendar + TODO organiser seemed like a great idea, so I got this 10" Inkplate back in July 2023. And the saga began.

The idea

The idea was simple: Calendar and TODO list a single glance away.

My working style is super chaotic, I tend to have a ton of things on plate and sometimes end up focusing on the wrong thing. A sorted TODO list with clear priorities would hopefully keep me focused and working on the right things.

Implementation

The inkplate comes with an ESP32 and you could do a lot of things with it. There are projects that actually generate the whole image in the ESP board itself. However, this is one of my first microcontroller projects, and I am not too fluent in C++ and I wanted to be done with this as quickly as possible.

So the next thing I looked into was to generate the image on a webserver and the inkplate just downloads the image at regular intervals and just displays it. This was simpler, and I had a fair idea of what this involves.

Attempt #1: Render webpages directly

The most obvious solution is to use either phantomJS or chrome-headless, navigate to Todoist and Google Calendar and to render the HTML as images. Or use a chrome webdriver to control the browser running on my computer.

This had a couple of problems:

  1. Login / cookie problem: For this to work, I need to log-in to my work email which is not very trivial and needs a couple of layers of 2FA. And in general the security posture and reliability here looked low.
  2. RISC-V problem: The current always-on computer I had was a VisionFive 2 RISC-V board which didn't have a lot of performance, and running a full blown Chrome on it seemed like a bad idea.

Attempt #2: Render custom images in Go

While the login problem was an issue, I could still use the Todoist and Google APIs to get the JSON needed and then render my own HTML view the way I wanted it. I started working on it and managed to get both the Todoist (easy) and Calendar events (tricky) JSONs.

As I started to write some HTML, I thought why not generate the whole image in Go. I came across this excellent blog post by Mat Ryer on generating images with the gg library. Huh, it presented a straightforward way to render all the rectangles and text I wanted!

So off I went and after writing a bunch of REALLY UGLY code, I got it working! I literally learnt how to use gg as I built this, so I can already a bunch of clean ups I could do.

Now the inkplate just calls the Go server every 5mins and downloads the rendered image. The rendering and transmission takes about 4s on average and I feel like most of it is still getting the data from Todoist and Google Calendar APIs.

Find the Code here

You can find the code here: https://github.com/gouthamve/gophercal, with detailed instructions on how to create the Todoist and Google credentials and running the server.

Side projects need to be sequential

I hadn't done any side-projects in a while and GopherCal made me realise how long they take the patience you need to "finish" one. I don't have a lot of free time and having many side-projects at once means I won't make meaningful progress on any of them.

After nearly a year of tinkering around with it, and finally printing a stand for it, I think I can call GopherCal "done". Now on to the next side-project which is low-effort monitoring for Prusa 3D Printers 😄

It is super helpful

Having the calendar one glance away has been a godsend. It is easy to understand how much I get done today, and also if I can take a walk or step out for lunch.

The other interesting thing is that I can tell very easily if I'm overloaded. If my todo list is super long, I start cutting down on things and ping my manager that I need some help.

Bonus: Yak shaving for a stand

Initially I had GopherCal sitting next to my computer but it wasn't too stable and sometimes go into the way of my monitor. So I mounted it to the top of the monitor with some 3M velcro patches.

But I wasn't really happy about this either and wanted to print it a proper a stand so it sit next to my monitor at a decent height. And this I used to justify buying a 3d printer. But I was missing a place to put the printer, so I teamed up with Ben to build a workbench! After all that, I finally printed a stand for the GopherCal that I am thrilled with!