Homematic switch actuator summarize the time it is online

Sadly, this is not something that OH is particularly good at. I can see three strategies for this.

  1. Install InfluxDB and use an everyMinute strategy on these Items (you can have more than one persistence database at the same time). Then in a Rule you can do something like
val numDays = now.getDayOfWeek
val minsOn = TV.sumSince(now.minusDays(numDays).withTimeAtStartOfDay, "influxdb")

This works because InfluxDB saves switch states as 1 for ON and 0 for OFF in the database (unlike MySQL) and because we save everyMinute we know how many minutes the TV was on by counting the number of 1s in the DB over the given time period. And getDayOfWeek returns the day of the week as a number with Sunday being 0 so if we go back that number of days we are going back to Sunday this week. The withTimeAtStartOfDay gets us to midnight on Sunday. This is probably the easiest to implement from a Rules perspective.

tl;dr count the number of 1s in the DB since midnight on Sunday of this week.

  1. @5iver posted a solution that uses the REST API to query the database and then parses the time stamps to calculate the ON time. See Time in state for an item - using persistence

  2. Keep track of the time in Rules using unbound Items or global variables.

rule "Calculate TV runtime"
when
    Item TV changed
then
    if(previousState == NULL) return; // ignore changes from NULL

    if(TV.state == OFF) {
        val lastOn = (TV_ON_Time.state as DateTime).getZonedDateTime.toEpochSecond * 1000
        val totalRuntime = TV_Runtime_Millis.state as Number + (now.millis - lastOn)
        TV_Runtime_Mills.postUpdate(TV_Runtime_Millis.state as Number + (now.millis - lastOn))

        if(totalRuntime > 1000*60*60*10) { // 10 hours in millis
            // alert
        }
    }
    else {
        TV_ON_Time.postUpdate(new DateTimeType)
    }
end

rule "Reset TV runtime"
when
    Time cron "..." // use the Quarts cron builder to have this run at midnight every Sunday
then
    TV_Runtime_Millis.postUpdate(0)
    if(TV.state == ON) TV_ON_Time.postUpdate(new DateTimeType)
end

I just typed this in from memory. I’m sure there are errors.

The theory of operation is when the TV turns OFF save a timestamp in an Item (use persistence with restoreOnStartup so the time is preserved when OH restarts or you modify Items).

When the TV turns OFF calculate the number of milliseconds since the TV turned ON (using the previously saved timestamp) and add that to the total runtime Item.

At midnight on Sunday, reset the total runtime Item back to 0 and if the TV happens to be on at that time, change the TV ON timestamp to now.

The above will only work if you have persistence on these Items with restoreOnStartup and you will have to bootstrap the initial value of the timestamp Item and the total runtime Item with initial values or else the Rule will fail. You can either give them initial values through the REST API or create a temporary System started Rule to populate the Item that you can then remove and let persistence with restoreOnStartup populate them from now on.

I plan on writing these three options up as a DP at some point. I just haven’t had the time.

1 Like