JS Scripting: How find group that item event trigger is assigned to?

In my OS 2.5 system I use some Jython rules that allow users to select a lighting preset, heating preset, etc. The rules frequently use the following line of code to determine which room group the triggering item is assigned to:

triggeringRoomGroup     = [group for group in ir.getItem("gRoom").members if group.type == "Group" and ir.getItem(event.itemName) in group.members][0]

There is a group gRoom beneath which are all the room groups in the house: gKitchen, gLivingroom, gUtilityroom, etc. The trigger for the heating preset rule is:

@when("Member of gHeatingModeSetting received update")

This allows a single rule to be used for any room in the house. The code to determine the heating preset that a user has selected is:

heatingPresetName       = "HeatingPresetSetpoint_{}_{}".format(str(triggeringRoomGroup.name), str(event.itemState))

This allows a user to select a heating preset 1, 2, 3 or 4 (the UI maps these to Eco, Comfort, etc.) and an item name like HeatingPresetSetpoint_gLivingroom_1 will be derived and then the value of that item sent to the thermostat setpoint item for that room.

In my OH 3.2 system I’ve started building a location hierarchy so instead of a flat layout like the gRoom group I described above I have a top level gHouse group beneath which are gGroundfloor, gFirstfloor, etc, beneath those are the individual rooms and then beneath those are the items.

I have a JS Script rule with the following code:

      var memberlist = "";
      items.getItem("gHouse").descendents
                   .forEach(function(heatingMode) { memberlist = memberlist + heatingMode.label +": "+ heatingMode.state + "\r\n"; } );
      logger.info("memberlist is {}!", memberlist);

When this is triggered I see in the log a list of all the items that are assigned somewhere beneath the gHouse group. If I change the .descendents to .members I see nothing in the log, I assume because there are no items assign to gHouse, only groups representing floors of the house.

I’ve looked at the JS Scripting documentation and I can’t see a method that will allow me to achieve with JS Script what I did with Jython because I can’t see how to return all the members of a group and check if any of the members are a group.

I could create the gRoom group in OH3 as I had in OH2.5 but then I’d have the room groups assigned in both the flat gRoom group and the hierarchical gHouse group. I haven’t thought that through sufficiently to know if that would be a problem but it doesn’t seem ideal. Alternatively, I could maybe use item tags instead of the item group assignment to check if the triggering item has a tag that matches a tag on another item to determine if both items are in the same room. It seems a bit wasteful to have the same location data represented both by group assignment and tag assignment. It wouldn’t be the end of the world though. :slight_smile:

TL,DR:

Is there a way to do the Jython code:

triggeringRoomGroup     = [group for group in ir.getItem("gRoom").members if group.type == "Group" and ir.getItem(event.itemName) in group.members][0]

in JS Script?

Having looked into this further I think the .descendents and .members functions are working as designed as per the documentation here and here. The change from a flat hierarchy to a nested hierarchy means that I’ll need to update the code to:

  1. use a recursive function to walk through the location group hierarchy
  2. add a group with all room groups in it so the old 2.5 approach will work
  3. use tags on items to identify which room they’re in

I’ve written some code that can recurse through the groups in a hierarchy and build an array of GroupItems.

function groupGetGroupsRecursive(resultArray, groupItem) {

  if (groupItem.type === "GroupItem") {
    resultArray[resultArray.length] = groupItem;
    resultArray[resultArray.length - 1].members.forEach(function(subGroup) { groupGetGroupsRecursive(resultArray, subGroup)} );
  }
}

It needs to be called with two arguments: the array to store the group items and group in the hiearchy you wish to start reading from:

      const groupArray = [];
      groupGetGroupsRecursive(groupArray, topGroup);

topGroup could be set like this:

  var topGroup = items.getItem("gHouse");
1 Like