Repeat some actions (and waiting) in rule

I’m trying to makemyself some irrigation logicˇin OH 2.4 … i need to run my water pump every second day for sequence “run -> wait 5 min -> run -> wait 5 min -> run”. It’s because land is not soaking up water quickly enough.

I have item:

Switch greenhouse_Button "Pump" { mqtt=">[mqtt:greenhouse/POWER:command:*:default],<[mqtt:greenhouse/POWER:state:default]", expire="30s,command=OFF" }

Now i wanted to solve it with cron rule:

rule "Greenhouse watering"
when
	Time cron "0 0 23 ? * */2 *" run every other day
then
	var i = 0
	while ((i=i+1) < 2){
		logInfo("Irrigation", i + " test ")
		 Thread::sleep(1000)
	}
end

(In the place for log info right now will be command to turn greenhouse_Button.)
But i’d like to sleep for 5 minutes and with Thread::sleep it’s not recommended.

Can somebody point me in right direction?

Alternatively, you could just set up three cron triggers at five-minute intervals.

Time cron "0 0 23 ? * */2 *" or
Time cron "0 5 23 ? * */2 *" or
Time cron "0 10 23 ? * */2 *"

Personally, I prefer to use createTimers in rules instead of expire bindings (turn the switch on, set a timer for 30 seconds, and then turn it off). I just like being able to see/adjust timers in rules, rather than creating dedicated switch items for expiration purposes.

I’ll have to agree with timers but i can’t figure it out how to do it.
Expire binding is temporary solution at the moment for manual run’s but i’d have to agree timers would be better.

I was thinking about multiple cron run’s but it would get messy quite quickly.

Do i have to use patterns to make such kind of rule to work ?

The Actions documentation says to create a timer using this syntax:

var Timer myTimer = createTimer(now.plusSeconds(30), [ |
    logInfo("rules", "Timer activated")
    ])

I’ve seen other examples that don’t use variables. I think the only difference is that using a variable enables you to use the methods detailed in the Actions documentation. So if you don’t need to cancel, check, or reschedule the timer, this works fine:

greenhouse_Button.sendCommand(ON)
createTimer(now.plusSeconds(30)) [ greenhouse_Button.sendCommand(OFF) ]

You have a few options. You could use a loop (but someone else will have to help you with that, as I’m out of practice). You could use multiple crons as I suggested earlier (I’m not sure why they would get messy if you only need three). Or you could just write out the entire sequence, since its only repeated twice:

greenhouse_Button.sendCommand(ON)
createTimer(now.plusSeconds(30)) [ greenhouse_Button.sendCommand(OFF) ]
createTimer(now.plusSeconds(300)) [ greenhouse_Button.sendCommand(ON) ]
createTimer(now.plusSeconds(330)) [ greenhouse_Button.sendCommand(OFF) ]
createTimer(now.plusSeconds(600)) [ greenhouse_Button.sendCommand(ON) ]
createTimer(now.plusSeconds(630)) [ greenhouse_Button.sendCommand(OFF) ]

I’ve never done something like this, and there might be a good reason to avoid it. Hopefully someone with more expertise will chime in to say that it’s a bad idea. :wink:

Hah. I should have realized you’d have a design pattern for this, Rich. Now I need to find a reason to implement a looping timer.

Out of curiousity, do you typically use expire bindings or timers? I just read your design pattern for expire binding timers, and it seems to me that the timer drawbacks you list pertain to very specific scenarios. I’m guessing it mostly makes no difference, except for a few cases where one is better than the other.

I use Expire binding timers except when I don’t know a priori how long I need to sleep for, or if it’s a “fire and forget” type timer that I don’t have to worry about canceling later. I’d rather not have to write the code to keep up with the timers if I don’t have to so the vast majority of the time I’ll use Expire base Timers coupled with the Associated Items DP and I usually end up with cleaner code as a result.

But I’m personally willing to create lots of Items if it saves complexity in my Rules. Some users would rather have fewer Items rather than simpler/shorter Rules.

Is there a possibility that someone can help making a loop.
With copy and paste it’s doable but would like to make it more generic…

(command repetation in rule)

sendCommand(Valve, ON)
createTimer(now.plusMinutes(1)) [| 
	sendCommand(Valve, OFF)
	createTimer(now.plusMinutes(1)) [| 
		sendCommand(Valve, ON)
		createTimer(now.plusMinutes(1)) [| 
			sendCommand(Valve, OFF)
		]
	]
]

What i’d like is to have Item RepeateLoopXTimes and then i can change it and it “magically” happens.

It would be great to cancel the timer but at the moment the simpliest way would be helpful.

See Design Pattern: Looping Timers which should get you started and provide the explanations for the following:

var maxLoops = 10
var Timer myTimer = null
myTimer = createTimer(now.plusSeconds(0), [ |
    Valve.sendCommand(if(Valve.state != ON) OFF else ON)
    maxLoops = maxLoops - 1
    if(maxLoops > 0) myTimer.reschedule(now.plusMinutes(1))
])

Usually myTimer would be declared as a global so you can cancel the loop from some other Rule if you need to. The first time the Timer is scheduled to run immediately. After maxLoops times the timer exits without being rescheduled.

Excellent, thank you.

I was reading Design patterns but didn’t get it … too hard for my brain :frowning:

Now i’ll have to test if it’s working like it should :slight_smile: