Skip to content

Instantly share code, notes, and snippets.

@byurhannurula
Created January 23, 2025 17:35
Show Gist options
  • Select an option

  • Save byurhannurula/f9a93957c03b93bb35a3f9e802cbdb5f to your computer and use it in GitHub Desktop.

Select an option

Save byurhannurula/f9a93957c03b93bb35a3f9e802cbdb5f to your computer and use it in GitHub Desktop.
ESPHome AQI calculation based on PM2.5
// https://en.wikipedia.org/wiki/Air_quality_index#Computing_the_AQI
// Borrowed from https://github.com/kylemanna/sniffer/blob/master/esphome/sniffer_common.yaml
sensor:
- platform: template
name: "PM 2.5 AQI"
id: pm2_aqi
update_interval: ${pms_update_interval}
unit_of_measurement: "AQI"
icon: "mdi:air-filter"
accuracy_decimals: 0
filters:
- skip_initial: 1 # Skip initial invalid data from PM2.5 sensor
lambda: |-
// AQI calculation based on PM2.5 concentration
if (id(pm2).state <= 12.0) {
// Good
return ((50.0 - 0.0) / (12.0 - 0.0) * (id(pm2).state - 0.0) + 0.0);
} else if (id(pm2).state <= 35.4) {
// Moderate
return ((100.0 - 51.0) / (35.4 - 12.1) * (id(pm2).state - 12.1) + 51.0);
} else if (id(pm2).state <= 55.4) {
// Unhealthy for Sensitive Groups
return ((150.0 - 101.0) / (55.4 - 35.5) * (id(pm2).state - 35.5) + 101.0);
} else if (id(pm2).state <= 150.4) {
// Unhealthy
return ((200.0 - 151.0) / (150.4 - 55.5) * (id(pm2).state - 55.5) + 151.0);
} else if (id(pm2).state <= 250.4) {
// Very Unhealthy
return ((300.0 - 201.0) / (250.4 - 150.5) * (id(pm2).state - 150.5) + 201.0);
} else if (id(pm2).state <= 350.4) {
// Hazardous
return ((400.0 - 301.0) / (350.4 - 250.5) * (id(pm2).state - 250.5) + 301.0);
} else if (id(pm2).state <= 500.4) {
// Hazardous Level 2
return ((500.0 - 401.0) / (500.4 - 350.5) * (id(pm2).state - 350.5) + 401.0);
} else {
return 500; // Max AQI value
}
text_sensor:
- platform: template
name: "PM2.5 AQI Label"
id: pm2_aqi_label
update_interval: ${pms_update_interval}
lambda: |-
// Categorize AQI into descriptive labels
if (id(pm2_aqi).state <= 50) {
return {"Good"};
} else if (id(pm2_aqi).state <= 100) {
return {"Moderate"};
} else if (id(pm2_aqi).state <= 150) {
return {"Unhealthy for Sensitive Groups"};
} else if (id(pm2_aqi).state <= 200) {
return {"Unhealthy"};
} else if (id(pm2_aqi).state <= 300) {
return {"Very Unhealthy"};
} else {
return {"Hazardous"};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment