PSA: Turn on/off all lights in Home Assistant 0.104+ (group.all_* changes)

That is the solution! Perfect!!! :+1:

Another way would be to insert a Template Condition at the beginning of the sequence. The template would confirm the length of lights_off is greater than zero. If not, the template evaluates to false and execution is halted.

Something like this:

alias: example 1
variables:
  lights_off: >
    {{ expand('group.living') | selectattr('state','eq','off')
       | map(attribute='entity_id') | list | join(', ') }}
sequence:
  - condition: template
    value_template: "{{ lights_off | length > 0 }}"
  - service: light.turn_on
    data:
      entity_id: "{{ lights_off }}"
  - delay: '00:03:00'
  - service: light.turn_off
    data:
      entity_id: "{{ lights_off }}"
mode: single

Ok, I have checked the template solution. It worked also perfectly!

using the exact, well almost, code myself here:

  sequence:
    service: light.turn_off
    data:
      entity_id: >
        {% set lights_on =
           expand('group.all_inside_lights')|selectattr('state','eq','on')
           |map(attribute='entity_id')|list %}
        {{lights_on|join(', ') if lights_on|length > 0 else 'none'}}

I was seeking to find a reason the new variables: technique would be the preferred option. So rewrote my own automation like you suggest here. Which looks very clean. Still, I can’t help wondering why we would need to set a second variable in the variable itself. Wouldn’t that be more complex inside the HA internals? Maybe fractional, but still, as an academic discussion?

My understanding is it’s a template like any other template. For a more detailed analysis, someone from the development team is better qualified to answer the question.

You aren’t setting a second variable
 You’re setting a variable in the automation. And you’re setting a variable inside the template. 2 very different things.

No, its a temporary memory address. And garbage collection will delete it after some time. It adds nothing to the computation time, it just makes your ram go up a smidge (bytes) until garbage collection removes it. You’re definitely overthinking this.

Thanks for the help @petro!
Using the “All lights off?” condition as a trigger works great. My only problem is that I’m too inexperienced to add a duration to my ‘All lights off? trigger’. In other words: I would like to set up a ‘If all lights have been turned off for 30:00 min, then do x’ trigger.
Any suggestion on how to solve this is highly appreciated!

It’s documented here: Holding a state.

1 Like

just asking if this the appropriate or efficient way to handle the shutdown of both lights and switches in 1 script

all_off: 
  alias: all lights and switches off 
  mode: single
  variables:
    lights_on: >
     {{ expand('group.all_light') | selectattr('state','eq','on')
         | map(attribute='entity_id') | list | join(', ') }}
    switches_on: >
     {{ expand('group.all_sockets') | selectattr('state','eq','on')
         | map(attribute='entity_id') | list | join(', ') }}
  sequence:
    - condition: template
      value_template: "{{ lights_on | length > 0 }}"
    - service: light.turn_off
      data:
        entity_id: "{{ lights_on }}"
    - delay: '00:15:00'    
    - condition: template
      value_template: "{{ switches_on | length > 0 }}"
    - service: switch.turn_off
      data:
        entity_id: "{{ switches_on }}"

You could consolidate the two groups and then use homeassistant.turn_off to turn off both lights and switches.

{{ expand('group.all_light', 'group.all_sockets') | etc .. 

The script can be simplified to:

all_off: 
  alias: all lights and switches off 
  sequence:
    - service: homeassistant.turn_off
      data:
        entity_id:
          {% set x = (expand('group.all_light', 'group.all_sockets') | selectattr('state','eq','on')
              | map(attribute='entity_id') | list | join(', ') %}
          {{ x if x | length > 0 else 'none' }}

However, if you must have a delay between turning off lights and switches then use your version.

1 Like

Thanks for the quick help, @123! Implemented ‘- for: “00:30:00”’, that should do it.

Hate to bother you guys again but in yet another automation I need to add ‘Have all lights been off for 15 minutes?’ as a condition. I tried the following

condition:
  - condition: template
    value_template: >
      {% set domain = 'light' %}
      {% set state = 'off' %}
      {{ states[domain] | count == states[domain] | selectattr('state','eq', state) | list | count }}
    for: '00:15:00'

But that only returns the following error message: “Message malformed: extra keys not allowed @ data[‘condition’][0][‘for’]”, which is because of the fact that template conditions don’t accept for variables as far as my understanding goes

Again: Thanks in advance for any suggestions!

Can anyone tell me how to update the following to filter the list of entity_id name that contain certain string?
Thanks in advance

- condition: template
  value_template: >
      {% set domain = 'switch' %}
      {% set state = 'off' %}
      {% set is_on = states[domain] | selectattr('state','eq', state) | list | count > 0 %}
      {% set state = 'off' if is_on else 'on' %}
      {{ states[domain] | selectattr('state','eq',state) | map(attribute='entity_id') | list | join(', ') }}

That condition
 is very odd. It provides a list of entities. Conditions require templates that return true/false. This seems like a copy/paste error. Not sure what it’s end goal for that was.

Anyways, to filter a list with contains


{% set domain = 'switch' %}
{% set state = 'off' %}
{% set contains = 'some_string' %}
{% set ns = namespace(entities = []) %}
{% for s in states[domain] | selectattr('state','eq', state) %}
  {% if contains in s.entity_id %}
    {% set ns.entities = ns.entities + [ s ] %}
  {% endif %}
{% endfor %}
{{ ns.entities | map(attribute='entity_id') | list | join(', ') }}
- service: light.turn_on
  entity_id: all

Can someone please help me understand how to make this ONLY turn on lights (as it says it will) and not switches? Feels like basic functionality that should be avaible easily without appdaemon and whatnot

that’s all it does, this will only turn on lights, not switches.

Hm, interesting. Perhaps I should file a bugreport then :confused:

You’re using light.turn_on and it’s turning on switches? I’d be willing to bet you’re using the light switch integration which turns switches into lights.

This is an example of a switch that turns on.

It is from this integration:

I see now however that:

Switches are devices like power plugs and sirens.

Note that devices in the switch platform identify as lights, so there is a manually curated list that defines which “lights” are switches.

I have no idea what “so there is a manually curated list that defines which “lights” are switches” mean however :confused:

Seems like a limitation of deCONZ
 time to switch to ZHA. Unless I’m wrong, but I did find ZHA much better that deCONZ.