Create a notification when air humidity is too high

I want to test all humidity sensors once per hour if their humidity is above 60 percent and then have a notification via Sonos loudspeaker: “humidity is too high in room A, C, F and G”.

What I tried so far is to create an automation with all sensors one by one:

alias: Warnung hohe Luftfeuchtigkeit
description: ""
triggers:
  - trigger: time_pattern
    hours: "*"
    minutes: "45"
    seconds: "0"
conditions:
  - condition: or
    conditions:
      - condition: numeric_state
        entity_id: sensor.node_19_humidity
        above: 60
      - condition: numeric_state
        entity_id: sensor.sensor1_luftfeuchtigkeit
        above: 60
     - ... further sensors
actions:
  - action: tts.speak
    metadata: {}
    data:
      cache: true
      media_player_entity_id: media_player.tv_samsung_q60_series_55
      message: >-
        Luftfeuchtigkeits-Warnung! Achtung, die Luftfeuchtigkeit ist zu hoch.
        Bitte lüften! 
      language: de
    target:
      entity_id: tts.google_translate_en_com
    enabled: false
mode: single

Problem 1: I have to reedit the automation each time a new sensor is added. I’d rather want something like a “wildcard selection” for all sensors containing “_luftfeuchtigkeit” but I don’t know how to achieve this in an automation.

Problem 2: This triggers if at least one sensor value is above 60, but I don’t know which sensor it is and where it is located. So I am unable to name the areas of the sensor. Is there a way to collect the area names of each sensor with a value above 60 and use this as text in the action? Like adding them into an array and looping through it.

I just read some information about templates, groups and helpers but I must admit that I don’t understand how I can get these together.

With a bit of templating your goal is very achievable. But before we can help, you need to decide on the grouping mechanism.

Options:

  • Naming convention: “all sensors containing _luftfeuchtigkeit” will work, as long as that’s a convention you can stick to.
  • Labels: These can be added and removed easily through the UI and can be used in templates, actions, and some triggers and conditions.
  • Sensor Group Helper: A UI-defined entity that groups your sensors. One advantage of a sensor group is that you can have it’s state represent one of a number of statistical value of the group like Max, Min, or Mean.

From a templating perspective they are all equally easy to use for your purpose.

Example using naming convention
alias: Warnung hohe Luftfeuchtigkeit
description: ""
triggers:
  - trigger: time_pattern
    hours: "*"
    minutes: "45"
    seconds: "0"
variables:
  humid_areas: |
    {% set st_objs = states.sensor | selectattr('entity_id', 'search', '_luftfeuchtigkeit')
    | selectattr('state', 'is_number') | list %}
    {% set sens_states = st_objs | map(attribute='state')
    | map('float') | select('ge',60) | map('string') | list%}
    {{ st_objs | selectattr('state','in',sens_states)
    | map(attribute='entity_id') | map('area_name') | unique | list }}
conditions:
  - condition: template
    value_template: "{{ humid_areas | count > 0 }}"
actions:
  - action: tts.speak
    metadata: {}
    data:
      cache: true
      media_player_entity_id: media_player.tv_samsung_q60_series_55
      message: >-
        Luftfeuchtigkeits-Warnung! Achtung, die Luftfeuchtigkeit ist zu hoch.
        Bitte lüften Sie die folgenden Räume! {{ humid_areas }}
      language: de
    target:
      entity_id: tts.google_translate_en_com
    enabled: false
mode: single
1 Like

Awsome! This is exactly what I was searching for. Many thanks!

What cathphrase can I search for in the documentation? For my understanding:

 {% set st_objs = states.sensor | selectattr('entity_id', 'search', '_luftfeuchtigkeit')
 | selectattr('state', 'is_number') | list %}

Here you get all entities where the entity_id contains _luftfeuchtigkeit

 {% set sens_states = st_objs | map(attribute='state')
 | map('float') | select('ge',60) | map('string') | list%}

This collects all of them where the state is >= 60

 {{ st_objs | selectattr('state','in',sens_states)
 | map(attribute='entity_id') | map('area_name') | unique | list }}

Finally you enrich st_objs whith the entitie’s area_name. Why do you use double braces here?

Can I concatenate the area name with further information like humidity? Like “Room X 70% air moisture, Room Y 62% air moisture”

Again, my problem is solved, this would only be the optional extra. Many thanks for your help!

The Jinja2 template engine docs can be found at https://jinja.palletsprojects.com/en/stable/templates/. The Home Assistant specific template function are all described in the Building Templates page.

Kind of… It’s not just a list of the entity IDs that is being set as the variable’s value; it’s their state objects.

Correct, I get the state… then, since states are always strings, I need to convert them to real numbers before selecting them based on numerical comparison. Once that comparison is done, I have to change them back to strings so they can be used in the next step.

Again, kind of… I go back to the state object (which contain the entity IDs and states) and select the objects that have states that match the list from step 2. Then I use map to return the entity IDs from those state object. Finally, I use map to apply another function across all the items in the list. The function area_name is a Home Assistant specific function that takes an entity ID as its input and outputs the name of the area that entity is assigned to.

Yes. There are different ways to do it, but one option would be to use a loop, but you wold want to set the variables up a little differently:

Using a loop to list area and humidity
alias: Warnung hohe Luftfeuchtigkeit
description: ""
triggers:
  - trigger: time_pattern
    hours: "*"
    minutes: "45"
    seconds: "0"
variables:
  selected_entities: |
    {% set st_objs = states.sensor | selectattr('entity_id', 'search', '_luftfeuchtigkeit')
    | selectattr('state', 'is_number') | list %}
    {% set sens_states = st_objs | map(attribute='state')
    | map('float') | select('ge',60) | map('string') | list%}
    {{ st_objs | selectattr('state','in',sens_states)
    | map(attribute='entity_id') | list }}
conditions:
  - condition: template
    value_template: "{{ selected_entities | count > 0 }}"
actions:
  - variables:
      humid_areas: |
        {%- for x in selected_entities if area_name(x) is not none-%}
          {{area_name(x)}} {{ states(x)}}% air moisture,
        {%endfor%}
  - action: tts.speak
    metadata: {}
    data:
      cache: true
      media_player_entity_id: media_player.tv_samsung_q60_series_55
      message: >-
        Luftfeuchtigkeits-Warnung! Achtung, die Luftfeuchtigkeit ist zu hoch.
        Bitte lüften Sie die folgenden Räume! {{ humid_areas }}
      language: de
    target:
      entity_id: tts.google_translate_en_com
    enabled: false
mode: single

If there’s a specific format you are looking for, and you can’t figure it out, let us know and someone can probably help you achieve it.