I am a beginer when it comes to automations and I am trying to avoid getting into a situation again as I had a few days ago where most of my battery operated sensors had run out of battery.
I am trying to make an automation that is only actioned once in a given time period, but so far all the suggestions I have seen give me an error of some form.
This is an extract of my automations.yaml
#
# Low Battery Warnings
# Bathroom
#
- id: bathroom_low_battery
alias: Bathroom temperature sensor low battery
description: 'Send low battery warning for bathroom temperature sensor'
trigger:
- platform: numeric_state
entity_id: sensor.bathroom_battery_percent
below: 40
for:
hours: 0
minutes: 15
seconds: 0
condition:
- condition: template
# Only run if more than 6 hours (21,600 sec) since it last ran
value_template: '{{(as_timestamp(now()) - as_timestamp(state_attr("automation.bathroom_low_battery", "last_triggered") | default(0)) | int > 21600 )}}'
action:
- service: notify.home_assistant
data:
message: "Low battery detected in Bathroom temperature sensor {{ states('sensor.bathroom_battery_percent') }}%"
title: "WARNING: Low battery detected"
- service: persistent_notification.create
data:
message: "Low battery detected in Bathroom temperature sensor {{ states('sensor.bathroom_battery_percent') }}%"
title: "Notice: Low battery detected"
mode: single
#
If I take out the condition section it works, but I get repeated messages over the given time period as the device reports the battery level going up/down during the day.
With the condition when I try to the test the condition in Automations and Scenes I get:
Error occurred while testing condition
In ‘template’ condition: ValueError: Template error: as_timestamp got invalid input ‘None’ when rendering template ‘{{(as_timestamp(now()) - as_timestamp(state_attr(“automation.bathroom_low_battery”, “last_triggered”) | default(0)) | int > 21600 )}}’ but no default was specified
If the automation never was triggered before, state_attr("automation.bathroom_low_battery", "last_triggered") results in none. Default for the comparison above is now().timestamp() or an integer.
Copy the following into Developer Tools > Template:
{% set x = state_attr("automation.bathroom_low_battery", "last_triggered") %}
{{ (as_timestamp(now()) - as_timestamp(x, now().timestamp() ) > 21600 ) }}
{{ (as_timestamp(now()) - as_timestamp(x, 22000) > 21600 ) }}
{{ x is not none and (now() - x).seconds < 21600 }} ## false, if the automation never was triggered before
{{ x is none or now() - x > timedelta(hours=6) }}
The automation will be called automation.bathroom_temperature_sensor_low_battery because the entity name is derived from the alias not the id.
You’re not providing a default for as_timestamp, which is required for when the last_triggered attribute can’t be converted to a UNIX timestamp. If you think your default filter is doing that job, it isn’t.
This replacement for your existing value_template line will fix those issues:
However, you should also be aware that after the first notification is sent, this will not send another notification until the battery level drops from above to below 40% again.
Triggers when the battery level drops below 40%, and also when six hours has passed since the automation last ran. It then checks both those things are still true before proceeding to send the notification.
Techie note: the automation last_triggered attribute appears to record the time of last successful execution — when the action was reached, not when any of the triggers fired. So once a new battery is fitted, the above automation will trigger once more (six hours after the last notification), get blocked by the battery level condition, and then go idle until the battery level drops again.
Also note there used to be a bug in testing template conditions. I haven’t heard if that is fixed yet. So it may be the template condition works fine if the automation is working when fired normally, but not when tested. This too can be verified by pasting your template in the template tester in developer tools.