Synchronize the on/off state of 2 entities

Hmm, Seems the lights unsynced again. Any idea why this is happening? Maybe a different solution? Thanks.

So I set this up to synchronize the lights at the top and bottom of my stairs. However, it’s not exactly what I want, as I only really have one switch I want to use and so I really want to unidirectionally “copy” state from one entity (a switch) to another (a receptacle). Also, my receptacle device is slow, and sometime it is slow enough (or maybe it just misses the state change) the old, incorrect state gets copied BACK and the light turns off! It’s also overall slower than I would like. I switched to HA from ST to try and avoid cloud delays, but if anything it’s slower now. I often end up halfway down the stairs before the light at the top (connected to the “controlled” receptacle) turns on.

I realize a blueprint to just “copy” a binary state is actually a pretty trivial (probably I should try to set it up directly as an automation) but it still would be pretty useful to have as a blueprint just to allow for a nicer setup UI.

If it matters both devices are Z-Wave (for now; the light at the top is an addressable LED strip, eventually to be turned into an ambient data display via MQTT probably, but for now I just want to control it by switching power on and off). Anyway, the future extension I have in mind is why I want to do this with an automation rather than Z-wave direct association etc.

Thank you for your solution. I’ve tried this solution and if touching the switch so quick, they are still being flicked repeatedly.

I’m guessing you added a condition to prevent flickering/loop. If you think about it, it can still go to an infinite loop if states are not updated in real time. Personally I found that the only way to truely prevent a loop is to add a 0.5-1 second delay to one switch/light triggering the other. So it goes like this: If light A is turned on/off, then immediately turn light B on/off. If light B is turned on/off FOR ONE SECOND, then turn light A on/off. Let me know your thoughts. In my use case the delay is not a big deal and preventing the loop really gives me peace of mind

1 second delay is too long to my liking. It also have the side effect of not registering if the switch was turned ON then OFF in less than 1s.
I’ve been runing this for almost a year and never experienced flickering. I do agree that it could still happen in some edge cases.

One thing you may test is adding a condition on the context, to block state change if it was triggered by the automation itself. I tested it briefly and it seems to do the trick:

condition: template
value_template: >-
    {{ trigger.to_state.context.parent_id is none or 
      (trigger.to_state.context.id         != this.context.id and 
       trigger.to_state.context.parent_id  != this.context.id) }}

I tested this one extensively this morning, and worked very well for me.
I have versions of this with up to 5 switches and fast clicking did not resulted in flickering.

Please let me know if it works for you.

blueprint:
  name: Synchronize 2 States
  description: Bind two switches together to act in unison
  domain: automation
  input:
    switch_1:
      name: Switch 1
      selector:
        entity:
          domain: switch
    switch_2:
      name: Switch 2
      selector:
        entity:
          domain: switch

variables:
  switches: 
    - !input switch_1
    - !input switch_2

trigger:
  - platform: state
    entity_id: 
      - !input switch_1
      - !input switch_2


mode: queued
max_exceeded: silent

condition:
  - condition: template
    value_template: '{{ trigger.to_state.state != trigger.from_state.state }}'

  - condition: template
    value_template: >
      {{ trigger.to_state.context.parent_id is none or 
      (trigger.to_state.context.id         != this.context.id and 
       trigger.to_state.context.parent_id  != this.context.id) }}

action:

  # Set to target value
  - service: 'switch.turn_{{ trigger.to_state.state }}'
    target: 
      entity_id: '{{ expand(switches) | selectattr("entity_id", "!=", trigger.entity_id) | map(attribute="entity_id") | list }}'  

3 Likes

I have some recessed lights that are in the ceiling 2 next to each other. Unfortunately some lights come on without being triggered. Always on by the way, never off or any other change.
Could I use this template to check each pair and if 1 is of, to also switch the other off?
How would I do this?

Appreciate this Blueprint very much. It works perfectly for my needs! Thank you for your solution.

Thank you for your sharing. It seems to be better but still not cover all the cases.
I’ve tested your updated blueprint and if still touch button 1 very fast, there is still a loop (I test 3 times and got 1 time loop).

Beside that, if touch button 1 very fast then touch button 2 only 1 time, the button 1 is not synced with button 2.

I tested with the zigbee switch via zigbee2mqtt

This doesnt work well, some weired flipflop, not many, one or 2 flipflop and it will stop. Sometime stop at the wrong state…Need to refine. Not usable for now.

This one work perfectly so far. Thanks @hebus , I have tried everything including fast clicking of either switch, never get into flipflop situation. I like the fact that you did not use the delay method, which I think is not addressing the root cause. Great Job, Thanks…
If you have time to explain your blueprint line briefly, that will be greatly appreciated…for learning.
Just need to understand the “Condition” and “Action” code…

I disagree with @chinhhut, either his conditoin is different or he accidentally refer to the wrong blueprint. My condition: 2 zigbee wall switch, use Z2M, HASS on Pi4, ZZH dongle.

I imported the original post blueprint and works like a charm!
Now my actuar and controller can be turned on/off at same time :slight_smile:
Thanks!

The condition filter out events that were triggered by the automation itself. The documentation is not very precise on the “context” field used here. I ended up with that condition through trial and error.

The action selects every switches that did not trigger the automation and turn them to the target state.

1 Like

@hebus, thanks for the explanation. I studied your code and I did alot of permutation, not to doubt you but try to learn each and every line of the code.

What I found out. Actually you gave a very deep thought in the code.

  1. In your second condition, you allow the manual switch trigger, you block the automation trigger but you allow automation triggered from outside of current session.
    This is exactly my situtation, my light switch is also triggered by a motion sensor, very usefull.
    1b. However I don’t quite understand the AND logic,
    {{ trigger.to_state.context.id != this.context.id and trigger.to_state.context.parent_id != this.context.id }}

  2. I like your action code to act on all other switch/es, the code is so short and sharp. Fantastic!

  3. However, I find that the first condition is not neccessary (maybe I’m wrong), to_state and from_state isn’t by design they are not equal?
    {{ trigger.to_state.state != trigger.from_state.state }}
    I tried to remove the first condition and it does work perfectly.

Could you kind enough to explain 1b. please?
{{ trigger.to_state.context.id != this.context.id and trigger.to_state.context.parent_id != this.context.id }}

Thanks and really appreciate this blueprint.

I also am getting that error in my logs now

2022-03-05 16:32:04 INFO (MainThread) [homeassistant.components.automation.sync_floods] Sync Floods: Restarting
2022-03-05 16:32:04 INFO (MainThread) [homeassistant.components.automation.sync_floods] Sync Floods: Running automation actions
2022-03-05 16:32:04 INFO (MainThread) [homeassistant.components.automation.sync_floods] Sync Floods: Executing step call service
2022-03-05 16:32:04 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: 'dict object' has no attribute 'to_state' when rendering 'homeassistant.turn_{{ trigger.to_state.state }}'
2022-03-05 16:32:04 ERROR (MainThread) [homeassistant.components.automation.sync_floods] Sync Floods: Error executing script. Error for call_service at pos 1: Error rendering service name template: UndefinedError: 'dict object' has no attribute 'to_state'
2022-03-05 16:32:04 ERROR (MainThread) [homeassistant.components.automation.sync_floods] Error while executing automation automation.sync_floods: Error rendering service name template: UndefinedError: 'dict object' has no attribute 'to_state'
2022-03-05 16:32:11 INFO (Thread-4) [wirelesstagpy] Start listen for push update
2022-03-05 16:32:39 INFO (MainThread) [homeassistant.components.automation.sync_floods] Sync Floods: Restarting
2022-03-05 16:32:39 INFO (MainThread) [homeassistant.components.automation.sync_floods] Sync Floods: Running automation actions
2022-03-05 16:32:39 INFO (MainThread) [homeassistant.components.automation.sync_floods] Sync Floods: Executing step call service

Version: 2022.3.1

I can confirm that I’m getting this error now as well, it started as soon as I upgraded to 2022.3.0.

This Blue Print works extremely well for quite a while then recently started throwing this error:

Error: Error rendering service name template: UndefinedError: 'dict object' has no attribute 'to_state'

I’ve taken the ideas presented here (especially @hebus’s fantastic template work above) and created a new blueprint which allows the selection of multiple switch devices.

HI, I have a wall switch named switch.radio_button which fires script.radio. Script.radio turns on mediaplayer.onkyo + sets network mode and fires internet radio threw google cast integration - this works great.
I wanted to sync state of mediaplayer.onkyo and the wall button, after onkyo is turned on by remote controler or phisical button. This works …almost. Because every time sync is trigered, script.radio is also trigered.
Can you advice, how to use this blueprint, together with a condition, that sync should not triger the script?

Nice, it works for me using 2 and 3 switches, thanks! It is very easy to extend