Rule running only once per day, no matter what...?

help needed, please…

I am trying to figure out a rule which runs only once per day no matter, whether the system reboots, or .items triggering a reload…

How it should work:

rule once per day
if someValue changed
var date = today()
if (date != date.saved) {
runOnce
date = date.saved
}

date.saved should be persisted – maybe map-persist works (as it is a date, not a number?

Designer does not give me an option for the date… only DateTime.

Hi,

If I understand you correctly, you’re asking two questions. To ensure a rule is executed once a day (without going all out with parsing log or lockfiles), simply use a cron condition in the rule, like in the following example:

rule "Rulename"
     when
         Time cron "0 0 8 * * ?"
     then
         ...
end

You can find the details of the cron syntax for rules here: http://www.quartz-scheduler.org/documentation/quartz-2.1.x/tutorials/tutorial-lesson-06

I’m not quite sure what your second question is exactly, but if you want to to date/time work, I would recommend importing some of the following in your rules:

import org.joda.time.*
import java.text.SimpleDateFormat
import java.text.DateFormat
import java.util.Date

Which allows you to format the date any way you wish;

    var Date dToday = new Date();
    var String strDate = new SimpleDateFormat("yyyy-MM-dd").format(dToday);

Hope this helps.

Cheers,

PelliX

Wow, this was quick…

Looks like I have been looking at this problem for too long – trees and forest :slight_smile:

I basically need a proxy item, which one rule sets on, and another sets it off – I think.
I have done this before, but here the state should be changed only once per day.

E.g. I have a battery, which is being recharged to SOC =100%
I trigger other rules based on this value having reached 100 (percent).
But when I restart the system, the rule is triggered again, due to 100 being restored on startup.

So, I want to say, if SOC = 100
check the day(date, and if you already ran today do nothing.

Hey,

maybe I’m a little dense, or maybe it’s early Sunday morning and my coffee intake is still insufficient, but I think what you’re angling at is ‘persistence’. Obviously, you can also have your “when battery full rule” write a lock- or logfile which that same rule could check before performing any actions. As far as I know, there is no ‘native’ way within rules to parse this information, but with a little script it should be a walk in the park.

Persistence is, IMHO, the proper way to go about it. As I do not know what kind of persistence services you have available, I can’t really supply you with a practical example, but this should help:

Also, make sure your “when battery full rule” uses

rule "when battery full"
    when
        Item changed to 100
...

There is, I think, a really dirty way of fixing the startup issue, too;

rule "startup values"
    when
        System started
    then
        postUpdate(SOC, 100)
end

Just an afterthought: you could also let your “battery full” rule create a temporary file somewhere, and have a second rule (with a daily cron condition) delete that file every day. Make sure the battery full rule performs no operations if the file is (still) present. Not very clean, but it should work.

Cheers,

PelliX

1 Like

I don’t see why that shouldn’t work.
trigger when battery changed to 100
if battery charging … (else it would be system boot)
then set proxy to ‘now’ datetime

persist proxy

when some rule wants to test …
if proxy date part = today then it has already run once today (dont care about time part)

when date changes at midnight “lock” will automagically unlock

:slight_smile: I am sort of clear on the logic
I struggle with the methods of different functions.

Got it…
.item: Switch spp_SOC100RanOnce

rules:

    if (Battery_SOC.state == 100) {

      if (spp_SOC100RanOnce == OFF) {
        postUpdate(spp_SOC100RanOnce, ON)
        ...
      }
    }

and reset:

rule "Midnight stuff"
  when
    //         s m h D M DoW Y
    Time cron "0 1 0 * * ? *"
    // here: 00:01
  then
    postUpdate(spp_SOC100RanOnce, OFF)
end

Thanks guys… a break does wonders… maybe the coffee helped…

It’s not quite “no matter what”, it needs OH to be operational at midnight or you might lose a day. (I’m assuming your RanOnce flag is persisted and survives an outage)
Would that be a problem?

An alternative to the midnight reset rule is to use the “expire” binding to time out the flag after 24 hours. Thats not the same behaviour, and may be suited better or worse for what you are doing - but it is simple. That would I think restart the clock at each reload of a persisted Item - not sure though?? Again not the same behaviour.

The date-stamp based approach is I think the way to make it truly bombproof. Date comparisons are not that difficult. Finding a reliable trigger is important - is your battery state persisted, what happens if it restores 100 at reload? (perhaps that is one that shouldn’t be persisted)

1 Like

Thanks and understood :slight_smile:

I moved away form checking on the date or day name…
… and use the above. yes, everything is persisted with maddb or rrdj4.

The reason for this functionality is: when the SOC reaches 100%, which it does on 355 days per year, the hotwater booster will be switched on. It sits on a 2h OH timer, and switches off after that or when the thermostat says I am done.

On a system restore or rule reload or whatever, I do not want this SOC100 switch to come on again… which my solution does achieve.

In any case, it helped greatly to have some external input! … which I do appreciate.