Callable timer function taking function and delay as parameter

Hi community,

I need a timer function that executes an other function over and over again until stopped.

I assume that this is possible and i think that it could look like this.

rule file:

define TimerFunction(function, delay) → execute the input function every delay-seconds

Rule “FooBar”

Trigger it is midnight

define a function

call the TimerFunction with the previously defined function

thank’s

Alternative structure

Rule “FooBar”

Trigger it is midnight

create a standard timer
[  timer code
do whatever
reschedule itself for N seconds
end timer]

end rule

hi @rossko57 ,
this will not work as the noted in the documentation If the Timer has terminated this method does nothing

Oddly enough, when it executes the reschedule() code the timer is executing, not terminated. Try it.

you might be right, but this is not what I want. I realy need a timer that is called recursivly over and over again, until an event stops it. I probably did not write my question well.

Sure, make it reschedule itself, after it has done whatever you wanted it to do.

Have that event run a rule that cancels the timer.

Without frills -

var loopy = null

rule "initiate everlasting timer"
when
   Item masterSwitch changed to ON
then
   loopy = createTimer(now.plusSeconds(1), [ |
      logInfo("test", "Beep boop") 
      loopy.reschedule(now.plusSeconds(5))
   ]
end

rule "abort timer"
when
   Item masterSwitch changed to OFF
then
   loopy.cancel
end

For more on rossko57’s suggestion see Design Pattern: Looping Timers. Another variation on the overall concept is discussed in Design Pattern: Cascading Timers. Though that is a bit more complicated than what you describe.

thank you both for your answers. the solution with the reschedule timer is working, but I am still interested in my initial idea, if it is possible to write an own timer function that takes an other function as input.

I can’t imagine a case where this would actually make anything simpler, easier to understand, or solve a problem that can’t be solved more easily and safely in a more simple way, but yes, there is a createTimerWithArgument action (which somehow isn’t in the docs anymore) that lest you pass any arbitrary Object as the second argument. This argument will be passed to the lambda which is the third argument. Since a lambda is an Object you can pass a lambda to a lambda in this way.

val MyProcedure = [ |
    // do something
]
createTimerWithArgument(now.plusSeconds 10, MyProcedure, [ arg1 |
    arg1.apply()
]

But it’s way simpler and easier to understand and follow if you just put // do something into the lambda passed to createTimer in the first place. This redirection just makes the code more complicated without actually doing anything for you.

And before you start heading down the path of trying to define MyProcedure as a global variable and use it in multiple Timers, realize that lambdas are not thread safe. If it’s called from two or more separate timers at the same time, they will be stomping all over each other. So this approach will lead to intermittent and inexplicable errors in the long run unless you can guarantee that only one Timer can use the lambda at a time, at which point why not just put that into the Timer itself?