How to Display Your InfluxDB Dashboards on E-Ink
InfluxData sponsored this post.
Have you ever wanted to see your InfluxDB dashboards rendered as a single image? Or even better — have you been able to show them on your TV or other displays, so you can constantly see the status of things you care about? Recently, I wrote open source code for doing just that. Here’s the story and some background.
Recently, I bought a 9.7-inch E-Ink display to test how it can be used. I plugged it into my Raspberry Pi and started testing how to send any raster image to it using Python. Here’s a photo of it, displaying the InfluxData logo in my living room (above).
E-Ink displays have one huge feature: they are very cheap to keep running. My Raspberry Pi, along with the display, consume less than 10W of power — so running it 24/7 in many regions costs less than €2 per month (or $2, depending on which currency you prefer). This makes it a great fit for showing up-to-date information all the time. Set the E-Ink display in a visible place and use it for a clock, possibly also showing information like air quality at home, currency exchange rates, or how busy your Linux box is.
Even before I joined InfluxData, I have been using InfluxDB to store a lot of information. I figured it would be great to use InfluxDB and its dashboards as a way to define what my E Ink display should show.
One of the great features that InfluxDB 2.0 provides is that all of the dashboards can be accessed using APIs. It made me think, how hard would it be to show a dashboard like this…
…onto my new E-Ink display, so that it looks like this:
As I’ve found out, it is doable and did not require a significant effort; but rather, simply using and integrating multiple components.
I have used Python for this project, as it’s a generic scripting language and already has a client I can use.
The tool I’ve written has been split into several components that I’m going to describe in more detail below.
Programmatically Sending Images to E Ink Displays
My E-Ink display came in a bundle with a Raspberry Pi HAT (Hardware Attached on Top), which can be put on top of a Raspberry Pi. That’s also exactly what I did, and it was all that was required on the hardware side.
On the software side, the E-Ink display I have uses the IT8951 controller, which is very popular and has multiple clients available. I decided to use Python and the IT8951 open source package. Installation was simply a matter of running the pip command twice, as described in the README file.
Next, I wrote simple code that reads an image from disk or an HTTP response and renders it onto the display.
This allowed me to render any image onto the E-Ink display, such as the logo or dashboard above.
Now I could continue with creating images from my InfluxDB dashboards, so I can then send them to the E-Ink display.
InfluxDB API Client
The project uses the Python InfluxDB 2.0 client, which provides almost all of the functionality to communicate with InfluxDB.
However, I had to extend the client to support passing variables — this is needed for Flux queries that use v variables, like v.timeRangeStart. These are the parameters that the InfluxDB user interface passes to queries — the variables in the dashboard, window period and time range.
At the time of writing this post, the Python InfluxDB 2.0 client does not provide a way to pass the variables directly. Because of that, the dashboard renderer uses a lower-level API and wraps it to allow passing any variable. The code can be found on GitHub and is split into two parts.
- The first handles defining external variables and serializing them into the format that InfluxDB 2.0 APIs expect.
- The second uses InfluxDB client’s functionality to define external object v and call the query API with the external variable.
This was needed as most dashboards I wanted to render allowed customizing time period or require having one or more variables set. The dashboard renderer I’ve written supports any variables, including the built-in ones.
Generating and Configuring Output Images
Since I started working on the renderer, I wanted it to render full-color images that I can use anywhere, but also black-and-white and greyscale ones for E-Ink. I also assumed that my images should include DPI (dots per inch). The reason is that 1280×825 image for 10-inch E-Ink and 1920×1080 image for a 40-inch LCD TV should have different sizes of certain elements of the UI, such as labels.
The part of my dashboard rendering code is responsible for deciding background color and calculating size of labels. It’s also determining colors for cells — such as the indicators for a gauge cell, color of graph line and fill color below it.
Rendering Cells and Dashboards
The main functionality is rendering the dashboards. The code simply divides the output image into a number of columns and rows, based on the layout of the original dashboard. It then renders each cell individually and pastes its content into the output image.
The way in which a cell is rendered depends on its type. At the time of writing, only a subset of cell types is supported:
- Graph visualization — rendered using matplotlib Python library; multiple Flux queries and multiple resulting tables are properly supported; supports color themes
- Single Stat visualization — renders the latest value from the last table from all the Flux queries in the cell using a simple drawing of a text to fit the text in the cell; usually single stat cells contain one query that returns a table with a single row; supports color themes
- Graph + Single Stat visualization — combines logic from Graph and Single Stat visualizations in a single cell and supports color themes for both graphs and stat text
- Gauge visualization — rendered using custom code leveraging matplotlib Python library; supports 2-color and multicolor themes; renders the latest value from the last table from all the Flux queries in the cell using a simple drawing of a text to fit the text in the cell
For cells with any other type of cell, the rendering process is skipped and that part of the dashboard is left blank. I plan to support additional cell types in the future. I also welcome pull requests with code to render additional types of cells.
The rendering also adds labels above each cell — same as the visualization in InfluxDB UI.
All cell formats support cell configuration options for the number of decimal places, value prefix and suffix. These are reflected when rendering labels and values.
With the functionality to render dashboards in place, the next thing I have implemented together with InfluxData’s Rick Spencer, is to create a web server that you can call (or
curl) and will render an image for you.
We’ve also created a Dockerfile and a container to make it easier to run everywhere. To start a webserver container, simply run:
$ docker run \
-e INFLUXDB_TOKEN=(influxdb-all-access-token) \
-e INFLUXDB_URL=https://us-west-2-1.aws.cloud2.influxdata.com \
-p 5000:5000 wojciechka/influxdb-dashboard-renderer
…where value for
INFLUXDB_TOKEN is an all-access token for my InfluxDB Cloud 2.0 account or my InfluxDB local server. The address that
INFLUXDB_URL is set to should point to InfluxDB Cloud 2.0 or your local InfluxDB server.
After starting the container, http://localhost:5000/render?org_id=(org-id)&id=(dashboard-id) can be used to render a dashboard. It can be visited from a browser or used as part of automation to download the image and then use it — such as to render it on the E ink display or a large monitor / TV.
The values for
(dashboard-id) are the identifiers organization and the dashboard identifiers respectively. They can be retrieved from the dashboard URL, which contains both — such as https://us-west-2-1.aws.cloud2.influxdata.com/orgs/(org-id)/dashboards/(dashboard-id) for dashboards in InfluxDB Cloud 2.0.
Below is a render of the same dashboard, using the full-color output with a dark background:
And below is the same rendering when invoked with width=1200&height=825&dpi=150&mode=bw4&bright=true options, which renders output suitable for E Ink:
The server also accepts parameters that can be used to customize output — such as width, height or dpi for output. The options can be passed in the URL or as environment variables. The full list of accepted parameters can be found in the available options section of the server README in the repository.
The web server can be integrated with notification systems, such as sending the state of the dashboard along with Slack or MS Teams notifications.
Among other things, InfluxDB 2.0 provides APIs to retrieve dashboards. This can be used to render the dashboard as images. The influxdb-dashboard-renderer project is one example of how the APIs can be used.
Originally, my goal was to write a small tool for myself so I can render the dashboards onto E-Ink. Over time, I realized it has many more use cases — such as sharing rendered images of dashboards via email, Slack, Teams, or even embedding the dashboards in other websites. I recommend you give it a try.
At this time, The New Stack does not allow comments directly on this website. We invite all readers who wish to discuss a story to visit us on Twitter or Facebook. We also welcome your news tips and feedback via email: email@example.com.