Template loop detected while processing event

Given that the template is using states.sensor you could probably remove the initial startswith('sensor.') because only sensors are included in the collection.

NOTE

Depending on how the new template analysis works, it may still cause the error message if the analysis takes into consideration states.sensor without evaluating the balance of the template. In other words, it may creates listeners for all sensors just because it sees states.sensors in the template. I’m hoping the new template analysis technique (introduced a few versions ago) is more sophisticated than that. If not, every time sensor.current-consumption is updated, it will (because it’s part of states.sensor cause the template to be re-evaluated (which is a loop, of course).

Ah I see, now I understand the issue. Thanks for an explanation.
So far no error, but I didnt used to get it every time. I give it some time and report here.

No, that didnt helped. I’m still getting the same error:

2020-12-16 10:26:22 WARNING (MainThread) [homeassistant.components.template.template_entity] Template loop detected while processing event: <Event state_changed[L]: entity_id=sensor.current_consumption, old_state=<state sensor.current_consumption=207.0; unit_of_measurement=W, friendly_name=Current Power, icon=mdi:transmission-tower @ 2020-12-16T10:26:20.723463+01:00>, new_state=<state sensor.current_consumption=191.0; unit_of_measurement=W, friendly_name=Current Power, icon=mdi:transmission-tower @ 2020-12-16T10:26:21.725318+01:00>>, skipping template render for Template[{% set ns = namespace(states=[]) %} {% for s in states.sensor if s.entity_id.startswith('sensor.') and s.object_id.endswith('_power') and s.state not in ['unavailable', 'unknown' ] %}
  {% set ns.states = ns.states + [ s.state | float ] %}
{% endfor %} {{ (ns.states | sum) | round(2) }}]

I have checked and it is not possible to add attributes for esphome sensors.

If you loop through all the sensors, regardless of filters applied, that message has a chance to appear.

That means it’s not a error. You can safely ignore it, it’s just letting you know that you have a template that might reference itself. If you want it out of your logs, remove it by configuring logger to ignore warnings for the template sensor integration.

It’s possible to add custom attributes to Home Assistant’s entities by defining them in customize.yaml or via the menu: Configuration > Customizations. You can add whatever extra information you want to each entity.

Customizing Entities

However, the warning message may be due to the template’s reliance on states.sensor (which will automatically include sensor.current_consumption). My suggestion to use custom attributes still relies on using states.sensor so I now doubt it would prevent the warning.

The following suggestion avoids the use states.sensor. However, it requires that you create a group containing all of the power-related sensors. The Template Sensor is reduced to this:

- platform: template
  sensors:
    current_consumption:
      friendly_name: Current Power
      unit_of_measurement: W
      icon_template: mdi:transmission-tower
      value_template: >
        {{ expand('group.my_sensors') | rejectattr('state', 'in', ['unavailable', 'unknown'])
            | map(attribute='state') | map('float') | sum | round(2) }}

Thanks, thats probably only option I have.
Could you point me to the documentation for rejectattr and other such commands used with expand? I’m not able to find it.
I would like to learn additional options. Also I would like to know if it is possible to add additional filter similar to endswith using this method.

Removing warnings globally for all template sensors is not an option. I need them in case I mess up anything in the future.
I’m using HA for over a year now, but I still keep discovering new things and new ways to do things almost weekly, so I tinker with it a lot.
It sort of became my hobby, from configuration to creating integrations :slight_smile:

This is Jinja, it’s not something that is specific to Home Assistant. I suggest google Jinja, here’s a reference to built in jinja filters.

It is not possible. EDIT: Seeing that you know how to code, an easier solution would be to add a new filter thats similar to rejectattr/selectattr that accepts startswith/endswith. Adding a test to it would require you to override the whole method.

Ah, I see. I have much to learn :slight_smile:

Here is what I’m testing now:
Group:

energy:
    name: Energy
    entities:
        - sensor.dac_daily_energy
        - sensor.dac_power
        - sensor.dell_monitor_daily_energy
        - sensor.dell_monitor_power
        - sensor.eizo_monitor_daily_energy
        - sensor.eizo_monitor_power
        - sensor.grow_light_5_daily_energy
        - sensor.grow_light_5_power
        - sensor.ha_daily_energy
        - sensor.ha_power
        - sensor.headphones_daily_energy
        - sensor.headphones_power
        - sensor.hp_monitor_daily_energy
        - sensor.hp_monitor_power
        - sensor.marantz_daily_energy
        - sensor.marantz_power
        - sensor.nas_daily_energy
        - sensor.nas_power
        - sensor.nc_gw1_daily_energy
        - sensor.nc_gw1_power
        - sensor.pc_daily_energy
        - sensor.pc_power
        - sensor.prusa_daily_energy
        - sensor.prusa_power
        - sensor.usb_daily_energy
        - sensor.usb_power

Sensors:

sensor:
- platform: template
  sensors:
    energy_total:
      friendly_name: Total Energy
      unit_of_measurement: kWh
      icon_template: mdi:calendar-today
      value_template: >
        {{ expand('group.energy') 
        | selectattr('attributes.unit_of_measurement', 'equalto', 'kWh')
        | rejectattr('state', 'in', ['unavailable', 'unknown'])
        | map(attribute='state') | map('float') | sum | round(2) }}
          
- platform: template
  sensors:
    current_consumption:
      friendly_name: Current Power
      unit_of_measurement: W
      icon_template: mdi:transmission-tower
      value_template: >
        {{ expand('group.energy') 
        | selectattr('attributes.unit_of_measurement', 'equalto', 'W')
        | rejectattr('state', 'in', ['unavailable', 'unknown'])
        | map(attribute='state') | map('float') | sum | round(2) }}

utility_meter:
  daily_energy:
    source: sensor.energy_total
    cycle: daily

  monthly_energy:
    source: sensor.energy_total
    cycle: monthly

I just didnt wanted to create 2 groups if it was not necessary. It will be easier to maintain this way.
It is unfortunate that I need to use groups to avoid that warning spam. I would prefer for it to be fully automatic, as I keep adding and removing those esp devices a lot.

1 Like

if you want to be super lazy with your group. Create an automation that fires at startup, iterates your sensors and creates the group with all entities that end in ‘energy’. You could even have it execute on template reload.

I can have an automation to create and update a group? that would actually solve the issue, if I could have group update like every hour.
I have to research this.
Having dynamic groups could be really powerful tool.

So what do you envision you will use in the automation’s Template Trigger? Obviously something that monitors all sensors to check for new ones, like states.sensor:slightly_smiling_face: (EDIT: Just joking. No need to monitor all sensors. It’s highly unlikely that new sensors are being created so frequently.)

The very end of the first post in this thread demonstrates how to use a python_script to dynamically generate a group.

no reason to have it update every hour. Just have it update when things reload or you restart. Every hour is overkill.

What is the use-case that causes such frequent additions/removals of sensor entities?

Right now, its constantly rebuilding hardware for development environment I need to work on my mikrotik integration and my indoor garden project, since I’m testing various grow lights and ventilation systems and their different setup.
I measure power draw for every device separately, specially my garden project to calculate cost and efficiency vs umol.
Its probably an extreme case and overkill, but its something I like to look at in detail.

OK, here’s a simple example of a group created on startup or when groups are reloaded:

# Dynamically create a group
- alias: 'Create My Sensors Group'
  trigger:
  - platform: homeassistant
    event: start
  - platform: event
    event_type: 'call_service'
    event_data:
      domain: 'group'
      service: 'reload'
  action:
  - service: group.set
    data_template:
      name: 'My Sensors'
      entities: >
        {{ states.sensor  
          | selectattr('attributes.unit_of_measurement', '==', 'W')
          | selectattr('attributes.device_class', '==', 'power')
          | selectattr('attributes.power_type', '==', 'whatever')
          | list }}

The template contains ‘everything but the kitchen sink’ and is only meant to demonstrate several ways to select desired entities. It shows how to select them by unit_of_measurement, device_class and a custom attribute called power_type.

In your case, you might use some or none of those techniques. In fact, you might want to use a template very similar to the one you used in your Template Sensor, something like this:

        entities: >
          {% set ns = namespace(entities=[]) %}
          {% for s in states.sensor if s.object_id.endswith('_power') or s.object_id.endswith('_energy') %}
            {% set ns.entities = ns.entities + [ s.entity_id ] %}
          {% endfor %}
          {{ ns.entities }}
4 Likes

Thank you, this is exactly what I need. I have adjusted it as follows:

- alias: 'Update Group - Daily Energy'
  trigger:
  - platform: homeassistant
    event: start
  - platform: event
    event_type: 'call_service'
    event_data:
      domain: 'group'
      service: 'reload'
  action:
  - service: group.set
    data_template:
      name: 'Energy - Daily'
      object_id: energy_daily
      entities: >
          {% set ns = namespace(entities=[]) %}
          {% for s in states.sensor if s.object_id.endswith('_energy') and s.attributes.unit_of_measurement == "kWh" and not s.attributes.meter_period %}
            {% set ns.entities = ns.entities + [ s.entity_id ] %}
          {% endfor %}
          {{ ns.entities }}
          
- alias: 'Update Group - Power'
  trigger:
  - platform: homeassistant
    event: start
  - platform: event
    event_type: 'call_service'
    event_data:
      domain: 'group'
      service: 'reload'
  action:
  - service: group.set
    data_template:
      name: 'Energy - Power'
      object_id: energy_power
      entities: >
          {% set ns = namespace(entities=[]) %}
          {% for s in states.sensor if s.object_id.endswith('_power') and s.attributes.unit_of_measurement == "W" and not s.attributes.meter_period %}
            {% set ns.entities = ns.entities + [ s.entity_id ] %}
          {% endfor %}
          {{ ns.entities }}

Since its automatic, I will use 2 groups.

I have tried using component loaded trigger, but that does not work for me.

  - platform: event
    event_type: 'component_loaded'
    event_data:
      component: esphome
1 Like

Glad to hear it solves the original problem.

To close out this topic, please consider marking my post (either the initial one suggesting to use expand with a group or the one demonstrating how to generate a dynamic group) with the Solution tag. It will automatically place a check-mark next to the topic’s title which signals to other users that this topic has an accepted solution (only one Solution per topic). This helps other users find answers to similar questions.

Hi,
thanks for this.
I think I understand everything but have a minor issue with some of the logic.
I want to create a group for energy entities for each room (i.e kitchen, bedrooms, living room, etc) to track the used energy and then a total energy for the home (which will add all the rooms together)

I’m currently running 2021.12.7 and I have this automation code.

- id: "1641380832863"
  alias: Update Energy Groups
  description: ""
  trigger:
    - platform: homeassistant
      event: start
    - platform: event
      event_type: call service
      event_data:
        domain: group
        service: reload
  condition: []
  action:
    - service: group.set
      data_template:
        name: Master Bedroom Energy
        entities: >
          {% set ns = namespace(states=[]) %}
          {% for s in states.sensor %}
            {% if s.entity_id.startswith('sensor.leftbedroom') and s.object_id.endswith('_energy') or s.entity_id.startswith('sensor.rightbedroom') and s.object_id.endswith('_energy') or s.entity_id.startswith('sensor.masterbedroom') and s.object_id.endswith('_energy') and s.state not in ['unavailable', 'unknown' ] %} 
            {% set ns.states = ns.states + [s.state | float] %}
            {% endif %}
          {% endfor %} 
          {{ ns.states | sum | round(2) }}
  mode: single

when i run the automation i get the following error

Stopped because an error was encountered at January 5, 2022, 10:35:23 PM (runtime: 0.17 seconds)

’float’ object is not iterable

I know that they recently changed the float so it should read something like float (default=0) but i think its more than that.

Once I understand this part I want to add multiple actions for each room group update and then work on the value template for each room.

Does anyone know what the logic should be for this?
Any help or ideas would be greatly appreciated

Thanks

{{ states.sensor 
   | selectattr('object_id', 'search', '^(benbedroom|susiebedroom|masterbedroom)')
   | selectattr('object_id', 'search', '(_energy)$')
   | rejectattr('state', 'in', ['unavailable', 'unknown'])
   | map(attribute='state') | map('float', none)
   | reject('==', none)
   | sum | round(2) }}

EDIT: I just realized you’re using this on a group set. This has to be an entity_id list, not the actual math you want to employ…

{{ states.sensor 
   | selectattr('object_id', 'search', '^(benbedroom|susiebedroom|masterbedroom)')
   | selectattr('object_id', 'search', '(_energy)$')
   | map(attribute='entity_id') | list }}

Then your template sensor that calculates the group will be

{{ expand('group.master_bedroom_energy')
   | map(attribute='state') 
   | map('float', none)
   | reject('==', none)
   | sum | round(2) }}
1 Like

Thanks again Petro,
this worked great, I was able to create all the rooms and then another group that collected them all.
If I may, could I ask 2 follow up questions?

1.) Would I add this to the automation group or the template sensor
rejectattr(‘state’, ‘in’, [‘unavailable’, ‘unknown’, ‘none’])

2.) range filters as described here
https://www.home-assistant.io/integrations/filter/#range
I’ve seen some wild numbers from time to time so I’m looking to remove them so it doesn’t blow out the graphs.
Do you have any advise on if it can go with the group or template sensor as above or still call it out as described in the link?

thanks again for your help