I was able to get this working with a couple of rest
sensors and several template
sensors to further parse them.
Step 1: Register for an API key at AirNow
Step 2: Use the query builder AirNow provides to construct the URL for your latitude, longitude and API key, and save it in secrets.yaml
eg:
airnow_current_url: http://www.airnowapi.org/aq/observation/latLong/current/?format=application/json&latitude=12.34567&longitude=-89.01234&distance=25&API_KEY=ABCDEF-12345-67890-GHIJKLM
Step 3: Use AirNow’s query builder to determine what kind of data is available to you. For my location, there were 2 reported measurements: PM2.5 and O3. Some coordinates I tried only had one, some may have more. Narrow in on what’s available to you, and if you don’t want to use all of it, decide on that. I decided to report both into HA as sensors for now.
Step 4: Create a rest sensor for each measurement you want to report in HA (I could not determine how to encapsulate the array of measurements in a single rest
sensor based on AirNow’s JSON format. If someone else does, let me know!)
- platform: rest
name: airnow_current_pm25
resource_template: !secret airnow_current_url
json_attributes_path: "$.[?(@.ParameterName=='PM2.5')]"
json_attributes:
- AQI
- Category
value_template: OK
- platform: rest
name: airnow_current_o3
resource_template: !secret airnow_current_url
json_attributes_path: "$.[?(@.ParameterName=='O3')]"
json_attributes:
- AQI
- Category
value_template: OK
Step 5: Use template
sensors to further extract the data:
- platform: template
sensors:
airnow_current_pm25_category:
unique_id: sensor.airnow_pm25_category
friendly_name: AirNow PM2.5 Category
value_template: "{{ state_attr('sensor.airnow_current_pm25', 'Category')['Name'] }}"
airnow_current_pm25_observed:
unique_id: sensor.airnow_pm25_aqi
friendly_name: AirNow PM2.5 Observation
value_template: "{{ state_attr('sensor.airnow_current_pm25', 'AQI') }}"
airnow_current_ow_category:
unique_id: sensor.airnow_o3_category
friendly_name: AirNow Ozone Category
value_template: "{{ state_attr('sensor.airnow_current_o3', 'Category')['Name'] }}"
airnow_current_o3_observed:
unique_id: sensor.airnow_o3_aqi
friendly_name: AirNow Ozone Observation
value_template: "{{ state_attr('sensor.airnow_current_o3', 'AQI') }}"
I surface the resulting AQI numbers in Lovelace with the dual-gauge-card custom card, with color codes based on data from aqicn.org
:
type: 'custom:dual-gauge-card'
title: Air Quality
min: 0
max: 400
inner:
entity: sensor.airnow_current_o3_observed
label: Ozone
outer:
entity: sensor.airnow_current_pm25_observed
label: PM2.5
colors:
- color: '#8B0000'
value: 301
- color: var(--label-badge-purple)
value: 201
- color: var(--label-badge-red)
value: 151
- color: '#CF5300'
value: 101
- color: var(--label-badge-yellow)
value: 51
- color: var(--label-badge-green)
value: 0
Note that the likely reason that AirNow and your weather app agree is that your weather app is sourcing AQI from AirNow.