yamljinja2home-assistant

Home Assistant Template Sensor: "this" is undefined -- why?


I'm trying to use self-referencing templates in Home Assistant, because I want to make a reusable way to add an AQI calculation to every air sensor I have in my house (which have recently multiplied since IKEA made one that integrates really well with HA).

All I really want is to allow code reuse (really, just define a function to which I can pass a single variable), but self-referencing plus merge keys are the only way I've found to do that. If there's some way better method for doing this, I'm all ears.

I have the following template, but when I enter it in the template editor, it returns UndefinedError: 'this' is undefined. I've read about the need to guard for startup issues but that doesn't seem to apply.

# AQI Calculation from https://www.airnow.gov/sites/default/files/2020-05/aqi-technical-assistance-document-sept2018.pdf p14
- sensor:
  - name: "Nursery AQI"
    unique_id: "sensor.nursery_aqi"
    attributes:
      particulates: "{{ states('sensor.airlink_pm_2_5') | float }}"
    <<: &aqi_from_pm25
      unit_of_measurement: "aqi"
      icon: mdi:blur
      state: >
        {% set pm = this.attributes.particulates %}
        {% if pm <= 12.0 %}
          {% set low = 0.0 %}
          {% set high = 50.0 %}
          {% set lowpm = 0.0 %}
          {% set highpm = 12.0 %}
        {% elif pm <= 35.4 %}
          {% set low = 50.0 %}
          {% set high = 100.0 %}
          {% set lowpm = 12.1 %}
          {% set highpm = 35.4 %}
        {% elif pm <= 55.4 %}
          {% set low = 101.0 %}
          {% set high = 150.0 %}
          {% set lowpm = 35.5 %}
          {% set highpm = 55.4 %}
        {% elif pm <= 150.4 %}
          {% set low = 151.0 %}
          {% set high = 200.0 %}
          {% set lowpm = 55.5 %}
          {% set highpm = 150.4 %}
        {% elif pm <= 250.4 %}
          {% set low = 201.0 %}
          {% set high = 300.0 %}
          {% set lowpm = 150.5 %}
          {% set highpm = 250.4 %}
        {% elif pm <= 350.4  %}
          {% set low = 301.0 %}
          {% set high = 400.0 %}
          {% set lowpm = 250.5 %}
          {% set highpm = 350.4 %}
        {% elif pm <= 500.4 %}
          {% set low = 401.0 %}
          {% set high = 500.0 %}
          {% set lowpm = 350.5 %}
          {% set highpm = 500.4 %}
        {% else %}
          {% set low = 501.0 %}
          {% set high = 502.0 %}
          {% set lowpm = 500.5 %}
          {% set highpm = 15000.0 %}
        {% endif %}
        {% set i_diff = high-low %}
        {% set pm_diff = highpm-lowpm %}
        {% set conc = pm-lowpm %}
        {{ ((conc * ((i_diff) / pm_diff)) + low) | round(0) }}
  - name: "Family Room AQI"
    unique_id: "sensor.family_room_aqi"
    <<: *aqi_from_pm25
    attributes:
      particulates: "{{ states('sensor.ikea_of_sweden_vindstyrka_particulate_matter_2') | float }}"
  - name: "Living Room AQI"
    unique_id: "sensor.living_room_aqi"
    <<: *aqi_from_pm25
    attributes:
      particulates: "{{ states('sensor.ikea_of_sweden_vindstyrka_particulate_matter') | float }}"
  - name: "TEST Outdoor AQI"
    unique_id: "sensor.test_outdoor_aqi"
    <<: *aqi_from_pm25
    attributes:
      particulates: "{{ states('sensor.airnow_pm2_5') | float }}"


Solution

  • The answer (for anyone looking in the future) was that this was a guard issue. Here's the key line to fix:

    {% set pm = ((this.attributes.particulates| default(-1, false)) | float) %}
    

    Adding the guard here made me decide to add the float conversion here as well, so I dropped |float from the attributes.particulates line.