Below is the YAML I made but I can’t really test it until a battery is actually below 20% so for now I have a few questions; First, is the most efficient way to be doing this?
Second, when I run test it says, “The door sensor battery is below 20 percent.” and skips over the trigger.entity_id part which I guess makes sense since an entity didn’t actually trigger the automation but when it does run, will it say a friendly name of the device/event or read out the actual ID of the code like, “7basdfasdfasdf0e” ?
avoid device triggers they do not survive device replacement, instead look for state or numeric state triggers that do the same thing.
Then if your device gets replaced all you need is give the new entity old name and your automation keeps going.
Second no. It will say ’ the door sensor is’ [entity_id] because thats what trigger.entity_id is. You probably want the ‘friendly_name’ attribute of entity_id instead - use select_attr
Of course you can! Go to the developer tools and set the battery state to 19%
That will trigger your automation if it’s set up correctly. Don’t worry about your actual battery state - it’ll bounce back to the correct value when your device sends another report
Thanks for the tip, I’ve changed the conditional triggers to reference the numeric state as you suggested. I’m not familiar with select_attr, can you tell me how to use it here or show an example? Thanks.
There are several issues here which might not have been immediately obvious to you.
Your initial automation had the problem that the trigger.entity_id is always going to be “sun.” The trigger variable references the trigger, not the conditions.
Seems you caught that in the second version you posted, but there is no such thing as condition.entity_id, unfortunately. If you want to trigger at a given time of day and use conditions, you will need some logic in your automation to identify which of the sensors is low, if any, even if that seems redundant with the conditions.
Finally, be aware that the conditions as written must ALL be met for the automation to fire–that is, every single sensor battery to be below 20. That’s because, by default, the list of conditions is evaluated as a logical AND. If you meant for the automation to run if any one of the sensors is low, you need to explicitly specify an OR:
Now, with all that out of the way, since you’re seemingly comfortable running this just once or twice per day, I suggest removing the conditions entirely and just doing an if, so that you only need the list of sensors in one place (as opposed to in the conditions: block and then in the actions: block).
For example,
alias: Door sensor (any) below 20%
description: ""
triggers:
- trigger: sun
event: sunset
offset: "00:05:00"
- trigger: time
at: "12:00:00"
actions:
- variables:
all_sensors:
"sensor.patio_door_sensor_battery" : "patio"
"sensor.mudroom_door_sensor_battery" : "mudroom"
"sensor.entryway_door_sensor_battery" : "entryway"
"sensor.basement_storage_door_battery" : "basement storage"
low_sensors: >
{% set NS = namespace(low_sensors=[]) %}
{% for sensor in all_sensors.keys() %}
{% if states(sensor)|int(0) <= 20 %}
{% set NS.low_sensors = NS.low_sensors + [all_sensors[sensor]] %}
{% endif %}
{% endfor %}
{{ NS.low_sensors }}
phrase: >
{% if low_sensors|length > 1 %}
{{low_sensors | length}} sensors are
{% else %}
sensor is
{% endif %}
- if: "{{low_sensors | length}}"
then:
- action: tts.cloud_say
metadata: {}
data:
cache: false
entity_id: media_player.home_assistant_voice_09b642_media_player
message: >-
The following {{phrase}} at battery level below 20 percent: {{low_sensors|join(', ')}}
mode: single
EDIT: I corrected a couple of small errors, including an indent. I haven’t tested this code, so if it gives you problems, just post here and I can help you fix.
I’m getting close but I’m missing the final piece. I created the /custom_templates folder and added formatter.jinja and did the reload custom templates action as per the helpful link. Then I changed my YAML to:
message: >-
The door sensor {% from 'formatter.jinja' import format_entity %} {{
format_entity('trigger.condition.entity_id') }} battery is below 20 percent.
and now it says “The door sensor none unknown battery is below 20 percent.”
I’ve tried trigger.condition.entity_id and condition.entity_id and a few other combos but I can’t get it right. Any suggestions?
This code has correct syntax and works on my system. I explain below how you can test/tweak it using the Template Editor, and I rewrote the code a bit to make that easier.
- alias: Door sensor (any) below 20%
description: ""
triggers:
- trigger: sun
event: sunset
offset: "00:05:00"
- trigger: time
at: "12:00:00"
actions:
- variables:
low_sensors: >
{# a dictionary of sensor entity_ids to be monitored, identifying sensor locations #}
{%
set all_sensors = {
'sensor.patio_door_sensor_battery' : 'patio',
'sensor.mudroom_door_sensor_battery' : 'mudroom',
'sensor.entryway_door_sensor_battery' : 'entryway',
'sensor.basement_storage_door_battery' : 'basement storage'
}
%}
{# build the list NS.low_sensors #}
{% set NS = namespace(low_sensors=[]) %}
{% for sensor in all_sensors.keys() %}
{% if states(sensor)|int(0) <= 20 %}
{% set NS.low_sensors = NS.low_sensors + [all_sensors[sensor]] %}
{% endif %}
{% endfor %}
{% set low_sensors = NS.low_sensors %}
{# print the list so the YAML binds it to the low_sensors variable #}
{{ low_sensors }}
phrase: >
{% set NS = namespace(phrase="sensor is") %}
{% if low_sensors | length > 1 %}
{% set NS.phrase = low_sensors|length|string + " sensors are" %}
{% endif %}
{% set phrase = NS.phrase %}
{# print the string so the YAML binds it to the phrase variable #}
{{ phrase }}
message: >
The following {{phrase}} have battery level below 20 percent: {{low_sensors|join(', ')}}
# I'm surprised that the bool filter is required here.
- if: "{{low_sensors | length | bool}}"
then:
- action: tts.cloud_say
metadata: {}
data:
cache: false
entity_id: media_player.home_assistant_voice_09b642_media_player
message: >-
{{ message }}
mode: single
The following code is not the same as the YAML above; it’s a copy-and-paste of only the Jinja code, which I contrived with some quirks to make it possible to seamlessly paste together for purposes of using the Template Editor. The following should work in the Template Editor, and give you an idea of what the code is doing. But note that you do NOT want to paste this into your automation–use the code above for that.
{# a dictionary of sensor entity_ids to be monitored, identifying sensor locations #}
{%
set all_sensors = {
'sensor.patio_door_sensor_battery' : 'patio',
'sensor.mudroom_door_sensor_battery' : 'mudroom',
'sensor.entryway_door_sensor_battery' : 'entryway',
'sensor.basement_storage_door_battery' : 'basement storage'
}
%}
{# build the list NS.low_sensors #}
{% set NS = namespace(low_sensors=[]) %}
{% for sensor in all_sensors.keys() %}
{% if states(sensor)|int(0) <= 20 %}
{% set NS.low_sensors = NS.low_sensors + [all_sensors[sensor]] %}
{% endif %}
{% endfor %}
{% set low_sensors = NS.low_sensors %}
{{ low_sensors }}
{# build grammatically correct phrasing for the message #}
{% set NS = namespace(phrase="sensor is") %}
{% if low_sensors | length > 1 %}
{% set NS.phrase = low_sensors|length|string + " sensors are" %}
{% endif %}
{% set phrase = NS.phrase %}
{{ phrase }}
{# print the message #}
The following {{phrase}} at battery level below 20 percent: {{low_sensors|join(', ')}}
Note that the Template Editor will output something nonsensical if there are NO sensors that are at or below 20. That’s okay, because the YAML logic has an if statement that will prevent the nonsensical message from ever hitting the airwaves.
Also, the Template editor is going to also output a whole bunch of whitespace. You can ignore that–it won’t get in the way of the YAML code working.
May I suggest that if you have trouble with this, you DM me–if there are any edits that are needed to the code, I’ll merge them into this post.
As to your other question, by the way:
That’s a macro, so it only does something if you call it explicitly.
The code that I wrote doesn’t use this macro. But if you wanted to see how it works, and/or add it to your code, try this in the Template Editor:
{% from 'formatter.jinja' import format_entity %}
{{ format_entity('sensor.patio_door_sensor_battery') }}
EDIT: YAML code edited to add a bool filter on the if: condition. I’m somewhat surprised that it’s needed, but… it… is.