Multi-year Home Assistant dashboards from long-term statistics

You can chart years of sensor data (e.g. a weather station’s daily min/mean/max temperature and rainfall) in Home Assistant without an external database. The data is already in HA’s long-term statistics. This page covers the pattern: a year-picker dashboard on top of those statistics, generated by a script instead of being built in the UI.

How it works

  • Long-term statistics. HA stores hourly aggregates (mean/min/max, or sum for totals) for every sensor that has a state_class (measurement, total, total_increasing). These are kept forever, independent of the recorder’s purge_keep_days. You don’t need InfluxDB or a custom archive for yearly charts.
  • Cards.
  • Year picker. An input_number helper holds the selected year. The template card turns it into the chart’s time window, and the buttons change the helper.
  • Drill-down. A click handler on a data point opens the history of that day.
  • Dashboard as code. A Python script generates the whole dashboard config and pushes it via the HA WebSocket API (lovelace/config/save). To change the dashboard, you edit the script and re-run it. No restart is needed, and the result is reproducible and versioned in the config repo.

Porting to another instance

Because the dashboard is generated, porting it is mostly remapping entities:

  1. Make a table from each source entity to the equivalent target entity (for example a different weather-station brand with other entity IDs). Every sensor needs a state_class, or it has no long-term statistics.
  2. Install missing custom cards. If they are not in the target’s HACS, copy them from the source instance’s www/community/ and register them as local Lovelace resources (/local/community/...).
  3. Create the input_number year helper and the dashboard registration (sidebar title, icon, URL path) to match.
  4. Run the generator against the target instance.

Pitfalls

  • A sensor without state_class has no long-term statistics, so there is nothing to chart beyond the recorder window.
  • Statistics exist only from the time the state_class was set. Earlier years stay empty.
  • apexcharts-card’s span and offset behave in non-obvious ways with calendar years. Test across a year boundary.
  • Editing .storage/ files directly (e.g. dashboard registration) can hit file-ownership problems in Docker setups. Prefer the WebSocket API, or fix ownership after editing.
  • Hand edits in the UI are overwritten the next time the generator runs.

Sources