Counting matching states

For your first problem you would use something like this:

{% for state in states.light if state.state == 'on' -%}
  {% if loop.first %}
    {{loop.length}}
    {% endif %}
{% endfor %}

The problem here is jinja variable scope. I forgot about that. The counter you use in a loop stays there. And there is not really a way to get around that. But jinja offers some fields for loops like “loop.lenght” which gives the counter for the loop and as we only need it once I checked if it is the first iteration.

For your second point jinja is pretty much python so string get handled like arrays of chars. So you can build substrings like this:

{{ state.state[:2] }}

would give you “on” if the state is “on” and “of” if the state was “off”.
But what you want to do is contains which is done like this:

{% for state in states.binary_sensor
   if ( state.state == 'open' and 'door' in state.name ) -%}

~Cheers

Is there an easy way to iterate over both state.light and state.switch?
Something like this: {% for state in [ states.light, states.switch ] %}

I can’t test it right now but this should work

{% set list = states.light+states.switch %}
{% for s in list %}

Maybe even this will work:

{% for s in (states.light+states.switch) %}

~Cheers

Neither works.

If both don’t work there is no easy way I think.

~Cheers

You could iterate over all states and filter for those two domains.

~Cheers

Thanks. This works, but I think it is a bug in HA: If any of my two light entities are on, the count is 2!

       {% for state in states
           if ( 'light' in state.entity_id 
                and state.domain in ['light','switch']
                and state.state == 'on' ) -%}
         {% if loop.first -%}
           {{ loop.length }}
         {%- endif %}
       {%- endfor %}

Correction: Using loop.length always results in 2 when 1 state are ‘on’. It counts 0,2,2,3,4,5,… Why is that?

1 Like

loop.index on the last iteration gave a correct count:

       {% for state in states
           if ( 'light' in state.entity_id 
                and state.domain in ['light','switch']
                and state.state == 'on' ) -%}
         {% if loop.last -%}
           {{ loop.index }}
         {%- endif %}
       {% else %}
         0
       {%- endfor %}
1 Like

I created a dictionary of known power for each light, and I want to sum the output of the loop. How do I do that?

      {% for state in states.light if state.state == 'on' -%}
        {{ list[state.entity_id] }}
      {% endfor %}

I have 7 cams and want to get a notification when 3 or more cams are down. I have ping sensors for all of them. They are called like binary_sensor.driveway_cam, binary_sensor.frontdoor_cam etc.

Can someone help in how can rebuild above to facilitate that? Above iterates a full domain while I only want to evaluate the 7 specific binary sensors.

First you have to declare your set of the 7 cams you want to have allowed like this:

{%- set cams = ["binary_sensor.driveway_cam", "binary_sensor.frontdoor_cam", "..."] -%}

after that you iterate over all of those with a condition like this:

{%- for cam in cams if is_state(cam, 'off') -%}

{%- endfor -%}

in this loop we can check the loop.length like this:

  {% if loop.length >= 3 -%}
    //STUFF THAT HAPPENS WHEN 3 ARE DOWN
  {% endif -%}

So all in all it looks like this:

{%- set cams = ["binary_sensor.driveway_cam", "binary_sensor.frontdoor_cam", "..."] -%}
{%- for cam in cams if is_state(cam, 'off') -%}
  {% if loop.length >= 3 -%}
    //STUFF THAT HAPPENS WHEN 3 ARE DOWN
  {% endif -%}
{%- endfor -%}

Hope that helps

~Cheers


Edit: Removed debug output in last statement

Did you try the sum filter?

{{ items | sum(attribute='points') }}

~Cheers

Ow, nice! Thanks @PhyberApex

Will try to implement tonight. QQ; Although I have made some template sensors myself , that is also the only way I uses this jinja scripting. So my Q is how to use this? Probably the easiest is to make a sensor out of it that becomes true when 3 cams are down?

That’d work yes you just have to edit it a bit like this:

{%- set cams = ["binary_sensor.driveway_cam", "binary_sensor.frontdoor_cam", "..."] -%}
{%- for cam in cams if is_state(cam, 'off') -%}
  {% if loop.length >= 3 AND loop.first-%}
    true
  {% elif loop.length <= 3 AND loop.first-%}
    false
  {% endif -%}
{%- endfor -%}

The additional ´´´loop.first``` is necessary to not have it return multiple trues or false but just one.

~Cheers

I was having a play with some of the solutions in this thread and they were really helpful for getting started, but I ended up settling on a more FP style:

{{ states.light
    | selectattr('state', 'eq', 'on')
    | rejectattr('attributes.is_hue_group')
    | list
    | count
}}

Which I find a little clearer and it cleanly handles the empty list state.

6 Likes

Holy moly where did you find out about those two filters? I could not find them in the documentation!

~Cheers

It’s in the Jinja documentation:

http://jinja.pocoo.org/docs/dev/templates/

Under “Builtin Filters”

1 Like

Awesome. Gonna have a lot of refactoring beforeme. Thanks!

~Cheers

excuse me for replying in this old topic, but this topic is the closest I found for my problem.

About a week my counting sensor does not work anymore. First I used this example, found in this topic of floreplan from Smoculetz, in my configuration.yaml file and it worked fine for a few months.

   sensor:
      - platform: template
        sensors:
          number_of_lights_on:
            value_template: >-
                {% for state in states if ( 'light' in state.entity_id and state.domain in ['light','switch'] and state.state == 'on' ) -%}
                    {% if loop.last -%}
                    {{ loop.index - 1}}
                    {%- endif %}
                    {% else %}
                        0
                {%- endfor %}

Then I changed my hardware and thereby also changed the entities of all my lights. All the entities are still part of the lights in the configuration.yaml file. But the sensor doesn’t count the ‘on’ state anymore.
Afther surching I found this topic with the example of Danrspencer and I used it in the hope the sensor would work again:

sensor:
  - platform: template
    sensors: 
      number_of_lights_on: 
        value_template: >-
            {{ states.light
            | selectattr('state', 'eq', 'on')
            | rejectattr('attributes.all_lights')
            | list
            | count
            }}

But with no succes.

Both examples work fine in the template editor. The sensor won’t detect any state change of the lights. when I put (for example) 3 lights on and restart HA then the sensor shows 3. When I put them out, or others on, without restarting HA, the sensor don’t changes the count. It just remembers the last state before restarting HA.

I have searched the forum but can’t find any changes or update failures of this topic with the new HA release. So my knowledge and options for now are out. therfor my screem for help.

Can someone help me to find what I am doing wrong?