Excluding specific sensor in Template based on entity name or friendly name?

Hi All,

I have built a template sensor that takes all of the power entities in an area and combines them into a new template sensor. the problem is that my logs are filled with errors in the logs that a loop has beed detected as the template sensor also exists in the area that its capturing (and rightfully so)

I want to add a filter to exclude the template sensor name from the calculation but i am struggling to find the right name for the attribute to exclude

{% for s in states.sensor  %}       
{% if s.state != 'unavailable'  and s.attributes.device_class == 'power' and s.attributes.unit_of_measurement == 'W'  and area_name(s.entity_id) == 'Living Room' and s.state >= '0' and **s.attributes.friendly_name** != 'Power-Area-Living Room-Total' %}
     {% set ns.states = ns.states + [ s.state | float ] %}
   {% endif %}
{% endfor %}
{{ ns.states | sum | round(2) }}
```

Don’t use for loops. Much better if you use selectattr() and regectattr()

e.g. Template w/Multiple Sensor Values - #2 by 123

1 Like

As already mentioned, rewrite to only use filters. I would probably do it something like below, completely untested so may well contain typos or other errors you need to correct.

Not quite sure whether this.entity_id is available to a template sensor, if not replace it with whatever hardcoded entity id your sensor has. Couldn’t quite figure out how to filter on area_name in just the one expression, so had to store an intermediate result in a variable and do a zip.

{% set sensors = states.sensor
| rejectattr('entity_id', '==', this.entity_id)
| rejectattr('state', '==', 'unavailable')
| selectattr('attributes.device_class', '==', 'power)
| selectattr('attributes.unit_of_measurement', '==', 'W')
| selectattr('state', '>=', 0) | list %}
{{ zip(sensors | map('attr', 'state') | map('float') | list, 
sensors | map('attr', 'entity_id') | map('area_name') | list)
| selectattr(1, '==', 'Living Room')
| map('first') | sum | round(2) }}
1 Like

Thanks for the advice!! I will have a play over the weekend

Ok after a bit of messing around this is working

{% set sensors = states.sensor
| rejectattr('state', '==', 'unavailable')
| rejectattr('state', '==', 'unknown')
| rejectattr('attributes.friendly_name', '==', 'Power-Area-Living Room-Total')
| selectattr('attributes.device_class', '==', 'power')
| selectattr('attributes.unit_of_measurement', '==', 'W')
| list %}

{{ zip(sensors | map('attr', 'state') | map('float') | list, 
sensors | map('attr', 'entity_id') | map('area_name') | list)
| selectattr(1, '==', 'Living Room') 
| map('first') | sum | round(2) }}

The only problem i have is that the selectattr for >= 0 “selectattr(‘state’, ‘>=’, 0)” returns TypeError: ‘>=’ not supported between instances of ‘str’ and ‘int’

I am not sure who to do a type change on state to make it work. Its not a huge problem as its just a sanity check in case i have a sensor that reading negative (some CT clamps are funny like that )

Cheers,

Lachlan

Hi, will this not work?

{{ zip(sensors | map('attr', 'state') | map('float') | list, 
sensors | map('attr', 'entity_id') | map('area_name') | list)
| selectattr(0, '>', 0)
| selectattr(1, '==', 'Living Room') 
| map('first') | sum | round(2) }}
1 Like

Cheers thats dont the trick, I can see now where the state is mapped to a float, Thanks for the tips love getting better at this stuff.

Ok final code to take an area and add all the power sensors to give you a power reading. This takes all the lines above and puts it into a single template sensor

{% set sensors = states.sensor
| rejectattr('state', '==', 'unavailable')
| rejectattr('state', '==', 'unknown')
| rejectattr('attributes.friendly_name', '==', 'Power-Area-Living Room-Total')
| selectattr('attributes.device_class', '==', 'power')
| selectattr('attributes.unit_of_measurement', '==', 'W')
| list %}

{{ zip(sensors | map('attr', 'state') | map('float') | list, 
sensors | map('attr', 'entity_id') | map('area_name') | list)
| selectattr(1, '==', 'Living Room') 
| selectattr(0, '>=', 0)
| map('first') | sum | round(2) }}

If the goal is compute the sum of all power sensors in a specific area, it’s preferable for the template to start by selecting all power sensors in the area (as opposed to starting with all sensors in the state machine).

area_entities()

{{ area_entities('Living Room')
  | select('match', 'sensor') | expand
  | rejectattr('state', 'in', ['unavailable', 'unknown'])
  | rejectattr('attributes.friendly_name', '==', 'Power-Area-Living Room-Total')
  | selectattr('attributes.device_class', '==', 'power')
  | selectattr('attributes.unit_of_measurement', '==', 'W')
  | map(attribute='state')
  | map('float', 0) | sum | round(2)
}}

It can be made slightly shorter if you provide me with the entity_id of the Template Sensor that will use this template.

1 Like

Ahh that makes a lot of sense to reduce the sensors selected to start with! The exact name of the sensor is sensor.power_area_living_room_total

Cheers

Lachlan

{{ area_entities('Living Room')
  | select('match', 'sensor') 
  | reject('search', '.*power_area_living_room_total$')
  | expand
  | rejectattr('state', 'in', ['unavailable', 'unknown'])
  | selectattr('attributes.device_class', '==', 'power')
  | selectattr('attributes.unit_of_measurement', '==', 'W')
  | map(attribute='state')
  | map('float', 0) | sum | round(2)
}}

Let me know if it provides the same result as your version.

FWIW, you may be able to remove one of the selectattr filters if all the power sensors have the same unit of measurement.

1 Like

This is great thank you! You are right in that i have been able to remove one filter and still get the same result, now the final step it to make it a repeatable template with something like this so every time i add an area the sensor gets auto generated!

This was an unexpected rabbit hole of leaning thanks for everyones contributions!

Cheers,

Lachlan

1 Like

You’re welcome!

Please consider marking my post with the Solution tag. Users looking for answers to similar questions will be led directly to the most concise way to filter entities within a given area.