Homeassistant Kindle Display

I use a kindle to display status information like next waste disposal and weather. This was the last consumer of my custom written sensor backend that I migrated to Homeassistant in the last months.

A website that can be displayed on an old Kindle4 is not able to use a lot of Javascript. I tried the basic solution described by nirkons on Github, but it was really annoying to debug for the stuff I want to display. So I decided to choose a different solution: Render a HTML file using a Template in Homeassistant and updating it via cron.

First the Template. I used the developer-tools inside Homeassistant to fiddle around with everything I want. The resulting template is stored in kindle.jinja in config/custom_templates. Important here: changing a template file on disk needs a Homeassistant restart.

Because of changes in Homeassistant 2024.4 there is no forecast in the weather state anymore. To get this back we need a new template in the configuration.yaml:

template:
  - trigger:
    - platform: time_pattern
      minutes: "*"
    - platform: homeassistant
      event: start
    - platform: event
      event_type: event_template_reloaded
    action:
      - service: weather.get_forecasts
        target:
          entity_id: weather.forecast_home
        data:
          type: daily
        response_variable: daily_forecast
    sensor:
      - name: "Weather Daily Forecast"
        unique_id: home_daily_forecast
        state: "{{ states('weather.forecast_home') }}"
        attributes:
          forecast: "{{ daily_forecast['weather.forecast_home'].forecast[:3] }}"

The file has lots of CSS on the top and quite a bit of HTML, but a minimal version of kindle.jinja looks like this:

{% macro kindle_html() %}
<html>
  <head>
    <title>Kindle Status Display</title>
  </head>
  <body>
    Current time and date: <p id="time"></p>, <p id="date"></p><br>
    next Recycling collection: {{ as_timestamp(states('sensor.yellow_bag')) | timestamp_custom('%d.%m.%Y') }}
    <pre>
    temperatures tomorrow:
    min: {{ state_attr('sensor.weather_daily_forecast', 'forecast')[1].templow|round }}&#176;C
    max: {{ state_attr('sensor.weather_daily_forecast', 'forecast')[1].temperature|round }}&#176;C
    </pre>
  </body>
  <script src="kindle.js"></script>
</html>
{% endmacro %}

The kindle.js is important to update the current time and date on the kindle and to trigger a regular reload. The code for this is as old school as possible:

function updateDate(){
  d = new Date();
  document.getElementById("date").innerHTML = d.getDate().toString() + "." + parseInt(d.getMonth()+1).toString() + "." + d.getFullYear();
  document.getElementById("time").innerHTML = d.getHours().toString() + ":" + d.getMinutes().toString();
}

updateDate();

setInterval(function(){
  updateDate();
}, 1000*60);

setInterval(function () {
  location.reload();
}, 1000*60*60);

The version I actually use adds extra '0' if needed and is a bit more messy. We store kindle.js and the rendered html template output later in config/www/ which can be accessed without any authentication via http://your-homeassistant-ip:8123/local/kindle.html. For more information about hosting html files with Homeassistant, see https://www.home-assistant.io/integrations/http/#hosting-files.

To render the macro we stored we need a long lived token which can be generated in the profile of Homeassistant. This curl command renders a template and stores it to kindle.html:

curl -s -H "Authorization: Bearer YOUR_LONG_LIVED_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"template": "{% from \"kindle.jinja\" import kindle_html %}{{ kindle_html() }}"}' \
  http://localhost:8123/api/template > ~/.homeassistant/www/kindle.html

The template command {% from "kindle.jinja" import kindle_html %}{{ kindle_html() }} imports the macro and calls it. This can of course be tested in the developer-tools like we did before. I put the curl command inside a script file and call this script via cron every 10 minutes. For later debugging on the bottom of the rendered html is a {{ now }} to see when the file was last rendered.

My kindle display now looks like this:

img1

The html/css can be optimized a bit more and some sensor averages may be nice, but this is enough for today.