esphome / issues

Issue Tracker for ESPHome
https://esphome.io/
290 stars 34 forks source link

Integration for a Template Sensor #2793

Open mc0110 opened 2 years ago

mc0110 commented 2 years ago

The problem

I need the integral of the power (V*A). The values for voltage and current are measured as ADC values and then the product is provided as a template sensor. Unfortunately, the platform integration does not work with a template sensor as described in the instructions. I have no idea how to map the integral.

Which version of ESPHome has the issue?

2021.11.4

What type of installation are you using?

pip

Which version of Home Assistant has the issue?

2021.11.4

What platform are you using?

ESP32

Board

lolin32

Component causing the issue

integration

Example YAML snippet

- platform: adc
    pin: GPIO32
    id: v32
    name: "Spannung Pin32"
    internal: true
    unit_of_measurement: "V"    
    accuracy_decimals: 3
    attenuation: auto
    update_interval: 1ms
    filters:
      - sliding_window_moving_average:
          window_size: 800
          send_every: 500

  - platform: adc
    pin: GPIO33
    id: v33
    name: "Spannung Pin33"
    internal: true
    unit_of_measurement: "V"    
    accuracy_decimals: 3
    attenuation: auto
    update_interval: 1ms
    filters:
      - sliding_window_moving_average:
          window_size: 800
          send_every: 500

  - platform: adc
    pin: GPIO36
    id: v36
    name: "Batteriespannung"
    unit_of_measurement: "V"    
    accuracy_decimals: 3
    attenuation: auto
    update_interval: 5ms
    filters:
      - sliding_window_moving_average:
          window_size: 800
          send_every: 500
      - multiply: 4.85899
      - offset: -0.295

  - platform: adc
    pin: GPIO34
    id: v34
    name: "Spannung Pin34"
    internal: true
    unit_of_measurement: "V"    
    accuracy_decimals: 3
    attenuation: auto
    update_interval: 1ms
    filters:
      - sliding_window_moving_average:
          window_size: 800
          send_every: 500

  - platform: adc
    pin: GPIO35
    id: v35
    name: "Spannung Pin35"
    internal: true
    unit_of_measurement: "V"    
    accuracy_decimals: 3
    attenuation: auto
    update_interval: 1ms
    filters:
      - sliding_window_moving_average:
          window_size: 800
          send_every: 500

  - platform: template
    id: a1
    name: "Strom 34-32"
    unit_of_measurement: "A"    
    accuracy_decimals: 3
    lambda: |-
      if (1 == 1)  
       {return (id(v35).state - id(v33).state);} else {return 0.0;};
    filters:
      - offset: 0.003
      - multiply: 362.2767545
    update_interval: 1s

  - platform: template
    id: a2
    name: "Strom 35-33"
    unit_of_measurement: "A"    
    accuracy_decimals: 3
    lambda: |-
      if (1 == 1)  
       {return (id(v35).state - id(v33).state);} else {return 0.0;};
    filters:
      - offset: 0.003
      - multiply: 362.11495
    update_interval: 1s

  - platform: template
    id: a
    name: "Strom"
    unit_of_measurement: "A"    
    accuracy_decimals: 3
    lambda: |-
       {return (id(a1).state + id(a2).state);};
    update_interval: 1s

  - platform: integration
    id: e
    name: "Total"
    sensor: p
    time_unit: s
    unit_of_measurement: "Ws"    
    accuracy_decimals: 3

  - platform: template
    id: p
    name: "Leistung"
    unit_of_measurement: "W"    
    accuracy_decimals: 3
    lambda: |-
       {return (id(a).state * id(v36).state);}; 
    update_interval: 1s

Anything in the logs that might be useful for us?

No response

Additional information

No response

oxan commented 2 years ago

Unfortunately, the platform integration does not work with a template sensor as described in the instructions.

Why do you think that?

mc0110 commented 2 years ago

grafik

mc0110 commented 2 years ago

First of all, don't get me wrong. ESPHOME is a great project. But I don't see any values from integration.

probot-esphome[bot] commented 2 years ago

Hey there @ottowinter, mind taking a look at this issue as it has been labeled with an integration (integration) you are listed as a code owner for? Thanks! (message by CodeOwnersMention)

oxan commented 2 years ago

The problem is that your template sensors are updated before the ADC is set-up. This causes the state of the ADC sensors to be NaN, which in turn propagates through to your template sensor, and that poisons the integration sensor (it'll only return NaN from then on). We should probably fix that the integration sensor gets poisioned when it receives a NaN, though I'm not sure what the best behaviour in that case is.

You can fix it in your case either by reseting the integration sensor after everything is initialized (using the sensor.integration.reset action), or by fixing your lambdas so they don't return NaN:

    lambda: |-
       auto val = id(a).state * id(v36).state;
       if (isnan(val))
          return {};
       return val;
mc0110 commented 2 years ago

Oh guys! I spent many hours yesterday trying to fix the problem. I also suspected it was due to undefined states, but I don't have any experience with bug fixing in esphome time schemes. You solved my problem, but I understand that it is not so easy to solve universally. Thanks a lot!!

syp1975 commented 2 years ago

Hi. I might have a similar issue with the integration component, but originated from a tuya power sensor. With this configuration, after boot, integration state remains nan until a reset action is called:

sensor:
- platform: tuya
  sensor_datapoint: 19
  id: power
  name: "Power"
  filters:
  - filter_out: nan
  - multiply: 0.1
- platform: integration
  sensor: power
  time_unit: h
  restore: true
  min_save_interval: 10min
  id: energy
  name: "Energy"

I suspected that the first time the integration sensor updates, the tuya sensor still has not been updated and its state is nan, and this poisons the integration sensor, so I tried this:

- platform: tuya
  sensor_datapoint: 19
  id: tuya_power
  name: "Power Internal"
  internal: true
  filters:
  - filter_out: nan
  - multiply: 0.1
  - throttle_average: 10s
  #do not poison power sensor, because it is used for energy integration
  on_value:
    then:
    - lambda: "if(!isnan(x)) id(power).publish_state(x);"         
- platform: "template"
  id: power
  name: "Power"
  filters:
  - filter_out: nan

Perhaps there is a more elegant solution w/o needing a template sensor, but this one worked for me.

To fix the issue, is it possible to just ignore all nan states of the source sensor when the integration component is updated, as if no update has ocurred?