Timer syntax in dsl rules

Hi,

Just recently I realized I’ve been using timers against the best practice syntax.

instead of:

rule "Cat Fountain"
when
    Item CatMotion received update ON
then
    if(timerCat === null) {
      timerCat = createTimer(now.plusMinutes(10) [ |
      LivingRoomFountain.sendCommand(OFF)
      timerCat?.cancel()
      timerCat = null
      ]
       ) 
        }    
    else
        {
timerCat.reschedule(now.plusMinutes(10))
}
end
```

I was closing timer ( ..) immediately like this:

rule "Cat Fountain"
when
    Item CatMotion received update ON
then
    if(timerCat === null) {
      timerCat = createTimer(now.plusMinutes(10)) [ |
      LivingRoomFountain.sendCommand(OFF)
      timerCat?.cancel()
      timerCat = null]
}    
    else
        {
timerCat.reschedule(now.plusMinutes(10))
}
end

I was lucky that DSL engine is forgiving, and it stil worked, it executed stuff inside lambda [ … ] with no issues.

So I wanted to rewrite my rules by the book, started fixing rules, and on first 2 rules that I did, they are now broken with this error:

2025-10-20 16:10:47.012 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'failsafe-4' failed: An error occurred during the script execution: index=1, size=1 in failsafe

so I had to revert back from “fixed” to wrong syntax and now the error is gone.

what gives?

I guess its not allowed to reschedule the timer inside the timer…

how would I have this rule retrying until pojacalo becomes = ON, will this work?

rule "AVR Power ON"
when
    Item AVRPower received command ON 
then
   if(timerAVR === null && pojacalo.state == OFF) {
     timerAVR = createTimer(now.plusSeconds(10),[ 
   if(pojacalo.state == ON)  {  
     IRCC_Power.sendCommand(ON)
     timerAVR.cancel
     timerAVR = null
}
else if (pojacalo.state == OFF)  {
    timerAVR.reschedule(now.plusSeconds(10)) }
]
 )
  }
end

the goal is, after AVR is powered on (with a smart switch that cuts off/on the power), wait for it to boot and become available on the network (takes about 20 seconds), and then issue the command to start (via sony binding)

The recommendation to use createTimer(time, [ | ]) over createTimer(time)[ | ] is for legibility, not something required by the syntax.

Rules DSL had all sorts of shortcuts built in. In this case, if the last argument to a function call is a lambda, you can define the lambda outside the closing paren.

But that makes it a little more challenging for us humans to follow sometimes so we recommend against that.

You are missing a comma

timerCat = createTimer(now.plusMinutes(10), [

You can reschedule, you can’t cancel though. The timer is already running, there’s nothing to cancel.

Why not just do it in another rule that is triggered when pojacalo changes to ON. Check if AVRPower is also on and you can even check to see if it turned on more than 20 seconds ago. Then send your additional on command.

No timers required.

hey thats a great idea, that simple rule can completely replace this rule, so no additional rule. I dont even need to check if AVRPower is on, because there is no way in hell a device responds to ping if it’s respective power socket is not ON.

I just have to see if the device is ready to accept IRCC commands via binding in the same milisecond it becomes online, or I should allow it some seconds to start breathing (so again timer, but still much lighter rule).

Probably with those 10sec retry intervals I am not hitting the exact second it became online so everything works.

I’ll just try it as is and then add timer if it won’t work.

thanks for the suggestion!