Multiway switch

@dangif,

I think your original approach was close to working. I’m no java coder, but java does have a bitwise exclusive-or operator, ^, which should behave as expected when applied to instances of boolean.

You might give the following a go:

rule "xyz"
when
    Item SwitchUpstairs changed
    or Item SwitchDownstairs changed
    or Item SwitchWeb changed        //should be handled differently in OpenHab?
then
    if((SwitchUpstairs.state == ON) ^ (SwitchDownstairs.state == ON) ^ (SwitchWeb.state == ON))
	sendCommand(StairwayLight, ON)
    else 
        sendCommand(StairwayLight, OFF)
end

Note that I added parens to ensure the bitwise xor was applied to the results of your equivalence tests.

Cheers!

@rlkoshak You are faster with edit than I with response. :slight_smile:

Probably solution by group can be better that I can freely add/remove switches to group, without altering rule.
Is there difference in terms of speed? As I want raspberry underclocked to stay cold.

Now I must look how to solve “SwitchWeb” in e.g. HABDroid, if I want to see on one line current light state and control to toggle it.
So, what if I put into the group only SwitchUpstairs, SwitchDownstairs. In site map I will have only StairwayLight, and write rule only to toggle?:

rule "StairwayLight"
when
    Item gStairwayLight received update
then
    if(StairwayLight.state == ON)
	sendCommand(StairwayLight, OFF)
    else 
        sendCommand(StairwayLight, ON)
end

Or is this totally wrong idea?

I don’t follow why the state of the switches needs examining? Isn’t the idea that if any switch changes state, the light should change state? i.e. the switches have no particular on or off position from a user point of view, you just move the lever and the light changes.

rule "xyz"
when
    Item SwitchUpstairs changed
    or Item SwitchDownstairs changed
    or Item SwitchWeb changed
then
    if(StairwayLight.state == OFF) {
	sendCommand(StairwayLight, ON)
    } else {
        sendCommand(StairwayLight, OFF)
    }
end

You might choose to do something different with the web / UI switch though.

@dangif and @rossko57, I think you nailed it. I didn’t see that forest for the trees :wink:

I don’t think XOR will quite do that for you. Keep in mind that XOR works on only two operands at a time and works from left to right. So if you write the truth table for a three item XOR in sequence like that you get.

‘’’
A B. C. Result
Off off off off
On off off on
Off on off on
Off off on on
On on off off
On off on off
Off on on off
On off on off
On on on on

I’m pretty sure that is not the behavior you are looking for.

To explain one of the word cases.

On on on:

On xor on = off. Off xor on = on

The problem is because it evaluates the first two operands and then uses the result of that operation with the last operand.

From your latest description it sounds like you don’t care what state the switches are in. If any of them change state your want to toggle the light.

That is pretty easy too but using the group update to trigger the rule is s problem because the group receives multiple updates for each event. So the rule becomes:

‘’’
rule “light”
when
Item Switch1 received command or
Item Switch2 received command or
Item Switch3 received command
then
Light.sendCommand(if(Light.state ==ON) OFF else ON)
end
‘’’

there difference in terms of speed?

If there is it is not enough to matter.

Or is this totally wrong idea?

Unfortunately this is one case where you can’t use groups because one change in a group’s Item generates multiple updates. And since you don’t care about the switch’s absolute state, only the fact that one of them changed, there is no clear way to filter out the extra events. Consequently your lights would flicker and may or may not end up where you want them.

However, with two extra lines of code my rule from above will work. Assuming Light3 is your WebSwitch:

‘’‘rule “light”
when
Item Switch1 received command or
Item Switch2 received command or
Item Switch3 received command
then
val newState = if(Light.state == ON) OFF else ON
Light.sendCommand(newState)
Switch3.postUpdate(newState)
end
‘’’

By using postUpdate we can change the state of Switch3 to always match the relay without retriggering the rule. So if you put Switch3 on your sitemap you can use this one Item to know the state of the light and to turn the light off and on. No need for separate status and control lines in the sitemap.

Note, typed all of the above on my phone. Pardon the errors.

When rule react on “changed” only, it turns light during startup, which is unacceptable, so on my test-bed I ended with:

rule "light"
when
    Item sw1 changed from OPEN to CLOSED
    or Item sw1 changed from CLOSED to OPEN
    or Item sw2 changed from OPEN to CLOSED
    or Item sw2 changed from CLOSED to OPEN
then
    light.sendCommand(if(light.state == ON) OFF else ON)
end

and items are:

Contact sw1 "sw1" { gpio="pin:19" }
Contact sw2 "sw2" { gpio="pin:26" }
Switch light "light" { gpio="pin:18" }

This works as wanted, light is toggled on any change of contacts (wall-switches), and from mobile can control directly the light.

There stay minor problem:
When change both contacts at same time, the rules react in parallel, so light is toggle only once, as “both rules” read same old state and set same new state.
I tried solve this by lock/unlock:

rule "light"
when
    Item sw1 changed from OPEN to CLOSED
    or Item sw1 changed from CLOSED to OPEN
    or Item sw2 changed from OPEN to CLOSED
    or Item sw2 changed from CLOSED to OPEN
then
    logWarn("gt", "begin")
    lock.lock()        
    logWarn("gt", "begin2")
    try {
        light.sendCommand(if(light.state == ON) OFF else ON)
    } finally{
        logWarn("gt", "end")
        lock.unlock()
    }
  end

But probably even if i guard the sendCommand, it looks like it didn’t guard the real “ItemStateChangedEvent”.
So sometimes the “second rule” still can read state before first rule applied.

Worse problem is, that I can achieve such problem when physical contact bounce:
Will examine this more, with this I crete new thread Contact bounce - lost events?

Hi rikoshak, I know this is an old thread but I am trying a two way switch with a third switch in the Habpanel.
The two Sonoff T1 switches are in a group called “Lounge_Light”. Below is the rule I created from your rule above but the log get hammered with “2018-07-02 10:26:52.497 [ome.event.ItemCommandEvent] - Item ‘SW2_02_1’ received command ON”

Here is the Rule
"
rule “Lounge_light”
when
Item SW3_01_1 received command or
Item SW2_02_1 received command
then
val newState = if(SW3_01_1.state == ON) OFF else ON
SW2_02_1.sendCommand(newState)
Lounge_Light.postUpdate(newState)
end
"

Any help appreciated

Note the endless loop - trigger on command, send command, trigger, send, etc.

This was avoided in earlier rule example where the switch Items representing user controls are different from the switch Item actually controlling the light. Depending on how you bind to the Sonoffs, can you arrange that? i.e. an input-only user-button reporting Item and a separate power control and status Item.

Without knowing what your Items actually are, do you need the rule to always act on the buttons, are they controlling the lamp directly without needing OpenHAB action?

Sorry, I’m totally new to this and don’t really understand what you mean. I can see the loop for sure but the rest went over my head. They will go in a stairway type configuration.
I have 2 Sonoff T1 swiches. They are items SW3_01_1 and SW2_02_1. At the moment they are just on the bench but when installed, SW3_01 will supply voltage to turn the light on/off and SW2_2_01 will only work via a rule (not actually connected to light).

The T1’s have a nice light when the relay is activated on, so I would like to mirror the switch activity.
When SW3_01_1 goes on then SW2_2_01 goes on
When SW3_01_1 goes off then SW2_2_01 goes off and the same from the other switch.

Does that make sense?

For further clarification here is my items file for the sonoff items.
"
//Sonoff T1- 3 Gang #1
Switch SW3_01_1 “Lounge Light SW1” (Lounge_Light){ mqtt=">[broker:cmnd/SW3_01/power1:command::default],<[broker:stat/SW3_01/POWER1:state:default]" }
Switch SW3_01_2 “Dinning Light SW1” (Living_Lights){ mqtt=">[broker:cmnd/SW3_01/power2:command:
:default],<[broker:stat/SW3_01/POWER2:state:default]" }
Switch SW3_01_3 “Kitchen Light SW1” (Living_Lights){ mqtt=">[broker:cmnd/SW3_01/power3:command:*:default],<[broker:stat/SW3_01/POWER3:state:default]" }

//Sonoff T1- 2 Gang #1
Switch SW2_01_1 “Dinning Light SW2” (Living_Lights){ mqtt=">[broker:cmnd/SW2_01/power1:command::default],<[broker:stat/SW2_01/POWER1:state:default]" }
Switch SW2_01_2 “Kitchen Light SW2” (Living_Lights){ mqtt=">[broker:cmnd/SW2_01/power2:command:
:default],<[broker:stat/SW2_01/POWER2:state:default]" }

//Sonoff T1- 2 Gang #2
Switch SW2_02_1 “Lounge Light SW2” (Lounge_Light){ mqtt=">[broker:cmnd/SW2_02/power1:command::default],<[broker:stat/SW2_02/POWER1:state:default]" }
Switch SW2_02_2 “Front Light Right” (Living_Lights){ mqtt=">[broker:cmnd/SW2_02/power2:command:
:default],<[broker:stat/SW2_02/POWER2:state:default]" }

I think so. You have two power control relays, A & B. Only one controls a real lamp, but you want both to work together because there is handy LED.

Each of the relays can be manually controlled, and you want that manual action to be “copied” to the other one.

Set up a pair of rules that trigger on changes in your Item state (rather than commands or simple updates).
The rule should then sendCommand the new state to the opposite switch.

rule “update lamp B”
when
   Item lamp_A changed
then
   if ( lamp_A.state == ON ) {
      lamp_B.sendCommand(ON)
   } else {
      lamp_B.sendCommand(OFF)
   }
end

There’s many ways to do that, but that one should behave sensibly in case of errors.
You’d have another mirror-image rule to copy changes the other way B → A

Because it works on changes and not just events it shouldn’t get in a loop… A good test is starting off with the two relays in different states, they should synch up at first manual action.

For neatness, you could even write a system started rule that looked at a ‘master’ relay current state, and forced the slave relay to that state as well initially.

Thanks for the advice, with this. The ON syncs for both switches but not the OFF. Ie Sw A turns on Sw B and Sw B turns on Sw A but each only turn themselves off. Any help apreciated

The rule trigger syntax includes e.g. changed to ON or changed to ON , if you need different behaviours

Edit - changed to OFF I meant, but I think I misunderstood your complaint as a request.
Note that my previous suggestion was for a pair of rules, and I gave one example, leaving you to figure out its partner.

Sorry, I dont understand what you mean. I added the rule and made an opposite rule for the other light and I have tried the rule and it only works as I described. On is in sync, Off is not

rule “update lamp B”
when
   Item lamp_A changed
then
    lamp_B.sendCommand(lamp_A.state.toString)
end

rule “update lamp A”
when
   Item lamp_B changed
then
    lamp_A.sendCommand(lamp_B.state.toString)
end
1 Like

Cheers Vincent, Ill try that tonight and let you know

Thank you Vincent, that worked perfectly.
I really appreciate it,
JD

Coolio, please mark the solution and like if you want.

hc_292

James,
I have read your post in the other thread and your little rant.
What @rlkoshak said is right.

We are not here to code for you. You can’t just plop in here and ask for code. You need to learn OH by writing your own. If it doesn’t work we’ll help you get it right and explain to you where you went wrong.

Read the docs again and again. There are good examples in there. Understand the docs and the examples. It’s not good just copying and pasting. When I want to learn something new I never copy and paste, I copy by typing so I get to learn the syntax and meaning of every bit of code. This is important.

By learning the basics (These two rules were very basic), you will then be able to write more complicated code latter on and again if it doesn’t work, check the docs, check the forum and only when you are really stuck post your question and we will do our best to help.

Help yourself and we’ll help you.

PS. Did you understand the rules I posted and why they work?

1 Like

Thanks for your help, Message understood.