A rule that only runs if not run within the past 23 hours?

Hello,

In order to keep rooms at a bearable temperature, I have created a rule that closes the blinds automatically at a given time if its hot enough and there is enough sun shining.

This is done with a “time trigger” and two “but only if” conditions like this:

While this works most days, it happens all to often that there is a cloud just at that time meaning that one condition is not met.

To overcome that, I simply added other time triggers to “repeat” the test a few times. But this gives another issue in that it moves the blinds at each repeat if one of the house occupants slightly reopened them to get some light.

Hence the question in the subject: Is there a way to add a condition that says “only if the rule has not been run in the past 23 hours”?

This is running openHAB 4.3 as I’m yet to migrate to v5

Thanks for your help

In OH 5 there is a “minimum interval” condition but which would be perfect for this.

For OH 4 you’ll have to keep track of when the rule ran yourself in your script action and add a script condition that checks to see how long has passed since the timestamp set by the script action. Use the shared cache to share the timestamp between the two.

In OH 5 you have more options available to you in addition to the minimum interval condition. In 5.1, where the event came from was added meaning you can record who/what last commanded the blinds and make decisions based on that in addition to just the time. For example, if the command came from a UI you know a user commanded the blinds, but if it came from a rule, maybe it’s OK to run the rule again even if it happend not that long ago.

I approached a similar situation with a combination of the average and current reading. It is a difficult problem because the light spans a huge range and the lights going on and off with passing clouds drives us crazy. Also restrict light readings to 5 minutes, not on a % threshold. Just a thought;

rule "Set Light Change Trigger"
when Item NookMotion37_SensorLuminance changed
then
    var lightaverage = NookMotion37_SensorLuminance.averageSince(now.minusMinutes(30))
    var lightlevel = NookMotion37_SensorLuminance.state as Number
    var lighttrigger = (lightlevel + lightaverage + lightlevel)/3
    Nook_luminence_hour_average.postUpdate(lighttrigger)    
end

Thanks to both of you, those suggestions are on par with what I already thought about.

Moving to OH5 is starting to be the most compelling solution as it also brings back to life the Renault binding…

Indeed.
The only downside is that it only accepts a value in milliseconds which is not very convenient.

I can help: 23 * 60 * 60 * 1000 = 82800000. Paste that number into the interval field, and you should be good to go :wink:

Well, yeah, I came up with that too, but what I’m implying is that it’s not user friendly. I mean, now that Units are used everywhere, it seems logical to me that it would be used here and allow to input, say 23h or even 60 minutes

If your blinds give you their position state, you could just check its lastStateChange timestamp and make sure it’s older than a certain duration / time before you start moving it again.

If its position updates even when manually operated, all the better.

The parameter is a number, not a string. So, you have to pick a unit, and milliseconds is the only thing that makes sense, as this will often use milliseconds spacing between executions.

What you’re suggesting is making it a string, implementing custom parsing, validation and all that. It’s certainly possible, but it’s more work and has more potential for bugs that the way it is now. Also, at this point, changing the parameter type would be a breaking change where everybody that already use it would have to reconfigure their rules to take a string, not a number.

Java has a build-in duration parsing format, but the format is so hostile that requiring that is must less user-friendly. It follows ISO-8610, and looks for example like this: PT8H30M. Running only every 23 hours is a very unusual requirement, and I think it’s fine to spend 1 second with a calculator when you need to do that.

Yes, I know all that, I’m just saying that from an end user point of view, milliseconds is a very weird unit.

And maybe, just maybe, it could be that the UI code accepts a Quantity but it gets stored as milliseconds so that existing values do not have to be converted.

That’s not currently possible, because the parameter is just an integer number - it has no unit, so the UI would have no way to know that this is a duration. Also, rules aren’t usually made in the UI (or, that varies of course), so it would only be a very partial “fix” affecting only those that use the UI to define the condition.

I’m not disagreeing with you about the “user-friendliness aspect”, I did in fact look into this exact situation on my own a few days ago, which is why I know the details of why changing it is problematic. I basically concluded that the best solution is to leave it as it is. In 97% of the use of this condition, it will be between 200 ms and 5 minutes - 23 hours is a very rare case.

When I have this type of aggregate of conditions to determine if an action should be taken, I generally use a switch item and two rules.

  • One rule to set the the switch to ON when all conditions are met. All items that are used as condition are also used as triggers (when changed).
  • Another rule that triggers when the switch change to ON, that executes the actual action.

Then the switch can be reset at midnight (or based on some other trigger depending on the use case). This ensures the action is only executed once each day, and immediately the first time all conditions are fulfilled.

Just for clarity, QuantityTypes (or Quantity if using JS Scripting rules) is only applicable to Item states, commands and updates. They are not universally supported everywhere in OH.

You could persist a value and use something like this:

//Get the charge state 24 hours ago

const PersistenceExtensions = Java.type(
  "org.openhab.core.persistence.extensions.PersistenceExtensions"
);

let battery = items.getItem("Solar_battery_soc");

let t = time.ZonedDateTime.now().minusHours(24);
let t1 = time.ZonedDateTime.now().minusHours(25);
//let pastState = PersistenceExtensions.persistedState(battery, t);
let pastState =  items.getItem("Solar_battery_soc").persistence.maximumBetween(t1, t).numericState.toFixed(0)
//update the 24h items
items.getItem("solar_battery_24hago").postUpdate(pastState.toString())

You can find the value between 2 time periods.
I use this to compare what my solar charge was 24 hours previous at the same time of day.
It’s probably the wrong way to calculate it but it gives me a good enough idea and it is correct if I compare the graphs that openHab generates for the time periods.

Anyway just an idea…

I have it on a cell on the overview: