Stumped on data template using expand/for/join

Hi all,
I’m trying to send an email listing the sensors in a group, which are on. Trigger is when the group (any of its members) have been on for a certain length of time.

I have a group with ID binary_sensor.aussenoeffnunggruppe and the following automation, which gives me the error

Error while executing automation automation.aussenoeffnung_lange_offen: Error rendering data template: UndefinedError: ‘binary_sensor’ is undefined

I have determined that this is in regards to the entity ID in the expand statement. This doesn’t make any sense to me, as the automation triggers successfully from the exact same entity ID. Where am I going wrong?

  alias: AussenOeffnung lange offen
  description: Sends a notification if any door/window to the outside is open for more than n minutes
  triggers:
  - trigger: state
    entity_id: binary_sensor.aussenoeffnunggruppe
    from:
    to: 'on'
    for:
      hours: 0
      minutes: 0
      seconds: 10
  condition: []
  action:
  - service: notify.by_mail
    data:
      title: Aussentuer/Aussenfenster lange offen!
      message: >
        {% set openfenestration = expand(binary_sensor.aussenoeffnunggruppe) | selectattr('state', 'eq', 'on') | map(attribute='object_id') | list %}
        {% set listtext = '' %}
        {% for item in openfenestration %}
          {% set listtext = listtext + [ "{{item.name}} in der Zone {{ item.area_name(trigger.entity_id) or ''(ohne Zone)'' }}\n" ] %}
        {% endfor %}
        {{join('Die folgenden Aussenfenster/Aussentüren sind gerade offen:\n\n', listtext,
        '\nEine oder mehrere oder eine Kombination von mehreren davon gemeinsam schon länger als 20 Minuten.')}}
      target:
      - [email protected]

There are multiple issues:

  • Quote marks missing around entity ID in expand() function.
  • Mapping to the object_id makes no sense.
  • item.area_name(trigger.entity_id) really makes no sense.
  • listtext needs to be setup as a list not a string.
  • A namespace is required to extract data from a loop.
  • Nested templates are not valid. Use the variables directly.
  • join has to be used as a filter.
  • There’s no need to put static text inside an expression; it just makes it more complicated.

I think the following will accomplish what you were going for:

{%- set openfenestration = expand('binary_sensor.aussenoeffnunggruppe') | selectattr('state', 'eq', 'on') | list %}
{%- set ns = namespace(listtext = []) %}
{%- for item in openfenestration %}
  {%- set ns.listtext = ns.listtext + [ item.name ~' in der Zone '~ area_name(item.entity_id)  | default('(ohne Zone)') ] %}
{% endfor %}
Die folgenden Aussenfenster/Aussentüren sind gerade offen:\n\n {{ ns.listtext | join('\n') }}\n 
Eine oder mehrere oder eine Kombination von mehreren davon gemeinsam schon länger als 20 Minuten.
1 Like

Thank you, Didgeridrew!
Many of the finer points of yaml syntax still elude me, so your list of issues definitely helps and your code did the trick.

Templates seem to gobble up whitespace, so I’ve had to find a solution for formatting the smtp mail text with newlines. Here’s the final code:

        {%- set openfenestration = expand('binary_sensor.aussenoeffnunggruppe') | selectattr('state', 'eq', 'on') | list %}
        {%- set ns = namespace(listtext = []) %}
        {%- set nl = '\n' %}
        {%- for item in openfenestration %}
          {%- set ns.listtext = ns.listtext + [ area_name(item.entity_id)  | default('ohne Zone') ~ ': ' ~ item.name ] %}
        {%- endfor %}
        Die folgenden Aussenfenster/Aussentüren sind gerade offen:
        {{ nl }}{{ nl }}{{ ns.listtext | join('\n') }}
        {{ nl }}{{ nl }}Einzeln oder in Kombination schon länger als 20 Minuten.