Data template with max and min

Im accessing an api to get the current liftetime value for my power meter. Works ok, but somtimes i get values that is not correct. It will sometimes return 0, or wildly inaccuate values. I get the correct value the next time i call the aip, so i can live with that, but it gives meed bad data in the statistics and the HA energy module.
I have tried to create a data_template for the data i get from the api but i just get UNKNOWN back.
Can someone help me create a data template where

  • there is a minimum value (lets say 5000 or not lower that the last value)
  • a max value (lets say 10.000, or not more than 1000 over the latest value)
    else use latest value or skip value.

My api call looks like this:

  - authentication: basic
    username: "xxxx"
    password: "xxxx"
    scan_interval: 600
    resource: https://smart-me.com:443/api/Devices/xxxx
    sensor:
      - name: "Power_Meter" #this shows the meter reading - from when the meter was installed
        value_template: '{{ value_json.CounterReading }}'
        unit_of_measurement: "kWh"
        device_class: "energy"
        json_attributes:
          - "ActivePower"
          - "Name"
          - "Serial"
          - "ActivePower"

the following template will do as the words above describe (I’m pretty sure at least as I haven’t tested it):

{% if (value_json.CounterReading > states('sensor.power_meter') | float or value_json.CounterReading > 5000)
      and (value_json.CounterReading < states('sensor.power_meter') | float + 1000 or value_json.CounterReading < 10000) %}
  {{ value_json.CounterReading }}
{% else %}
  {{ states('sensor.power_meter')}}
{% endif %}

I haven’t checked your logic just translated the words to logic.

Also I’m assuming where you wrote “10.000” you actually meant “10000”? otherwise it wouldn’t make sense at all. but if you really meant “10” you will need to modify the template.

Thanks for the help. It got me some of the way :slight_smile:
But it seems that i cant reference the old value, {{ states(‘sensor.power_meter’)}}, it just sets to 0.
Right now i have:

value_template: >
          {% set power_min = 9035 %} # I would like to change this to previos value, but then i keep getting 0
          {% set power_max = power_min+100 %}
          {% if (value_json.CounterReading > power_min | float) and (value_json.CounterReading < power_max | float) %}
            {{ value_json.CounterReading }}
          {% else %}
            {{power_min}}
          {% endif %}

Show the entire template the way you had it that didn’t work correctly.

I have an idea what could be the issue but I’d like to be sure (you aren’t casting the state in power_min to a float)

I tried to use the old sensor value as a min. Because the meter should always be increasing. But when i do that I get 0 in sensor value.

authentication: basic
    username: "xxxh"
    password: "xxxx"
    scan_interval: 300
    resource: https://smart-me.com:443/api/Devices/xxxx
    sensor:
      - name: "Power_Meter" #this shows the meter reading - from when the meter was installed
        value_template: >
          {% set power_min = states('sensor.power_meter') | float%}
          {% set power_max = power_min+100 | float %}
          {% if (value_json.CounterReading > power_min | float) and (value_json.CounterReading < power_max | float) %}
            {{ value_json.CounterReading }}
          {% else %}
            {{power_min}}
          {% endif %}
        unit_of_measurement: "kWh"
        device_class: "energy"
        json_attributes:
          - "ActivePower"
          - "Name"
          - "Serial"
          - "ActivePower"

What I think is happening is that the template might be getting messed up from the beginning.

Assume that when you reload the integration that the “sensor.power_meter” state is unknown until it gets initialized.

the template looks for the state (unknown) and tries to convert it to a float. but since “unknown” isn’t a number it defaults (for now) to 0.

then power_min = 0
power_max = 100

if the counter reading isn’t between 0 and 100 then it defaults to the “else” value (power_min) which is 0.

then the problem is that no matter what the counter reading is after that the sensor.power_meter will always be 0 and so will never be able to break out of the “else” and so the sensor will perpetually read 0.

I think what you will need to do is to revert your rest sensor to the original template and then create a separate template sensor to filter out the erroneous values.

so like this:

  - authentication: basic
    username: "xxxx"
    password: "xxxx"
    scan_interval: 600
    resource: https://smart-me.com:443/api/Devices/xxxx
    sensor:
      - name: "Power_Meter" #this shows the meter reading - from when the meter was installed
        value_template: '{{ value_json.CounterReading }}'
        unit_of_measurement: "kWh"
        device_class: "energy"
        json_attributes:
          - "ActivePower"
          - "Name"
          - "Serial"
          - "ActivePower"

and then the template sensor (this is using the legacy style template sensor syntax):

sensor:
  - platform: template
    sensors:
      friendly_name: "Power_Meter Filtered" 
      value_template: >
        {% set power_min = states('sensor.power_meter') | float%}
        {% set power_max = power_min+100 | float %}
        {% if (value_json.CounterReading > power_min | float) and (value_json.CounterReading < power_max | float) %}
          {{ value_json.CounterReading }}
        {% else %}
          {{power_min}}
        {% endif %}
      unit_of_measurement: "kWh"
      device_class: "energy"

I think…

Just use the filter sensor, no need for templates.

sensor:
- platform: filter
  name: filtered power meter
  entity_id: sensor.power_meter
  filters:
  - filter: range
    lower_bound: 1000
    upper_bound: 5000

You can apply other filters too if you want

In your suggestion would i not just use {{ value_json.CounterReading }} as the Minimal value. Then im back where i starded i think. Because if i get the invalid value from that reading, then “Power_Meter Filtered” vill also be wrong. or am i missing something?

Filters seems like a good choice. But i would like to set the filters to compare to previous reading, so that i could say that is needs to be higher than last reading, but not more than +100.
If i set i to static values i would need to change them in the sensor settings every time the meeter reaches that level.

There’s plenty of other filters

Seems like filters was the way to go.
I used the outlier filter, and it seems to work.
Thanks for the help

1 Like

Hi Nikolaj

How did you set it up to work?
I get format errors with:

  - sensor: 
    - platform: filter
      filters:
      - filter: range
        lower_bound: 0
        upper_bound: 10    
      name: "El MĂĽler stat" #the one that i use on the energy tab
      unit_of_measurement: kWh
      state: "{{ states('sensor.el_maler') }}"           
      attributes: 
        device_class: energy
        state_class: total_increasing  

You’re mixing template sensors and a filters. You can’t do that. You have to have a separate configuration for both and you’ll end up with 2 entities. A filtered entity and a template entity.