How do you want the count to decay? For example Marcoās post ten seconds after the last time the button is pressed the count resets all the way back to 0. But you could have it count up and then gradually count down also.
If you are using UI rules you can put the test for time of day into the condition part of the rule instead on inline as part of the action of the rule.
NOTE: Iām just typing this in to the forum, itās not been tested.
var OPENHAB_CONF = java.lang.System.getenv("OPENHAB_CONF");
load(OPENHAB_CONF+'/automation/lib/javascript/community/timerMgr.js');
this.timers = (this.timers === undefined) ? new TimerMgr() : this.timers;
this.uid = (this.uid === undefined) ? 0 : this.uid;
// The test for time would be in a Condition for the rule
this.uid++;
this.timers.check("Doorbell"+this.uid, "10s");
// I need to add a function to TimerMgr to get the count so the following isn't necessary
var count = 0;
for(var key in this.timers){
count++;
}
if(count == 5) {
doorOpener.sendCommand(ON);
this.timersCancelAll();
}
I created TimerMgr for just such situations where one needs to manage a bunch of timers based on a key. The code above loads the TimerMgr library and initializes the TimerMgr Object and a one up counter so we can have a unique ID per Timer. We increment the uid and the call check on TimerMgr which checks to see if there already is a timer with that ID and if not creates one. The TimerMgr will handle clearing the Timer out once it expires and we donāt really need to do anything when the Timer does go off so thatās it. Then we get a count of the Timers in timers and if itās 5 we trigger the actions and delete all the scheduled Timers.
The rule will be even simpler if I implement the count stuff in TimerMgr itself, for which Iām creating an issue right now so I donāt forget.
import java.util.Map
val Map<Number, Timer> doorbellTimers = newHashMap
rule "push doorbell 5 times within 10 seconds to activate door opener"
when
Item Doorbell changed to ON
then
if (now.getHour() < 6 || now.getHour() >= 20) {
return;
}
if (doorbellTimers.size == 4) {
doorOpener.sendCommand(ON)
for (i : 3 .. 0) {
doorbellTimers.get(i)?.cancel()
}
} else {
if (doorbellTimers.get(doorbellTimers.size) === null) {
doorbellTimers.put(doorbellTimers.size, createTimer(now.plusSeconds(2), [|
doorbellTimers.put(doorbellTimers.size, null)
]))
}
}
end
Going back to marcos reply, its not working for me. But i am probably
doing something wrong.
I have added the rule under Scrips in the OP3 setting section.
Is that correct?
Log says:
==> /var/log/openhab/openhab.log <==
2021-08-27 12:00:43.821 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ād600ba0e0aā failed: :1:10 Expected ; but found DoorbellTimer
var Timer DoorbellTimer = null
^ in at line number 1 at column number 10
No. @duiffie rule is intended to go in a xxx.rules file, and wonāt work in GUI entry, because you have nowhere āoutsideā of your GUI rule to define āglobalsā that persist between rule runs.
You can do something similar, but itāll need rewriting.
i have have entered a .rules with the rule from marco and i am getting this back:
2021-08-30 10:18:38.171 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model ārule-5doorbell.rulesā
2021-08-30 10:18:38.835 [WARN ] [e.runtime.internal.RuleContextHelper] - Variable āCounterā on rule file ārule-5doorbell.rulesā cannot be initialized with value āorg.eclipse.xtext.xbase.impl.XNumberLiteralImpl@1cb2ced (value: 0)ā: An error occurred during the script execution: null