Adding PM2.5-based Indoor AQI to Home Assistant

Add indoor AQI to your Home Assistant instance with an existing PM2.5 sensor.

Adding PM2.5-based Indoor AQI to Home Assistant

I recently moved to the PNW, which, if you weren't aware, was very recently On Fire Very Badly. Seattle actually had the worst air quality in the entire world (out of all the major cities) at one point.

I was constantly monitoring the AQI through AirNow and added its sensor to my Home Assistant dashboard, but I really wanted something to compare it to for my indoor AQI. I was expecting to throw the value from my PM2.5 sensor into a simple formula and get the AQI out, but it turns out that this is not a very straightforward thing to calculate because of how air quality was studied in the past and how the air quality index metric was developed.

AQI is actually a 24-hour index that is intended to be reported daily. There are efforts to make this more relevant and real-time (for example, the NowCast AQI which takes into account the last 12 hours of data, and weights the later data more heavily—this is what AirNow reports), but I thought it would be easiest to implement the standard AQI.

I did some googling around and it seems this is not a very common thing that people do for whatever reason, so I'm detailing the easiest way to implement an indoor AQI sensor in this post so you don't need to go through the trouble that I did.

Prerequisites

  • A PM2.5 sensor
  • Home Assistant

TL;DR

You will need a sensor for the 24-hour PM2.5 average, and another sensor which uses that average and throws it into the appropriate AQI formula for PM2.5. It will look something like this:

sensor:
  - platform: statistics
    unique_id: pm25_24hr_avg
    name: "PM2.5 24-hour Average"
    # REPLACE the below entity ID with your PM2.5 sensor
    entity_id: sensor.living_room_pm_2_5um_concentration
    state_characteristic: mean
    sampling_size: 15000
    max_age:
      hours: 24

template:
  - sensor:
      - name: "Indoor AQI"
        unique_id: indoor_aqi
        state_class: measurement
        device_class: aqi
        unit_of_measurement: AQI
        state: >
          {% macro aqi(val, val_l, val_h, aqi_l, aqi_h) -%}
            {{(((aqi_h-aqi_l)/(val_h - val_l) * (val - val_l)) + aqi_l)|round(0)}}
          {%- endmacro %}
          {% set v = states('sensor.pm2_5_24_hour_average')|round(1) %}
          {% if v <= 12.0 %}
            {{aqi(v, 0, 12.0, 0, 50)}}
          {% elif 12.0 < v <= 35.4 %}
            {{aqi(v, 12.1, 35.4, 51, 100)}}
          {% elif 35.4 < v <= 55.4 %}
            {{aqi(v, 35.5, 55.4, 101, 150)}}
          {% elif 55.4 < v <= 150.5 %}
            {{aqi(v, 55.5, 150.4, 151, 200)}}
          {% elif 150.4 < v <= 250.4 %}
            {{aqi(v, 150.4, 250.4, 201, 300)}}
          {% elif 250.5 < v <= 500.4 %}
            {{aqi(v, 250.5, 500.4, 301, 500)}}
          {% else %}
            500
          {% endif %}

Tweak it to your liking and use it where you please. You may tweak the average window from 24 hours to something else to get a more responsive result, but then the AQI is technically not correct. But as long as you're aware of that, that's all that matters.

You could also try to implement the NowCast AQI, but that seems significantly more complicated to do within Home Assistant. You can find details on NowCast here.

I hope this helped!