Create template for warning only when deteriorating

hi,
using the air quality integration, I used this automation for starters, with a hardcoded from: Good in the trigger platform to create a warning:

  - alias: Aqi Alert
    id: 'Aqi Alert'
    trigger:
      - platform: state
        entity_id: sensor.chinese_air_pollution_level
        from: 'Good'
      - platform: state
        entity_id: sensor.us_air_pollution_level
        from: 'Good'
    condition: []
    action:
      - service: notify.notify
        data_template:
          title: >
           {{as_timestamp(now())|timestamp_custom('%X')}} : Aqi Alert!
          message: >
            {{trigger.to_state.name}} deteriorated from 'Good' to {{trigger.to_state.state}}
            Check: https://www.airvisual.com/netherlands/north-brabant/huijbergen/huijbergen-vennekenstraat for more info

Of course that doesn’t suffice since there are a few more quality levels defined see https://www.home-assistant.io/integrations/waqi/#configuration-variables

So I made a more versatile automation based on any state change, with a templated from_ and to_state:

 - alias: Aqi Alert
    id: 'Aqi Alert'
    trigger:
      - platform: state
        entity_id: sensor.chinese_air_pollution_level
      - platform: state
        entity_id: sensor.us_air_pollution_level
    condition: []
    action:
      service: notify.notify
      data_template:
        title: >
         {{as_timestamp(now())|timestamp_custom('%X')}} : Aqi Alert!
        message: >
          {{trigger.to_state.name}} changed from {{trigger.from_state.state}} to {{trigger.to_state.state}}
          {% set url = 'https://www.airvisual.com/netherlands/north-brabant/huijbergen/huijbergen-vennekenstraatl' %}
          Check [your local Air quality station]({{url}}) for more info

What I’d like however, is to only create a warning when deteriorating… how can I write the template so it takes the available conditions into account?

['Good','Moderate','Unhealthy for Sensitive Groups','Unhealthy','Very unhealthy','Hazardous']

should I eg create a mapper like

{% set mapper =  {'Good':'5',
                  'Moderate':'4',
                  'Unhealthy for Sensitive Groups':'3',
                  'Unhealthy':'2',
                  'Very unhealthy':'1',
                  'Hazardous':'0' } %}

and then compare the
mapper[trigger.to_state.state] < mapper[trigger.from_state.state] ?

or, maybe even better use both improved and deteriorated, using a template like this:

    action:
      service: notify.notify
      data_template:
        title: >
         {{as_timestamp(now())|timestamp_custom('%X')}} : Aqi Alert!
        message: >
          {% set mapper = {'Good':'5','Moderate':'4','Unhealthy for Sensitive Groups':'3',
                           'Unhealthy':'2','Very unhealthy':'1','Hazardous':'0' } %}
          {{trigger.to_state.name}} {{'improved'
          if mapper[trigger.to_state.state] > mapper[trigger.from_state.state] 
           else 'deteriorated'}} from {{trigger.from_state.state}} to {{trigger.to_state.state}}
          {% set url = 'https://www.airvisual.com/netherlands/north-brabant/huijbergen/huijbergen-vennekenstraatl' %}
          Check [your local Air quality station]({{url}}) for more info

might also need an added safety catch for the mapper?
please have a look if this could be the way to go? thanks!

@petro would you be so kind to check with me here? Not really sure if this is working now, seem not to get too many warnings anymore :wink:

 - alias: Aqi Alert
    id: 'Aqi Alert'
    trigger:
      - platform: state
        entity_id: sensor.chinese_air_pollution_level
      - platform: state
        entity_id: sensor.us_air_pollution_level

    condition:
      condition: template
      value_template: >
        {% set values = ['Good','Moderate','Unhealthy for Sensitive Groups','Unhealthy','Very unhealthy','Hazardous'] %}
        {% if trigger.from_state.state in values and trigger.to_state.state in values %}
        {{ values.index(trigger.from_state.state) < values.index(trigger.to_state.state) }}
        {% else %}
          False
        {% endif %}
    action:
      service: notify.notify
      data_template:
        title: >
         {{as_timestamp(now())|timestamp_custom('%X')}} : Aqi Alert!
        message: >
          {{trigger.to_state.name}} changed from {{trigger.from_state.state}} to {{trigger.to_state.state}}
          {% set url = 'https://www.airvisual.com/netherlands/north-brabant/huijbergen/huijbergen-vennekenstraatl' %}
          Check [your local Air quality station]({{url}}) for more info
1 Like

nice! just so I understand: is this in fat a virtual mapper, mapping the values to a position in the list? I thought I needed to map the conditions to a number to be able to check ‘<’, but now think to understand this works the same way without actually mapping the verbosely?

ps. for anyone checking this, I made a typo in the original sensor which should be u_s_pollution_level

made it into this:

- alias: Aqi Alert alt
    id: 'Aqi Alert alt'
    trigger:
      - platform: state
        entity_id: sensor.chinese_air_pollution_level
      - platform: state
        entity_id: sensor.u_s_air_pollution_level
    condition:
      condition: template
      value_template: >
        {% set values = ['Good','Moderate','Unhealthy for Sensitive Groups','Unhealthy','Very unhealthy','Hazardous'] %}
        {{trigger.from_state.state in values and trigger.to_state.state in values}}
    action:
      service: notify.notify
      data_template:
        title: >
         {{as_timestamp(now())|timestamp_custom('%X')}} : Aqi Alert to {{trigger.to_state.state}}
        message: >
          {% set values = ['Good','Moderate','Unhealthy for Sensitive Groups','Unhealthy','Very unhealthy','Hazardous'] %}
          {{trigger.to_state.name}} {{'improved' if values.index(trigger.from_state.state) < values.index(trigger.to_state.state)
            else 'deteriorated'}} from {{trigger.from_state.state}} to {{trigger.to_state.state}}
          {% set url = 'https://www.airvisual.com/netherlands/north-brabant/huijbergen/huijbergen-vennekenstraatl' %}
          Check [your local Air quality station]({{url}}) for more info

with the guard in the condition, and a template to decide if things got better or worse…

thanks Petro!

1 Like

update on this.
I received notifications alright, but they kept reporting ‘deteriorated’ instead of ‘improved’ and vv.

Kept looking over and over, thinking 1 must be smaller than 2… etc

It then dawned on me the list order is what counts:

['Good','Moderate','Unhealthy for Sensitive Groups','Unhealthy','Very unhealthy','Hazardous']

Good being smaller than Moderate…

so, update to the template must be either change the order in the list, or a simple

{{'improved' if values.index(trigger.from_state.state) > values.index(trigger.to_state.state)
            else 'deteriorated'}}

should suffice

(must admit this goes against my ordering compulsion so in the end think I will change the order in the list :wink: )

Is this code still working for you. On another forum post (https://community.home-assistant.io/t/air-quality-automation/193480/7) you helped me with this and has been working fine, until a few days ago. Now nothing. Can not even trigger it in the automation ui.
I wonder if an update changed something.
This is the error message
Logger: homeassistant.components.automation.aqi_informational_alert
Source: components/automation/init.py:504
Integration: Automation (documentation, issues)
First occurred: 12:41:13 PM (2 occurrences)
Last logged: 12:41:59 PM
Error while executing automation automation.aqi_informational_alert: Error rendering data template: UndefinedError: ‘dict object’ has no attribute ‘to_state’

Any thoughts would be greatly appreciated.

Poste the code of this automation:

Anywhere in this automation is your error. This is a new warning, that a template variable isn’t ready for use. As per the changelog it shouldn’t end in an error or not working automation, but who knows… :slight_smile:

Here is the code I have been using

- id: '1588722851123'
  alias: AQI Informational Alert
  trigger:
    - platform: state
      entity_id: sensor.chinese_air_pollution_level
    - platform: state
      entity_id: sensor.u_s_air_pollution_level
  condition:
    condition: template
    value_template: >
      {% set values = ['Good','Moderate','Unhealthy for Sensitive Groups','Unhealthy','Very unhealthy','Hazardous'] %}
      {{trigger.from_state.state in values and trigger.to_state.state in values}}
  action:
    service: notify.telegram_carlton
    data_template:
      title: >
        {{as_timestamp(now())|timestamp_custom('%X')}} : Aqi Alert to {{trigger.to_state.state}}
      message: >
        {% set values = ['Good','Moderate','Unhealthy for Sensitive Groups','Unhealthy','Very unhealthy','Hazardous'] %}
        {{trigger.to_state.name}} {{'improved' if values.index(trigger.from_state.state) > values.index(trigger.to_state.state)
        else 'deteriorated'}} from {{trigger.from_state.state}} to {{trigger.to_state.state}}
        {% set url = 'https://www.iqair.com/usa/arizona/mesa' %}
          Check [your local Air quality station]({{url}}) for more info

Thanks

if anything you could check for existence and ‘guard’ against ‘unavailable’:

    condition:
      - >
          {{trigger.to_state is not none and
            trigger.from_state is not none and
            trigger.to_state.state != trigger.from_state.state}}

if this doesn’t suffice, you can add:

{{trigger.to_state.state not in ['unknown','unavailable'] and
  trigger.from_state.state not in ['unknown','unavailable']}}

still we should try to find out what happened ‘until a few days ago’ ? Did you update to the 2021.4.xx version?
Or is something amiss with the integration triggering the automation? Must say I didn’t see any warmings for a long time, but I didnt see any errors either.

I checked in the states:

enter Hazardous and click Set State, and the automation works as it should (though the url in the notification isnt correctly formatted…) But thats not what’s bugging you. No errors here.

Thanks
I changed a few things like you suggested and I will wait and see what happens.
Appreciate the help.

As said, you don’t have to wait, just change the State in the developer-tools