Interdependant sensors template

Hi all,

is there a way to avoid an infinite loop for sensors’ template which are interdependant? Like define a temporary variable or some workaround, not a big issue if the results are not 100% accurate.

My understanding is sensors are not calculated based on the position in the yaml file, so it’s a declarative language, so it happens I have A and B sensors I want to calibrate.

I would normally do:
ValueA = A + 0.5 * ValueB
ValueB = B - 0.1 * ValueA

I am OK if ValueA is not recalculated using new ValueB value, but my guess is an infinite loop happens.

Here is my code:

sensor:
  - platform: statistics
    name: "Average 1h H2S"
    entity_id: sensor.airq_compensated_calibrated_h2s
    state_characteristic: mean
    max_age:
      minutes: 60
    sampling_size: 60  
    
  - platform: statistics
    name: "Average 1h NO2"
    entity_id: sensor.airq_compensated_calibrated_no2
    state_characteristic: mean
    max_age:
      minutes: 60
    sampling_size: 60  
    
  - platform: statistics
    name: "Average 1h O3"
    entity_id: sensor.airq_compensated_calibrated_o3
    state_characteristic: mean
    max_age:
      minutes: 60
    sampling_size: 60  

template:
  - sensor:
    - name: "AirQ Compensated Calibrated NO2"
      unit_of_measurement: "µg/m³"
      state: "{{ 0.7 * states('sensor.airq_no2') | float - 0.15 * states('sensor.airq_compensated_calibrated_o3') | float - 0.85 * states('sensor.airq_temperature') | float + 0.05 * states('sensor.airq_humidity') | float  }}"

  - sensor:
    - name: "AirQ Compensated Calibrated H2S"
      unit_of_measurement: "µg/m³"
      state: "{{ states('sensor.airq_h2s') | float - 0.04 * (20 - states('sensor.airq_temperature') | float) + 0.18 * states('sensor.airq_compensated_calibrated_o3') | float + 0.2 * states('sensor.airq_compensated_calibrated_no2') | float }}"

  - sensor:
    - name: "AirQ Compensated Calibrated O3"
      unit_of_measurement: "µg/m³"
      state: "{{states('sensor.airq_ozone') | float / 1.8 - 0.5 * states('sensor.airq_compensated_calibrated_no2') | float  + 0.5 * states('sensor.airq_compensated_calibrated_h2s') | float }}"

You could use triggered template sensors that only updates on the change of one of the sensors, or a fixed time interval (time pattern trigger).

1 Like

Thanks for your reply, I like the idea!

Let me try it :slight_smile:
Cheers

hmmm I got errors from “unknown” value

My conf

  - trigger:
      - platform: time_pattern
        minutes: "/1"
        seconds: "1"   
    sensor:
    - name: "AirQ Compensated Calibrated NO2"
      unit_of_measurement: "µg/m³"
      state: "{{ 0.7 * states('sensor.airq_no2') | float - 0.15 * states('sensor.airq_compensated_calibrated_o3') | float - 0.85 * states('sensor.airq_temperature') | float + 0.05 * states('sensor.airq_humidity') | float  }}"

  - trigger:
      - platform: time_pattern
        minutes: "/1"
        seconds: "5"   
    sensor:
    - name: "AirQ Compensated Calibrated H2S"
      unit_of_measurement: "µg/m³"
      state: "{{ states('sensor.airq_h2s') | float - 0.04 * (20 - states('sensor.airq_temperature') | float) + 0.18 * states('sensor.airq_compensated_calibrated_o3') | float + 0.2 * states('sensor.airq_compensated_calibrated_no2') | float }}"

  - trigger:
      - platform: time_pattern
        minutes: "/1"
        seconds: "10"   
    sensor:
    - name: "AirQ Compensated Calibrated O3"
      unit_of_measurement: "µg/m³"
      state: "{{states('sensor.airq_ozone') | float / 1.8 - 0.5 * states('sensor.airq_compensated_calibrated_no2') | float  + 0.5 * states('sensor.airq_compensated_calibrated_h2s') | float }}"

Logger: homeassistant.components.template.sensor
Source: components/template/trigger_entity.py:190
Integration: Template (documentation, issues)
First occurred: 17:43:01 (3 occurrences)
Last logged: 17:43:10

  • Error rendering state template for sensor.airq_compensated_calibrated_no2: ValueError: Template error: float got invalid input ‘unknown’ when rendering template ‘{{ 0.7 * states(‘sensor.airq_no2’) | float - 0.15 * states(‘sensor.airq_compensated_calibrated_o3’) | float - 0.85 * states(‘sensor.airq_temperature’) | float + 0.05 * states(‘sensor.airq_humidity’) | float }}’ but no default was specified
  • Error rendering state template for sensor.airq_compensated_calibrated_h2s: ValueError: Template error: float got invalid input ‘unknown’ when rendering template ‘{{ states(‘sensor.airq_h2s’) | float - 0.04 * (20 - states(‘sensor.airq_temperature’) | float) + 0.18 * states(‘sensor.airq_compensated_calibrated_o3’) | float + 0.2 * states(‘sensor.airq_compensated_calibrated_no2’) | float }}’ but no default was specified
  • Error rendering state template for sensor.airq_compensated_calibrated_o3: ValueError: Template error: float got invalid input ‘unavailable’ when rendering template ‘{{states(‘sensor.airq_ozone’) | float / 1.8 - 0.5 * states(‘sensor.airq_compensated_calibrated_no2’) | float + 0.5 * states(‘sensor.airq_compensated_calibrated_h2s’) | float }}’ but no default was specified

I could find how to specify a default, just for the first value, but I fear those sensors/variable/whatever have a different scope?

|float(default value here)

e.g.

|float(42)

yup, thanks, I found it and already tried, works like a charm

Thanks a lot!

The first sensor employs the value of the third sensor. However, you just configured these three sensors so none have values yet and are all unknown.

While attempting to get the third sensor’s value, thefloat filter failed to convert unknown to a number. You didn’t supply the float filter with a default value, so the template failed with an error (i.e. the error you posted above).

If you provide a default, it will prevent the error message but the initial calculation will produce a result based on the default value (and not the third sensor’s actual value because it hasn’t triggered yet). After all three sensors have triggered at least once, then the computed results should be accurate.

1 Like