Problem with While loop

  • Platform information:
    • Hardware: RPi3
    • OS: openhabian
    • Java Runtime Environment: default for openhabian
    • openHAB version: 2.5.3
  • Issue of the topic:

I have been using the cascading timers DP for a long time. Recently I decided that I needed a little more control about which zones/valves were triggered. In order to accomplish this, I added a new switch item for each valve.

I have attempted to modify the cascading timers DP to consider whether the associated switch has been enabled. If it is on, the rule below will queue the zone up; if the switch is off, it will skip that zone and proceed to the next one, until it finds a zone to queue, or it runs out of possibilities.

I think I have most of it working, except for the following:

rule "Test Switch 2 Rule"
    when
	Item Test_Switch_2 received command ON
    then
	logInfo("Crib","Running Test Switch 2 Rule")

	gZoneSwitch.members.filter[allValves | allValves.state==ON].forEach[ onValve | logInfo("Crib","Item " + onValve.name + " is " + onValve.state) ]
	val totalValves = gZoneSwitch.members.size
	logInfo("Crib","Total items in " + gZoneSwitch.name + " group: " + gZoneSwitch.members.size)
	
	var currValveNum = 1
	logInfo("Crib","Current valve number is: " + currValveNum)
	
	var exitFlag = false
	var nextValveNum = currValveNum + 1

	while ( !exitFlag || nextValveNum <= totalValves ) {
		logInfo("Crib","Next valve number to check is: " + nextValveNum)
		
		var nextOnValve = gZoneSwitch.members.filter[ i | i.name == "Irrigation_Zone_" + nextValveNum + "_Switch" ].head
		logInfo("Crib","Next valve to check: " + nextOnValve.name)
		logInfo("Crib","Next valve state is: " + nextOnValve.state)
		logInfo("Crib","flag: " + exitFlag)

		if (nextOnValve.state == ON) {
			val nextValveName = "Irrigation_Zone_" + nextValveNum
			val nextValve = gAutoIrrigation.members.filter[ valve | valve.name == nextValveName ].head // null if there is no member by that name
			logInfo("Crib","Next actual valve is: " + nextValve)
			exitFlag = true
			logInfo("Crib","flag 2: " + exitFlag)
		}
		nextValveNum = nextValveNum + 1
		//exitFlag = true      <---  this should exit the while loop on the first iteration but doesn't
	}
	logInfo("Crib","Next actual is: " + nextValve.name)
end

The rule checks for a flag to ensure it continues (!exitFlag). It also keeps track of the number of members of the irrigation group and makes sure that the number of iterations doesn’t exceed that number (nextValveNum <= totalValves).

My experience with the rule as written is that even though exitFlag is changed to true, it never triggers an exit from the while loop. I even added an exitFlag = true at the very end the first iteration and it still doesn’t exit until it gets to 7 repetitions (there are 6 members in the group

If I remove the || nextValveNum <= totalValves then it exits correctly (however I want to catch to make sure that should all valves be disabled, it doesn’t continue indefinitely).

I know that I can probably do an if statement to set exitFlag = false at the very end, however I am keen to understand why what I have doesn’t work.

I found this reference which indicates that this sort of thing was possible in 2016.

The only other thing is that VSC complains about the nextValveNum part of the bit below, however the code still runs. Just hoping for any thoughts on how to remove this error
var nextOnValve = gZoneSwitch.members.filter[ i | i.name == "Irrigation_Zone_" + nextValveNum + "_Switch" ].head

As an additional note, currValveNum is set as 1, however once this code works I will use the last triggered valve to define this number.

Any advice on this is hugely appreciated.

The || is an OR so it will also continue for as long nextValveNum <= totalValves is true. So you probably want to use an AND here with && instead of ||.

1 Like

I would like it to exit if either of the conditions were true. Does the && still apply?

Yes when one of those conditions results in false the result of the && also results in false so it will exit the loop. :slight_smile:

See this link for more info on how operators work:

https://www.w3schools.com/jsref/jsref_operators.asp

1 Like

Thank you @wborn and thanks @H102 for your link . That was very helpful.