I need help from any Jinja2 experts out there. Here is my situation…
I want to create a template sensor that list down all entities from a group that has state = open.
I have added a bunch of sensors into a group call entrypoints
.
Then I created a template sensor with this value template…
{% for entity in states.group.entrypoints.attributes.entity_id %}
{%- if is_state(entity, 'open') %}
{{ entity }}
{%- endif %}
{%- endfor %}
When I run it, the sample result is…
sensor.front_door
sensor.living_room_window
sensor.back_door
sensor.kitchen_window
sensor.master_bedroom_window_a
sensor.master_bedroom_window_b
sensor.balcony_door
My question is, how do I make it list down the friendly name of each entities?
maybe {{ states.sensor.sensor_id.attributes.friendly_name }} ??
thanks but it is not correct.
fabaff
(Fabian Affolter)
January 21, 2017, 6:24pm
4
Works for me in “Developer Tools” → “Templates”
1 Like
You mean like this?
{% for entity in states.group.entrypoints.attributes.entity_id %}
{%- if is_state(entity, 'close') %}
{{ states.sensor.sensor_id.attributes.friendly_name }}
{%- endif %}
{%- endfor %}
It gives me this error “Error rendering template: UndefinedError: ‘None’ has no attribute ‘attributes’ ”
I wish I can do this…
{% for entity in states.group.entrypoints.attributes.entity_id %}
{%- if is_state(entity, 'open') %}
{{ getattr(entity, 'friendly_name') }}
{%- endif %}
{%- endfor %}
No, it was just example… replace sensor_id with your own sensor id.
dale3h
(Dale H)
January 21, 2017, 9:15pm
8
Try
{{ states[entity.split('.')[0]][entity.split('.')[1]].name }}
name
will be friendly_name
if it is set, otherwise it is generated from the entity_id
.
3 Likes
@dale3h
How to split each entities with a comma and the last one with an “and”?
I tried…
{% for entity in states.group.entrypoints.attributes.entity_id %}
{%- if is_state(entity, 'open') %}
{%- if loop.last %} and {% else %}, {% endif -%}
{{ states[entity.split('.')[0]][entity.split('.')[1]].name }}
{%- endif %}
{%- endfor %}
It gives me…
, Front Door, Back Door, Kitchen Window, Master Bedroom Window A, Master Bedroom Window B and Balcony Door
I think the solution is to add each friendly name in {%- if is_state(entity, 'close') %}
into an array first. But my understanding on Jinja is still very basic. Your help will be greatly appreciated. Thanks.
arch
January 24, 2017, 12:43am
11
Does the following achieve what you’re after?
{% for entity in states.group.entrypoints.attributes.entity_id %}
{%- if is_state(entity, 'open') %}
{%- if loop.last %} and {% elif loop.first %}{% else %}, {% endif -%}
{{ states[entity.split('.')[0]][entity.split('.')[1]].name }}
{%- endif %}
{%- endfor %}
No. It doesn’t. It sometimes add comma before the entity or the ‘and’ doesn’t appear before the last item.
The problem is loop.last
and loop.first
are in reference to the entities regardless of its states.
arch
January 24, 2017, 3:07am
14
Yes I get it now. Maybe append each open entity to a list first and then work with that list. I can’t test it at the moment (and I’m not really an expert - so I’m sure it could be done more elegantly) - but something like this should work:
{% set openentities = [] %}
{% for entity in states.group.entrypoints.attributes.entity_id %}
{%- if is_state(entity, 'open') %}
{% set x = openentities.append(states[entity.split('.')[0]][entity.split('.')[1]].name) %}
{%- endif %}
{%- endfor %}
{% for openentity in openentities %}
{%- if loop.last %} and {% elif loop.first %}{% else %}, {% endif -%}
{{ openentity }}
{%- endif %}
{%- endfor %}
thanks. but it gives this error…
Error rendering template: SecurityError: access to attribute ‘append’ of ‘list’ object is unsafe.
i think we are getting nearer.
arch
January 24, 2017, 5:06am
16
Sorry - I don’t why that happens in Home Assistant. When I run this python code in IDLE:
from jinja2 import Template
Templatex = Template ('{% set openentities = [] %} ' \
'{% for entity in mydata %}' \
'{% if 1 == 1 %}' \
'{% set x = openentities.append(entity) %}' \
'{% endif %}' \
'{% endfor %}' \
'{% for openentity in openentities %}' \
'{%- if loop.last %} and {% elif loop.first %}{% else %}, {% endif -%}' \
'{{ openentity }}' \
'{%- endfor %}')
myinput = ["Front Door", "Back Door", "Kitchen Window", "Master Bedroom Window A", "Master Bedroom Window B", "Balcony Door"]
mystring = Templatex.render(mydata=myinput)
print mystring
I get:
Front Door, Back Door, Kitchen Window, Master Bedroom Window A, Master Bedroom Window B and Balcony Door
1 Like
It’s OK. Thanks for your help anyway.
If you want loop.last to work properly I believe you need to add a filter to your for loop.
Something like
{% for entity in states.group.entrypoints.attributes.entity_id if states(entity, 'open') %}
{% if loop.last %}, and {% elif loop.first %}{% else %}, {% endif %}
{{ states[entity.split('.')[0]][entity.split('.')[1]].name }}
{% endfor %}
2 Likes
Wow! Thanks. It works with this…
{% for entity in states.group.entrypoints.attributes.entity_id if is_state(entity, 'open') %}
{%- if loop.last %} and {% elif loop.first %}{% else %}, {% endif -%}
{{ states[entity.split('.')[0]][entity.split('.')[1]].name }}
{%- endfor %}
@nordlead2005
How to count the number of entities that has the state open?
I wish to have something like this…
If only one entity in the loop, it outputs something like… “Front Door is open”.
If more than one entity… “Front Door, Master Bedroom Window B and Balcony Door are open”
if there are 10 entities in the loop… “All doors and windows are open ”