Template: Itterating through array without printing unmatched conditions

Sorry if the title is confusing. What I’m simply trying to do is create a notification that will tell me which sensors are “on”. I have a group called “windows_doors” with all of my window and door sensors specified. I’m testing this out by just calling the “notify.<my_mobile_app>” service. Here’s the jinja template code I have for the Service Data:

message: >
  {% if is_state('group.windows_doors', 'on') %}
  The following windows are open: 
    {% for window in expand('group.windows_doors') %} {% if window.state == 'on' %} {{ window.name }}
      {% endif %}
    {% endfor %}
  {% endif %}

The logic seems to work however the text has a line break for every entity that doesn’t match the “on” condition. So for example, I’ll get a notification that looks like:

Kitchen Window


Bathroom Window
Master Window





Laundry Window

How do I prevent it from showing a blank line for the entities that don’t match the condition? Ideally, I’d like for the notification to just be:

Kitchen Window, Bathroom Window, Master Window, Laundry Window.

I see how I can use the “loop.first” and “loop.last” to add or not add the commas. As you can tell, I have zero experience with Jinja. Thanks for the help!

Why not just use a conditional card ?

1 Like

Not 100% sure any more because I did it a long time ago, but I think I resolved it by using the >- and splitting the the code over several lines:

        message: >-
          {%- if is_state("sensor.ready_to_arm", "True") %}
            All doors and windows are CLOSED!
          {% else %}
            Open are:
            {%- set entities = [states.binary_sensor.garage_door_sensor, states.binary_sensor.stairs_door_sensor, states.binary_sensor.storage_room_sensor, states.sensor.gardengate ] -%}
            {%- for entity in entities -%}
              {%- if entity.state == 'off' %}
            - {{ entity.name }}
              {%- endif %}
            {%- endfor -%}
          {%- endif %}

Because I assume it’s for a notification, not for displaying it in Lovelace.

1 Like

Good point, well made :+1:

Perfect! Adding the %- did the trick. Thanks!

Yeah, it’s for a notification.

I believe you can do it like this:

message: >-
  {% if is_state('group.windows_doors', 'on') %}
  The following windows are open: 
  {% for window in expand('group.windows_doors') | selectattr('state', 'eq', 'on') %}
    {{ window.name }}
  {% endfor %}

EDIT: Ah appears I was too slow testing out the selectattr thing in my own HA. Oh well, I like puzzles haha

1 Like

You don’t need the for-loop to get the job done. This will produce a comma-separated list of entity names (like this: Kitchen, Bedroom, Garage)

message: >
  {{ expand('group.windows_doors') | selectattr('state', 'eq', 'on') 
     | map(attribute='name') | list | join(', ') }}

If none are on the message will be blank. I would use a condition to check for that and simply not send a notification if there is nothing to report.

5 Likes

Here is an example of what I do for detail notifications on plants that need attention.

{% for plant in states.plant if plant.state == "problem" -%}
  {{ plant.name }}: {{ plant.attributes.problem  | capitalize() }}
  {%- if not loop.last %}, {% endif -%}
{% else %}
  Good
{%- endfor %}
message: >
  {{ expand('group.windows_doors') | selectattr('state', 'eq', 'on') 
     | map(attribute='name') | list | join(', ') }}

I never thought of doing that way! Now I’m going to go reevaluate my template for loops. Learn something new everyday!