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
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.