Switch template not always calling turn_on, turn_off

I have a hardware MQTT switch (standalone; eg, not connected to any other hardware, with an LED showing the toggle state) and two hardware lights. In HA, I have the hardware switch set up as switch.dining_room_couch and the lights as light.dining_room_1 and light.dining_room_2

The switch and both lights work fine, and update the entities fine.

I’m trying to rig things so that the hardware switch will turn on/off both lights, and status should match the hardware state of at least one of the lights. So turning on either light should result in the switch being on, turning off both lights should result in the switch being off, and toggling the switch should apply the same toggle (off or on) to both lights.

There are probably many ways to do this, but I’m trying to find the least complex way of doing things (minimum number of configurations/automations/scripts to make this work). The simplest configuration I could think of is to use a switch_template and group (which provides the same on/off logic that I want anyway), which almost works:

(in groups)
Dining Room Couch:
entities:
- light.dining_room_1
- light.dining_room_2
- switch.dining_room_couch

(in switches)

  • platform: template
    switches:
    dining_room_couch_group:
    friendly_name: “Dining Room Couch”
    value_template: “{{ is_state(‘switch.dining_room_couch’,‘on’) }}”
    turn_on:
    service: homeassistant.turn_on
    data:
    entity_id: group.dining_room_couch
    turn_off:
    service: homeassistant.turn_off
    data:
    entity_id: group.dining_room_couch

The result of this is that toggling the HA switch will toggle the entire set of hardware (switch + both lights). However, toggling the hardware switch will toggle the HA switch but not the lights, and similarly toggling both lights won’t toggle the hardware switch.

Anyone have experience in such a setup who is willing to share?

Can’t you just create a group with just the lights in it and toggle that group instead?

How do I toggle the group from the hardware switch?

trigger:
  platform: state 
  entity_id: YOUR_SWITCH
action:
  service: homeassistant.toggle 
  entity_id: group.YOUR_GROUP_WITH_JUST_THE_LIGHTS

?

Or you could fine tune it with a service template if it is more complicated than that.

That will fix the switch to control the lights, but it won’t toggle the switch when the lights are both on/off (and without getting a bit fancier, if one light is on and the other is off, toggle isn’t helpful :stuck_out_tongue:slight_smile:
That’s why I was trying to use the group (including the switch) and the switch template

The alternative is that I could get rid of the switch template, leave the group as-is and create 4 automations (one for each on/off scenario) - it just seems that there should be a cleaner way

If one light is on the group will be on. Toggling it will switch the group off, and hence both lights off. Is that not what you wanted?

If not, I think you’ll still need the group so you can determine the logic of whether at least one light is on, regardless of the status of the switch.

No, toggling the group toggled both individual lights, so if one was on and the other off, the toggle would switch them :confused:

If I’m already forced to use automation, the closest I have is this which does everything, except that the events cascade, so turning on light_1 causes switch to turn on which in turn causes light_2 to go on. It sucks because it’s 5 automations (two for the switch to toggle the lights, 2 for the lights to toggle the switch, and one to read the initial switch state on startup)

- alias: Dining Room Couch Switch On
  hide_entity: True
  action:
    service: homeassistant.turn_on
    entity_id: group.dining_room_couch
  trigger:
    platform: state
    entity_id: switch.dining_room_couch
    to: 'on'
    
- alias: Dining Room Couch Switch Off
  hide_entity: True
  action:
    service: homeassistant.turn_off
    entity_id: group.dining_room_couch
  trigger:
    platform: state
    entity_id: switch.dining_room_couch
    to: 'off'
    
- alias: Dining Room Couch Sync On
  hide_entity: True
  action:
    service: homeassistant.turn_on
    entity_id: switch.dining_room_couch
  trigger:
    platform: state
    entity_id: group.dining_room_couch
    to: 'on'
   
- alias: Dining Room Couch Sync Off
  hide_entity: True
  action:
    service: homeassistant.turn_off
    entity_id: switch.dining_room_couch
  trigger:
    platform: state
    entity_id: group.dining_room_couch
    to: 'off' 

- alias: Dining Room Couch Initialize
  hide_entity: True
  action:
    service_template: >
      {% if is_state('group.dining_room_couch','on') %}
        switch.turn_on
      {% else %}
        switch.turn_off
      {% endif %}
    entity_id:
      switch.dining_room_couch
  trigger:
    platform: homeassistant
    event: start

Hmmm, OK, I have to get ready for work but if nobody else chimes in I’ll have a head scratch and see if I can get my head around it and neaten it up for you :+1:

OK - If I understand the logic you want correctly it looks like this:

  • If one or both of the lights are on, the switch should be on.
  • If both lights are off the switch shoud be off.

From the off position -

  • If one light is turned on, the switch should turn on
  • If the switch is turned on, both lights should turn on

From the on position

  • If both lights are on, and one is switched off, the other light and the switch should remain on
  • If one light (and the switch) are on, and the second light is switched on, then all three stay on
  • if either, or both lights are on and the switch is pressed all lights and the switch go off.
  • If one light (and the switch) are on, and the light is switched off, the swtch is turned off

Yes?

Hope so!

Here is the code that makes it happen:

### Remove the template switch completely

group:
  dining_room_lights:
    - light.dining_room_1
    - light.dining_room_2

automation:
  - alias: 'mf_social magic code 1'
    trigger:
      platform: state
      entity_id: switch.dining_room_couch
    action:
      entity_id: group.dining_room_lights
      service_template: >
        {% if is_state ('group.dining_room_lights' , 'off') %} homeassistant.turn_on
        {% else %} homeassistant.turn_off
        {% endif %}

  - alias: 'mf_social magic code 2'
    trigger:
      platform: state
      entity_id: group.dining_room_lights
    action:
      - service: homeassistant.turn_off
        entity_id: automation.mfsocial_magic_code_1
      - entity_id: switch.dining_room_couch
        service_template:
          {% if is_state ('group.dining_room_lights' , 'off') %} homeassistant.turn_off
          {% else %} homeassistant.turn_on
          {% endif %}
      - service: homeassistant.turn_on
        entity_id: automation.mfsocial_magic_code_1

So, starting from everything off:

  • If you flick the switch, automation 1 will fire and turn on the lights
  • If you switch on one (or both) of the lights, automation 2 will fire and turn on the switch, but first it disables automation 1 so it doesn’t instantly switch them back off, and then re-enables automation 1

With one or both lights on:

  • You can change the lights around manually as much as you like, without triggering any automations until they both go off, at which point automation 2 fires again, disables automation 1 to prevent it undoing what we’re about to do, and then switches off the switch, before re-enabling the automation again.
  • Or you could flick the switch, triggering automation 1, which fires and switches off the lights.

I think that’s you all sorted in 29 lines of code - let me know :wink:

[edit] - you might need to do the disable and re-enable thing for the second automation in the first automation too, It’s 1.30am here and I can’t work out whether it will create an endless loop or not, so it might be 33 lines of code. But still fairly neat :stuck_out_tongue_winking_eye:

1 Like

hi @anon43302295
Nice! just what i was looking for, having 3 table lights i need to switch on/off together :wink:

related question:

on Hassio, why would an automation with a state checker not react correctly when a group is in the entity_id definition, and does work as supposed to (react on state changes of any group member) when all separate entity_id’s are in the entity_id section of the automation?

you use:

trigger:
      platform: state
      entity_id: group.dining_room_lights

in my setup i always have to use:

trigger:
      platform: state
      entity_id: 'group.dining_room_light1, group.dining_room_light2, group.dining_room_light3 '

btw, this might also be the case in the OP, so changing the entity_id’s there could help?

Thanks!
Marius

1 Like

Ummm, not sure about the definition of entity_id’s off the top of my head, but try the various options and see which works best. group.something should change state only when the group itself goes on (one or more child is on) or off (all children are off) as I understand it.

It shouldn’t change when any of the children change, which is why using the group as the trigger platform should be the best for your specific case.

i guess it all depends on the use of your automation…
in case of the lights, it might seem very useful combining 3 table lights in =to the group.tablelights, and then be able to control those 3 lights with 1 slider/switch/colorpanel, and even use automations on it. Is that the case yet btw, i read a lot of issues of that not working as expected ?

in case of checking individual members of lets say the group.family, and displaying the absent and present members, my experience is we can’t use the group entity and show members, and need to use all entity_id’s of that same group…

Other case:
had to trigger an automation from a python.py using this group.family, to show who is online, and in the python this group name works fine, but the called automation needed all separate entity_ids, fire consequent actions

Well
hope to find the ultimate logic behind it someday.:wink:

Thanks,
you’re very helpful as is your repo!
Cheers,
Marius

1 Like

@anon43302295

I love the idea of the guard, but it doesn’t work reliably. Somehow HA doesn’t seem to guarantee the order of the events, and even with the guard, turning one light on will ultimately cause the other light to turn on, too :confused:

To clarify about the order - the race condition is whether the turning the automation back on happens before or after the event of toggling the switch hits the event bus

If that’s causing you a problem, you can always add a short delay before turning the automation back on?

Can I do that inside an automation?

Yup, the action of an automation is just a script.

  • service 1
  • service 2
  • delay
  • service 3

I never followed up here, but adding a 2 second delay indeed solved the bubbling issue. Thanks @anon43302295!

1 Like