Why is "this" undefined in a sensor template?

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 VINDSTYRKA).

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.

I’m somewhat at my wits’ end. Any assistance would be extremely gratefully appreciated!

# 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 }}"

Is it? You say:

…which is expected. It’s never going to work in the template editor, as there is no state object involved in there…

Confirm your template works by substituting in the object that this represents in the editor, then create the template sensor with this included. Does it work?

The Template Editor is meant for testing Jinja templates and nothing else.

The example you posted contains YAML and Jinja. The template editor doesn’t evaluate YAML and simply handles it like text. Therefore it has no idea that what you have there is the configuration for several Template Sensors. It will evaluate only what looks like a Jinja template, therefore it doesn’t understand you have used YAML, let alone the YAML Anchors and Aliases, or that the YAML represents the configuration for Template Sensors.

Because it doesn’t evaluate YAML, it doesn’t create Template Sensors from your configuration. Without actually creating a Template Sensor entity, the this object is undefined. Without an entity, there’s no “this” to reference.

In addition, the this object references the entity’s existing property values (not any values currently being computed).