Unreliable syntax for a jinja script

I have a sensor which sums the power used by all devices that I have got sensors for. It has to exclude some which are not usage sensors but power delivery sensors. It also exclude some sensors which are created from the original (eg tariff splits), also a sensor which is the aggregate of all my lights,

I then subtract this from the power delivered to my home to provide a sensor for all other power consuming items.

This works most of the time but I sometimes find errors in the log that I cannot understand.

Can anyone suggest if the script below could/should be made smarter.

      - name: Untracked Power Usage
        state: >
          {% set ns = namespace(states=[]) %}
          {% for s in states.sensor | selectattr('attributes.unit_of_measurement', 'defined') %}
          {% if s.attributes.unit_of_measurement == 'W' 
            and s.object_id[0:6] != 'shelly' 
            and s.object_id[0:5] != 'other'
            and s.object_id[0:4] != 'aca_'
            and s.object_id[0:4] != 'acb_'
            and s.object_id[-4:] != 'peak'
            and s.object_id[-8:] != 'shoulder'
            and 'battery' not in s.object_id            
            and s.object_id[0:9] != 'power_tot'
            and s.object_id[0:10] != 'office_x34'
            and s.object_id[0:9] != 'untracked'
            and s.object_id[0:10] != 'all_lights' %}
            {% set ns.states = ns.states + [ s.state | float(0) ] %}
          {% endif %}
          {% endfor %}
          {{ (states('sensor.power_total') | float(0) - (ns.states | sum | float(0)))|round(2) }}
        unit_of_measurement: "W"
        device_class: "power"

The log says this:

Template loop detected while processing event: <Event state_changed[L]: entity_id=sensor.untracked_power_usage, old_state=<state sensor.untracked_power_usage=77.72; unit_of_measurement=W, device_class=power, friendly_name=Untracked Power Usage @ 2023-02-06T13:14:00.347839+11:00>, new_state=<state sensor.untracked_power_usage=76.52; unit_of_measurement=W, device_class=power, friendly_name=Untracked Power Usage @ 2023-02-06T13:14:01.346732+11:00>>, skipping template render for Template…

This does not answer your actual question and I haven’t actually tried it out yet myself, but I think this might be a good case for the new sensor groups. Although the sensors can’t be dynamically added like your template…

Is there a reason why you are loading all those object id checks into the for loop instead of reject them beforehand? Or, even better, not bothering with a loop at all… just use the built-in filters.

        name: Untracked Power Usage
        state: >
          {% set o_id = 'shelly|other|aca
          |acb|peak|shoulder|battery
          |power_tot|office_x34|untracked|all_lights' %}
          {% set tracked = states.sensor 
          | selectattr('attributes.unit_of_measurement', 'defined') 
          | selectattr('attributes.unit_of_measurement', 'eq', 'W')
          | selectattr('state', 'is_number')
          | rejectattr('object_id', 'search', o_id) 
          | map(attribute='state') | map('float', 0) | sum %}
          {{ (states('sensor.power_total') | float(0) - tracked) | round(2) }}
        unit_of_measurement: "W"
        device_class: "power"
1 Like

I love your simplification which I will immediately use.

However my underlying issue is why do I get the error. Could it be down to the availability of a value as it assembles the sum? I have been assuming that |float(0) sorted that.

It could be…

Does this error persist for a while (or is it easily reproducible)? If so, when this happens, but your template in the template editor with a {{ ... }} construct to “print” the values of interest.

It’s also quite easy to add another filter to Drew’s suggestion to filter for unknown or unavailable entities, if that’s the issue.

2 Likes

I will do that. Thanks for your thoughts.

You could try addind a filter like this:

| rejectattr('state', 'in', ['unavailable','unknown']) 

And also exclude the sensor you are calculating to from your calculations (the root cause of your original error)

| rejectattr('entity_id', 'eq', 'sensor.untracked_power_usage')

@Didgeridrew I don’t think that rejectattr(‘object_id’,‘search’,…) is a valid syntax. It certainly isn’t excluding anything.

@EdwardTFN Unfortunately not the ‘root cause’ problem, you will see that I exclude ‘untracked’.

I added the other suggestion, but no change.

It is definitely valid syntax.

Ignore me, once I removed spaces the syntax cleanup suggestion works.

Still got the original reported issue though.

It does this every few minutes. I have added script to list the selected entity_ids in Template but nothing revealing shows up. I am puzzled how this error message also shows old and new values despite the error.

  • Template loop detected while processing event: <Event state_changed[L]: entity_id=sensor.untracked_power_usage, old_state=<state sensor.untracked_power_usage=19.76; unit_of_measurement=W, device_class=power, friendly_name=Untracked Power Usage @ 2023-02-07T16:24:29.636550+11:00>, new_state=<state sensor.untracked_power_usage=18.96; unit_of_measurement=W, device_class=power, friendly_name=Untracked Power Usage @ 2023-02-07T16:24:30.662828+11:00>>, skipping template render for Template[{% set ns = states.sensor | selectattr(‘attributes.unit_of_measurement’, ‘defined’) | selectattr(‘attributes.unit_of_measurement’, ‘eq’, ‘W’) | rejectattr(‘state’, ‘in’, [‘unavailable’,‘unknown’]) | rejectattr(‘object_id’, ‘search’, ‘shelly|other|aca_|acb_|peak|shoulder|battery|power_tot|office_x34|untracked|all_lights’) | map(attribute=‘state’) | map(‘float’, 0) | sum %} {{ (states(‘sensor.power_total’)|float(0)-ns) | round(2) }}]

I think it’s because the sensor you’re defining is also in the states you’re iterating over. Exclude sensor.untracked_power_usage.

Unfortunately not the ‘root cause’ problem, you will see that I exclude ‘untracked’.

Are you getting exactly the same error message when you try that?

Yes, basically identical, every few minutes…

  • Template loop detected while processing event: <Event state_changed[L]: entity_id=sensor.untracked_power_usage, old_state=<state sensor.untracked_power_usage=-5.57; unit_of_measurement=W, device_class=power, friendly_name=Untracked Power Usage @ 2023-02-07T17:40:10.599850+11:00>, new_state=<state sensor.untracked_power_usage=-7.27; unit_of_measurement=W, device_class=power, friendly_name=Untracked Power Usage @ 2023-02-07T17:40:11.591410+11:00>>, skipping template render for Template[{% set ns = states.sensor | selectattr(‘attributes.unit_of_measurement’, ‘defined’) | selectattr(‘attributes.unit_of_measurement’, ‘eq’, ‘W’) | rejectattr(‘state’, ‘in’, [‘unavailable’,‘unknown’]) | rejectattr(‘object_id’, ‘search’, ‘shelly|other|aca_|acb_|peak|shoulder|battery|power_tot|office_x34|untracked|all_lights’) | map(attribute=‘state’) | map(‘float’, 0) | sum %} {{ (states(‘sensor.power_total’)|float(0)-ns) | round(2) }}]

I don’t see this filter on the error message?

Do you have exactly the same error message when you add this filter?

It’s in here:

rejectattr(‘object_id’, ‘search’, ‘shelly|other|aca_|acb_|peak|shoulder|battery|power_tot|office_x34|untracked|all_lights’)

But it might not be working.

@ianadd modify your template to list all the entity IDs in the template editor.

Basically, replace

map(attribute=‘state’) | map(‘float’, 0) | sum

with

map(attribute='entity_id')

.

1 Like

You’ll always get a loop detection error here. You can safely ignore it if you filter it out. But that won’t stop the error from occurring. If you wanted to get rid of the error, you’d have to make an automation that creates a group with the entities you want using group.set. Then your template sensor would expand that group.

2 Likes

I have done that and all the expected ones are there and no others.