Avoiding loops when copying light status

Hi all,

I’ve setup some switches Sonoff (using Tasmota software) on the entrance and the corridor. As Sonoff Touch shows a light depending on the status (on/off) I mantain them in the same status (instead of toggling the other status). Only one is connected to the actual light and the rest are just for easy access. I’ve some automation scripts that copy the status of one switch to the others but some times they get into a loop that can only be stopped restarting home assistant.
Has anybody any better idea on how to do it to avoid the loop? I’ve try groups of ligths but it doesn’t solve the issue.

The automations are:

Control entry light

  • alias: “Entry light 1”
    initial_state: ‘on’
    trigger:
    platform: state
    entity_id: light.entry_light_1
    action:
    service_template: >
    {% if trigger.to_state.state == “on” %}
    light.turn_on
    {% elif trigger.to_state.state == “off” %}
    light.turn_off
    {% endif %}
    entity_id: light.entry_light_2

  • alias: “Entry light 2”
    initial_state: ‘on’
    trigger:
    platform: state
    entity_id: light.entry_light_2
    action:
    service_template: >
    {% if trigger.to_state.state == “on” %}
    light.turn_on
    {% elif trigger.to_state.state == “off” %}
    light.turn_off
    {% endif %}
    entity_id: light.entry_light_1

Thanks!

In your action for the first one, switch the second automation off, switch the light on, delay for 5 seconds and switch the second automation back on.

Similar thing for the second automation, turning off the first one and then back on again :+1:

Personally I’d add a condition that the other automation hasn’t ran in the last x sec (replace x with a number)

- condition: template
  value_template: '{{ (as_timestamp(now()) - as_timestamp(states.automation.entry_light_1.attributes.last_triggered | default(0)) | int > x)}}'
1 Like

What about creating a template switch based on Entry light 2 function and the state of Entry light 1 and bypass automation?

I tried with a template switch and the copy function but couldn’t make it work. :cold_sweat:
Trying the condition to ensure the other automation hasn’t run in the last x (2 seconds to start with).

Thanks.

By now it looks like it is working, let’s see in some days. Thanks to everybody!
Finally I’m doing a mix of ligth group with the condition:

  light:
    - platform: mqtt
      name: "entry light 1"
      command_topic: "cmnd/wsw_sonoff_entry_light_1/POWER"
      state_topic: "stat/wsw_sonoff_entry_light_1/POWER"
      availability_topic: "tele/wsw_sonoff_entry_light_1/LWT"
      qos: 1
      payload_on: "ON"
      payload_off: "OFF"
      payload_available: "Online"
      payload_not_available: "Offline"

    - platform: mqtt
      name: "entry light 2"
      command_topic: "cmnd/wsw_sonoff_entry_light_2/POWER"
      state_topic: "stat/wsw_sonoff_entry_light_2/POWER"
      availability_topic: "tele/wsw_sonoff_entry_light_2/LWT"
      qos: 1
      payload_on: "ON"
      payload_off: "OFF"
      payload_available: "Online"
      payload_not_available: "Offline"

    - platform: group
      name: "entry lights"
      entities:
        - light.entry_light_1
        - light.entry_light_2

  automation:
  # Control entry light
    - alias: "Entry light 1"
      initial_state: 'on'
      trigger:
        platform: state
        entity_id: light.entry_light_1
      condition: 
        - condition: template
          value_template: '{{ (as_timestamp(now()) - as_timestamp(states.automation.entry_light_2.attributes.last_triggered | default(0)) | int > 2)}}'
      action:
        service_template: >
        {% if trigger.to_state.state == "on" %}
        light.turn_on
        {% elif trigger.to_state.state == "off" %}
        light.turn_off
        {% endif %}
      entity_id: light.entry_lights

    - alias: "Entry light 2"
      initial_state: 'on'
      trigger:
        platform: state
        entity_id: light.entry_light_2
      condition: 
        - condition: template
          value_template: '{{ (as_timestamp(now()) - as_timestamp(states.automation.entry_light_2.attributes.last_triggered | default(0)) | int > 2)}}'    
      action:
        service_template: >
          {% if trigger.to_state.state == "on" %}
          light.turn_on
          {% elif trigger.to_state.state == "off" %}
          light.turn_off
          {% endif %}
        entity_id: light.entry_lights

you need to adjust your 2nd automation:
The condition points to the same automation, so it’ll never work.
Replace entry_light_2 with entry_light_1

        - condition: template
          value_template: '{{ (as_timestamp(now()) - as_timestamp(states.automation.entry_light_1.attributes.last_triggered | default(0)) | int > 2)}}'    

The idea is that if the other automation ran in the last 2 seconds, you don’t want to run this one. so you need to make sure you check when the other automation ran.
Hope that makes sense.

Thanks a lot, I just noticed it when I was applying the condition to other lights.
BTW, I have one group of 3 lights for the corridor, would it be ok this condition?

condition: 
      condition: and
      conditions:
        - condition: template
          value_template: '{{ (as_timestamp(now()) - as_timestamp(states.automation.corridor_light_2.attributes.last_triggered | default(0)) | int > 2)}}'
        - condition: template 
          value_template: '{{ (as_timestamp(now()) - as_timestamp(states.automation.corridor_light_3.attributes.last_triggered | default(0)) | int > 2)}}'

yes that would work too :slight_smile:

@angelpereyra

Did you manage to get this to work ok with your setup?
I have tried replicating what you have done. But switch 1 isn’t switching switch 2.

If i switch the group on/off on the interface both switches switch.

Hola @wills106, yes, it’s working for me. This is my setup in case it may help you (you may have already solved after 3d) :slight_smile: :

# lights setup
  - platform: mqtt
    name: "entry light 1"
    command_topic: "cmnd/wsw_sonoff_entry_light_1/POWER"
    state_topic: "stat/wsw_sonoff_entry_light_1/POWER"
    availability_topic: "tele/wsw_sonoff_entry_light_1/LWT"
    qos: 1
    payload_on: "ON"
    payload_off: "OFF"
    payload_available: "Online"
    payload_not_available: "Offline"

  - platform: mqtt
    name: "entry light 2"
    command_topic: "cmnd/wsw_sonoff_entry_light_2/POWER"
    state_topic: "stat/wsw_sonoff_entry_light_2/POWER"
    availability_topic: "tele/wsw_sonoff_entry_light_2/LWT"
    qos: 1
    payload_on: "ON"
    payload_off: "OFF"
    payload_available: "Online"
    payload_not_available: "Offline"

  - platform: group
    name: "entry lights"
    entities:
      - light.entry_light_1
      - light.entry_light_2  
# Automation
  - alias: "Entry light 1"
    initial_state: 'on'
    trigger:
      platform: state
      entity_id: light.entry_light_1
    condition: 
      - condition: template
        value_template: '{{ (as_timestamp(now()) - as_timestamp(states.automation.entry_light_2.attributes.last_triggered | default(0)) | int > 2)}}'
    action:
      service_template: >
        {% if trigger.to_state.state == "on" %}
        light.turn_on
        {% elif trigger.to_state.state == "off" %}
        light.turn_off
        {% endif %}
      entity_id: light.entry_lights

  - alias: "Entry light 2"
    initial_state: 'on'
    trigger:
      platform: state
      entity_id: light.entry_light_2
    condition: 
      - condition: template
        value_template: '{{ (as_timestamp(now()) - as_timestamp(states.automation.entry_light_1.attributes.last_triggered | default(0)) | int > 2)}}'    
    action:
      service_template: >
        {% if trigger.to_state.state == "on" %}
        light.turn_on
        {% elif trigger.to_state.state == "off" %}
        light.turn_off
        {% endif %}
      entity_id: light.entry_lights

Hope it helps!

BTW, I even have a 3 lights one that works fine too.

Thanks for the reply @angelpereyra I am using an alternative method based on what @icaman004 mentioned on another thread.

My working setup is here: [Resolved] 2 Way light switch using mqtt

I have not encountered any loops so far, but if I do I will have another look at your code.

Thanks