Controlling a group of devices together, without looping/echo

This sounds simpler than it is.

I have 4 zwave light switches that control different lights in the back yard. I have two outlets that control a set of hanging market lights.

I want to create an automation that does the following:

If any of these four switches turn on:
Switch 1
Switch 2
Switch 3
Switch 4

Turn on the following:
Switch 1
Switch 2
Switch 3
Switch 4
Outlet 1
Outlet 2

Here is the problem: It creates some sort of echo on the zwave network. If I was to physically turn on switch 1, it would turn on the others, but then since those turned on, it would again try to turn on all the other, and since they turned on, it would again try to turn everything on.

When one is turned on, I need it to happen once for all devices and stop. Same thing with the off action.

Anyone know how I would go about doing this?

input_boolean:
  loop_prevention:


automation:
  alias: synchronise switches
  trigger:
    platform: state
    entity_id:
      - Switch 1
      - Switch 2
      - Switch 3
      - Switch 4
  condition:
    - condition: state
      entity_id: input_boolean.loop_prevention
      state: 'off'
    - "{{ trigger.to_state.state != 'unavailable' }}" 
  action:
    - service: input_boolean.turn_on
      entity_id: input_boolean.loop_prevention
    - delay:
        seconds: 1
    - service: "homeassistant.turn_{{ trigger.to_state.state }}" 
      entity_id:
        - Switch 1
        - Switch 2
        - Switch 3
        - Switch 4
        - Outlet 1
        - Outlet 2
    - delay:
        seconds: 1
    - service: input_boolean.turn_off
      entity_id: input_boolean.loop_prevention
1 Like

Wow, awesome - thank you. Pretty brand new to HA so where would I put this code? I’m also guessing that I’d have to swap out the names of the switches as well? Not sure I know what to put in those places.

Yeah, you’ll need to replace ‘switch 1’ with the entity_id for switch 1, and the same for the rest.

Where to put it depends on how your configuration is split up (or even if it is split up).

You could just put that code exactly as it is (once the entity_ids are updated) in a fresh package. (this is probably the easiest)

Or you can put the input boolean directly into configuration.yaml and the automation into an automations.yaml (remove the automation key from the top and add a - to the start of the alias line to add it to the list).

But I don’t know how your configuration is split up :man_shrugging:

I don’t have anything split up or anywhere. I’ve made a few basic automations in the UI but that is about it.

What would be the recommended places where I should put it so I don’t learn the wrong way going forward? Sounds like keeping it in a fresh package - but I have no clue how to do that. Point me in the right direction on that one? I’ll of course find out the IDs for each device before.

OK, I presume you have some way of editing your configuration?

If not then you need to set that up - then…

Go to your configuration.yaml and add this

homeassistant:
  packages: !include_dir_named packages

Then save configuration.yaml

Then in the same directory as your configuration.yaml create a new directory called ‘packages’, then inside that create a new text file called ‘synchronised_lights.yaml’

Paste the code into that, swap out ‘Switch 1’ etc for your actual entity_ids.

Then save synchronised_lights.yaml

Go to Configuration > Server Controls and click ‘Check configuration’, make sure everything is ticketyboo, then click restart.

Once homeassistant is back up check the automation works as expected.

Perfect, I’ve installed the File Editor add-on already so I’ll use that. Really appreciate the help and direction here on this. I’ll get this added and see what happens and report back.

1 Like

Ok seems to be working. Here is the code that I’m using now below. Can you walk me through this so I can understand what is happening? I’d like to learn from it so I can use the knowledge elsewhere. In particular, I’m interested in the two delays.

input_boolean:
  loop_prevention:

automation:
  alias: Synchronize Back Yard Switches
  trigger:
    platform: state
    entity_id:
      - switch.back_porch_lights
      - switch.office_porch_light
      - switch.gym_porch_light
      - switch.shop_porch_light
  condition:
    - condition: state
      entity_id: input_boolean.loop_prevention
      state: 'off'
    - "{{ trigger.to_state.state != 'unavailable' }}" 
  action:
    - service: input_boolean.turn_on
      entity_id: input_boolean.loop_prevention
    - delay:
        seconds: 1
    - service: "homeassistant.turn_{{ trigger.to_state.state }}" 
      entity_id:
        - switch.back_porch_lights
        - switch.office_porch_light
        - switch.gym_porch_light
        - switch.shop_porch_light
        - switch.bocce_lights_north
        - switch.bocce_lights_south
    - delay:
        seconds: 1
    - service: input_boolean.turn_off
      entity_id: input_boolean.loop_prevention

Sure,

So - first we wait for a state change in switch.back_porch_lights, switch.office_porch_light, switch.gym_porch_light or switch.shop_porch_light.

When the state changes we check whether input_boolean.loop_prevention is on or off, and we also check that the state change isn’t that one of them has gone unavailable.

Now, if input_boolean.loop_prevention is ‘on’ the automation won’t run. This means that we’re effectively stopping it from triggering again to prevent the loop you were experiencing.

So, if input_boolean.loop_prevention is ‘off’ we run the action. The action works like this…

  • Turn input_boolean.loop_prevention on (prevent the automation triggering again when we turn the other switches on)
  • wait a second (just as a buffer really to ensure everything is in the right state before we continue)
  • turn on or off the rest of the switches based on the state of the device that triggered the automation
  • wait a second (another buffer)
  • turn input_boolean.loop_prevention back off ready for the next time the automation is triggered.

Hope this helps.

1 Like

So the list of items in the action section are executed in order that they appear there. It throws me off when the thing is called out after the action.

For example, I would think it would be like this:

action:
    - entity_id: input_boolean.loop_prevention
      service: input_boolean.turn_on

Say what you’re using, then turn that thing on or whatever. Can I do it like this or do you always call out the action first and then say what you’re doing it on second?

Each ‘step’ is executed in turn, the steps are designated by the - sign.

The keys inside each step can be in any order you like, but you’ll normally see them written the way I did because it makes more sense, ie

I want this step to: turn on my bedroom light

Would be

service: light.turn_on
entity_id: light.bedroom

Nobody ever says “I want this step to bedroom light my turn on” :wink:

1 Like

Ok, makes sense and that helps me a lot. Your last statement made me laugh… yeah it doesn’t sound right at all - and that is what really was the most help so I can read and comprehend these lines. Thanks again for all the help and all of the explanation.

1 Like

I’ve been doing the same thing in a slightly different way. Instead of the input boolean and delays, I added a “Wait” as the last action with a template that will keep the automation waiting until all the lights are in the expected on/off state.

With the default run mode of “single” this prevents the automation from running again for each switch (except perhaps the last one) but also prints a warning to the logs. I found that a bit annoying so I changed it to “queued” mode. This will trigger the automation again but doesn’t actually do anything since we’ve already waited for all lights to be in the correct state. Still not ideal, but you could extend it further to having a check in the condition that prevents it from running if the lights are all in the expected state or use the parallel mode with the input_boolean suggested here.

Still, I wish this was easier. It seems like a lot of jumping through hoops just to keep a group of switches in sync.

You can leave it in single mode and add max_exceed: silent to prevent the warning being dumped to the log.

Oh nice. Didn’t notice that. It looks like this is an option you have to go into the yaml to use? I don’t see it in the UI editor.

I’ve genuinely never used the UI for an automation, so I have no idea :man_shrugging: