Trying to create a rule with member.filter inside a member.forEach.... or any other suggestions

  • Platform information:
    • Hardware: x86
    • OS: Docker in Kubernetes
    • Java Runtime Environment: openhab/openhab:3.3.0
    • openHAB version: 3.3

Hi, I’m looking for a bit of help working with groups within groups.I could code this all out with a lot of repetition with fixes group and item names but that is going to be a bit of a nightmare and not scale.

Theoretical

Want to get a group from main group then get the members of the sub group
Main group
Sub group 1 = ON
Switch 1 = ON
Switch 2 = OFF
Switch 3 = ON
etc
Sub Group 2 = ON
Switch 1 = ON
Switch 2 = ON
Switch 3 = ON
etc
Sub Group 3 = OFF
Switch 1 = OFF
Switch 2 = OFF
Switch 3 = OFF
etc
More sub groups……

Rule

  1. Get a sub group that is a member of the main group and = ON
  2. Do stuff (this needs to run in a specific order, and is not sortable by number or letter)
    a. If switch 1 is ON then
    b. Else if switch 2 is on then
    c. etc
  3. Get the next sub group that is ON
    a. If switch 1 is ON then
    b. Else if switch 2 is on then
    c. etc
  4. Get the next sub group that is ON
    a. Etc.
  5. Etc.

Actaul itesms and what I have so far… (you can probably see where this is going… there will be a start time for each ‘mode’, so need to check through with else if)

gRoomModeRoomEnable.members.filter[ i | i.state == ON ].forEach[ i |
    logInfo("ROOM", i.toString)
]

Output

2022-10-24 09:55:31.121 [INFO ] [org.openhab.core.model.script.ROOM  ] - gLivingRoomModeEnable (Type=GroupItem, BaseType=SwitchItem, Members=19, State=ON, Label=Living Room Mode Enable, Category=settings, Groups=[gRoomModeRoomEnable, gLivingRoomModeSettings])
2022-10-24 09:55:31.121 [INFO ] [org.openhab.core.model.script.ROOM  ] - gDiningRoomModeEnable (Type=GroupItem, BaseType=SwitchItem, Members=19, State=ON, Label=Dining Room Mode Enable, Category=settings, Groups=[gRoomModeRoomEnable, gDiningRoomModeSettings])

First room

gLivingRoomModeEnable.members.filter[ i | i.state == ON ].forEach[ i |
    logInfo("ROOM", i.toString)
]

Output

2022-10-24 09:57:10.925 [INFO ] [org.openhab.core.model.script.ROOM  ] - livingRoomModeWeekdayEarlyEveningEnable (Type=SwitchItem, State=ON, Label=Living Room Enable Weekday Early Evening Mode, Category=switch, Tags=[Switch, Scene], Groups=[gLivingRoomModeEnable, gLivingRoomModeWeekdayEarlyEvening])
2022-10-24 09:57:10.926 [INFO ] [org.openhab.core.model.script.ROOM  ] - livingRoomModeWeekdayNightEnable (Type=SwitchItem, State=ON, Label=Living Room Enable Weekday Night Mode, Category=switch, Tags=[Switch, Scene], Groups=[gLivingRoomModeEnable, gLivingRoomModeNight])

Next room

gDiningRoomModeEnable.members.filter[ i | i.state == ON ].forEach[ i |
    logInfo("ROOM", i.toString)
]

Output

2022-10-24 09:58:50.774 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayEarlyMorningEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Early Morning Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeWeekdayEarlyMorning])
2022-10-24 09:58:50.774 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayMorningEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Morning Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeWeekdayMorning])
2022-10-24 09:58:50.775 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayDaytimeEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Daytime Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeWeekdayDaytime])
2022-10-24 09:58:50.775 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayEarlyEveningEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Early Evening Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeWeekdayEarlyEvening])
2022-10-24 09:58:50.775 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayEveningEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Evening Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeWeekdayEvening])
2022-10-24 09:58:50.776 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayNightEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Night Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeNight])

And all members of main group (just for info really)

gRoomModeRoomEnable.allMembers.filter[ i | i.state == ON ].forEach[ i |
    logInfo("ROOM", i.toString)

]

Output

2022-10-24 10:00:00.789 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayEveningEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Evening Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeWeekdayEvening])
2022-10-24 10:00:00.789 [INFO ] [org.openhab.core.model.script.ROOM  ] - livingRoomModeWeekdayEarlyEveningEnable (Type=SwitchItem, State=ON, Label=Living Room Enable Weekday Early Evening Mode, Category=switch, Tags=[Switch, Scene], Groups=[gLivingRoomModeEnable, gLivingRoomModeWeekdayEarlyEvening])
2022-10-24 10:00:00.789 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayEarlyMorningEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Early Morning Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeWeekdayEarlyMorning])
2022-10-24 10:00:00.790 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayDaytimeEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Daytime Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeWeekdayDaytime])
2022-10-24 10:00:00.790 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayEarlyEveningEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Early Evening Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeWeekdayEarlyEvening])
2022-10-24 10:00:00.790 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayNightEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Night Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeNight])
2022-10-24 10:00:00.791 [INFO ] [org.openhab.core.model.script.ROOM  ] - livingRoomModeWeekdayNightEnable (Type=SwitchItem, State=ON, Label=Living Room Enable Weekday Night Mode, Category=switch, Tags=[Switch, Scene], Groups=[gLivingRoomModeEnable, gLivingRoomModeNight])
2022-10-24 10:00:00.791 [INFO ] [org.openhab.core.model.script.ROOM  ] - diningRoomModeWeekdayMorningEnable (Type=SwitchItem, State=ON, Label=Dining Room Enable Weekday Morning Mode, Category=switch, Tags=[Switch, Scene], Groups=[gDiningRoomModeEnable, gDiningRoomModeWeekdayMorning])

What I was thinking is

gRoomModeRoomEnable.members.forEach[ i | {
    var groupName = i.name.toString
    logInfo("GROUP", groupName)

    var modes = groupName.members.filter[ i | i.state == ON ].map[ name ]
    logInfo("ROOM", modes.toString)
// I can make the below work     
    //room = some code to remove the the prefix g and suffix ModeEnable = diningRoom
    if(modes.contains(room + "ModeWeekdayNightEnable")) {
    //   check = "night"
        logInfo("contains", "night")
    }
    else if(modes.contains(room + "ModeWeekdayDaytimeEnable")) {
    //  check = "daytime"
        logInfo("contains", "day")
    }
    else if{
//        etc. etc.
    }
}
]

This works in seperate parts, but groupName.members.filter isnt happy. I think it is porbably looking for a Group item called groupName, rather than using the output of the gRoomModeRoomEnable.members.forEach and I dont know how to achieve that. Any other ideas are welcome as this is by far the most complex rule I have created and the frst time really using members.

Thanks.

That’s a string variable, then

String variables just don’t have .member methods, etc.

This all gets a bit fiddly.

I think I’d look for an approach like -

gRoomModeRoomEnable.members.forEach[ i | { 
// that produces a list, so var i is a list entry of I think generic Item type.

// I think you'll need to coerce it to a Group type to use Group methods
gRoomModeRoomEnable.members.forEach[ GroupItem i | {

// now you can use the Group type i
// but don't trample over it

var modes = i.members.filter[ k | k.state == ...

That’s untested code to show the principles.

A caution; Group handling in the bowels of openHAB used to have some threading issues, which I think still exist. The practical effect is that if you run extensive code using .members.forEach type access at the same time as the Group is updating (due to multiple member Item updates, say) you will get the occasional null list entry return.
That may be acceptable, and you just need to bullet proof your code against acting on null. Or you may need to take some alternate action, maybe just a delay.

Thanks, will digest your pointers, but I think I may have just got it (after seeing this Use variable for item - #9 by rlkoshak)

change var groupName = i.name.toString to var groupName = i as GroupItem

and add the .toString to the log groupName.toString

Now gives me

2022-10-24 12:24:40.686 [INFO ] [org.openhab.core.model.script.GROUP ] - gLivingRoomModeEnable (Type=GroupItem, BaseType=SwitchItem, Members=19, State=ON, Label=Living Room Mode Enable, Category=settings, Groups=[gRoomModeRoomEnable, gLivingRoomModeSettings])
2022-10-24 12:24:40.688 [INFO ] [org.openhab.core.model.script.ROOM  ] - [livingRoomModeWeekdayEarlyEveningEnable, livingRoomModeWeekdayNightEnable]
2022-10-24 12:24:40.688 [INFO ] [org.openhab.core.model.script.GROUP ] - gDiningRoomModeEnable (Type=GroupItem, BaseType=SwitchItem, Members=19, State=ON, Label=Dining Room Mode Enable, Category=settings, Groups=[gRoomModeRoomEnable, gDiningRoomModeSettings])
2022-10-24 12:24:40.690 [INFO ] [org.openhab.core.model.script.ROOM  ] - [diningRoomModeWeekdayEarlyMorningEnable, diningRoomModeWeekdayMorningEnable, diningRoomModeWeekdayDaytimeEnable, diningRoomModeWeekdayEarlyEveningEnable, diningRoomModeWeekdayEveningEnable, diningRoomModeWeekdayNightEnable]

Which, I think is what I want.

Sure, same thing. Note that variable groupName is not a name at all, but your actual Group Item.

I’d still take care about trampling over your i variable.

Yep, realised that after I’d looked though your answer, which saves a line basically :slight_smile: Its so obvious when you know how :smiley:

Ok, will have a think if I can do the other stuff outside in another rule or something that just gets triggered here.

edit - seen you edit… I think it will be acceptable, and you just need to bullet proof your code against acting on null, and null is tripping me up a bit so far so am checking for it and coding to ignore it or alerting that something isn’t right.

Thanks.

This doesn’t address your original question but you might be able to use the semantic actions to navigate the Group hierarchy and possibly simplify some of this code.

Thanks, I’ll have a look. I’ll probably post my finished attempt so everyone can tell me there’s a better way!