Sensor Sum returns wrong / erratic values

Hi,

I’m having troubles with summing up sensor values:

energie_verbrauch_summe_test:
        friendly_name: "Energie Verbrauch Summe Test"
        value_template: "{{ (states('sensor.shellyem3_84cca8aca23e_channel_a_energy') |float
                   + states('sensor.shellyem3_84cca8aca23e_channel_b_energy') |float  
                   + states('sensor.shellyem3_84cca8aca23e_channel_c_energy') |float 
                   + states('sensor.shellyem3_84cca8ad71ae_channel_a_energy') |float
                   + states('sensor.shellyem3_84cca8ad71ae_channel_b_energy') |float
                   + states('sensor.shellyem3_84cca8ad71ae_channel_c_energy') |float) |round(2)  }}"
        unit_of_measurement: 'kWh'    

This gives me strange results, with regular drops in the values:

However, the underlying sensors all look fine:

Could somebody have a look at my sum yaml and check what the problem could be?

Thanks!

Hi, this might be caused by one or more of the individual entities going unavailable for a short period of time. I have noticed that although entities appear to hold last value when they go unavailable this is not the case within template expressions where an unavailable entity is evaluated as zero.

You can test this by seeing what happens when you restart HA - the entities should hold last value but the template should evaluate to zero.

A possible way to work around this might be to restructure your template as an if-then-else so that if any entity is unavailable it uses the previous value otherwise it re-evaluates your template as above when all entities are not unavailable.

Thanks, that seems plausible. As in fact these entities do sometimes turn unavailable due to weak wifi…

Could you help me in rewriting the yaml?

I must admit I’m pretty new in the topic and the code Im using is basically just copy and paste from someone else from the forum… :wink:

Thanks so much!

OK, try something like this but test it first by pasting into Developer Tools - Templates as it might have some syntax errors:

energie_verbrauch_summe_test:
  friendly_name: "Energie Verbrauch Summe Test"
  value_template: >
    {% set current = states('sensor.energie_verbrauch_summe_test') | float %}
	{% set new = "{{ (states('sensor.shellyem3_84cca8aca23e_channel_a_energy') |float
      + states('sensor.shellyem3_84cca8aca23e_channel_b_energy') |float  
      + states('sensor.shellyem3_84cca8aca23e_channel_c_energy') |float 
      + states('sensor.shellyem3_84cca8ad71ae_channel_a_energy') |float
      + states('sensor.shellyem3_84cca8ad71ae_channel_b_energy') |float
      + states('sensor.shellyem3_84cca8ad71ae_channel_c_energy') |float) |round(2) }}"
    {% if (states('sensor.sensor.shellyem3_84cca8aca23e_channel_a_energy') == "unavailable"
       or states('sensor.shellyem3_84cca8aca23e_channel_b_energy') == "unavailable"  
       or states('sensor.shellyem3_84cca8aca23e_channel_c_energy') == "unavailable" 
       or states('sensor.shellyem3_84cca8ad71ae_channel_a_energy') == "unavailable"
       or states('sensor.shellyem3_84cca8ad71ae_channel_b_energy') == "unavailable"
       or states('sensor.shellyem3_84cca8ad71ae_channel_c_energy') == "unavailable") current
	{% else %} new
	{% endif %)
  unit_of_measurement: 'kWh'

Try this. It assumes that the current reading cannot be lower than the last sensor value:

value_template: >-
   {{ 
     [
      states('sensor.shellyem3_84cca8aca23e_channel_a_energy') |float,
      states('sensor.shellyem3_84cca8aca23e_channel_b_energy') |float,  
      states('sensor.shellyem3_84cca8aca23e_channel_c_energy') |float,
      states('sensor.shellyem3_84cca8ad71ae_channel_a_energy') |float,
      states('sensor.shellyem3_84cca8ad71ae_channel_b_energy') |float,
      states('sensor.shellyem3_84cca8ad71ae_channel_c_energy') |float,
    ] | sum | max(states('sensor.energie_verbrauch_summe_test') | float)
  }}

Thanks! It works in the developer tool, however Im getting the following error in the file editor:

missed comma between flow collection entries at line 116, column 28:
| sum | max(states('sensor.energ …
^

ok another try:

energie_verbrauch_summe_test:
        friendly_name: "Energie Verbrauch Summe Test"
        value_template: >-
   {{ 
     [
      states('sensor.shellyem3_84cca8aca23e_channel_a_energy') |float,
      states('sensor.shellyem3_84cca8aca23e_channel_b_energy') |float,  
      states('sensor.shellyem3_84cca8aca23e_channel_c_energy') |float,
      states('sensor.shellyem3_84cca8ad71ae_channel_a_energy') |float,
      states('sensor.shellyem3_84cca8ad71ae_channel_b_energy') |float,
      states('sensor.shellyem3_84cca8ad71ae_channel_c_energy') |float,
    ] | sum | max(states('sensor.energie_verbrauch_summe_test') | float)
  }}
        unit_of_measurement: 'kWh'

now Im getting this error in the file editor:

bad indentation of a sequence entry at line 111, column 4:
{{
^

works fine in the developer tool though…

Actually, I tested the expression in the developer tools, but not as a value_template. Try to put it all into one line and remote the comma after the last shelly sensor.

hmmm… removed the comma, still same error. Also one line doesnt work:

energie_verbrauch_summe_test:
        friendly_name: "Energie Verbrauch Summe Test"
        value_template: >-
   {{ 
     [
      states('sensor.shellyem3_84cca8aca23e_channel_a_energy') |float,
      states('sensor.shellyem3_84cca8aca23e_channel_b_energy') |float,  
      states('sensor.shellyem3_84cca8aca23e_channel_c_energy') |float,
      states('sensor.shellyem3_84cca8ad71ae_channel_a_energy') |float,
      states('sensor.shellyem3_84cca8ad71ae_channel_b_energy') |float,
      states('sensor.shellyem3_84cca8ad71ae_channel_c_energy') |float
    ] | sum | max(states('sensor.energie_verbrauch_summe_test') | float)
  }}
        unit_of_measurement: 'kWh'

Thanks, tried it. Got: TemplateSyntaxError: expected token ‘end of statement block’, got ‘{’

Honestly I’m totaly lost what that could mean… :blush:

This works (or at least does not throw any errors). Mind the precise indentation!

sensor:
  - platform: template
    sensors:
      energie_verbrauch_summe_test:
        friendly_name: "Energie Verbrauch Summe Test"
        unit_of_measurement: "kWh"
        value_template: >
          {{[
            states('sensor.shellyem3_84cca8aca23e_channel_a_energy') |float,
            states('sensor.shellyem3_84cca8aca23e_channel_b_energy') |float,  
            states('sensor.shellyem3_84cca8aca23e_channel_c_energy') |float,
            states('sensor.shellyem3_84cca8ad71ae_channel_a_energy') |float,
            states('sensor.shellyem3_84cca8ad71ae_channel_b_energy') |float,
            states('sensor.shellyem3_84cca8ad71ae_channel_c_energy') |float,
          ] | sum | max(states('sensor.energie_verbrauch_summe_test') | float) }}

grafik

Here’s the other version in case you need it:

- platform: template
  sensors:
    energie_verbrauch_summe_test:
      friendly_name: "Energie Verbrauch Summe Test"
      unit_of_measurement: "kWh"
      value_template: >
        {% set current = states('sensor.energie_verbrauch_summe_test') | float %}
        {% set new = (states('sensor.shellyem3_84cca8aca23e_channel_a_energy') |float
          + states('sensor.shellyem3_84cca8aca23e_channel_b_energy') |float  
          + states('sensor.shellyem3_84cca8aca23e_channel_c_energy') |float 
          + states('sensor.shellyem3_84cca8ad71ae_channel_a_energy') |float
          + states('sensor.shellyem3_84cca8ad71ae_channel_b_energy') |float
          + states('sensor.shellyem3_84cca8ad71ae_channel_c_energy') |float) %}
        {% if (states('sensor.shellyem3_84cca8aca23e_channel_a_energy') == "unavailable"
           or states('sensor.shellyem3_84cca8aca23e_channel_b_energy') == "unavailable"  
           or states('sensor.shellyem3_84cca8aca23e_channel_c_energy') == "unavailable" 
           or states('sensor.shellyem3_84cca8ad71ae_channel_a_energy') == "unavailable"
           or states('sensor.shellyem3_84cca8ad71ae_channel_b_energy') == "unavailable"
           or states('sensor.shellyem3_84cca8ad71ae_channel_c_energy') == "unavailable") %} 
             {{ current |float |round(2) }}
        {% else %}
          {{ new |float |round(2) }}
        {% endif %}

image

Try this:

- platform: template
  sensors:
    energie_verbrauch_summe_test:
      friendly_name: "Energie Verbrauch Summe Test"
      unit_of_measurement: "kWh"
      value_template: >
        {% set sensors = ['sensor.shellyem3_84cca8aca23e_channel_a_energy', 'sensor.shellyem3_84cca8aca23e_channel_b_energy', 
                          'sensor.shellyem3_84cca8aca23e_channel_c_energy', 'sensor.shellyem3_84cca8ad71ae_channel_a_energy',
                          'sensor.shellyem3_84cca8ad71ae_channel_b_energy', 'sensor.shellyem3_84cca8ad71ae_channel_c_energy'] %}
        {% set values = expand(sensors)|map(attribute='state')|list %}
        {{ states('sensor.energie_verbrauch_summe_test') if 'unavailable' in values else values|map('float')|sum|round(2) }}   

Perfect, working! You made my day, thanks so much!

Thanks to everybody else as well! :wink:

For future reference, if any of your energy sensors has a legitimate reason to report a new lower value then this technique (using the max filter) is susceptible to producing an incorrect result. It works only if all energy sensors normally report a new higher aggregate value. If the new aggregate value is legitimately lower (i.e. not due to one or more sensors being unavailable) then the Template Sensor will compute the wrong value.

Like being reset …

Might be better using a Filter instead, but have not tried it yet.

The simplest way is to detect if any of the sensors report unavailable. If just one does then the aggregate value is rendered invalid and should be rejected (and the previous aggregate value should be used). That’s the technique employed in Jonah1970’s example and mine.

Another technique is to use availability_template. However, it will report no value if any of the sensors are unavailable which produces a gap in the graph (as opposed to a zero value). This behavior might be useful for users who wish to see (in the graph) when the actual value was unavailable.