Home Assistant模板传感器报错:'this'未定义,原因何在?
Home Assistant 可复用AQI计算模板问题及优化方案
问题背景
家中添置多台宜家Vindstyrka空气质量传感器后,需要在Home Assistant中实现可复用的AQI计算逻辑,核心需求是定义一个能传入单个变量的可复用函数。尝试用自引用+合并键的方式编写模板,但在模板编辑器中运行时返回错误:UndefinedError: 'this' is undefined,启动防护方案也不适用此场景。
原错误代码
# 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 }}"
问题原因
this变量仅在传感器实体运行时生效,模板编辑器调试阶段实体尚未创建,因此会报this未定义错误。此外,通过属性传递PM2.5值的方式不够直观,不利于调试。
优化方案:使用模板宏(Template Macro)
更优的实现方式是定义一个可接收PM2.5数值参数的宏,直接在每个传感器中调用宏完成计算,既解决调试问题,又提升代码复用性和可读性。
优化后的代码
# AQI Calculation 基于AirNow官方标准 - sensor: # 定义AQI计算宏 - name: "AQI Calculation Macro" unique_id: "aqi_calculation_macro" state: > {% macro calculate_aqi(pm_value) %} {% if pm_value <= 12.0 %} {% set low = 0.0 %}{% set high = 50.0 %}{% set lowpm = 0.0 %}{% set highpm = 12.0 %} {% elif pm_value <= 35.4 %} {% set low = 50.0 %}{% set high = 100.0 %}{% set lowpm = 12.1 %}{% set highpm = 35.4 %} {% elif pm_value <= 55.4 %} {% set low = 101.0 %}{% set high = 150.0 %}{% set lowpm = 35.5 %}{% set highpm = 55.4 %} {% elif pm_value <= 150.4 %} {% set low = 151.0 %}{% set high = 200.0 %}{% set lowpm = 55.5 %}{% set highpm = 150.4 %} {% elif pm_value <= 250.4 %} {% set low = 201.0 %}{% set high = 300.0 %}{% set lowpm = 150.5 %}{% set highpm = 250.4 %} {% elif pm_value <= 350.4 %} {% set low = 301.0 %}{% set high = 400.0 %}{% set lowpm = 250.5 %}{% set highpm = 350.4 %} {% elif pm_value <= 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_value - lowpm %} {{ ((conc * (i_diff / pm_diff)) + low) | round(0) if pm_diff != 0 else 0 }} {% endmacro %} # 宏实体无需实际状态,设置为隐藏 entity_category: diagnostic hidden: true # 各房间AQI传感器 - name: "Nursery AQI" unique_id: "sensor.nursery_aqi" unit_of_measurement: "aqi" icon: mdi:blur state: > {% from 'sensor.aqi_calculation_macro' import calculate_aqi %} {{ calculate_aqi(states('sensor.airlink_pm_2_5') | float) }} - name: "Family Room AQI" unique_id: "sensor.family_room_aqi" unit_of_measurement: "aqi" icon: mdi:blur state: > {% from 'sensor.aqi_calculation_macro' import calculate_aqi %} {{ calculate_aqi(states('sensor.ikea_of_sweden_vindstyrka_particulate_matter_2') | float) }} - name: "Living Room AQI" unique_id: "sensor.living_room_aqi" unit_of_measurement: "aqi" icon: mdi:blur state: > {% from 'sensor.aqi_calculation_macro' import calculate_aqi %} {{ calculate_aqi(states('sensor.ikea_of_sweden_vindstyrka_particulate_matter') | float) }} - name: "TEST Outdoor AQI" unique_id: "sensor.test_outdoor_aqi" unit_of_measurement: "aqi" icon: mdi:blur state: > {% from 'sensor.aqi_calculation_macro' import calculate_aqi %} {{ calculate_aqi(states('sensor.airnow_pm2_5') | float) }}
方案优势
- 调试友好:宏定义可单独在模板编辑器中测试,直接传入数值验证计算逻辑
- 复用性强:每个传感器只需一行代码调用宏,无需重复编写计算逻辑
- 逻辑清晰:PM2.5数据源直接传入宏参数,避免通过属性传递的间接性
- 容错处理:添加
pm_diff != 0判断,避免除以零的错误
替代方案:使用YAML锚点+变量传递
如果不想使用宏,可通过调整锚点结构,直接在每个传感器中传递PM2.5变量,避免使用this:
# AQI Calculation 基于AirNow官方标准 - sensor: - name: "Nursery AQI" unique_id: "sensor.nursery_aqi" unit_of_measurement: "aqi" icon: mdi:blur <<: &aqi_sensor state: > {% set pm = pm_value %} {% 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) if pm_diff != 0 else 0 }} variables: pm_value: "{{ states('sensor.airlink_pm_2_5') | float }}" - name: "Family Room AQI" unique_id: "sensor.family_room_aqi" <<: *aqi_sensor variables: pm_value: "{{ states('sensor.ikea_of_sweden_vindstyrka_particulate_matter_2') | float }}" - name: "Living Room AQI" unique_id: "sensor.living_room_aqi" <<: *aqi_sensor variables: pm_value: "{{ states('sensor.ikea_of_sweden_vindstyrka_particulate_matter') | float }}" - name: "TEST Outdoor AQI" unique_id: "sensor.test_outdoor_aqi" <<: *aqi_sensor variables: pm_value: "{{ states('sensor.airnow_pm2_5') | float }}"
此方案通过variables字段传递PM2.5数值,避免了this的使用,同样能实现代码复用,调试时可直接替换pm_value的数值测试逻辑。
内容的提问来源于stack exchange,提问作者USSJoin
相关产品推荐
相关产品推荐

