Race condition on computed value from template

Hello, I’m having a strange behavior on the value obtained from a template.
The datasource is a daily utility meter calculating the energy consumed and the energy got from distributer (taken from a shelly EM)

utility_meter:
    shelly_em_distributor_energy:
        source: sensor.meter1_total
        cycle: daily
        name: Distributor energy (EM)

    shelly_em_home_consumed_energy:
        source: sensor.meter0_total
        cycle: daily
        name: home consumed energy (EM)

And in order to calculate the self consumed energy (coming from solar panels) i have a template sensor making the difference

template:
  - sensor:
      - name: "Selfconsumption FV (EM)"
        state: >
              {% set energy = (states('sensor.home_consumed_energy_em')|float - states('sensor.distributor_energy_em')|float) | round(2, none) %}
              {% if (energy < 0) %}
              {%	set energy = 0 %}
              {% endif %}
              {{ energy }}
        unit_of_measurement: "Wh"
        device_class: energy
        state_class: total

Everything works fine, except for the the first statistics of the day (the one at 00:00:00) thats gets a negative value.
Looks like the template registers the energy at 00:00:00 when sensor.home_consumed_energy_em has been reset to 0 (cycle is daily) while sensor.distributor_energy_em gets reset to 0 immediately after.
The strange thing is that in the template i have included the logic to consider 0 a negative value and from the developer tools seems to work fine.

The only workaround I have at the moment is to go in developer tools every day and to manually correct the statistic at time 00:00:00.

Any idea on why it’s happening and on how to solve?

your value never goes negative. The value is positive and when your item clears the data it goes from a large positive number to 0, adding a negative value to your days total.

You can fix this in the template by checking the time and dropping the value to zero before midnight.

{% set a = states('sensor.home_consumed_energy_em')|float(0) %}
{% set b = states('sensor.distributor_energy_em')|float(0) %}
{% set midnight = today_at() %}
{% if midnight <= now() <= midnight + timedelta(minutes=1) %}
  0
{% elif midnight + timedelta(hours=23, minutes=59) <= now() <= midnight + timedelta(days=1) %}
  0
{% else %}
  {{ (a - b) | round(2) }}
{% endif %}

This template forces the data ± 1 minute from midnight to be zero.

You might be able to get away with just midnight.

Edit: now that I think about it, you might want to wipe the data only after midnight.

{% set a = states('sensor.home_consumed_energy_em')|float(0) %}
{% set b = states('sensor.distributor_energy_em')|float(0) %}
{% set midnight = today_at() %}
{% if midnight <= now() <= midnight + timedelta(seconds=10) %}
  0
{% else %}
  {{ (a - b) | round(2) }}
{% endif %}

Hi Pietro, first of all thanks for your answer.
I have not completely understood this part of your answer:

I’m saying that because in the statistics I’m able to see the negative value resulting from the subtraction, as you can see in the attached screenshot:

Since both values are going to 0 in the same time I should see 0 in the difference too. Am i wrong?

The negative number in your database is the result of the reset occurring before you data was cleared. I.e. when midnight hits, your sensor is still reading 1000. Then your sensor resets to 0, resulting in a -1000 being added to your energy consumption statistic. You need to ensure that the 1000 does not carry over from before midnight to after.

I have configured two additional sensors having the two solutions you suggested. Tomorrow morning we’ll see if they solved the issue.

In the mean time, can you point me out some documentations to understand how the energy consumption component works? I would like to debug and understand it better.

Thanks

Hi Pedro,
both the solution provided are not working, because the drop is still there.
the only difference is that the drop of solution #1 occurs at 23:55:00 of day before instead of 00:00:00.

Does it exists a service able to change to 0 the value of a statistic at a certain time?