I have a switch entity and would like to create a sensor that measures the total runtime (on-time) of the switch over the complete lifetime, i.e., it should be monotonically increasing. Since I have (almost) all of my helpers configured via the UI, I would also like the total runtime entity to be configured in the UI rather than in the configuration.yaml. I have a few ideas to accomplish this, but none of these are satisfying:
My first idea was to the history_stats integration. This would be the most convenient, but it is not suited for a lifetime sensor because, as the docs also say, the history stats sensor will only have the data from the last purge_keep_days days and will therefore forget about older events, which means the value will decrease again.
My next idea was to first create a template sensor, which is zero when the switch is off and 1 when it is on ({{ 1 if is_state('switch.name', 'on') else 0 }}) and then have an integral sensor integrating this template sensor. This almost works as I want, with one exception: I cannot make the integral sensor have the correct unit, which should be h, when I create both the template and the integral helpers via the UI. What I want is that the template sensor is dimensionless, such that integrating it over time, the integral sensor will have unit h. However, as far as I see I cannot define a dimensionless template sensor via the UI. Is does not seem to be possible to set the custom unit as the empty string (or not even a space). When giving it no unit (probably corresponding to unit_of_measurement = None), the integral sensor also has no unit. However, I want unit_of_measurement = "". Is a dimensionless template sensor helper (which is something different than a template sensor without unit) not configurable in the UI?
Another idea would be to define something like an input_number, a history stats sensor, which resets daily and create an automation, which adds the value of the daily history stats sensor to the input number at the end of each day. However, that feels much more complicated than it should be.
So what is the recommended solution to define a total runtime sensor without defining entities in configuration.yaml? I feel like this is a common enough use case, such that there should exist a native solution. I'm happy for any suggestions.
Option 2 is likely the most native solution. What happens if you set the unit to count?
The other way is to use an input number accumulator and to trigger an automation on every state change from on to off: you'd use the last changed properties on the state object to calculate the duration and add that. You might get some artifacts if your switch goes unavailable or if you have an odd sequence of events over an HA restart.
Option 2 is likely the most native solution. What happens if you set the unit to count?
Then my integral sensor will have unit counth because the integral sensor multiples (appends) h to the unit of the underlying sensor. That's why I want the unit to be the empty string, which is possible to set in yaml, but not in the UI.
Your idea using trigger.from_state.last_changed is nice. This really helps! The automation is already fine, but I agree that the trigger-based sensor is even better. However, this is also only configurable via the yaml, right? But I guess I have to live with that unless anyone else has another idea
In the end I ended up with (when I had the trigger within the sensor I got an error so I defined it outside):
Not sure if this is OP's case, but if you are using ESPHome, Duty Time does this directly.
Even if the switch itself is not on the ESPHome device, you can import it and have it calculate the runtime.
I would suggest to create a history_stats sensor as you proposed in the first bullet point.
Make it count the time the switch was on per day (so start at {{ today_at() }}
Then create a utility meter on that entity, without a restart, that will give you the lifetime totay.
Thanks @TheFes! That also sounds like a good solution. I now created both sensors and will see over time, which solution I prefer.
Thanks again everyone.