Only allow a sensor value to increase

I need to monitor the energy consumption of an entire building, so I have the follow template sensor to combine the energy consumption:

  - platform: template
    sensors:
      energy_consumption:
        friendly_name: "Energy Consumption"
        unit_of_measurement: "kWh"
        value_template: "{{ (states('sensor.fibarowp9_electric_consumed_kwh') | float + states('sensor.fibarowp10_electric_consumed_kwh') | float + states('sensor.fibarowp11_electric_consumed_kwh') | float + states('sensor.fibarowp12_electric_consumed_kwh') | float + states('sensor.fibarowp13_electric_consumed_kwh') | float + states('sensor.fibarowp14_electric_consumed_kwh') | float + states('sensor.fibarowp15_electric_consumed_kwh') | float + states('sensor.fibarowp16_electric_consumed_kwh') | float + states('sensor.fibarowp17_electric_consumed_kwh') | float) | round(3) }}"      

Then I use the utility meter to generate energy consumption reports:

utility_meter:
  energy_consumption_quarter_hourly:
    source: sensor.energy_consumption
    cycle: quarter-hourly
  energy_consumption_hourly:
    source: sensor.energy_consumption
    cycle: hourly
  energy_consumption_daily:
    source: sensor.energy_consumption
    cycle: daily
  energy_consumption_weekly:
    source: sensor.energy_consumption
    cycle: weekly
  energy_consumption_monthly:
    source: sensor.energy_consumption
    cycle: monthly
  energy_consumption_yearly:
    source: sensor.energy_consumption
    cycle: yearly

The problem is, sensor.energy_consumption sometimes decreases in value when a sensor is unavailable. This messes up the reporting from utility meter. Is there any way to ensure that sensor.energy_consumption can only increase in value? Or can I make a new sensor using a template that only increases in value?

Ideally, I would have some kind of template which compares the new value to the previous value, and if the new value is less than the previous value, discard it.

You need to add an availability_template to your template sensor.

The simplest way would be to multiply all the dependant sensors together and check the result is > 0. If any of the sensors are unavailable the |float filter for that sensor will return 0, thus the whole multiplication will be zero.

availability_template: >
  {{ states('sensor.fibarowp9_electric_consumed_kwh') | float *
     states('sensor.fibarowp10_electric_consumed_kwh') | float *
     states('sensor.fibarowp11_electric_consumed_kwh') | float *
     states('sensor.fibarowp12_electric_consumed_kwh') | float * 
     states('sensor.fibarowp13_electric_consumed_kwh') | float *
     states('sensor.fibarowp14_electric_consumed_kwh') | float *
     states('sensor.fibarowp15_electric_consumed_kwh') | float * 
     states('sensor.fibarowp16_electric_consumed_kwh') | float * 
     states('sensor.fibarowp17_electric_consumed_kwh') | float > 0 }}
1 Like

Thank you, I was not aware of that functionality, I will give it a try :grinning:

Unfortunately, this does not work because sometimes the value of sensor.fibarowpXY_electric_consumed_kwh is actually 0 (some wall plugs are not yet used. thus 0 is correct).

Ok then, try this:

availability_template: "{{ 'unavailable' not in [ states('sensor.fibarowp9_electric_consumed_kwh'), states('sensor.fibarowp10_electric_consumed_kwh'), states('sensor.fibarowp11_electric_consumed_kwh'), states('sensor.fibarowp12_electric_consumed_kwh'), states('sensor.fibarowp13_electric_consumed_kwh'), states('sensor.fibarowp14_electric_consumed_kwh'), states('sensor.fibarowp15_electric_consumed_kwh'), states('sensor.fibarowp16_electric_consumed_kwh'), states('sensor.fibarowp17_electric_consumed_kwh') ] }}"
1 Like

So this solves part of the problem, but it seems the sensors are unreliable and sometimes report 0 instead of unavailable.

Is there really no way to create a template which does the following:

if new_state < old_state # should not be allowed to decrease
  state = old_state
else
  state = new_state

Take a look at my post here:

which should be simple to adapt for upwards-only logic. Uses an input_number as a proxy for a sensor — you can always create a template sensor from it if needed.

1 Like

Sorry, just for my own understanding, you are using the input number to store the old_state basically?

Yes, and then adjust it depending on the incoming new value. I’ve just remembered I do something closer to what you want with my house “maximum power” record:

- alias: Max power recorder
  trigger:
    - platform: state
      entity_id: sensor.power_meter_house
  condition:
    - condition: template
      value_template: "{{ (states('sensor.power_meter_house')|float > states('input_number.max_power')|float) }}"
  action:
    - service: input_number.set_value
      data_template:
        entity_id: input_number.max_power
        value: "{{ states('sensor.power_meter_house')|float }}"

Again, this is an input_number, and it is storing the maximum house power draw, updated via this automation which triggers whenever the prior maximum is exceeded. I wrote this some while ago: should probably have the template in the trigger instead of the condition, and there’s no need for data_template any more, as data works fine.

1 Like

Thank you so much! I was able to come up with a solution based on yours.

Step 1: Create an input number to store the old sensor value (input_number.energy_consumption_old_state)

Step 2: Create an automation to update the input number input_number.energy_consumption_old_state only when the sensor value of sensor.energy_consumption increases

automation energy_consumption:
  - alias: "Check new state of sensor.energy_consumption and store it in input_number.energy_consumption_old_state if it has increased"
    trigger:
      - platform: state
        entity_id: sensor.energy_consumption
    condition:
      - condition: template
        value_template: "{{ (states('sensor.energy_consumption') | float > states('input_number.energy_consumption_old_state') | float) }}"
    action:
      - service: input_number.set_value
        data_template:
          entity_id: input_number.energy_consumption_old_state
          value: "{{ states('sensor.energy_consumption') | float }}"

Step 3: create a sensor (sensor.energy_consumption) with a value template that checks the old state stored in input_number.energy_consumption_old_state, if the new value is smaller than the old value, keep using the old value. If not, update to the new value.

sensor:
  - platform: template
    sensors:
      energy_consumption:
        friendly_name: "Energy Consumption"
        unit_of_measurement: "kWh"
        value_template: >
          {% set new_state = (states('sensor.fibarowp9_electric_consumed_kwh') | float + states('sensor.fibarowp10_electric_consumed_kwh') | float + states('sensor.fibarowp11_electric_consumed_kwh') | float + states('sensor.fibarowp12_electric_consumed_kwh') | float + states('sensor.fibarowp13_electric_consumed_kwh') | float + states('sensor.fibarowp14_electric_consumed_kwh') | float + states('sensor.fibarowp15_electric_consumed_kwh') | float + states('sensor.fibarowp16_electric_consumed_kwh') | float + states('sensor.fibarowp17_electric_consumed_kwh') | float) | round(3) %}
          {% if new_state >= states('input_number.energy_consumption_old_state') | float %}
            {{ new_state }}
          {% else %}
            {{ states('input_number.energy_consumption_old_state') | float }}
          {% endif %}

What an absolute pain to make something so simple :slight_smile: Thanks a lot @Troon

4 Likes