Air Quality to RGB Light in Home Assistant

I wanted to show the AQI scale as a color in a continuous spectrum between the points. I based the color points off the colors shown on the AirNow site, but it could be customized. This will start at green when AQI is 0, and gradually become more yellow as it increases until it becomes fully yellow when the  AQI is 50, and so on.

The actual calculation could likely be optimized, but I broke it into multiple lines to make it easier to read. 

To use this, you’ll need to enable python scripts and place aqi2rgb.py in the appropriate directory, and add the automations (changing the entity names as needed). I have it set up to control an RGB LED on an ESP32, but in theory any RGB light would work.

First, the python script that converts the raw AQI to RGB values (aqi2rgb.py):

#!/usr/bin/env python3

# Author: Benjamin Loomis <ben@catsheavyindustries.com>
# Date: 2020-06-05
# This script is in the public domain.

raw_aqi = data.get("aqi","world")
aqi=int(raw_aqi)

# defaults to white 
r=255
g=255
b=255

# 0:    (0, 255, 0)
# 51:   (255, 255, 0)
# 101:  (255, 127, 0)
# 151:  (255, 0, 0)
# 201:  (255, 0, 255)
# 301+: (127, 0, 32)

if (50 >= aqi):
    r=0
    g=255
    b=0
    # "Good"
    adj_aqi = aqi - 0                   # subtract the previous ranges
    aqi_range = 50                      # range of this section
    distance = (aqi_range - adj_aqi)    # distance to next point
    mul = 1 - (distance / aqi_range)    # Percentage of next point
    r = mul * 255
elif (100 >= aqi):
    r=255
    g=255
    b=0
    adj_aqi = aqi - 50                  # subtract the previous ranges
    aqi_range = 50                      # range of this section
    distance = (aqi_range - adj_aqi)    # distance to next point
    mul = 1 - (distance / aqi_range)    # Percentage of next point
    g = g - (128 * mul)
elif (150 >= aqi):
    r=255
    g=127
    b=0
    adj_aqi = aqi - 100                 # subtract the previous ranges
    aqi_range = 50                      # range of this section
    distance = (aqi_range - adj_aqi)    # distance to next point
    mul = 1 - (distance / aqi_range)    # Percentage of next point
    g = g - (127 * mul)
elif (200 >= aqi):
    r=255
    g=0
    b=0
    adj_aqi = aqi - 150                 # subtract the previous ranges
    aqi_range = 50                      # range of this section
    distance = (aqi_range - adj_aqi)    # distance to next point
    mul = 1 - (distance / aqi_range)    # Percentage of next point
    b = (255 * mul)
elif (300 >= aqi):
    r=255
    g=0
    b=255
    adj_aqi = aqi - 200                 # subtract the previous ranges
    aqi_range = 100                     # range of this section
    distance = (aqi_range - adj_aqi)    # distance to next point
    mul = 1 - (distance / aqi_range)    # Percentage of next point
    r = r - (127 * mul)
    b = b - (223 * mul)
else:
    r = 127
    g = 0
    b = 32


r = int(r)
g = int(g)
b = int(b)

hass.bus.fire("aqi_color", {"r": r, "g" : g, "b" : b })

Next, the trigger to launch the script when the AQI changes:

- id: 'aqi_trigger'
  alias: AQI Trigger
  description: ''
  trigger:
  - above: '0'
    below: '999'
    entity_id: sensor.waqi_san_jose_jackson_st_santa_clara_california
    platform: numeric_state
  condition: []
  action:
  - data_template:
      aqi: '{{ states("sensor.waqi_san_jose_jackson_st_santa_clara_california") }}'
    service: python_script.aqi2rgb

Finally, the trigger to catch the script output and change the color of the light:

- id: 'aqi_set_color'
  alias: AQI color
  description: ''
  trigger:
  - event_type: aqi_color
    platform: event
  condition: []
  action:
  - data_template:
      rgb_color:
      - '{{ trigger.event.data.r }}'
      - '{{ trigger.event.data.g }}'
      - '{{ trigger.event.data.b }}'
    entity_id: light.teststring_1
    service: light.turn_on