Pattern for operating on single OR groups of items

I have two types of hardware that allow either operating items individually or as a group. Typically they listen for either a command addressed to them, or to a group that they belong to. My two examples are:

  • Zigbee lights - these can operate as part of a zigbee group such that a single zigbee command operates a groups or them
  • RF blinds - same as the lights - some blinds can be part of a group and listen for a group broadcast

In this example, one option I have is to ignore the group functionality build into the hardware, and simply use OH groups. In this case everything works, but is slower and the operations are not simultaneous.

What I currently do for the lights (although I think it’s buggy right now), is use a virtual group item (with no members) as well the real group item (with members), which when it receives a command it uses the hardware broadcast mechanism, then postUpdate's the state to the members of the real group item.

Before I attempt to fix the bugs and reimplement for the blinds, is there a pattern that I’m unaware of that may be a better way of doing this? It must be a fairly common problem.

Thanks

Your virtual Group Item probably should be just a regular old Item. We call this a proxy Item and the fact that it is proxying a Group isn’t really relevant. I assume it’s linked to a Channel that lets you use the hardware broadcast mechanism.

The binding aught to update the Items on it’s own. If not, you can sendCommand(REFRESH) and the binding should poll the device for it’s current state. This might be a little more reliable as if the command to one of the devices fails you will see that. However, you probably need to schedule the REFRESH to occur half a second or so after the initial command to avoid overloading the network and give the devices time to react. You might need to spread the commands out a bit as well if you start to see weird responses.

Or you can just assume that the command worked and update the Items with the state you assume them to be which is your current approach. Most of the time, that assumption is safe and reasonable.

I’m pretty sure that the Zigbee binding implements the REFRESH command, Zwave does and it’s the same developer for both bindings.

Not as common as you may think. Each technology deals with this sort of thing differently and often there is no option but to use openHAB Groups. The fact that Zigbee allows your approach is, AFIK, unique.

Mqtt group topics with tasmota for example springs to mind…

I’m not actually sure of the type of the virtual Group item right now, but it is behaving as a proxy item (and yes it’s linked to a broadcast channel). As for the binding updating the child items - that’s a good point in that I should be able to do this for zigbee (as they report changes), but not for the blinds as they report nothing, so there’s no implicit knowledge in OH that a broadcast on a specific channel corresponds to state changes to a set of distinct items.

It sounds like (other than hooking into zigbee state changes) I’m already doing the right thing.

I was wondering whether there was a way to ‘intercept’ commands going to a group item and handle them differently, but I guess a proxy item is exactly this pattern.

Unfortunately, the zigbee binding does not support this. It looks to just be a matter of time (OHC needs some changes first)…

Reportedly, this is available using zigbee2mqtt… and should be available using the Wink binding.

Eventually @chris will get this setup :slightly_smiling_face:. Until then, in my setup, I just use OH groups and live with lights occasionally not being perfectly in sync. The lighting effect is actually a bit of a “feature”… when the lights come on around the room fractions of a second delayed from the previous… the order seems consistent too, so basically a chase pattern!

I’m actually already using zigbee2mqtt - I have lots of Xiaomi Aqara things which I don’t think work with the OH binding. I just don’t (yet) read the status reports coming from zigbee2mqtt.

In general I completely appreciate the ‘feature’ - the only issue has been when others have tried to turn on the lights (with a zigbee button that is used for this), and when then don’t see a specific light turn on immediately they click it again…

The big problem with using ZigBee groups is that OpenHAB doesn’t support such a group concept. This makes things difficult for the binding - I have some ideas on how this might be coded, but it’s complex.

If OpenHAB has a concept which supported such groups it would make life a lot easier :frowning:

The ZigBee binding does support xiaomi devices and many people use them.

Just to circle back as today I ported my existing rules implementing this to javascript. I took the relatively short path of porting, rather than (for example) moving everything off zigbee2mqtt to the OH Zigbee binding (although thanks @chris for letting me know it does support Xiaomi). It ended up like this, using metadata:

Group gzKitchenLights (gZigbeeGroups) { zigbeeGroupId="KitchenLights", zigbeeProxyItemName="zgKitchenLights" }
Color zgKitchenLights "Kitchen Lights" { channel="...zigbeeGroupChannel..." }

Color Light1 (gzKitchenLights) { zigbeeId="...zigbeeId...", channel="...zigbeeChannel..." }
Color Light2 (gzKitchenLights) { zigbeeId="...zigbeeId...", channel="...zigbeeChannel..." }

gzKitchenLights is the OH group of lights, zgKitchenLights is the ‘zigbee group’ item that broadcasts to all items. I then have a single script which propagages the groups to zigbee2mqtt, and also ensures that commands going to the zigbee group get posted to the children in OH too:

const { items, actions, fluent } = require('ohj');
const mqtt = actions.get("mqtt", "mqtt:broker:mosquitto");

for(let zigbeeGroupItem of items.getItem('gZigbeeGroups').members) {
    let zigbeeGroupId = zigbeeGroupItem.getMetadataValue('zigbeeGroupId');
    //first create the group in zigbee2mqtt
    mqtt.publishMQTT("zigbee2mqtt/bridge/config/remove_group", zigbeeGroupId);
    mqtt.publishMQTT("zigbee2mqtt/bridge/config/add_group", zigbeeGroupId);

    //add members to the group in zigbee2mqtt
    for(let zigbeeItem of zigbeeGroupItem.members) {
        mqtt.publishMQTT(`zigbee2mqtt/bridge/group/${zigbeeGroupId}/add`, zigbeeItem.getMetadataValue('zigbeeId'));
    }

    //find the 'special' proxy item that sends out zigbee group commands
    let zigbeeGroupProxyItem = items.getItem(zigbeeGroupItem.getMetadataValue('zigbeeProxyItemName'));
    
    //wire up proxy item so that when it receives a command, the state also propagates to the group members
    with(fluent) {
       when(item(zigbeeGroupProxyItem).receivedCommand()).then(postIt().toItems(zigbeeGroupItem.members));
    }
}

(note that this code requires ES6 + CommonJS + the related core module.)