Match name of similiar items in two different groups

So when the state of my home change to Night or similar I will change my heating setpoint to the night level.

My items are:

Number Heating_LivingRoom_Setpoint (Group_SetPoint, Group_LivingRoom)
Number Heating_LivingRoom_Setpoint_Night (Group_SetPointNight, Group_LivingRoom)

so in my rule I have:

Heating_LivingRoom_Setpoint.state= Heating_LivingRoom_Setpoint_Night.state
Heating_BedRoom_Setpoint.state= Heating_LivingRoom_Setpoint_Night.state

But to make it more generic and share the code here I was thinking about looping through the group instead of copying to each room:

Group_SetPoint.members.filter[l|forEach[l| l.sendCommand((l.name + "_Night").state)) ]

and to even make it more compact “_Night” could be taken from the TimeOfDay varaible, but not all time of the day has its own set temperature…

My complete rule for reference is here:

rule StateRule
when
    Item TimeOfDay received command
then
	//if WORKMODE.state.toString == "NORMAL") 
		if(TimeOfDay.state.toString == "MORNING") {
			//heatUp to 18C in bedrooms, 21C in livingroom,23C in bathroom
			Heating_LivingRoom_Setpoint = Heating_LivingRoom_Setpoint_Day
		}
		else if(TimeOfDay.state.toString == "DAY") {
			//Dim lights for 15 minutes from 0% to 100% 
			//dimLights(Group_LivingRoom,100,15*60).apply	
			//dimLights(Group_MasterBedRoom,70,15*60).apply
			//dimLights(Group_Hallway,85,15*60).apply	
			//heatConstant to 18C in bedrooms, 21C in livingroom,23C in bathroom
		}
		else if (TimeOfDay.state.toString == "WORK") {
			//heatDown to 10C in bedrooms, 12C in livingroom,16C in bathroom
		}
		else if (TimeOfDay.state.toString == "AFTERNOON") {
			//heatUp to 18C in bedrooms, 19C in livingroom,23C in bathroom
		}
		else if TimeOfDay.state.toString == "EVENING") {
			//Dim lights for 60 minutes from 100% to 40% 
			//dimLights(Group_LivingRoom,40,60*60).apply	
			//dimLights(Group_Hallway,40,60*60).apply
			//heatup to 21C in living Room
			
		else if TimeOfDay.state.toString == "NIGHT")	
			//heatDown to 14C in bedrooms, 10C in livingroom,18C in bathroom
			Heating_LivingRoom_Setpoint = Heating_LivingRoom_Setpoint_Night
		}
	//}
end

This is a great implement of the Associated Items Design Pattern. Thanks for sharing!

I do something almost identical for my lighting. The biggest difference is I went ahead and created a Group for all the times of day (two Groups actually, one for entering a time of day and one for exciting) and left them empty if I didn’t have anything to be done during that time period.

Note, I assume the above is pseudo code and you are actually using sendCommand to change the states of your Items.

Here is my code for the curious.

rule "Set lights based on Time of Day"
when
  Item vTimeOfDay changed
then
  // reset overrides
  gLights_WEATHER_OVERRIDE.postUpdate(OFF)

  val offGroupName = "gLights_OFF_"+vTimeOfDay.state.toString
  val onGroupName = "gLights_ON_"+vTimeOfDay.state.toString

  logInfo(logName, "Turning off lights in " + offGroupName)
  val GroupItem offItems = gLights_OFF.members.filter[g|g.name == offGroupName].head as GroupItem
      offItems.members.filter[l|l.state != OFF].forEach[l | l.sendCommand(OFF)
  ]

  logInfo(logName, "Turning on lights for " + onGroupName)
  val GroupItem onItems = gLights_ON.members.filter[g|g.name == onGroupName].head as GroupItem
      onItems.members.filter[l|l.state != ON].forEach[l | l.sendCommand(ON)
  ]

end

Hi,

I tried this approach with a slight modification and faced error I cannot figure out.

val GroupItem lights = gLAuto.members.filter[ n | n.name.startsWith("tr_SW_KC")].head as GroupItem

I’m getting error:

[ERROR] [rg.eclipse.smarthome.model.rule.runtime.internal.engine.RuleEngineImpl] - Rule 'test': Could not cast [tr_SW_KC_Kitchen_Auto (Type=SwitchItem, State=ON, Label=Worktop auto switch, Category=switch, Tags=[Switchable], Groups=[gLAuto]), tr_SW_KC_KitchenUP_Auto (Type=SwitchItem, State=OFF, Label=Sink auto switch, Category=switch, Tags=[Switchable], Groups=[gLAuto])] to org.eclipse.smarthome.core.items.GroupItem; line 5, column 25, length 77

Any clue what I’m doing wrong?

If these are both Items, this is a bit sketchy.
First off we should be dealing with Item .state

Second, although lines like
thisItem.state = thatItem.state
do appear to work in at least some versions of OH, it’s not documented. The more formal method is preferred
thisItem.postUpdate ( thatItem.state.toString )

Hi,

I was badly reffering to @rlkoshak approach which is similar to what I tried using groups. :slight_smile:

The only problem I’m facing is with this line of code:

val GroupItem lights = gLAuto.members.filter[ n | n.name.startsWith("tr_SW_KC")].head as GroupItem 

Where I’m getting error:

[ERROR] [rg.eclipse.smarthome.model.rule.runtime.internal.engine.RuleEngineImpl] - Rule 'test': Could not cast [tr_SW_KC_Kitchen_Auto (Type=SwitchItem, State=ON, Label=Worktop auto switch, Category=switch, Tags=[Switchable], Groups=[gLAuto]), tr_SW_KC_KitchenUP_Auto (Type=SwitchItem, State=OFF, Label=Sink auto switch, Category=switch, Tags=[Switchable], Groups=[gLAuto])] to org.eclipse.smarthome.core.items.GroupItem; line 5, column 25, length 77

Your group gLAuto has a member Item tr_SW_KC_KitchenUP_Auto which is a Switch type and so cannot be cast as Group type.

So what would be the approach in order to create ‘light’ group which will contain only items that match gLAuto.members.filter results?

Rick’s rule looks through a group to find name-matched group members that are themselves groups. Sub-groups, if you will.
Then it works through the chosen sub-group doing stuff to each of the individual member Items.

What is it that you are trying to achieve?

This is a working example:

gMSensors is the group of motion sensors.
gLAuto is the group of Switch items that represents lights that needs to be played with once some of sensors state is changed
gBrightness is the group of Switch items that are connected to light Dimmer Item
gLightSwitches is the group of Switch items that are connected to light Switch Item

Items:

Dimmer		tr_KC_KitchenUP_Brightness			"Sink light"					    <dimmablelight>		(Kitchen, gBrightness, gKCBrightness_Dimmer)	[ "Lighting" ]      { channel="tradfri:0100::trKCKitchenUPTrans:brightness" }
Switch		tr_SW_KC_KitchenUP_Brightness		        "Sink light switch"				    <switch>			(Kitchen, gKCAllLight_SW, gLightSwitches)                           { channel="tradfri:0100::trKCKitchenUPTrans:brightness" }
Switch		tr_SW_KC_KitchenUP_Auto			        "Sink auto switch"      		            <switch>                    (gLAuto)                                        [ "Switchable" ]

Switch 	        Xi_MotionSensor_KC_Status 		        "Xi Motion status"										        <motion>       	(gMSensors)                     { channel="mihome:sensor_motion:::motion" }

Rule:

rule "Auto lights on"
when
	Member of gMSensors changed
then
	val sensor = triggeringItem
	gLAuto.members.filter[ n | 
			n.name.startsWith("tr_SW_" + sensor.name.split("_").get(2))
	    ].forEach[al |
            if(al.state==ON){
                if(sensor.state==ON){
                    val light= gBrightness.members.findFirst[ n | 
                        n.name == "tr_" + sensor.name.split("_").get(2) + "_" + al.name.split("_").get(3) +"_Brightness" 
                    ] as DimmerItem 
                    if((AS_Sun_Elevation.state as DecimalType).intValue >=0){
                        sendCommand(light,80)
                    }else{
                        sendCommand(light,(AS_Sun_Elevation.state as DecimalType).intValue+80)
                    }                
                }else{
                    val light= gLightSwitches.members.findFirst[ n | 
                        n.name == "tr_SW_" + sensor.name.split("_").get(2) + "_" + al.name.split("_").get(3) +"_Brightness" 
                    ] as SwitchItem
                    sendCommand(light,OFF)
                }
            }   
	    ]

end

The only problem is that I would like to make it more readable by making new group of switch items on the fly to play with.

As rossko57 said, the Rule I posted above runs on a Group of Groups.

gLights_OFF is a Group that contains just other Groups as it’s members. For example, gLights_OFF_MORNING. These subgroups contain the actual Switch Items.

Here is the .items file that goes with that Rule.

Group:Switch:OR(ON,OFF) gLights_ALL "All Lights"
        <light>

Group:Switch:OR(ON, OFF) gLights_ON
Group:Switch:OR(ON, OFF) gLights_OFF
Group:Switch:OR(ON, OFF) gLights_ON_MORNING    (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_MORNING   (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_DAY        (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_DAY       (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_AFTERNOON  (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_AFTERNOON (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_EVENING    (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_EVENING   (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_NIGHT      (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_NIGHT     (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_BED        (gLights_ON)
Group:Switch:OR(ON, OFF) gLights_OFF_BED       (gLights_OFF)
Group:Switch:OR(ON, OFF) gLights_ON_WEATHER
Group:Switch:OR(ON, OFF) gLights_WEATHER_OVERRIDE

Switch aFrontLamp "Front Room Lamp"
  (gLights_ALL, gLights_ON_MORNING, gLights_OFF_DAY, gLights_ON_AFTERNOON, gLights_ON_EVENING, gLights_OFF_NIGHT, gLights_OFF_BED, gLights_ON_WEATHER) [ "Lighting" ]
  { channel="zwave:device:dongle:node2:switch_binary" }
Switch aFrontLamp_Override "Override Cloudy FR" (gLights_WEATHER_OVERRIDE)

Switch aFamilyLamp "Family Room Lamp"
  (gLights_ALL, gLights_ON_MORNING, gLights_OFF_DAY, gLights_ON_AFTERNOON, gLights_ON_EVENING, gLights_OFF_NIGHT, gLights_OFF_BED, gLights_ON_WEATHER) [ "Lighting" ]
  { channel="zwave:device:dongle:node4:switch_binary" }
Switch aFamilyLamp_Override "Override Cloudy F" (gLights_WEATHER_OVERRIDE)

Switch aPorchLight "Front Porch"
  (gLights_ALL, gLights_OFF_MORNING, gLights_OFF_DAY, gLights_ON_AFTERNOON, gLights_ON_EVENING, gLights_OFF_NIGHT, gLights_OFF_BED) [ "Lighting" ]
  { channel="zwave:device:dongle:node3:switch_binary" }
Switch aPorchLight_Override "Override Cloudy Porch" (gLights_WEATHER_OVERRIDE)

Were I to implement this again I’d do a few things differently but the overall approach is still sound.