Two-way switch with two one-way switches

I assume if the switch is already “on” pressing it “on” again doesn’t trigger your light you’re working with right?

I wonder if the switch devices are taking longer than 1s to report a state change to HA? I have some ge zwave dimmers that need a polling delay for automations to work. Otherwise operating the switches themselves would give weird behavior, but from the gui all worked fine (similar to the OP). I think it had to do with “non-standard” zwave implementation. Just wondering if something similar is underlying here.

The reaction between the two switches is certainly lower than 1s; pressing the button on one switch almost instantly set the other.

If I set the two rules automations (one for one, and one for off) then everything works nicely.
When I press one switch, the other will go the other direction.
In my current setup, the light is only connected to one switch; but like in a 2-way switch setup, you should be able to control the light with a 2nd switch.

In any case, I’d prefer we stop on the “why do you want to do that” type of things, and concentrate on why we’re seeing this behaviour with 0.113

It’s certainly unexpected.

I think you may be onto something in regards to the states not being valid.
I get good result with this automation rule

- id: '1595569230149'
  alias: hallway on
  description: ''
  trigger:
  - device_id: 9516ecb1c0c14e74ab41779656a00d06
    domain: switch
    entity_id: switch.hallway_1_switch
    platform: device
    type: turned_on
  - device_id: b55a3e1dd81d4975a81b1202e082bf33
    domain: switch
    entity_id: switch.hallway_2_switch_2
    platform: device
    type: turned_on
  condition: []
  action:
  - device_id: 9516ecb1c0c14e74ab41779656a00d06
    domain: switch
    entity_id: switch.hallway_1_switch
    type: turn_on
  - device_id: b55a3e1dd81d4975a81b1202e082bf33
    domain: switch
    entity_id: switch.hallway_2_switch_2
    type: turn_on
  mode: single

This is using the device platform with turned_on type.
This is 100% working.

with the template:

alias: 'Hallway 2-way'
trigger:
- platform: state
  entity_id: switch.hallway_1_switch, switch.hallway_2_switch_2
mode: single
action:
- service_template: "homeassistant.turn_{{trigger.to_state.state}}"
  entity_id: switch.hallway_1_switch, switch.hallway_2_switch_2
- delay:
    seconds: 1

which will set both switches to the next state, as soon as you turn on a switch, it gets switched off.
It appears that the value of trigger.to_state.state isn’t valid at the time the automation rule is called; though I don’t know how to verify this theory.

1 Like

Sorry for the spam, but I think I see what’s going on.

I enabled all logs and it does:

2020-07-24 16:09:42 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on zigbee2mqtt/hallway_2_switch: b'{"state_top":"OFF","linkquality":72,"state_bottom":"OFF"}'
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=switch.hallway_2_switch_1, old_state=<state switch.hallway_2_switch_1=off; state_top=OFF, linkquality=87, state_bottom=ON, friendly_name=hallway_2_switch_1 @ 2020-07-24T15:57:49.422320+10:00>, new_state=<state switch.hallway_2_switch_1=off; state_top=OFF, linkquality=72, state_bottom=OFF, friendly_name=hallway_2_switch_1 @ 2020-07-24T15:57:49.422320+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=switch.hallway_2_switch_2, old_state=<state switch.hallway_2_switch_2=on; state_top=OFF, linkquality=87, state_bottom=ON, friendly_name=hallway_2_switch_2 @ 2020-07-24T16:07:48.325669+10:00>, new_state=<state switch.hallway_2_switch_2=on; state_top=OFF, linkquality=72, state_bottom=OFF, friendly_name=hallway_2_switch_2 @ 2020-07-24T16:07:48.325669+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=sensor.0x00158d0004771720_linkquality, old_state=<state sensor.0x00158d0004771720_linkquality=87; state_top=OFF, linkquality=87, state_bottom=ON, unit_of_measurement=lqi, friendly_name=hallway_2_switch_linkquality, icon=mdi:signal @ 2020-07-24T16:07:48.330753+10:00>, new_state=<state sensor.0x00158d0004771720_linkquality=87; state_top=OFF, linkquality=72, state_bottom=OFF, unit_of_measurement=lqi, friendly_name=hallway_2_switch_linkquality, icon=mdi:signal @ 2020-07-24T16:07:48.330753+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=switch.hallway_2_switch_2, old_state=<state switch.hallway_2_switch_2=on; state_top=OFF, linkquality=72, state_bottom=OFF, friendly_name=hallway_2_switch_2 @ 2020-07-24T16:07:48.325669+10:00>, new_state=<state switch.hallway_2_switch_2=off; state_top=OFF, linkquality=72, state_bottom=OFF, friendly_name=hallway_2_switch_2 @ 2020-07-24T16:09:43.019942+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=sensor.0x00158d0004771720_linkquality, old_state=<state sensor.0x00158d0004771720_linkquality=87; state_top=OFF, linkquality=72, state_bottom=OFF, unit_of_measurement=lqi, friendly_name=hallway_2_switch_linkquality, icon=mdi:signal @ 2020-07-24T16:07:48.330753+10:00>, new_state=<state sensor.0x00158d0004771720_linkquality=72; state_top=OFF, linkquality=72, state_bottom=OFF, unit_of_measurement=lqi, friendly_name=hallway_2_switch_linkquality, icon=mdi:signal @ 2020-07-24T16:09:43.024074+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.components.homekit.type_switches] switch.hallway_2_switch_2: Set current state to False
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=automation.hallway_2_way, old_state=<state automation.hallway_2_way=on; last_triggered=2020-07-24T16:07:48.840151+10:00, mode=single, friendly_name=Hallway 2-way @ 2020-07-24T15:57:10.559755+10:00>, new_state=<state automation.hallway_2_way=on; last_triggered=2020-07-24T16:09:43.216504+10:00, mode=single, friendly_name=Hallway 2-way @ 2020-07-24T15:57:10.559755+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event automation_triggered[L]: name=Hallway 2-way, entity_id=automation.hallway_2_way>
2020-07-24 16:09:43 INFO (MainThread) [homeassistant.components.automation] Executing Hallway 2-way
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=automation.hallway_2_way, old_state=<state automation.hallway_2_way=on; last_triggered=2020-07-24T16:09:43.216504+10:00, mode=single, friendly_name=Hallway 2-way @ 2020-07-24T15:57:10.559755+10:00>, new_state=<state automation.hallway_2_way=on; last_triggered=2020-07-24T16:09:43.219197+10:00, mode=single, friendly_name=Hallway 2-way @ 2020-07-24T15:57:10.559755+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event automation_triggered[L]: name=Hallway 2-way, entity_id=automation.hallway_2_way>
2020-07-24 16:09:43 INFO (MainThread) [homeassistant.components.automation] Executing Hallway 2-way
2020-07-24 16:09:43 WARNING (MainThread) [homeassistant.components.automation] Hallway 2-way: Already running
2020-07-24 16:09:43 INFO (MainThread) [homeassistant.components.automation] Hallway 2-way: Running script
2020-07-24 16:09:43 INFO (MainThread) [homeassistant.components.automation] Hallway 2-way: Executing step call service
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=switch, service=turn_on, service_data=entity_id=switch.hallway_1_switch>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=mqtt, service=publish, service_data=topic=zigbee2mqtt/hallway_1_switch/set, qos=0, retain=False, payload=ON>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.components.mqtt] Transmitting message on zigbee2mqtt/hallway_1_switch/set: ON
2020-07-24 16:09:43 INFO (MainThread) [homeassistant.components.automation] Hallway 2-way: Executing step delay 0:00:01
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on zigbee2mqtt/hallway_1_switch: b'{"state":"ON","linkquality":150}'
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=switch.hallway_1_switch, old_state=<state switch.hallway_1_switch=off; state=OFF, linkquality=150, friendly_name=hallway_1_switch @ 2020-07-24T16:07:48.712530+10:00>, new_state=<state switch.hallway_1_switch=off; state=ON, linkquality=150, friendly_name=hallway_1_switch @ 2020-07-24T16:07:48.712530+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=sensor.0x00158d0004622393_linkquality, old_state=<state sensor.0x00158d0004622393_linkquality=150; state=OFF, linkquality=150, unit_of_measurement=lqi, friendly_name=hallway_1_switch_linkquality, icon=mdi:signal @ 2020-07-24T16:00:00.897916+10:00>, new_state=<state sensor.0x00158d0004622393_linkquality=150; state=ON, linkquality=150, unit_of_measurement=lqi, friendly_name=hallway_1_switch_linkquality, icon=mdi:signal @ 2020-07-24T16:00:00.897916+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=switch.hallway_1_switch, old_state=<state switch.hallway_1_switch=off; state=ON, linkquality=150, friendly_name=hallway_1_switch @ 2020-07-24T16:07:48.712530+10:00>, new_state=<state switch.hallway_1_switch=on; state=ON, linkquality=150, friendly_name=hallway_1_switch @ 2020-07-24T16:09:43.553837+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=automation.hallway_2_way, old_state=<state automation.hallway_2_way=on; last_triggered=2020-07-24T16:09:43.219197+10:00, mode=single, friendly_name=Hallway 2-way @ 2020-07-24T15:57:10.559755+10:00>, new_state=<state automation.hallway_2_way=on; last_triggered=2020-07-24T16:09:43.569952+10:00, mode=single, friendly_name=Hallway 2-way @ 2020-07-24T15:57:10.559755+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event automation_triggered[L]: name=Hallway 2-way, entity_id=automation.hallway_2_way>
2020-07-24 16:09:43 INFO (MainThread) [homeassistant.components.automation] Executing Hallway 2-way
2020-07-24 16:09:43 WARNING (MainThread) [homeassistant.components.automation] Hallway 2-way: Already running
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=automation.hallway_2_way, old_state=<state automation.hallway_2_way=on; last_triggered=2020-07-24T16:09:43.569952+10:00, mode=single, friendly_name=Hallway 2-way @ 2020-07-24T15:57:10.559755+10:00>, new_state=<state automation.hallway_2_way=on; last_triggered=2020-07-24T16:09:43.692102+10:00, mode=single, friendly_name=Hallway 2-way @ 2020-07-24T15:57:10.559755+10:00>>
2020-07-24 16:09:43 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event automation_triggered[L]: name=Hallway 2-way, entity_id=automation.hallway_2_way>
2020-07-24 16:09:43 INFO (MainThread) [homeassistant.components.automation] Executing Hallway 2-way
2020-07-24 16:09:43 WARNING (MainThread) [homeassistant.components.automation] Hallway 2-way: Already running

you can see the it process the mqtt event that the switch got turned off once it’s done the 1s delay.
And so the switch will be turned off.

Now what is very bizarre, with the following two automation rules; it works perfectly.

- id: '1595578058005'
  alias: Sync Hallway - On
  description: ''
  trigger:
  - entity_id: switch.hallway_2_switch_2, switch.hallway_1_switch
    platform: state
    to: 'on'
  condition: []
  action:
  - service_template: switch.turn_{{trigger.to_state.state}}
    data:
      entity_id: switch.hallway_1_switch, switch.hallway_2_switch_2
  - delay: '1'
  mode: single
- id: '1595580244911'
  alias: Sync Hallway - Off
  description: ''
  trigger:
  - entity_id: switch.hallway_2_switch_2, switch.hallway_1_switch
    platform: state
    to: 'off'
  condition: []
  action:
  - service_template: switch.turn_{{trigger.to_state.state}}
    data:
      entity_id: switch.hallway_1_switch, switch.hallway_2_switch_2
  - delay: '1'
  mode: single

yet, the functionally equivalent:

- id: '1595578058005'
  alias: Sync Hallway
  description: ''
  trigger:
  - entity_id: switch.hallway_2_switch_2, switch.hallway_1_switch
    platform: state
  condition: []
  action:
  - service_template: switch.turn_{{trigger.to_state.state}}
    data:
      entity_id: switch.hallway_1_switch, switch.hallway_2_switch_2
  - delay: '1'
  mode: single

will cause the two switch to be in the exact opposite state; is it possible for trigger.to_state.state to be something else than ‘on’ or ‘off’?

Edit:

I found a solution for a single template which works quite nicely.

- alias: Sync Hallway
  description: ''
  trigger:
  - entity_id: switch.hallway_2_switch_2, switch.hallway_1_switch
    platform: state
  condition:
    condition: template
    value_template: "{{ 'on' in trigger.to_state.state or 'off' in trigger.to_state.state }}"
    condition: template
    value_template: "{{ trigger.from_state.state != trigger.to_state.state }}"
  action:
  - service_template: homeassistant.turn_{{trigger.to_state.state}}
    data:
      entity_id: switch.hallway_2_switch_2, switch.hallway_1_switch
  mode: single

Difference to before is in the condition I make sure the state is either on or off; and that the new state must be different to the old one.

This works perfectly without delay needed.
Because I was on my smartphone, I simply created two automations from the automation menu in Lovelace.
This commands my kitchen light from two different Sonoff mini switches (one is connected to the light, the second is only connected to the wifi).
Automation 1: kitchen on
Triggers:

  • state light kitchen from off to on
  • state light kitchen wifi from off to on
    Actions:
  • service homeassistant turn on light kitchen
  • service homeassistant turn on light kitchen wifi

Automation 2 : kitchen off
… The same but on’s and off’s inverted.

The easy way is often the best :wink:
I hope it will help.

1 Like

yeah, but that’s no fun. And rather painful when you have multiple 2-way switches to setup (this is a method mentioned multiple times here earlier)

Additionally, you’ll find with your solution, that if switching on/off very quickly, you may enter in a rapid loop where they switch on/off/on/off super quickly and the only way to stop it is by disabling the automation entries.

Sorry to say that but here even if I switch quickly on and off from the physical switches … It’s working fine.
And because the triggers are both mentioned and the actions are both mentioned too, it can’t go in a loop.
Maybe because it’s two separated automation to set on and off it can’t go in a loop because whatever trigger is taken into account, the result is that both switches goes to the same state.
The only thing is that if I switch on off very very very quickly about 10 times, it can be that the switch in WiFi is not following and that I need to switch once more to resync both switches and that’s really acceptable

But I agree, as programmer … that’s no fun :joy:

Here is a simpler version of the 1-automation rule that will do exactly as your two ones.

- alias: Sync Hallway
  description: ''
  trigger:
  - entity_id: &entities
      - switch.hallway_2_switch_2
      - switch.hallway_1_switch
    platform: state
    to:
    - 'on'
    - 'off'
  action:
  - service_template: homeassistant.turn_{{trigger.to_state.state}}
    data:
      entity_id: *entities
  mode: single

Only have to list all the entities once. Much simpler to maintain.

5 Likes

What is that &entities and *entities all about?! Looks like C pointers in YAML. Is this documented anywhere?

They are YAML anchors. They are documented in YAML documentation (not in HA docs).

2 Likes

Also, anchors do not pass through !includes. So they are largely useless in most of HA configuration. They are good for lovelace though.

2 Likes

this is a fine read up Thomas Lovén - YAML for Non-programmers
read all the way down

1 Like

How?

This works great in a sub-folder where I have all my automations which is included via:
!include_dir_merge_list automations/

I have about 6-pair of devices I sync via automations like this now. Working great.

The only downside I’ve seen is that you can only have one per file; as it’s global to that file

It works in your 1 specific use case for automations where your anchor is contained in 1 file. But it doesn’t work in the most asked for use case: Creating a group of entities as an anchor and having that anchor pass to all other files.

hmmm. not it doesn’t.

I have one room’s automation per file; so 6-pair of switch/light in 6 different rooms; 6 different use of “entities” in 6 different yaml file.

I see no conflicts with that usage.

If I use the same anchor in the same file, then yes, I will get an error about the redefinition of an anchor. But the anchor is only local to a yaml file.

Maybe you didn’t understand my post?

I simply said that you cannot declare an anchor in a file and expect it to be passed into a !include file.

I’m trying to use this code but it’s not working

  • alias: Sincronizar corredor
    description: ‘’
    trigger:
    • entity_id: &entities
      • light.3a_smart_home_de_lxn_3s27lx1_0_level_on_off
      • light.3a_smart_home_de_lxn_3s27lx1_0_d3974a04_level_on_off
        platform: state
        to:
      • ‘on’
      • ‘off’
        action:
    • service_template: homeassistant.turn_{{trigger.to_state.state}}
      data:
      entity_id: *entities
      mode: single

Edit:
now it’s working, thnkx

Noob question. Where does one put this code? Thanks.