Rule review: trigger rule "item changed" from itself

Greetings from Germany,

for controlling the light in my rooms I decided to set them in “states”. Those states will change the lighting and so on. Hardware-Switches or Motion Sensors will set the State, not write to the light-bulbs directly.
An important feature I’d like to have is a kind of “auto-state”, which depends on the virtual item “TimeOfDay” and therefore chooses the correct light setting.

  • when turning ON the light, the state will be changed from “0” (OFF) to “1” (ON_AUTO), this “1” is my “auto-state”

  • this State “1” doesn’t switch any lights but chooses, depending on the virtual item “TimeOfDay”, another state like “10” for sleeping-time, “11” for dawn, “12” for day-mode and “13” for maximum brightness

  • states 10,11,12 or 13 turns the actual hardware ON

  • state 0 turns the lights OFF

  • Example: Light is OFF (State 0) --> Switch is pressed --> State 1 --> item “state” changed --> rule is executed and chooses to set the same state to 12 because TimoOfDay is “Tag” --> item “state” changed again --> same rule is executed an turns on the lights

my question:

  • is it possible to trigger the rule for “changed item” from itself by changing this item with “sendCommand” (or maybe “sendUpdate”?)

Thanks in advance,
Axel

Items (without the groups)

String 	vTimeOfDay 	"Tageszeit [%s]"				(gDay)
Number 	vState_WZ 	"Lichtstimmung Wohnzimmer"	<colorpicker>	(gLightStates)

Dimmer 	WZ_Yeelight_WallLeft_Brightness 		<slider> 	(gWohnzimmer, gDimmLicht)		{ channel="yeelight:Wonder:0x00000000036d7XXX:Brightness" }
Dimmer 	WZ_Yeelight_WallLeft_ColorTemperature 		<colorlight>	(gWohnzimmer, gColorLicht)		{ channel="yeelight:Wonder:0x00000000036d7XXX:Color_Temperature" }

//--- Groups (not all)
Group 		gWohnung
Group 			gWohnzimmer  			(gWohnung)
Group 			gAktoren      			(gWohnung)
Group:Number			gLicht			(gAktoren)
Group:Number:AVG			gDimmLicht	(gLicht)
Group:Number:AVG			gColorLicht	(gLicht)

Rule

//------ Light Settings
	val sleep_Brightness = 1
	val sleep_ColorTemperature = 20
	val night_Brightness = 20
	val night_ColorTemperature = 22
	val day_Brightness = 80
	val day_ColorTemperature = 24
	val max_Brightness = 100
	val max_ColorTemperature = 28
	
//------ Light StateMachines
	rule "vState_WZ"
	when
		Item vState_WZ changed
	then
		switch (vState_WZ.state) {
			//	AUS
			case 0: {
				gWohnzimmer.members.filter[light | light.getGroupNames.contains("gLicht")].forEach[ light | if (light.state == ON) light.sendCommand(OFF)]
			}
			//	AUTO --> Auswahl nach Tageszeit
			case 1: {
				switch (vTimeOfDay.state) {
					case "Schlafen": 		vState_WZ.sendCommand(10)
					case "Morgen": 			vState_WZ.sendCommand(11)
					case "Tag": 			vState_WZ.sendCommand(12)
					case "Nachmittag": 		vState_WZ.sendCommand(12)
					case "Abend": 			vState_WZ.sendCommand(11)
					case "Nacht": 			vState_WZ.sendCommand(10)
				}
			}
			// Schlafen
			case 10: {
				gWohnzimmer.members.filter[light | light.getGroupNames.contains("gDimmLicht")].forEach[ light | light.sendCommand(sleep_Brightness) ]
				gWohnzimmer.members.filter[light | light.getGroupNames.contains("gColorLicht")].forEach[ light | light.sendCommand(sleep_ColorTemperature) ]
			}
			// Dämmerung
			case 11: {
				gWohnzimmer.members.filter[light | light.getGroupNames.contains("gDimmLicht")].forEach[ light | light.sendCommand(night_Brightness) ]
				gWohnzimmer.members.filter[light | light.getGroupNames.contains("gColorLicht")].forEach[ light | light.sendCommand(night_ColorTemperature) ]
			}
			// Tag
			case 12: {
				gWohnzimmer.members.filter[light | light.getGroupNames.contains("gDimmLicht")].forEach[ light | light.sendCommand(day_Brightness) ]
				gWohnzimmer.members.filter[light | light.getGroupNames.contains("gColorLicht")].forEach[ light | light.sendCommand(day_ColorTemperature) ]
			}
			// Maximal
			case 13: {
				gWohnzimmer.members.filter[light | light.getGroupNames.contains("gDimmLicht")].forEach[ light | light.sendCommand(max_Brightness) ]
				gWohnzimmer.members.filter[light | light.getGroupNames.contains("gColorLicht")].forEach[ light | light.sendCommand(max_ColorTemperature) ]
			}
		
		}
	end

Item vState_WZ changed

gWohnzimmer must be a Group

Hi there,

maybe you try to change “item” to “Item”?

What is your Item-definition for vTimeOfDay?

it is. i will add the group definitions above

i will definitely try this when I come home!

also added above

I looks like your errors have been addressed by the other responders. I’m going to address the wider problem.

https://docs.openhab.org/configuration/editors.html

If you use a properly configured VSCode with the openHAB extension you will see these errors as you type which will greatly speed up your ability to detect and correct errors.

I don’t understand the question.

See https://docs.openhab.org/configuration/rules-dsl.html#event-based-triggers

Thank you. Now the rule is accepted, but not working

the rule for “Item vState_Flur changed” changes this item “vState_Flur” and therefore shall be executed again … this is not working as intended

Then you have to trigger the Rule with received command and in the rule change the Item’s state using post update.

Of course, this also means that you always have to use a command to trigger the Rule.

Ultimately, you should separate the check against vTimeOfDay from the other cases so you are not changing the state of vState_WZ in the rule in the first place.

A couple of other notes:

  • if you use a String Item for vState_WZ your code will be much more self-documenting and clear
  • Are there members of gDimmLicht that are not members of gWohnzimmer? If not just gDimmLicht.sendCommand().
//------ Light Settings
	val sleep_Brightness = 1
	val sleep_ColorTemperature = 20
	val night_Brightness = 20
	val night_ColorTemperature = 22
	val day_Brightness = 80
	val day_ColorTemperature = 24
	val max_Brightness = 100
	val max_ColorTemperature = 28

//------ Light StateMachines
	rule "vState_WZ"
	when
		item vState_WZ changed
	then
            // get the current state
            var s = vState_WZ.state

            // override the current state based on vTimeOfDay if we are in Auto mode
            if(s == "Auto") {
                switch(vTimeOfDay.state) {
                    case "Schlafen":   s = "Schlafen"
                    case "Morgen":     s = "Dämmerung"
                    case "Tag":        s = "Tag"
                    case "Nachmittag": s = "Tag"
                    case "Abend":      s = "Dämmerung"
                    case "Nacht":      s = "Schlafen"
                }
            }

            // If the state is to turn everything off, just do it
            if(s == "Aus") {
                gWohnzimmer.members.filter[light | light.getGroupNames.contains("gLicht")].forEach[ light | if (light.state == ON) light.sendCommand(OFF)]
            }

            // Set the brightness and color temp
            else {

                // Use the swithc statement to determine what the brightness and color temp is
                var brightness = 0
                var color = 0

                switch(s){
                    case "Schlafen":  { brightness = sleep_Brightness color = sleep_ColorTemperature }
                    case "Dämmerung": { brightness = night_Brightness color = night_ColorTemperature }
                    case "Tag":       { brightness = day_Brightness   color = day_ColorTemperature }
                    case "Maximal":   { brightness = max_Brightness   color = max_ColorTemperature }
                    default:          { brightness = max_Brightness   color = max_ColorTemperature }
                }

                // Only loop through the Groups to apply the dimmer and color temp in one place in the rule.
                gWohnzimmer.members.filter[light | light.getGroupNames.contains("gDimmLicht")].forEach[ light | light.sendCommand(brightness) ]
                gWohnzimmer.members.filter[light | light.getGroupNames.contains("gColorLicht")].forEach[ light | light.sendCommand(color) ]
            }
        end

Thank you very much Rich.
I changed to use VSCode now and also changed the rules according to your hints.

The reason I used numbers instead of a string for the states was, that a have double-button wall-mounted switches, which will increase/decrease the state. I thought it would be better to do this with numbers.

Sounds like a good reason.