Turn off ALL light ON from > 3hours (not using group)

Hi,
I need to turn OFF al lights (in domain “light”) in state ON from 3 hours.
this works form me to get lights ON

{{ states.light | selectattr('state','eq','on') |
          map(attribute='name') | join('\n') }}

and this same result using cycle for

{%- set gruppo = states.light | selectattr('state','eq','off') |
          map(attribute='name') -%}
{% for state in gruppo -%}
- {{state + "\n"}}
{%- endfor %}

However no idea how to gets (and then turn off) the light ON from 3 hours.
Any suggest?

Ok to manage this using single entity, but I want to “universalize” the code using every light in her domain.

Thanks
.onfrom3h

I haven’t tried it - but I would expect that you then create an empty list, and then loop through the group that you have, comparing the last_changed attribute to

{% set timenow = now() - timedelta( hours = -3) %}

Any entry in the group was changed < timenow has been on for 3 hours and can then be added to the list. which you use in the light.turn_off service call for entity_id.

The list should ONLY be a list of entity_id’s and nothing else.

Thanks Andrew,
my limit is the correct syntax to do your steps…

I was away writing up some sample code - which I will admit took a lot of Googling, and a lot more time than I had expected. Anyway - THIS:

{%- set gruppo = states.light | selectattr('state','eq','on') |
          map(attribute='entity_id') -%}
{%- set lights = namespace(entities=[]) -%}
{%- set timenow = now() - timedelta(hours=-3) -%}
{%- set timenowts = timenow|as_timestamp -%}
{%- for l in gruppo -%}
 {%- if states[l].last_changed|as_timestamp < timenowts -%}
   {%- set lights.entities = lights.entities + [l] -%}
 {%- endif -%}
{%- endfor -%}
{{ lights.entities }}

Will return a list of all lights that have been switched on for more than 3 hours.

1 Like

Andrew, many thanks!
Your code is perfect (changing the sign)
wrong

{%- set timenow = now() - timedelta(hours=-3) -%}

right

{%- set timenow = now() - timedelta(hours=3) -%}

This yaml works perfectly (tested with 10 second lights on)

alias: 001 longtime liths on
description: ''
trigger:
  - platform: time
    at: '16:11'
condition: []
action:
  - service: light.turn_off
    target:
      entity_id: >-
        {%- set gruppo = states.light | selectattr('state','eq','on') |
                  map(attribute='entity_id') -%}
        {%- set lights = namespace(entities=[]) -%} {%- set timenow = now() -
        timedelta(seconds=10) -%} {%- set timenowts = timenow|as_timestamp -%}
        {%- for l in gruppo -%} {%- if states[l].last_changed|as_timestamp <
        timenowts -%} {%- set lights.entities = lights.entities + [l] -%} {%-
        endif -%} {%- endfor -%} {{ lights.entities }}
mode: single

Many thanks!

This template lists all lights that have been on for more than 3 hours.

{{ states.light | selectattr('state', 'eq', 'on')
   | selectattr('last_changed', 'lt', now() - timedelta(hours=3)) 
   | map(attribute='entity_id') | join(', ') }}
3 Likes

Thanks, I knew there had to be a better way of doing it. Oddly {{ state_attr('entity_id','last_changed') }} tells me the return value is None and I could only get access using {{ states.entity_id.last_changed }} which is weird.

EDIT: Can you use that as is in a service call, or do you need to change the join filter to list ?

If you look at the properties of an entity’s State Object you’ll see that last_changed is a property of the entity’s State Object. It’s not within the State Object’s attributes property. That’s why you can’t use state_attr to access last_changed.

1 Like