Rules to only fire when its :00 or :30

rules
Tags: #<Tag:0x00007fe053d7c1f8>

(N. Jordan) #1

Hi all,
i would like to block an existing rule that is triggered every minute. As soon as the solar battery is low it would send an email per minute…which is high and produces over night thousands of emails…one way would be to have a flag that is set when triggered first time. That is the ultimate goal - but for now i would be happy if this rule only fires an email every 30mins or every hour…so it reduces the amount of emails…

i guess it would be done via cron statement on top, but not sure, so would be happy if someone could help me with the additional code required…

// ***************************************************************************************************
rule “PVisland Voltage below 23V Alert - Notification”
when
Item PVislandVolt received update
then
if (PVislandVolt.state instanceof DecimalType) {
if (PVislandVolt.state < 23) {
sendMail(“xxxxxxxxxxxxxxxxxx”, “PVisland | Battery Voltage Level Alert | " + PVislandVolt.state + " V”, “—EoM—”)
}
}
end


(Harry) #2
Time cron "0 0,30 * ? * * *"

(Mihai Badea) #3

Take a look at the documentation.
You’re rule should look like this:

rule “PVisland Voltage below 23V Alert - Notification”
when
    Time cron "0 0/30 * 1/1 * ? *"
then
    if (PVislandVolt.state instanceof DecimalType) {
.........................................................

Also, for better visibility in forum, you should use code fences


(Scott Rushworth) #4

This is definitely the way to go to prevent annoyance.

var Boolean pvAlert = false// global variables need to be at the top of the rule file, after any imports

// ***************************************************************************************************
rule "PVisland Voltage below 23V Alert - Notification"
when
    Item PVislandVolt received update
then
    if (PVislandVolt.state instanceof DecimalType) {
        if (PVislandVolt.state < 23) {
            if (!pvAlert) {
                pvAlert = true
                sendMail("xxxxxxxxxxxxxxxxxx", "PVisland | Battery Voltage Level Alert | " + PVislandVolt.state + " V", "—EoM—")
            }
        }
        else {
            pvAlert = false
        }
    }
end

(N. Jordan) #5

Thanks…

Can the when part be combined…?


when 
    (Item PVislandVolt recieved update) && (Time cron "0 0/30 * 1/1 * ? *")....

Does this work?


(Harry) #6
rule “PVisland Voltage below 23V Alert - Notification”
when
   Time cron "0 0,30 * ? * * *" or
   Item PVislandVolt received update
then
   ...

(N. Jordan) #7

Harry, Thanks…

are you sure OR…because i want to trigger if its 0 or 30mins of the hour + an update has taken place. I do not want to trigger the rule if only its 0 or 30 but in addition an update has happened…

or will this not work in sync as the updates come per minute (if sensor is online) … but is not exaclty at x:30:00.

Not sure if you get what I mean. rule should not trigger just due to the fact that its 0 or 30…but in combination with 0/30 + an update comes in…only i’m not sure if this comes only true when its :0:0 or 30:0.
or it triggers for a whole minute of e.g. 30:00 to 30:59…this way it would definitely cover an update as it has to happen some time within this single minute.


(Harry) #8

no

than you have to use

rule “PVisland Voltage below 23V Alert - Notification”
when
   Time cron "0 0,30 * ? * * *"
then
   // check here if the values has changed
   // do
   // store the actual values for the next check
end

(Scott Rushworth) #9

I found and issue in the code I posted. It’s been updated. If you would like repeated alerts, here are some options 1) make a timer that will keep bugging you every 30 min, 2) use a timestamp instead of a boolean for the flag and check that 30 min has passed. Neither of these use a cron trigger.


(N. Jordan) #10

OK thanks.

Harry, but if i trigger on 0 and 30mins per hour…than it would trigger exactly at zero second i guess…but if the update comes in at 25sec or 45sec or whatever sec within this minute it would not do the if part at all.

Could this somehow be turned arround … so if an update comes in the if part checks if current time is 0 or 30mins…this would definitely work from being in sync between the update and actual time…


(Harry) #11

You can’t use a AND-condition in the WHEN-Part, only OR.
The rule uses the actuel value of the item. If it runs every 30 min. is’t not importent, if the value is from 29:xx or form 30:xx.


(N. Jordan) #12

I agree, but think about a situation where the PVisland system goes offline and no updated values are sent…if the latest value is as low that it would trigger…it will trigger every 30mins as the value does not change anymore even if no updated values come in…

or maybe i do understand this wrong…

How would this be coded in the if part: // check here if the values has changed


(Harry) #13

I presume PVislandVolt is a number-Item.

var Number lastValue = 0

rule "PVisland Voltage below 23V Alert - Notification"
when
   Time cron "0 0,30 * ? * * *"
then
    logInfo("___",lastValue.toString +" "+ PVislandVolt.state.toString)
    if (PVislandVolt.state < 23 && lastValue != PVislandVolt.state) {
       logInfo("___","changed")
//     sendMail(“xxxxxxxxxxxxxxxxxx”, “PVisland | Battery Voltage Level Alert | " + PVislandVolt.state + " V”, “—EoM—”)
       lastValue = PVislandVolt.state}
end

(Rich Koshak) #14

If you take away the requirement that the alert come exactly at 00 and 30 and make your requirement that it only report every 30 minutes it is below the threshold it becomes much simpler. I’ll use Design Pattern: Expire Binding Based Timers and Design Pattern: Separation of Behaviors.

rule "PVisland Voltage below 23V Alert - Notification"
when
    Item PVislandVolt changed
then
    // NULL isn't a value we can use in this rule
    if(PVislandVolt.state == NULL) return;

    // If the Timer is already running we have nothing to do
    if(PVislandVolt_Timer.state == ON) return;

    // Voltage is low, alert
    if(PVislandVolt.state < 23) {
        aAlert.sendCommand("PVisland | Battery Voltage Level Alert | " + PVislandVolt.state + "V", "--EOM--")
        PVislandVolt_Timer.sendCommand(ON)
    }

    // Voltage is back above threshold, cancel alerts
    else {
        PVislandVolt_Timer.postUpdate(OFF)
    }
end

rule "PVislandVol timer expired"
when
    Item PVislandVolt_Timer received command OFF
then
    // No more alerts if the voltage goes above the threshold
    if(PVislandVolt.state == NULL || PVislandVolt.state >= 23) return;

    // alert and reschedule the Timer for another 30 minutes while it remains below threshold
    aAlert.sendCommand("PVisland | Battery Voltage Level Alert | " + PVislandVolt.state + "V", "--EOM--")
    PVislandVolt_Timer.sendCommand(ON)
end

If you only want the one alert when it first goes below the threshold and not get repeats, which you stated is your ultimate goal, then Scott already provided that answer in post 4.

As you can see, minor changes in your requirements can result in drastically different solutions. And all things considered, implementing your ultimate goal is actually far easier than your stated compromise solution.


(N. Jordan) #15

@rlkoshak sorry for the delay. recently tried your rules above including a switch item for the timer. It works great to only allow a first threshold go-below but if voltage goes up again it seems to not reset at all. So until i reboot openhab machine i do not see any warnings anymore…even if it goes above 23V and later again below 23V.

Can you have a quick look what could be wrong or maybe i forgot to implement beneath these scripts.
Thanks Norbert


(Rich Koshak) #16

Add logging to the Rule to see when it is triggering and what it is doing.


(N. Jordan) #17

OK, will try to add some logging information. But what should that show us except from what I already see from the dummy-switch state i already see in the event logs?
There i see that the switch goes ON but never OFF.

btw. why did you use postupdate instead of sendcommand for the OFF? Regards/Thanks Norbert

    pi@SmartPi:~ $ cat /var/log/openhab2/events.log.5 |grep PVislandVolt_
2018-10-30 06:01:07.331 [ome.event.ItemCommandEvent] - Item 'PVislandVolt_Timer' received command ON
2018-10-30 06:01:07.338 [vent.ItemStateChangedEvent] - PVislandVolt_Timer changed from NULL to ON
pi@SmartPi:~ $ cat /var/log/openhab2/events.log.6 |grep PVislandVolt_
2018-11-02 06:01:07.507 [ome.event.ItemCommandEvent] - Item 'PVislandVolt_Timer' received command ON
2018-11-02 06:01:07.516 [vent.ItemStateChangedEvent] - PVislandVolt_Timer changed from NULL to ON
pi@SmartPi:~ $ cat /var/log/openhab2/events.log.5 |grep PVislandVolt_
2018-10-30 06:01:07.331 [ome.event.ItemCommandEvent] - Item 'PVislandVolt_Timer' received command ON
2018-10-30 06:01:07.338 [vent.ItemStateChangedEvent] - PVislandVolt_Timer changed from NULL to ON
pi@SmartPi:~ $ cat /var/log/openhab2/events.log.4 |grep PVislandVolt_
2018-10-26 09:51:28.618 [ome.event.ItemCommandEvent] - Item 'PVislandVolt_Timer' received command ON
2018-10-26 09:51:28.623 [vent.ItemStateChangedEvent] - PVislandVolt_Timer changed from NULL to ON
pi@SmartPi:~ $ cat /var/log/openhab2/events.log.3 |grep PVislandVolt_
pi@SmartPi:~ $ cat /var/log/openhab2/events.log.2 |grep PVislandVolt_
2018-10-21 09:32:10.349 [ome.event.ItemCommandEvent] - Item 'PVislandVolt_Timer' received command ON
2018-10-21 09:32:10.353 [vent.ItemStateChangedEvent] - PVislandVolt_Timer changed from NULL to ON
pi@SmartPi:~ $ cat /var/log/openhab2/events.log.1 |grep PVislandVolt_

(Rich Koshak) #18

It’s the rule running at all?

Are they right if statements of the rule running when PVislandVolt is in its various states?

When something doesn’t work as expected you need to gather information to figure out why. Otherwise you are just guessing.

As I documented in the Expire Binding Based Timers DP I linked above, to cancel the Timer you use postUpdate. If you use sendCommand, the second rule will run and that rule should only run when the timer expires, not when it is cancelled.


(N. Jordan) #19

Thanks for your feedback…
What i found out now is a suspicious line in the openhab.log file…but i cannot see anything wrong.

2018-10-21 09:30:04.097 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'PVisland Voltage below 23V Alert - Notification': The name 'PVislandVolt_Timer' cannot be resolved to an item or type; line 59, column 8, length 18

However I have a Switch item integrated in the default items file…I marked the line that is mentioned with ** **

Switch PVislandVolt_Timer

// ***************************************************************************************************
rule "PVisland Voltage below 23V Alert - Notification"
when
    Item PVislandVolt changed
then
    if(PVislandVolt.state == NULL) return;
    **if(PVislandVolt_Timer.state == ON) return;**
    if(PVislandVolt.state < 23) {
        sendMail("norasdfasfdasfdm", "PVisland | Battery Voltage Level Alert | " + PVislandVolt.state + " V", "---EoM---")
        PVislandVolt_Timer.sendCommand(ON)
    }
    else {
        PVislandVolt_Timer.postUpdate(OFF)
    }
end

rule "PVislandVolt timer expired"
when
    Item PVislandVolt_Timer received command OFF
then
    if(PVislandVolt.state == NULL || PVislandVolt.state >= 23) return;
    PVislandVolt_Timer.sendCommand(ON)
end

(Rich Koshak) #20

Do you see this every time the rule runs or only when oh first starts?