I’m trying to improve my templating skills, so this is more a general templating question than a specific issue to resolve.
My questions are:
- How to defined a list of entities to check in one place
- Understand how HA determines what entities to “listen” to for changes.
I created a binary_sensor template to tell me if my house is all locked up. It’s a “lock” device_class and has a “message” attribute will say what sensors are unlocked:
When a doors are opened:
But, I’m hard-coding the entities I want to check - twice.
I had to replace a sensor and I only updated one of the lists by mistake and didn’t notice. Bad practice to define the same thing in multiple places, of course.
In my template I define an array of entities to check (and the state to check against):
binary_sensor template:
- binary_sensor:
- name: House Locked
device_class: lock
state: >
{%- set sensors = [
['binary_sensor.front_door', 'off'],
['binary_sensor.family_sliding_door', 'off'],
['binary_sensor.living_sliding_door', 'off'],
['binary_sensor.kitchen_deck_door', 'off'],
['binary_sensor.primary_bed_sliding_door', 'off'],
['binary_sensor.single_garage_open_intrusion','off'],
['binary_sensor.double_garage_open_intrusion','off'],
['lock.front_door_deadbolt', 'locked'],
['cover.ratgdov25i_f615a8_door', 'closed'],
['cover.ratgdov25i_fa8ef5_door', 'closed']
] -%}
{%- set ns = namespace(locked='off') -%}
{% for entity in sensors -%}
{% if states( entity[0] ) != entity[1] -%}
{% set ns.locked = 'on' -%}
{% endif -%}
{% endfor %}
{{ ns.locked }}
attributes:
message: >-
{% set sensors = [
['binary_sensor.front_door', 'off'],
['binary_sensor.family_sliding_door', 'off'],
['binary_sensor.living_sliding_door', 'off'],
['binary_sensor.kitchen_deck_door', 'off'],
['binary_sensor.primary_bed_sliding_door', 'off'],
['binary_sensor.single_garage_open_intrusion','off'],
['binary_sensor.double_garage_open_intrusion','off'],
['lock.front_door_deadbolt', 'locked'],
['cover.ratgdov25i_f615a8_door', 'closed'],
['cover.ratgdov25i_fa8ef5_door', 'closed']
] -%}
{% set ns = namespace(unlocked=[]) -%}
{% for entity in sensors -%}
{% if states( entity[0] ) != entity[1] -%}
{% set ns.unlocked =
ns.unlocked
+ [state_attr(entity[0], 'friendly_name')|trim
+ ': '
+ state_translated(entity[0])] -%}
{% endif -%}
{% endfor -%}
{% if ns.unlocked|length -%}
{{ ns.unlocked| join(', ') }}
{% else -%}
House is locked
{% endif -%}
What’s a good way to define my set of entites to test but in just one place?
I’m a bit surprised, but it seems HA figures out which entities to watch for. Does it work the same when I define the binary_sensor in configuration.yaml?
I thought about doing something crazy like find all the entities by looking at their device_class, but the developer templates says This template listens for all state changed events.
which seems like a very bad approach. I assume that means any state change re-runs this template code.
Searching for entities by device_class
{% set ns = namespace(entities=[]) -%}
{% for entity_type in [
['door','off'],
['garage_door','off'],
['garage','closed']
] -%}
{% for entity in
states
|selectattr('attributes.device_class', 'eq', entity_type[0])
|map(attribute='entity_id') -%}
{% if states( entity ) != entity_type[1] %}
{% set ns.entities = ns.entities +
[
state_attr(entity, 'friendly_name')|trim
+ ': '
+ state_translated(entity)
] -%}
{% endif %}
{% endfor -%}
{% endfor -%}
--->
{{ ns.entities|join("\n") }}
This also seems to confuse the developer UI as the right side will revert to some previous templating after a few seconds. Plus, I have a lock entity that doesn’t have a device_class.
Is there a better approach when I need to know the entity and the state to test against?
Thanks,