Loop condition state refresh issue

Hi all,
I am certain I have read somewhere that their is known feature issue around do loop conditions not being checked and using a cached state rather than getting it fresh on each loop, but I cannot recal where I read it and even if its true I need a fresh way to deal with my se case so I have opened this thread to present options.

I am turning on a heater for a hardcoded amount of time and after the time expires I turn off the heater, 95% of the time that is it everything is great but sometimes the sonoff does not turnoff and rather than just advise us that the timer has expired I would like it to advise us that the heater did not turn off when it should have, that way a human will switch off the heater.

I have tried many ways to deal with this and found that the voltage is not being seen to have changed to 0 volts thus indicating that it has been correctly turned off. looking for improvements in the approach.

RULE

rule "Alexa bedroom getting dressed"
when
	Member of EchoCmds changed to "bedroom getting dressed" or
	Item rGettingDressed received command ON
then
	logInfo("getting-dressed","BR1_Temp_Auto : " + BR1_Temp_Auto.state)

	// record current temp control setting
	val String AUTO_START = BR1_Temp_Auto.state.toString
	logInfo("getting-dressed","AUTO_START : " + AUTO_START)	

	// turn off temp control
	BR1_Temp_Auto.postUpdate(OFF)

	// turn on heater
	sendCommand(BR1_Heater,ON)

	// start timer for ten minutes, then turn temp control to previous setting
	// turn off heater
	createTimer(now.plusMinutes(1)) [ | {
		BR1_Temp_Auto.postUpdate(AUTO_START)			

		var Number Attempts = 0
		
		
		//for (Attempts = 0; Attempts < cars.length; Attempts++) { 
		//	logInfo("getting-dressed", "Turn off Bedroom heater, Attempt:"+Attempts.toString+" Voltage:"+BR1_Heater_Voltage.state.toString)			
		//}
		
		
		
		do {
			createTimer(now.plusSeconds(3)) [ | {
				Attempts += 1
				sendCommand(BR1_Heater,OFF)
				logInfo("getting-dressed", "Turn off Bedroom heater, Attempt:"+Attempts.toString+" Voltage:"+BR1_Heater_Voltage.state.toString)
			}]
		} 	while (BR1_Heater_Voltage.state!=0 && Attempts < 3)
		
		if (Attempts >= 3) {
			logError("getting-dressed", "3 failures turning off Heater")
			if (BR1_Echo_Notify.state != OFF) {BR1_Echo_TTS.sendCommand('The getting dressed timer has expired but the heater has not turned off.')}
			if (LR_Echo_Notify.state != OFF) {LR_Echo_TTS.sendCommand('The getting dressed timer has expired but the heater has not turned off.')}
			if (BR4_Echo_Notify.state != OFF) {BR4_Echo_TTS.sendCommand('The getting dressed timer has expired but the heater has not turned off.')}
		}      

		if (BR1_Heater_Voltage.state==0) {
			// Announce getting dressed period has ended and heater has turned off.
			if (BR1_Echo_Notify.state != OFF) {BR1_Echo_TTS.sendCommand('The getting dressed timer has expired')}
			if (LR_Echo_Notify.state != OFF) {LR_Echo_TTS.sendCommand('The getting dressed timer has expired')}
			logInfo("getting-dressed","expiration announcment complete.")	
			if (HO_Echo_Notify.state != OFF) {HO_Echo_TTS.sendCommand('The getting dressed timer has expired')}
		}
	}]
	logInfo("getting-dressed","rule exited.")		
end

The rule above is just where it happened to be when I decided to reach out it is not the best way I have found so far.
Hopefully providing the whole rule helps with context but really its only a small functional block of code that needs to be modified (or so I think).

Regards
Paul

Do-loop in rules are almost always to be avoided.

I don’t think your draft do loop would work as expected anyway. It would quickly whizz round and make three timers, all set to go off at much the same time.

I think I’d separate out the tasks here. Have your main timing rule just issue heater off.
A separate rule can listen for command off to heater, and start a timer to check later, while bumping a counter. The timer can resend command if needed (which will fire its parent rule again, maybe spawning another timer if counter below threshold)

@rossko57 Thanks for the alternative approach.
I will give it a try and provide the final solution for others when it functions how I would like.

Regards

Paul

The difficult part is figuring out when to reset the “retry counter”.
A little rule that fires when device status actually changes would cover normal working. Don’t be afraid to have several little rules acting in concert.

I must confess I was trying to simplify by reducing the number of moving parts.
Although using your approach I think I can gain some safty improvements froo all heaters and other items that I want to ensure actually turn off when instructed.

I am in the process of tweaking my rules for best results.

Regards
Paul