Emulate a three way switch

I currently have two switches, each one backed by a sonoff switch.

Each switch controls a group of lights. So, we have

Switch A => sonoff A => light group A
Switch B => sonoff B => light group B

I want to group both light groups, such that when I press either one, both light groups are switched on/off.

I tried creating 4 automations that basically do this:

  • Trigger: state sonoff A on => off ==> Action: Sonoff B off
  • Trigger: state sonoff A off => on ==> Action: Sonoff B on
  • Trigger: state sonoff B on => off ==> Action: Sonoff A off
  • Trigger: state sonoff B off => on ==> Action: Sonoff A on

However, when I activated these automations, clicking any button would make my lights go into some sort of loop, with the list flickering constantly.

I did the same kind of setup through the ewelink app and that seems to work fine.
What am I doing wrong with this setup and/or is there any other way to accomplish this?

Thats not really a 3 way switch. A 3 way switch is 2 switches controlling a set of lights with the following logic:

switch 1 on, switch 2 off -> lights on
switch 1 off, switch 2 on -> lights on
switch 1 off, switch 2 off -> lights off
switch 1 on, switch 2 on -> lights off

You just want to pair the switches together.

A dynamic automation that does that would look like this:

trigger:
- platform: state
  entity_id: switch.a
- platform: state
  entity_id: switch.b
condition:
- condition: template
  value_template: >
    {% set switches = ['switch.a', 'switch.b'] %}
    {% set target = trigger.to_state.state %}
    {{ states | selectattr('entity_id', 'in', switches) | selectattr('state','eq', target) | list | length != switches | length }}
action:
- service_template: switch.turn_{{ trigger.to_state.state }}
  data_template:
    entity_id: >
      {% set switches = ['switch.a', 'switch.b'] %}
      {% set target = trigger.to_state.state %}
      {{ states | selectattr('entity_id', 'in', switches) | selectattr('state','!=',target) | map(attribute='entity_id') | list | join(', ') }}

So what this does is it triggers off a or b. Then the condition checks if all the lights are already the target state. If they all are already the target state, the automation does not fire. If they are not, it builds a list of entities to set to the target state.

This will work with any size list. So if you add more lights or switches in the future, all you need to do is add them to the list.

Now, I did notice that we may have to make a map because these switches may not coorelate to your light group.

I can adjust this automation to account for that but I need to see your entity_idā€™s for all switches & light groups.

4 Likes

The logic you defined is exactly what Iā€™m after, so it really is an (emulated) 3-way switch.
I think the issue in this case is that by switching one of the sonoffs, it directly controls the light it is attached to already.

Iā€™m not sure what you mean by ā€œpair the switches togetherā€.

That just means when you turn the one switch on, the other switch will turn on. Just post all your entity_ids and I can build a replica 3 way switch automation.

Iā€™ve implemented this succesfully, seems to be working much better than my first iteration.
I do notice however that thereā€™s a bit of a delay. If I trigger it through the home assistant app, itā€™s instant, but triggering it through the physical switch gives me a second of delay, which is a bit jarring.

Do you have any idea on how to remove that delay?

If not, no worries, thanks for your help!

The delay is most likely caused by the delay in updating the switch. Meaning, your hardware switch doesnā€™t instantly send a i'm this state message. Probably nothing you can do about that other than replacing the hardware.

Hi Petro, Ive been following this feed with interest. I currently have 4 sonoff 3 gang switches which all function the same. One switch operates the porch light, one the hall lights and the last operates the landing light. Ive had these working using a rather rudumental automation which has worked nicely however im trying to consolidate the automation and was trying to use what you have written above however it doesnt seem to work, Could you provide me with any guidance:

The 4 entites im using for the first button are Hallm, Hall2, Hall3 and Hall4.

Thank you

I never saw this post. When you reply, please reply to the person, not the thread. Otherwise your post gets lost.

This can only be done in yaml, outside the automation editor:

trigger:
- platform: state
  entity_id: &entities
  - switch.a
  - switch.b
  - switch.c
  - switch.d
  from: &states
  - 'on'
  - 'off'
  to: *states
variables:
  entities: *entities
  value: > 
    {{ trigger.to_state.state }}
  targets: >
    {{ expand(entities) | rejectattr('entity_id','eq', trigger.entity_id) | selectattr('state','!=', value) | map(attribute='entity_id') | list }}
condition:
- condition: template
  value_template: >
    {{ targets not in ([], none) }}
action:
- service: homeassistant.turn_{{ value }}
  target:
    entity_id: "{{ targets }}"
2 Likes

Iā€™ve got a similar use case and I stumbled upon this and just wanted to say thanks for posting this.

I do see the lag, and itā€™s about 3 seconds or so. Hasnā€™t really annoyed me yet and serves its purpose so itā€™s all good!

This is a little off topic but Iā€™ve been unable to find an answer anywhere else. Petro, you introduced new syntax that Iā€™m unfamiliar with, specifically &entities, &states, *entities, &states. These seem to be provide some kind of list or wildcard capability but Iā€™m unsure if the ā€œstatesā€ and ā€œentitiesā€ are keywords or just chosen names. A short explanation or link where I can read more would be awesome.

They are not wildcards they are yaml anchors. & sets a variable to contain the yaml below it. * recalls the yaml in the variable and reuses it in this new spot.

Declaring entities for use in another yaml field

Populating entities variable into another yaml field.

1 Like

Thanks for the quick reply! That is slick. I wonder why Iā€™ve not a seen a single example elsewhere that uses anchors since often the same ā€˜listā€™ of entities are found throughout. Iā€™m going to go back and do some cleanup.

Tks so much, this was Iā€™m looking long time ago to optimize my 4 automatizations in just 1ā€¦
3 way / ligths - multicontrol

  • Trigger: state A on => off ==> Action: B off
  • Trigger: state A off => on ==> Action: B on
  • Trigger: state B on => off ==> Action: A off
  • Trigger: state B off => on ==> Action: A on

Hi All,
I would like to achive something similar: I have 2 different sonoff switches in 2 different rooms. The first switch connected to a light in the first room. The second switch not connected to any light: it is a dummy switch. I have created automations to ā€œsynchronizeā€ the 2 switches: if I turn on the first switch it turns on the light and modify the state of the second switch. And so on.
It works flawless from home assistant user interface, but tapping the dummy switch: it do nothing.
Do you have any idea how I can manage the dummy switch to work without any connected light?
(I know that there is an RF-based sonoff switch that would work, Iā€™ve already tried it, I think it is not a good solution)
The sonoff switches are running with esphome firmware.
Thanks:
Peter!

Hello Peter. I have read your instructions on this topic but I am a beginner in HA and I do not understand much although I have studied a bit about automation and HA. I have the same problem with the multiple association of 3 zigbee tuya switches to control a single bulb. The 3 switches are Bseed Zigbee Model TS0001
Zigbee Manufacturer _TZ3000. They can be associated in the Smart Life and Tuya application, but I have HA on an orange pi 5 plus with SkyConnect coordinator. The 3 switches are integrated in zigbee 2mqtt and are connected to the current according to the diagram. I tried their association in YAML by copying a sketch of yours and just changing the IEEA address but I donā€™t know how and it didnā€™t work. I tried automation and scenes using triggers, but I still didnā€™t succeed. Please, and I am paying for this service, if you can teach me step by step how to solve this problem for beginners. I think it would be easier for me with automation in automation and scenes. Thank you in advance.