Perfect !!! Thank you so much.
Two hours trying to figure out the problem…until i decided to post it here.
Now…no delay.
If they’re all in the group then petro’s suggestion is the way to go.
Yeah, thanks Taras. Tried and working fine.
For future reference, if you want the Template Sensor to include an entity that is not in the group (and for whatever reason you don’t want it within the group), you can simply add it to expand
like this:
value_template: "{{ expand('group.luces', 'light.whatever') | selectattr('state','eq','on') | list | count }}"
EDIT
Correction. Removed errant closing parenthesis.
Just to share how I did it.
To explain a bit:
- My second floor is organized in 4 areas.
- I have renamed all lights that are part of another light to something like “2nd Floor xyz”. These are for instance IKEA bulbs in a lamp with 3 bulbs. I have organized this using light groups into one light.
- I use custom button cards for the buttons. Check out https://github.com/custom-cards/button-card.
- platform: template
sensors:
lights_number_on_in_2nd_floor:
friendly_name: 'Lights on in 2nd floor'
unique_id: lights_number_on_in_2nd_floor
value_template: >
{%- set search_state = 'on' %}
{%- set search_areas = ['Office', 'Loft', 'Bedroom', 'Master bedroom'] %}
{%- set ns = namespace(lights=[]) %}
{%- for light in states.light | selectattr('state','eq', search_state) %}
{%- for area in search_areas %}
{% if area_name(light.entity_id) == area and "2nd Floor" not in state_attr(light.entity_id, "friendly_name") %}
{%- set ns.lights = ns.lights + [ light.entity_id ] %}
{% endif%}
{%- endfor %}
{%- endfor %}
{{ ns.lights| list | length }}
Edit: Thanks to @petro and everyone else for the help in the thread.
If you wish, you can reduce the template to this (no for-loops required):
value_template: >
{{ states.light | selectattr('state', 'eq', 'on')
| rejectattr('name', 'search', '2nd Floor')
| map(attribute='entity_id') | map('area_name')
| select('in', ['Office', 'Loft', 'Bedroom', 'Master bedroom'])
| list | count }}
EDIT
Explanation of how the template works:
- Start by selecting all lights.
- Select only the lights that are
on
. - Reject lights whose
friendly_name
contains the string2nd Floor'
. - Reduce the information to just each light’s
entity_id
. - Find the area in which each light is located.
- Select only the areas matching one of these four: Office’, ‘Loft’, ‘Bedroom’, ‘Master bedroom’.
- Convert the resulting information into a list.
- Count the number of items in the list.
EDIT
Correction. Replaced attributes.name
with name
.
Thanks. Will look at it later. More compact code is nice.
Edit: Thanks @123 ! It is working perfectly and the code is more compact. I just had to change attributes.name
to attributes.friendly_name
. Thanks again man!
Yes, that will work but the mistake I made was including the word attributes.
in attributes.name
. It only needs to be name
because that’s synonymous with the friendly_name
attribute (if it exists).
Here’s what I mean:
I have corrected the example in my previous message.
it’s possible to use an event trigger to automatically update the count without having to specify every light in your template.
template sensors that show a count of lights on for a light group:
template:
- trigger:
- platform: event
event_type: state_changed
sensor:
- name: Lights On Downstairs
state: >
{% set entities = state_attr('light.lights_downstairs',"entity_id") %}
{% set result = namespace(turned_on=[]) %}
{% for entity in entities if is_state(entity,'on') %}
{% set result.turned_on = result.turned_on + [entity] %}
{% endfor %}
{{ result.turned_on | count }}
- name: Lights On Upstairs
state: >
{% set entities = state_attr('light.lights_upstairs',"entity_id") %}
{% set result = namespace(turned_on=[]) %}
{% for entity in entities if is_state(entity,'on') %}
{% set result.turned_on = result.turned_on + [entity] %}
{% endfor %}
{{ result.turned_on | count }}
- name: Lights On Outside
state: >
{% set entities = state_attr('light.lights_outside',"entity_id") %}
{% set result = namespace(turned_on=[]) %}
{% for entity in entities if is_state(entity,'on') %}
{% set result.turned_on = result.turned_on + [entity] %}
{% endfor %}
{{ result.turned_on | count }}
light group:
light:
- platform: group
name: Lights Downstairs
entities:
- light.breakfast_room_light
- light.family_room_light
- light.dining_room_light
- light.kitchen_light
- light.living_room_light
- light.living_room_reading_light
- light.office_light
- light.tv_light
- light.foyer_light
- light.closet_light
- light.stairs_light
- light.desk_light
this type of template sensor would perform better if the event trigger data filter accepted wildcards, e.g.
- trigger:
- platform: event
event_type: state_changed
event_data:
entity_id: light.* # not supported in 2021.11.1 ...
*edit: complete sensor, light group, and failed event_data wildcard filter test result
It’s possible, but not recommended.
You are suggesting to use an Event Trigger to monitor state_changed
events. That means it will be triggered by every state-change that occurs in Home Assistant’s state machine (locks, binary_sensors, sensors, fans, timers, switches, etc). The three Trigger-based Template Sensors will be evaluated far more often than simply when a light changes state.
Just use the expand()
function; the templates will be evaluated only when one of the Light Group’s members undergoes a state-change. Counting them can also be done without using a for-loop.
template:
- sensor:
- name: Lights On Downstairs
state: "{{ expand('light.lights_downstairs') | selectattr('state', 'eq', 'on') | list | count }}"
- name: Lights On Upstairs
state: "{{ expand('light.lights_upstairs') | selectattr('state', 'eq', 'on') | list | count }}"
- name: Lights On Outside
state: "{{ expand('light.lights_outside') | selectattr('state', 'eq', 'on') | list | count }}"
true, and I believe the catch-all state changes code I posted may have been causing a stabilization issue in my instance …and, I’ve removed it…
since I’m using “light” groups and not a “group” of lights, I had to make a small modification to your code, but it appears to be working muuuch better:
template:
- sensor:
- name: Lights On Downstairs
state: "{% set entities = state_attr('light.lights_downstairs','entity_id') %} {{ expand(entities) | selectattr('state', 'eq', 'on') | list | count }}"
- name: Lights On Upstairs
state: "{% set entities = state_attr('light.lights_upstairs','entity_id') %} {{ expand(entities) | selectattr('state', 'eq', 'on') | list | count }}"
- name: Lights On Outside
state: "{% set entities = state_attr('light.lights_outside','entity_id') %} {{ expand(entities) | selectattr('state', 'eq', 'on') | list | count }}"
“light” groups support additional features and play well with other integrations such as homekit and alexa out of the box, which is why I prefer them. however every non-dimmer zwave toggle switch requires a “light” switch before it can be added to a “light” group… a regular group will take both lights and switches, but the “group” entity doesn’t expose a turn_on/off service right? there is a smoothness still missing here
scenes are my favorite light groups, and I have created a working “light” scene custom component that allows scenes to be treated as a “light”, so that scenes can be toggled on and off, and the scene light maintains an ‘on’ state until a child light is changed and allow for useful/stateful scene button ui
Ah, my mistake. The expand
function is capable of automatically expanding the entity_id
attribute of a Group but not a Light Group. A compact way of handling a Light Group would be like this:
template:
- sensor:
- name: Lights On Downstairs
state: "{{ state_attr('light.lights_downstairs','entity_id') | expand | selectattr('state', 'eq', 'on') | list | count }}"
- name: Lights On Upstairs
state: "{{ state_attr('light.lights_upstairs','entity_id') | expand | selectattr('state', 'eq', 'on') | list | count }}"
- name: Lights On Outside
state: "{{ state_attr('light.lights_outside','entity_id') | expand | selectattr('state', 'eq', 'on') | list | count }}"
You would use the generic homeassistant.turn_on
service (and turn_off
).
Hi, this works.
but how can I find number of lights “on” in a specified “area”? ( in a room only, not in the whole house?)
thanks.
{{ expand(area_entities('Living Room')) | selectattr('domain','eq','light') | selectattr('state','eq','on') | list | count }}
make sure your area is actually named “Bedroom 1” and that the “Bedroom 1” contains those bedroom lights.
EDIT Also found a typo, review my original post again with the updates
area name : Bedroom 1
Area ID: bedroom_1
see my edit
YES! that works.
I am also trying to get light brightness and when it was last on? could you please help me.
thanks.