How to create a list of binary_sensors (or other objects) such that it can be modified dynamically and be used in templates?

I have several binary sensors that I want to be able to use for templates. For example I want to start with 3 binary_sensors A,B,C and add them to some sort of list/group/other structure so I can easily add/remove sensors.

Then using this structure, I want to be able to create templates that accomplish the following:

  • get a list of strings of these sensor names. e.g. A, B, C
  • create a template that gives me the count of sensors that are on. e.g. 2
  • get a list of the sensors that are on e.g. A,C
  • sensors that are off e.g. B

Now I want to be able to add binary_sensor D to the “list” without having to change the templates.

I can manage to create templates that accomplish these bullet points, but I have to hard code the binary sensor names. There’s gotta be a cleaner OO way of doing this.

You can add and remove entities from groups Group - Home Assistant

You can work with groups in templates Templating - Home Assistant

Not sure if that meets your needs.

Sure sounds like, it! Can’t believe I never saw this.

I think I have it, but there’s always something else, as I’m trying to parse the results. I can easily find the “on” sensors using selectattr, but I’m having a b*** parsing the returned values.


{{ 
   expand(['binary_sensor.mygroup']) | selectattr("state",'eq','on')
      | list  
}}

This gives me

ult type: string
[<template TemplateState(<state binary_sensor.downstairs_sensor_occupancy=on; device_class=occupancy, friendly_name=Downstairs sensor Occupancy @ 2024-03-10T19:13:18.546237-04:00>)>]

How can I get a list (yes, there’s only one item returned in this example) of binary_sensor names and/or the friendly_name value? Something like:

binary_sensor.downstairs_sensor_occupancy Downstairs sensor Occupancy

do you mean something like this:

{{ expand(state_attr('binary_sensor.test_binary_sensor_group', 'entity_id')) | map(attribute='name') | list | join(', ')
 }}

or if you only want those that are on:

{{ expand(state_attr('binary_sensor.test_binary_sensor_group', 'entity_id')) | selectattr("state",'eq','on') | map(attribute='name') | list | join(', ')
 }}
1 Like

Create a group of sensors via Helpers.

Install auto-entities from HACS:

Use the card to display group entries; in my case:

type: custom:auto-entities
card:
  type: entities
  state_color: true
  title: Outer doors and windows
filter:
  include:
    - group: binary_sensor.outer_doors_and_windows
      options:
        secondary_info: last-changed
  exclude: []
show_empty: true
sort:
  method: last_changed
  reverse: true

Screenshot 2024-03-11 at 01.15.35

The attribute entity_id of the group helper contains a list of the entity IDs of all the entities in the group.

Master the map() filter and don’t use expand() where it isn’t necessary. The functionality of map() has been expanded over the last year or so to greatly reduce the places where you need to use expand().

  1. get a list of strings of these sensor names. e.g. A, B, C
{{ state_attr('binary_sensor.example_group', 'entity_id') 
| map('state_attr', 'friendly_name') | list }}
  1. create a template that gives me the count of sensors that are on. e.g. 2
{{ state_attr('binary_sensor.example_group', 'entity_id') 
| select('is_state','on') | list | count }}
  1. get a list of the sensors that are on e.g. A,C
{#  Returns a list of the entity IDs #}
{{  state_attr('binary_sensor.example_group', 'entity_id') 
| select('is_state','on') | list }}

{#  Returns a list of the friendly names #}
{{ state_attr('binary_sensor.example_group', 'entity_id') 
| select('is_state','on') | map('state_attr', 'friendly_name') | list }}
1 Like

I’d say, the expand versions is shorter to write and more user friendly (explicit in what its doing). Let’s take your first example:

{{
state_attr('binary_sensor.outer_doors_and_windows', 'entity_id') 
| map('state_attr', 'friendly_name')
| list 
}}  

# vs

{{
expand('binary_sensor.outer_doors_and_windows')
| map(attribute='attributes.friendly_name') 
| list
}}

When I say that the expand version is more explicit, I mean that I’d never guess that state_attr('binary_sensor.outer_doors_and_windows', 'entity_id') would give me a LIST of entity_ids of the group members → I’d assume it gives just the group’s entity_id. It looks like a hack / bad naming.

Okay, but you don’t have to guess, because it is directly observable in the state object:

I agree with you that the naming isn’t great.

But your argument of “explicitness” requires a number of seemingly incongruous things. First it needs knowledge of how expand() works with a specific subset of entities (groups and group helpers) compared to other all other entities. At the same time, it requires a lack of understanding the differences between properties of the state object and attributes. And still, it uses attributes.friendly_name in the map() filter, demonstrating an understanding that attributes is a property of the state object containing a dictionary of other values. :man_shrugging:

The bottom line, as I understand it, is that using expand() is more process hungry than the other option. According to current published analytics, relatively low-spec systems represent a large proportion of Home Assistant’s user base. So, wherever possible, we should share and promote efficient practices to the best of our abilities and knowledge.

1 Like