Help! Air purifier automation based on air quality value

Hey everybody!

I’m new here, so please be gentle! :blush:

I’m working on an automation to turn on my Dyson Air Purifier when the air quality falls below a certain threshold. To avoid checking each air quality sensor on my purifier (PM2.5, PM10, VOC, NO2, HCHO), I’ve created a helper that combines all of them into a single AQI sensor with five states, ranging from Excellent to Very Bad.

Here are the snippets for both:

Combining sensors:

{% set hcho = states('sensor.dyson_purifier_hcho') | float %}
{% set no2 = states('sensor.dyson_purifier_nitrogen_dioxide_index') | float %}
{% set pm10 = states('sensor.dyson_purifier_pm_10') | float %}
{% set pm25 = states('sensor.dyson_purifier_pm_2_5') | float %}
{% set voc = states('sensor.dyson_purifier_volatile_organic_compounds_index') | float %}
{% set air_quality = (hcho + no2 + pm10 + pm25 + voc) / 5 %}
{{ air_quality }}

And breaking the single index into 5 states:

{% set aqi = states('sensor.combined_air_quality_index') | float %}
{% if aqi <= 20 %}
  Excellent
{% elif aqi <= 40 %}
  Good
{% elif aqi <= 60 %}
  Moderate
{% elif aqi <= 80 %}
  Bad
{% else %}
  Very bad
{% endif %}

After that I’ve created an automation:

alias: Clean up air
description: ""
triggers:
  - triggers:
      - entity_id: sensor.air_quality_level
        to: Moderate
        trigger: state
      - entity_id: sensor.air_quality_level
        to: Bad
        trigger: state
      - entity_id: sensor.air_quality_level
        to: Very bad
        trigger: state
conditions:
  - condition: or
    conditions:
      - condition: state
        entity_id: sensor.air_quality_level
        state: Moderate
      - condition: state
        entity_id: sensor.air_quality_level
        state: Bad
      - condition: state
        entity_id: sensor.air_quality_level
        state: Very bad
actions:
  - type: turn_on
    device_id: MY DEVICE ID
    entity_id: MY ENTITY ID
    domain: fan
mode: single

But when I try to run an action, even though the created sensor indicates the quality as ‘Excellent’, the air purifier still starts, even though it shouldn’t meet the condition.

Please, help me find out the reason :face_exhaling:

If by “run an action” you mean selecting Run actions from the … menu, that would always bypass your separately declared conditions and go directly to the actions. Those conditions only apply to the triggers.

1 Like

Yes, that’s exactly what I meant. Really? I didn’t realize that. I thought it would launch the full sequence, allowing to check if the conditional logic works as well, not just trigger the final action.

I really appreciate your quick response, @Mayhem_SWE. I would have spent hours trying to figure out what the heck with my automation and sensors :face_exhaling:

FWIW, for this particular application, there is no benefit to adding conditions that confirm what the triggers do.

It’s like triggering only when a door opens and then using a condition to confirm the door is open. Of course it’s open, the trigger already established that fact.

alias: Clean up air
description: ""
triggers:
  - trigger: state
    entity_id: sensor.air_quality_level
    to:
      - Moderate
      - Bad
      - Very bad
conditions: []
actions:
  - type: turn_on
    device_id: MY DEVICE ID
    entity_id: MY ENTITY ID
    domain: fan
mode: single

If you want to set fake states to test your triggers and conditions, that should be possible from the developer tools. I don’t quite remember if you need to manually enable something to show that though, possibly Advanced Mode in your user’s preferences?

1 Like

Will it trigger the turn-off action if I remove the condition and the state differs from what I set in the ‘When’ section? I used the condition to avoid creating a separate automation for turning off the purifier. As I understand it, the existing automation only triggers the start but doesn’t limit how long the purifier should run afterward.

Your automation will never turn off the fan unless you explicitly tell it to.

I will give it a try, thanks for the tip!

That’s not going to work. Second line not needed.

I was using the visual editor to create the automation, which generated the code.

Unless what you posted is a fragment of some larger automation, what’s posted doesn’t contain any action to turn off the purifier

Quick and dirty:

alias: Clean up air
triggers:
  - trigger: state
    entity_id: sensor.air_quality_level
actions:
  - action: >-
      fan.turn_{{ 'on' if trigger.to_state.state.casefold()
      in ['moderate', 'bad', 'very bad'] else 'off' }}
    target:
      entity_id: fan.my_entity_id

Also as above, use a fan.turn_on / fan.turn_off action, not a device action. The latter makes the code unreadable. Replace the entity id with the human readable entity id, not the one used by your device trigger.

The logic for this kind of automation would be much more clean if you based it on your other sensor though…

alias: Clean up air
triggers:
  - trigger: state
    entity_id: sensor.combined_air_quality_index
actions:
  - action: "fan.turn_{{ ['off', 'on'][trigger.to_state.state | int <= 60] }}"
    target:
      entity_id: fan.my_entity_id

And another alternative which is not quite as dirty:

alias: Clean up air
triggers:
  - trigger: numeric_state
    entity_id: sensor.combined_air_quality_index
    below: 60
    id: turn_on
  - trigger: numeric_state
    entity_id: sensor.combined_air_quality_index
    above: 60
    id: turn_off
actions:
  - action: "fan.{{ trigger.id if trigger.id is defined else 'toggle' }}"
    target:
      entity_id: fan.my_entity_id

(Running this automation manually toggles the fan.)

1 Like

Does this mean that separate automation is needed to trigger the turn-off? Is there a way to combine all the conditions and triggers into a single automation using simple logic: if the air quality equals “A,” then turn on the device; if it equals “B,” then turn it off?

I see you already replied. Thank you!

That’s interesting because I just used it to create three State Triggers and the resulting YAML is in the traditional format (no “- triggers:” key, just one “triggers:”) and not the way it appears in your example.

Though I agree the extra - triggers: is entirely superfluous in this case, it should still work.

Interesting. The documented example shows the application of a nested trigger list in a blueprint. I am surprised the Automation Editor used it to create a simple list of State Triggers in a vanilla automation.

Not sure if it’s related to the latest version (or something else) because I just used the Automation Editor in 2024.12.5 and it didn’t generate a nested list of State Triggers.

I don’t normally use the Editor but I don’t see a way to force it to make make a nested trigger list in Visual mode. Odd; curious to know how it was achieved.