Expand function, lists in template entity attribute and self-referencing

For an enhancement request I created the template sensor below as an example (Binary_sensor group, add attributes to show which entities in the group are on resp. off)

It’s intention is to mimic a binary_sensor group but add attributes that show which group members are on and which are off.
The implementation below seems to work but I’m not 100% sure I fully understand what I am doing here ;-).

  1. I’m fairly new to the expand() function and still struggle a bit what exactly it is doing. Also it seems that this function is not part of the Jinya specification but an add-on by Home Assistant - right ? Does anyone have a good reference to learn more about it ?
    The initiailization for self reference via this also seems to be tricky, what comes first ? The only way I was able to make sure I don’t get errors in the logbook at startup was to add defaults to all those references.

  2. I read somewhere in the docs that attributes can be of any type, including lists. The only way I was able to create such a list for an attribute was with the somewhat clumsy notation below (I’m glad though @petro mentioned this way in a post - otherwise it wouldn’t have worked at all). Is there a better way to specify a static list for an attribute? Idealy I would be able to use the node anchors I had created and used in the groups - that way the lists could be re-used.

template:
  binary_sensor:
  - name: "Contact Sensors"
    # important to set a default, this.attributes.sensors_on may not yet be initialized when the state is evaluated
    state: "{{ (this.attributes.sensors_on | default([])) != [] }}" 
    attributes:
      entity_id: >
        {% set sensors = [ 
          "binary_sensor.contact_a_state",
          "binary_sensor.contact_b_state",
          "binary_sensor.contact_c_state"
        ] %}
        {{ sensors }}
      sensors_on: "{{ expand(this.attributes.entity_id | default([])) | selectattr('state', 'eq', 'on') | map(attribute='entity_id') | list }}"
      sensors_off: "{{ expand(this.attributes.entity_id | default([])) | selectattr('state', 'eq', 'off') | map(attribute='entity_id') | list }}"
    device_class: "opening"
1 Like

Dear Michael,

Many thanks for sharing this code, I have used this in my approach to get an alarm on tripping a certain number of sensor in a certain timeframe (I will update the link here later).

One small comment, the indentation for the sensors_on and off is a little off, I had to reduce it to make these attributes come to life.

Again, many thanks for this mainly elegant solution.

kind regards,

Ben

Glad you could make use of this snippet. you are right, the two lists are wrongly indented on the post, they are proper im my installation though.

I simplified the templates a bit :slight_smile:

template:
  binary_sensor:
  - name: "Contact Sensors"
    # the get function is used to provide a default in case the attribute is not initialized
    state: "{{ this.attributes.get('sensors_on', []) != [] }}" 
    attributes:
      entity_id: >
        {{
          [ 
            "binary_sensor.contact_a_state",
            "binary_sensor.contact_b_state",
            "binary_sensor.contact_c_state"
          ]
        }}
      sensors_on: "{{ this.attributes.get('entity_id', []) | select('is_state', 'on') | list }}"
      sensors_off: "{{ this.attributes.get('entity_id', []) | select('is_state', 'off') | list }}"
    device_class: "opening"
1 Like

FWIW, given recent enhancements, I would suggest labeling the desired entities with the word contact and then referencing them with label_entities.

- binary_sensor:
    - name: "Contact Sensors"
      state: "{{ this.attributes.get('sensors_on', []) != [] }}" 
      device_class: opening
      attributes:
        sensors_on: "{{ label_entities('contact') | select('is_state', 'on') | list }}"
        sensors_off: "{{ label_entities('contact') | select('is_state', 'off') | list }}"

Reference

Labels


If for some reason you still want to see a list of all contact sensors in an entity_id attribute:

- binary_sensor:
    - name: "Contact Sensors"
      state: "{{ this.attributes.get('sensors_on', []) != [] }}" 
      device_class: opening
      attributes:
        entity_id: "{{ label_entities('contact') }}"
        sensors_on: "{{ this.attributes.get('entity_id', []) | select('is_state', 'on') | list }}"
        sensors_off: "{{ this.attributes.get('entity_id', []) | select('is_state', 'off') | list }}"
2 Likes