Switch group rules triggering multiple times when sending command to group

  • Platform information:
    • Hardware: Raspberry PI 3b+
    • OS: openhabian
    • Java Runtime Environment:
      • openjdk version “1.8.0_222”
      • OpenJDK Runtime Environment (Zulu8.40.0.178-CA-linux_aarch32hf) (build 1.8.0_222-b178)
      • OpenJDK Client VM (Zulu8.40.0.178-CA-linux_aarch32hf) (build 25.222-b178, mixed mode, Evaluation)
    • openHAB version: 2.5.0-1

I’m trying to set up a group of switches, where I want to turn all switches on or off by sending commands to the group. The member items are linked via MQTT to a bunch of tasmota smart plugs.

I notice that when I send the OFF command to the group when more than 1 of the member items are ON, the state of the group changes to OFF, then ON again briefly, and finally OFF again. If I have any rules that trigger on this group state going from ON to OFF, they will be triggered twice.

From looking at the logs, I can see why. With all items ON, when I set the group to OFF from the basic ui:

  1. the group state goes from ON to OFF
  2. the individual items are sent the OFF command
  3. the first item receives the OFF command, it transitions to OFF
  4. the groups’ OR aggregate function evaluates to ON since the other items are still in ON state, so the group state goes from OFF to ON
  5. finally, when all items have received the OFF command and transitioned to the OFF state, the aggregate OR evaluates to OFF and the group state goes from ON to OFF again

I think this is expected behaviour, yet it causes me some problems. When I have rules triggering on the group state going from ON to OFF, these rules will trigger twice. For example, I have a rule that turns on some things when all my lights go off. Due to it firing twice, the things that are switched in response are switched ON, OFF, ON again quickly. That is not really how I want to treat my equipment :slight_smile:, let alone the havoc this creates on my AC mains supply.

I’ve seen some topics here discussing similar issues, and they go into complicated setups with timers to debounce things and/or locks. While carefully crafting such solutions would certainly be possible, it is fraught with the possibilities of race conditions and dead-locks, which I hope to avoid by keeping things simple.

It seems to me that if I had a way to have the group state not change based on the sendCommand, but only on the basis of one of its members changing (ie, the group state would directly reflect the aggregate function result, not change state by itself on receiving a command), I would avoid this particular issue. Is this possible?

I’m sure i’m missing something obvious here, how do others deal with this issue?

My test.items:

Group:Switch:OR(ON,OFF) Test_Group

Switch Test1 "Test 1" <lightbulb> (Test_Group) { channel="mqtt:topic:plug009:switch", autoupdate="false" }
Switch Test2 "Test 2" <lightbulb> (Test_Group) { channel="mqtt:topic:plug010:switch", autoupdate="false" }
Switch Test3 "Test 3" <lightbulb> (Test_Group) { channel="mqtt:topic:plug011:switch", autoupdate="false" }

I also have a test.sitemap to be able to see what happens and send ON/OFF commands to the group:

sitemap test label="Test"
{
    Switch item=Test_Group label="All Test"
    Switch item=Test1 label="Test1"
    Switch item=Test2 label="Test2"
    Switch item=Test3 label="Test3"
}

The log for sending an OFF command when all items are ON:

2019-12-22 10:38:05.158 [ome.event.ItemCommandEvent] - Item 'Test_Group' received command OFF 
2019-12-22 10:38:05.186 [ome.event.ItemCommandEvent] - Item 'Test1' received command OFF 
2019-12-22 10:38:05.211 [ome.event.ItemCommandEvent] - Item 'Test2' received command OFF 
2019-12-22 10:38:05.238 [ome.event.ItemCommandEvent] - Item 'Test3' received command OFF 
2019-12-22 10:38:05.346 [GroupItemStateChangedEvent] - Test_Group changed from OFF to ON through Test2
2019-12-22 10:38:05.351 [vent.ItemStateChangedEvent] - Test2 changed from ON to OFF 
2019-12-22 10:38:05.355 [vent.ItemStateChangedEvent] - mqtt_topic_plug010_switch changed from ON to OFF 
2019-12-22 10:38:05.363 [vent.ItemStateChangedEvent] - mqtt_topic_plug009_switch changed from ON to OFF 
2019-12-22 10:38:05.366 [vent.ItemStateChangedEvent] - Test1 changed from ON to OFF 
2019-12-22 10:38:05.377 [vent.ItemStateChangedEvent] - mqtt_topic_plug011_switch changed from ON to OFF 
2019-12-22 10:38:05.380 [GroupItemStateChangedEvent] - Test_Group changed from ON to OFF through Test3
2019-12-22 10:38:05.387 [vent.ItemStateChangedEvent] - Test3 changed from ON to OFF 

The things are set up via paper ui:


Let’s call it known long standing behaviour. It’s not very nice, but is the way it is.

This is actually what happens. Group state ignores any group commands. The issue arises because recalculating group state from member states is an iterative process, and it seems early results “escape” into the wild, only to be corrected later.

Crafting a workaround for your particular requirement.is usually possible. Hints;

Rule triggers for e.g. Member of myGroup changed are reliable.

There’s always race risks with Group handling, since it always possible for some other member to change while you’re processing.

Items can be members of more than one Group ; you might have a Group with an aggregation function just for display purposes, and another group with different or no function for rules triggering.

You can of course use a dummy Item to represent a “group” and have rules manage it as you wish.

What to do in any given case rather depends on your exact requirements.

I’m not too sure that is what is happening. When I create a second group with the exact same members, that second group will not transition twice. For example, if I expand my test.items like so:

Group:Switch:OR(ON,OFF) Test_Group
Group:Switch:OR(ON,OFF) Test_Events

Switch Test1 "Test 1" <lightbulb> (Test_Group, Test_Events) { channel="mqtt:topic:plug009:switch" }
Switch Test2 "Test 2" <lightbulb> (Test_Group, Test_Events) { channel="mqtt:topic:plug010:switch" }
Switch Test3 "Test 3" <lightbulb> (Test_Group, Test_Events) { channel="mqtt:topic:plug011:switch" }

I see Test_Group still transitioning twice, but Test_Events does not:

2019-12-22 21:42:36.343 [vent.ItemStateChangedEvent] - network_pingdevice_onkyo_ip_latency changed from 32.0 to 22.0
2019-12-22 21:42:36.654 [vent.ItemStateChangedEvent] - network_pingdevice_onkyo_ip_lastseen changed from 2019-12-22T21:42:26.299+0100 to 2019-12-22T21:42:36.640+0100
2019-12-22 21:42:37.465 [ome.event.ItemCommandEvent] - Item 'Test_Group' received command OFF
2019-12-22 21:42:37.508 [ome.event.ItemCommandEvent] - Item 'Test1' received command OFF
2019-12-22 21:42:37.539 [ome.event.ItemCommandEvent] - Item 'Test2' received command OFF
2019-12-22 21:42:37.569 [ome.event.ItemCommandEvent] - Item 'Test3' received command OFF
2019-12-22 21:42:37.778 [vent.ItemStateChangedEvent] - mqtt_topic_plug009_switch changed from ON to OFF
2019-12-22 21:42:37.782 [vent.ItemStateChangedEvent] - Test1 changed from ON to OFF
2019-12-22 21:42:37.788 [GroupItemStateChangedEvent] - Test_Group changed from OFF to ON through Test1
2019-12-22 21:42:37.792 [vent.ItemStateChangedEvent] - mqtt_topic_plug011_switch changed from ON to OFF
2019-12-22 21:42:37.796 [vent.ItemStateChangedEvent] - Test3 changed from ON to OFF
2019-12-22 21:42:37.826 [vent.ItemStateChangedEvent] - Test2 changed from ON to OFF
2019-12-22 21:42:37.830 [GroupItemStateChangedEvent] - Test_Group changed from ON to OFF through Test2
2019-12-22 21:42:37.836 [GroupItemStateChangedEvent] - Test_Events changed from ON to OFF through Test2
2019-12-22 21:42:37.841 [vent.ItemStateChangedEvent] - mqtt_topic_plug010_switch changed from ON to OFF

I’ll settle for having two groups: one for the control, another for generating events and triggering other rules. It’s slightly sub-optimal (you see the group switch toggle back and forth when turning it off), but the simplest I can think of right now for my particular wishes:

  • Be able to turn on and off all items in the group with a single switch
  • Have that single switch transition to ON as soon as at least one of the member switches is ON
  • Have that single switch transition to OFF as soon as all member switches are OFF

Ie, I want to be able to control the switches with one master switch, while still able to control the individual switches and have the master switch respond to individual member switch changes.

Well, in your example you also have to account for member data changes coming in while group evaluations are in progress. To figure it out exactly, you’d need to observe the exact sequence of state changes against the progress of two slightly staggered evaluations through groups with members possibly in a different order. The log timestamps are not reliable in this situation - note Groups can often be seen to change before the reported member apparently does.
Whatever, it’s chaos for 50mS and you need to find a way round.it.

Ignore the cosmetic stuff, what’s important?
I’m homing in on -

That’s easy ; trigger your rule from the group state change … and wait. It settles to a final result in N mS.
How long N is depends on what you are relying on to update your Items (and so in turn the group).
If it’s autoupdate (internal to OH) 50mS will probably do.
If you rely on actual feedback from your devices, you’ll have to observe your technology to find out (it’s possibly fighting to get a batch of commands out as well as status back)

Simplest

when
    Item someGroup changed to XX
then
   Thread::sleep(50)   // wait for group to settle
   if (someGroup.state == XX ) {   // recheck state
       otherThings.sendcommand(ON)
   }
       // or perhaps more gracefully in case of multiple triggers
       if (otherThings.state != ON) {
          otherThings.sendcommand(ON)
       }

For a longer delay you’d probably deploy a timer; that also gives you the option of ignoring retriggers while timing , or rescheduling/extending. You’ve probably seen these constructs.
I don’t think you need locks anywhere near this problem.

Interesting topic. I noticed similar behavior and was scratching my head for a while what could cause this.

Sometimes my lights switch OFF, ON, OFF when they should only turn OFF.

I control all my lights through groups like Group:Switch:OR(ON,OFF). Each room in the house has its own group, and some rooms have subgroups.

Your observations second my findings in

I expect you do not see multiple triggers if you send an ON command to the group.