Long-term statistics for binary sensors and enums

Home Assistant’s long-term statistics only work for numeric sensors. There is no native support for discrete data — binary sensors (on/off), or enum states like open/closed/opening/closing,
heating/cooling/idle/off — so their history vanishes when the recorder purges.

This integration fills that gap: GitHub - exciton/discrete-statistics: Long-term statistics for binary and enum Home Assistant entities: per-state transition counts and durations, retained independently of purge_keep_days. · GitHub

Open this repository in HACS
Add integration to HA

  • Works with any entity whose state is a label: binary sensors, switches, covers, climate, enum sensors, input_select, person/device_tracker…
  • Records hourly long-term statistics per state: time spent in it, and number of times it entered that state
  • Stored as long-term statistics, so they are never purged — kept forever, independent of purge_keep_days
  • Backfills from existing recorder history on first run, so you start with whatever the recorder still holds rather than from zero
  • Discrete Statistics Card produces fully functional charts, with all states, in a few clicks
  • Also draws with the stock statistics-graph card: change for totals/averages over days/weeks/months
  • New states are picked up automatically as they appear — no per-state config needed
  • unavailable/unknown (or any state you choose) can be ignored, with the previous state carried across the gap instead of a hole
  • Debounce: a state that lasts less than a minimum duration can be ignored, per state or for everything
  • States can be mapped onto one another (e.g. heat_cool → heating), or renamed
  • Set up from the UI or YAML; per-state mappings are YAML-only for now
  • Recalculate any range at any time — it only ever rewrites what it has source data for and never deletes anything

Some examples:



Configuration UI:

8 Likes

I really love how you solved the problem to make it compatible with other statistics and charts, by creating sperate statistics with an appendix for the state.

Well done. :slightly_smiling_face::+1:

Should also help to avoid problems introduced by HA updates, as these structures have been like that for a long time.

Will definitely play around with that after my holidays.
There are a few entities that I miss history after switching from a dedicated DB with Grafana back to HA internal recorder / charting dashboard cards.
This integration should help to solve this. :upside_down_face:

3 Likes

Indedd. Looks incredibly interesting.

@Thyraz I might even crack open the hist stats handler in my stuff to add support if it does what I think it does…

1 Like

It works well with built in statistics graph, but could be a little quicker to configure charts with a little bit of logic that understands how to grab related states statistics. Maybe a custom chart or adaptation of an existing one.

Maybe I can add some logic here:

(Beside the name, it’s not only for energy related stuff anymore, but a more customizable card using the HA-internal echarts library)

1 Like

My agent say…


Good news — no code change needed at all. I checked the tool’s actual logic (not just help text): it does zero validation on statistic_ids beyond “not empty,” and passes the string straight through to recorder.get_statistics. So discrete_statistics:binary_sensor_grid_status_on_duration-style IDs will work mechanically as soon as the integration exists and produces them — nothing to “lift.”
The one real update needed is the help text, which currently says “only sensors with a valid state_class and unit_of_measurement are supported” — that becomes actively misleading once this integration is installed, since it’d wrongly discourage querying the new discrete_statistics:* IDs.


So I’ll let you know what Friday thinks. This solves a very specific question my build tomorrow will make people ask… (I basically boil each room down to a sensor… With a room state enum, you may have solved a problem I was running against in automatically building priors for room presence baysean sensors…)

Yes - if you have a single enum you want to track over time, this will work perfectly. You can track the duration in each state and the number of times each state was activated over all history. Use the Statistics Graph card for now, and I’ll likely add a custom one to make config simpler (with Statistics Graph you have to manually add an entry for each state - but if the states don’t change this is a one-time job).

1 Like

I added a custom card, that’s based on the Statistics Graph card, but makes it much easier to build charts for entities with many states. You only need to select the entity from the list (it will show only configured entities that generate discrete statistics), and it will pull in all states (even new ones as they appear).

1 Like

v0.4: period sensors — the numbers, not just the charts

The most common workaround people describe in these threads is a handful of history_stats sensors per entity — time and count for today, this month, this year
— which drift or reset once the window reaches past purge_keep_days. The integration can now give you those numbers directly, read from the statistics it
already records, so they have no purge horizon and always agree with the chart.

Open an entry on the integration page and choose Add sensor:

Add sensor

  • States — one or more (added together), picked from the states the entity has recorded, or typed in.
  • Measure — time in hours, share of the period as a percentage, or number of changes into the states.
  • Period — today, yesterday, this/last week, month, year, all time; the last hour, 24 hours, 7, 30 or 365 days; or a custom window from start/end/duration
    templates, exactly as history_stats takes them ({{ today_at(‘09:00’) }}, {{ state_attr(‘sun.sun’, ‘next_rising’) }}).
  • Include the current hour — statistics are compiled hourly; with this on, the sensor follows the entity’s changes since the last compiled hour as they
    happen, so “time on today” is live to the second.

The sensor dialog

A custom window

Each sensor is an ordinary entity — tiles, automations, templates — with period_start, period_end and compiled_until attributes. Sensors are attached to the
entry, so deleting one deletes it; the entry itself still has no entities of its own.

A sensor’s details

Two things worth knowing:

  • Reading is cheap at any range. A year-long window is arithmetic on a handful of precompiled rows plus at most a couple of hours of raw history (the hour in
    progress, and the hour a window edge falls in) — not a year of state changes every minute.
  • Exact while the recorder holds the hours, accurate after. Over a window the recorder still has history for, the sensor reads the same rows history_stats
    would, to the same result. Once purge has taken the hour a rolling window starts in, that one hour is estimated from its hourly total, and an estimated
    attribute says so. Calendar periods start on the hour and are always accurate, and never estimated.

Also in this release:

  • Time at places — a person or device_tracker entity’s zones are states like any other, so “hours at the office this week” and “trips to the gym this year”
    have always worked; the README now has the example.
  • Download diagnostics on the entry’s menu, for “it isn’t compiling” reports.

Release: Release 0.4.1 · exciton/discrete-statistics · GitHub — and it’s in the HACS default queue.

1 Like

When I try and create a card, I am seeing this (on HA 2026.8.3). I can see the statistics for my entry in the stats page.

I also cannot get my head around the resolution it records by default.

So for heating, I want to see further back than the standard 7 day for when the heating was on and for how long. Will this just show the same entity in history for longer?

You need to do a crtl-shift-r (hard refresh) in your browser after you restart HA with the new integration to refresh the cached javascript.

The history view will not extend past the default 7 recorder days (it looks at raw state changes), but the Discrete Statistics card will look back forever (once the statistics are built).

You also need to add an entry in the integration page, to actually record the statistics.

So steps are:

  • Install the custom component in HACS, restart HA
    Open this repository in HACS
  • Do ctrl-shift-R refresh in your browser
  • Go to the integrations page to add the integration:
    Add integration to HA
  • Add the item you want to the integration with the “Add entry” button
  • Wait a minute or two for the statistics to be build (you’ll get a notification)
  • Then add the Discrete Statistics card to your dashboard

Actually there was a bug. Try 0.4.2 - and you should be able to create a new card.

1 Like

Big new release just went out:

  • 9x faster at writing statistics to the database
  • ~80% reduction in number of statistics rows written to db (another 5x write speed increase)
  • Every read is a single SQL query optimised per storage engine (SQLite, MariaDB, PostgreSQL each optimised)
  • Only required rows sent for graphs with Discrete Statistics card (e.g. 13 rows for a 12-month graph)
  • Notifications for recompute action
  • Repairs for missing entities
  • Renaming an entity moves its statistics with it
  • Replacing an entity with a new one bridges statistics from the replacement device
1 Like

New release adding a multi-entity version of the card. It allows showing the same (or similar) state from multiple entities side-by-side (or stacked):

1 Like

New release adding an (optional) convenience sensor to give you the mapped, filtered, debounced value of the source sensor - in the same way as the statistics calculator would record it.

1 Like