Item change state and wait time

I’m trying to write a rule where if the “pir_port” item changes from OPEN to CLOSE and the item “arm_pir == OFF”
play the mp3 file, and wait a minute before playing it again, even if the “pir_porta” item changes its status

rule "pir_move"

when

Item pir_porta changed from OPEN to CLOSED

then

 if (arm_pir.state==ON){
sendCommand(luce_scale, ON)
sendCommand(madia, ON)
}

if (arm_pir.state==OFF){
//else {
playSound("movimento_porta_rilevato.mp3")
Thread::sleep(60000) // 60 secondi
}	
end

thanks for your help
Davide

You have a whole lot of errors in these rules. Some major, some minor.

  • Always use the method on the Item instead of the Action when you know the Item in the Rule. For example, luce_scale.sendCommand(ON)

  • I’m not sure why you commented out the else. In a case like this where arm_pir can only have two valid states the else is the better approach. If for some reason arm_pir.state changes while the if(arm_pir.state == ON) is executing, both if statements will be run. Also, it is causing the Rule to do extra work.

You basically already have the code already. As written you just need to add the playSound after the Thread::sleep to play it again. That will cause the sound to be played again after one minute.

One thing to realize is that every time that an event occurs, in this case pir_porta changing from OPEN to CLOSED an instance of this Rule will be triggered and start running. So if pir_porta goes to OFF during the Thread::sleep it doesn’t matter to the Rule, it is already running. BUT, if pir_porta goes to CLOSED again within that minute then the whole Rule will run again and you will have two copies of this Rule running at the same time and the sound will be played again for that one. And if this happens five times in a row, it will mean that NO other Rules will be able to run until one of these stops running. See Why have my Rules stopped running? Why Thread::sleep is a bad idea

So to solve your basic problem without using Thread::sleep use a Timer to schedule the second playSound in a minute.

rule "pir_port changed to CLOSED"
when
    Item pir_port changed from OPEN to CLOSED
then
    if(arm_pir.state == OFF) {
        playSound("movimento_porta_rilevato.mp3")
        createTimer(now.plusMinute(1), [ | playSound("movimento_porta_rilevato.mp3") ])
    }
end

now it’s work! thanks!
and thanks also for the suggestion:

createTimer(now.plusMinute(1), [ | playSound(“movimento_porta_rilevato.mp3”) ])

I had tried to make it work in other rules without success

rlkoshak
I have taken your rule and tried to modify it to send a command if the door is left open longer than 15 seconds. My failed attempt just completes my command 15 seconds after the door is “OPEN”, no matter if it is “CLOSED” before the timer completes. How can I get the timer to stop if the door is “CLOSED” and if the door is not “CLOSED” repeat the command every 15 seconds until the door is closed?

rule "DoorOpenTooLong"
when
    Item PatioDoorSensor changed
then
    if(PatioDoorSensor.state == OPEN) {
                 createTimer(now.plusSeconds(15), [ | executeCommandLine("flite -voice awb -f /Doors/ShutPatioDoor.txt") ])
                 logInfo("DOOR", "Patio Door is Still " + PatioDoorSensor.state)
    }
else                             
	if(PatioDoorSensor.state == CLOSED){
                logInfo("DOOR", "Patio Door is finally " + PatioDoorSensor.state)
    }
end

Thanks in advance for any help

Recent similar thread

You need to keep a handle on the timer, so that you can cancel it later if required

1 Like

Thanks, I have this working now after looking in several threads, including here https://community.openhab.org/t/design-pattern-expire-binding-based-timers/32634

For anyone wanting to do something similar keep in mind I am not a coder. I would be interested to hear feedback on my solution.

I created an Item with an expire timer to help keep track of the timer. I can also manually start/stop the timer.

Switch PatioDoorTimer "PatioDoor Timer" {expire="15s,command=OFF"}

Then I created a rule to turn on that timer when the door opens. When the door closes, it sends an update to turn off the timer. It continues to repeat the command every 15 seconds until the door is shut.

Rules:

rule "DoorOpenTimerStart"
when
    Item PatioDoorSensor changed from CLOSED to OPEN
then

PatioDoorTimer.postUpdate ("ON")
    
end


rule "DoorOpenTimerAlert"

when

	Item PatioDoorTimer changed from ON to OFF

then
	if (PatioDoorSensor.state == OPEN)  {
		
		executeCommandLine("flite -voice awb -f /Doors/ShutPatioDoor.txt")
		logInfo("DOOR", "Patio Door Open longer than 15 seconds, reseting Timer")
		PatioDoorTimer.postUpdate ("ON")	
	}
else
 if (PatioDoorSensor.state == CLOSED) {
  PatioDoorTimer.postUpdate ("OFF")
  logInfo("DOOR", "Patio Door Closed, Timer OFF")
 
  
  }
  end
2 Likes