Five buttons on five things to switch one different thing

Hi there, I am haveing a small Problem with switching a central light in my house.

It is needed to switch this light from five different places, that all have different things to sense the buttonpress.
What I need ist a possibility to update the state of all the connected points if one of the states changes.

My problem ist, that by changing the states with a rule I retrigger the rule.

My script is like this.

If button a oder button b or button c changes to on
change switch thing on
change a to on b to on c to on.
same for off.

There must be a more elegant way to do this.

These are all Items? All these Items are linked to Channels?

As long as you are not ending up in an infinite loop there really isn’t a problem. You don’t show your code but based on the way you wrote it there might be some things you can do to make that code simpler. But as long as the rule needs to be triggerable from any one of the switches, you cannot avoid retriggering the rule during the synchronization.

Try this rule in dsl first group all that to make it easier

Group gSyncSwitches

Switch Button1 "Button 1" (gSyncSwitches)
Switch Button2 "Button 2" (gSyncSwitches)
Switch Button3 "Button 3" (gSyncSwitches)
Switch Button4 "Button 4" (gSyncSwitches)
Switch Button5 "Button 5" (gSyncSwitches)
Switch Light1 "Light 1" (gSyncSwitches)

And then the rule

rule "Sync Switches and Light"
    Member of gSyncSwitches changed
    val newState = triggeringItem.state
    gSyncSwitches.members.filter[ light | != && light.state != newState ]
                         .forEach[ light | light.postUpdate(newState.toString) ]

This approach won’t really work the way you think it will. Since OH 3 each rule gets it’s very own thread but only one thread. That means if the rule triggers while it’s already running, it will queue up those triggers and work them off in sequence and in order.

So you will never have a case where the rule actually starts running and isRuleRunning is true. So all of that is doing nothing productive.

To avoid the infinite loop all you need to do is postUpdate instead of sendCommand to the other Items. Updates won’t cause the rule to trigger.

There are other problems too. triggeringItemName doesn’t exist in Member of triggered rules and newState doesn’t exist for command triggered rules.

rule "Sync Switches and Light"
    Member of gSyncSwitches changed
    gSyncSwitches.members.filter[ light | != && light.state != newState ]
                         .forEach[ light | light.postUpdate(newState.toString) ]

That’s all you need. Making sure that only one instance of the rule runs at a time is handled by the rule engine for you. The filter avoids updating the Item that triggered the rule (probably unnecessary because even if you update it again, the state won’t change so there will be no infinite loop) or updating a switch that is already in the desired state (again not really necessary because of our choice in triggers, but it helps the queued triggers unroll really quickly).

If a changes state to ON:

  1. rule triggers for a changing to ON
    a. updates b, c, d, and e to ON
  2. rule triggers for changing b to ON
    a. nothing because, depending on timing, a, c, d, and e are already ON
  3. rule triggers for changing c to ON
    a. nothing because by now a, b, d, and e are already ON
  4. rule triggers for changing d to ON
    a. nothing because a, b, c, and e are already ON
  5. rule triggers for changing e to ON
    a. nothing because a, c, d, and d are already ON

You can’t avoid the rule triggers but that simple loop means that after the first trigger, none of the other triggers have anything to do and they just exit. Obviously, if there are some switches that are already ON, those will be skipped right out of the gate and the rule will trigger fewer times.

1 Like

Wow :astonished:.

In best case you have different items for the buttons AND different items for the service that you want to switch on/off (e.g. a lightbulb).

Then you can do a simple rule like:

If button a,b,c… changes
Send command on/off to light

This will avoid any loop

But not update the button’s states, only the lights. My reading of OP’s requirements is that both the lights and the buttons need to be in sync.