I have a sensor.start_times variable which contains a string like: 11:00:30, 14:20:11, 16:12:10. These are the times in a day when I want to switch on a relay for a previously configured duration. The variable can contain 1 from 10 exact times so it can change.
Is it possible to change the triggers of an automation when I push a button or something? Or do you have any other idea how to implement this logic? I was suggested to create an automation which is triggered in every second to check if the current time is equal to one of my times but that just sounds a waste of resource.
Interesting problem. Do you really need precision down to the second? I don’t think that is possible using normal automation triggers. A time trigger only supports limited templates, so it cannot query the state of an entity. While you can use a template trigger that compares the times in the sensor against now(), that would only run once at the start of each minute.
So what can you do instead? The first thought that pops into my head would be to put the trigger in the actions of the automation. Put the next execution time into a variable and use a time trigger, which ought to work even with only limited templates? Put the automation in mode restart along with a state trigger that reacts to any changes in the sensor, as well as when HASS starts or the automation is enabled.
Something like below, just add your automation actions at the bottom. Completely untested, probably has typos or something I haven’t considered, caveat emptor. If the time trigger does not work (due to template limitations), the delay alternative definitely should though.
mode: restart
triggers:
- trigger: state
entity_id: sensor.start_times
to: ~
- trigger: event
event_type: automation_reloaded
- trigger: template
value_template: "{{ is_state(this.entity_id, 'on') }}"
variables:
next_trigger: >-
{{ states('sensor.start_times').split(',')
| map('today_at') | select('>', now()) | sort | first }}
actions:
- wait_for_trigger:
- trigger: time
at: "{{ next_trigger.time() }}"
# - delay: "{{ (next_trigger - now()).total_seconds() }}"
# YOUR ACTIONS HERE
Probably someone else will chime in and suggest that you instead pair your existing sensor with a binary_sensor that turns true when the automation should fire. I haven’t really worked with template entities at all though, so the above is what I’d go with.
Write an automation that triggers on the state of your sensor that has the times in it. (So when the list of times changes, this automation runs.)
In the automation, parse the list of times and figure out the one that is next. Calculate the time difference between now and that next time. Then set a timer for that amount of time.
Then use the timer as the trigger for your dynamic automation.
In this approach, you always have a timer running. But the automations don’t need to fire every second.
@zbertalan - I think this question from 123 is critical. It would give us a chance to help you.
Maybe post your automation in full?
Also, what do you try to achieve? Could you elaborate your setup / your sensors / the automation / background / what are you trying to do at the end? I’m thinking maybe there are other ways to achieve the same, without comparing timestamps.
trigger: template
value_template: |
{% set times_list = (states('sensor.start_times')).split(',') | map('today_at') | list %}
{{ now() > (times_list|select('>',now()-timedelta(minutes=1))|sort|first).replace(second=0) }}
Keep in mind that the use of now() means the template will be rendered at the top of each minute.
Optionally, (if you think you might need it elsewhere) you could just put the above template in a Template binary sensor, then use the sensor’s state in a State trigger.