Automating Ventilation based on AQ sensor

I have an AirGradient AQ sensor that has entities for CO2 and PM2.5 those values show up in states as numbers like ‘439’ and ‘0’ respectively. I tried to make an automation to trigger different fan speeds based on these numbers. But when I do a “test” of conditions they are always not met regardless of the numbers associated with the sensors. I really am at a loss as to why this isn’t working the way I expect. Here’s my YAML:

alias: Basement Ventilation by AQ
description: ""
triggers:
  - trigger: numeric_state
    entity_id:
      - sensor.i_9psl_carbon_dioxide
    above: 1000
    id: High_CO2
  - trigger: numeric_state
    entity_id:
      - sensor.i_9psl_pm2_5
    id: High_PM2.5
    above: 60
  - trigger: numeric_state
    entity_id:
      - sensor.i_9psl_carbon_dioxide
    above: 700
    id: Mid_CO2
    below: 1000
  - trigger: numeric_state
    entity_id:
      - sensor.i_9psl_pm2_5
    id: Mid_PM2.5
    above: 10
    below: 60
  - trigger: numeric_state
    entity_id:
      - sensor.i_9psl_carbon_dioxide
    id: Normal_CO2
    below: 500
  - trigger: numeric_state
    entity_id:
      - sensor.i_9psl_pm2_5
    id: Normal_PM2.5
    below: 10
conditions: []
actions:
  - choose:
      - conditions:
          - condition: trigger
            id:
              - High_CO2
              - High_PM2.5
        sequence:
          - action: climate.set_fan_mode
            metadata: {}
            data:
              fan_mode: circulate
            target:
              entity_id: climate.dreamwoodhvac_zone_1
          - action: fan.set_percentage
            metadata: {}
            data:
              percentage: 100
            target:
              entity_id: fan.air_circulator
          - action: fan.turn_on
            metadata: {}
            data: {}
            target:
              entity_id: fan.breakfast_kitchen_fan
      - conditions:
          - condition: trigger
            id:
              - Mid_CO2
              - Mid_PM2.5
        sequence:
          - action: climate.set_fan_mode
            metadata: {}
            data:
              fan_mode: circulate
            target:
              entity_id: climate.dreamwoodhvac_zone_1
          - action: fan.set_percentage
            metadata: {}
            data:
              percentage: 60
            target:
              entity_id: fan.air_circulator
          - action: fan.turn_off
            metadata: {}
            data: {}
            target:
              entity_id: fan.zcooking_kitchen_fan_switch
      - conditions:
          - condition: trigger
            id:
              - Normal_CO2
          - condition: trigger
            id:
              - Normal_PM2.5
        sequence:
          - action: climate.set_fan_mode
            metadata: {}
            data:
              fan_mode: auto
            target:
              entity_id: climate.dreamwoodhvac_zone_1
          - action: fan.set_percentage
            metadata: {}
            data:
              percentage: 40
            target:
              entity_id: fan.air_circulator
          - action: fan.turn_off
            metadata: {}
            data: {}
            target:
              entity_id: fan.zcooking_kitchen_fan_switch
mode: single

How did you perform the “test”?

In the automation, I click on the Three Dots on the condition and choose the option “Test” from the dropdown. This is a way I would test a condition in a lighting automation, or whatever. In this AQ/fan automation it always returns an orange “Condition did not pass” banner, even when (as far as I can tell) the conditions are met.

That test is inconclusive because it’s attempting to test a Trigger Condition.

A Trigger Condition only works after the automation has been triggered because the trigger id value is created only when triggered. If there’s no trigger, id has no value.

tl;dr
You can’t use that Test feature for a Trigger Condition.


The only way to properly test your automation is to wait until one of its six triggers is triggered. Then you can examine the automation’s trace to see how it processed each step.

If you don’t want to wait for a sensor’s value to change and cause triggering, you can manually “force” the sensor’s value to be whatever you want. I described the procedure to another user in this post:

1 Like

Ok…I think I understand. The conditions don’t check to see if a value is true, they just get triggered when a value changes.

So if I go breathe on the sensor for minute the CO2 will raise above a threshold vale, triggering the condition and the fans will kick on/up. Then as CO2 levels drop it will trigger the option that turns the fans back down.

Is there a way to make it test? My trouble here is in the returning to normal portion because I want both CO2 and PM2.5 to be low so that trigger has an AND instead of an OR. But if CO2 only went up and triggered higher fan speeds when CO2 comes down it won’t trigger lowering the speed because PM2.5 stayed zero all along.

Even if the fans don’t come on, you should be able to see in the traces if the ‘choose conditions’ were evaluated as true or false.
Keep in mind that the trigger values need to pass the threshold - if they are above it already nothing will happen,

1 Like

You can set fake values for sensors in states tab of the developer tools.

You can manually set (“force”) the sensor values to whatever you want as described in the link I shared in my previous post.

The sensor values you set manually are temporary and will be (eventually) overwritten by the sensor’s integration. How quickly it’s overwritten depends on how frequently the integration updates the sensor.

Manually changing a sensor’s value is the easiest way to test a trigger (easier than breathing on a CO2 sensor or warming a temperature sensor, etc).

Triggers are never ANDed, they’re always ORed. You cannot AND triggers.

This means the trigger id can be Mid_CO2 or Mid_PM2.5.

- condition: trigger
   id:
     - Mid_CO2
     - Mid_PM2.5

I think in order for the last set of ids to work you need to add some numeric conditions as well:

actions:
  - choose:
      - conditions:
.
.
.
          - condition: trigger
            id:
              - Normal_CO2
              - Normal_PM2.5
          - condition: numeric_state
            entity_id: sensor.i_9psl_carbon_dioxide
            below: 500
          - condition: numeric_state
            entity_id: sensor.i_9psl_pm2_5
            below: 10

As the conditions are evaluated as AND this will check, if both values - CO2 and PM2.5 - are in the normal range before it moves on to execute the sequence.
If only one of them is, it will ‘wait’ until it’s triggered again by the other one.

1 Like

You can safely eliminate the Trigger Condition.

actions:
  - choose:
      - conditions:
          - condition: numeric_state
            entity_id: sensor.i_9psl_carbon_dioxide
            above: 1000
          - condition: numeric_state
            entity_id: sensor.i_9psl_pm2_5
            above: 60
        sequence:
          ... actions ...
      - conditions:
          - condition: template 
            value_template: "{{ 700 <= states('sensor.i_9psl_carbon_dioxide') | int(0) < 1000 }}"
          - condition: template 
            value_template: "{{ 10 <= states('sensor.i_9psl_pm2_5') | int(0) < 60 }}"
        sequence:
          ... actions ...
      - conditions:
          - condition: numeric_state
            entity_id: sensor.i_9psl_carbon_dioxide
            below: 700
          - condition: numeric_state
            entity_id: sensor.i_9psl_pm2_5
            below: 10
        sequence:
          ... actions ...

It can also be reduced to this:

actions:
  - variables:
      co2: "{{ states('sensor.i_9psl_carbon_dioxide') | int(0) }}"
      pm25: "{{ states('sensor.i_9psl_pm2_5') | int(0) }}"
  - choose:
      - conditions: "{{ co2 > 1000 and pm25 > 60 }}"
        sequence:
          ... actions ...
      - conditions: "{{ 700 <= co2 < 1000 and 10 <= pm25 < 60 }}"
        sequence:
          ... actions ...
      - conditions: "{{ co2 < 700 and pm25 < 10 }}"
        sequence:
          ... actions ...
1 Like

This was excellent. Thank you. So for the first two conditions I did change it to “or” from “and”

So now, when either CO2 or PM2.5 rise above certain thresholds the fans turn up by degrees. And when both come down, then fans turn down.

Thank you so much for your help!

1 Like