I have the following automation that I expected to toggle the light on my desk every minute
alias: Test time trigger
description: ""
trigger:
- platform: template
value_template: |2-
{% set t = now() %}
{{ not t.second }}
condition: []
action:
- type: toggle
device_id: c4792938aa12840e6dbe8d4d9cf6d3a8
entity_id: switch.desk_light
domain: switch
mode: single
However it only toggled the light the first time and not on subsequent minutes. When viewing the automation in the visual editor, every minute a blue bar would appear above the trigger saying TRIGGERED but the action does not occur.
Is there some configuration to specify that the automation should repeat? What have I overlooked?
I realise there are simpler ways to trigger every minute but my actual needs are more complex - this is just a test of using timers in templates
What I actually want is a trigger for my kettle at 6:30 Monday, 6:55 Tuesday, 6:30 Wed, 6:55 Thu, 6:30 Fri, not at all Sat/Sun. Is there a way I can pass these times as configuration to a template? Is there a better way of doing this than a template trigger?
I realise this is technically 2 questions so happy for answers to just the first
Yes, that’s pretty neat and looks like it would definitely work. It hadn’t occurred to me that you could layer the trigger and the conditions like that.
However it’s not very concise as the time needs to be included in both the trigger and the conditions (giving a maintenance overhead, albeit a small one and some unnecessary complexity)
As a Python developer I can see myself using (abusing?) the template triggers extensively so I would still like to know why my original example only triggered once
So first time you ran it, it is likely that the seconds were non-zero, so the template was false. Next run would have been evaluated at the top of the minute, so {{ not 0 }} is true, trigger fires once.
Subsequent runs are also at 0 seconds, template remains true and does not fire again.
Make a Schedule entity and configure it with the desired times and days. Then create a simple automation that turns on the kettle whenever the schedule is on.
alias: example
trigger:
- platform: state
entity_id: schedule.kettle
from: 'off'
to: 'on'
condition: []
action:
- service: switch.turn_on
target:
entity_id: switch.kettle
You can can create a Schedule entity either via the UI (as a Helper) or via YAML.
My original solution was to check that I understood how template timers work. It did its job as I didn’t understand them, it took @Troon to set me straight. This is I reckon the most concise solution to my problem
alias: Test time trigger
trigger:
- platform: template
value_template: |2-
{% set t = now() %}
{% set config = [[0, 6, 30], [1, 6, 55], [2, 6, 30], [3, 6, 55], [4, 6, 30]] %}
{% for item in config if t.weekday() == item[0] and t.hour == item[1] and t.minute == item[2] %}True{% endfor %}
- service: switch.turn_on
entity_id: switch.YOUR_KETTLE
However @Troon solution is far more readable and IMHO the better solution - @Hellis81 I’ll agree with you concise isn’t always better
The disadvantage of your approach (maybe only from an elegance point of view unless your system is weak or busy) is that the system is evaluating that template at the top of every minute in order to run four times per week — 0.04% efficient. Mine and @Hellis81’s trigger 14 times per week (28% efficient), and as usual @123 wins with a 100% efficient once-a-day trigger that doesn’t fire at the weekend if you set the schedule up correctly.
Yep that’s a fair point. I don’t think a time calculation trigger once a minute would tax any real world system (even an arduino) but, seeing as we are just point scoring 3 working solutions, I’m happy to concede the concise solution is neither readable nor efficient.
I guessed Home Assistant follows the python approach of if it ain’t ‘true’ it’s false - and it does. It’s a shortcut but that is the essence of golf, right?
Speaking of which, I don’t think I can squeeze it any more than your last solution - which is also more efficient as it uses hashing instead of a brute force loop so it’s most likely O(1) instead of O(n)
Definitely not readable, but it’s fun to think about all the different ways to solve this. This one occurred to me walking home from the supermarket.
Divide the UNIX epoch timestamp by 300 to get number of five minute blocks since the start of 1970. Take the modulo of 2016 (number of 5 min blocks in a week) which gives you an offset from an arbitrary starting point which is the same each week. Then look for one of the magic numbers corresponding to the days / times you want.
EDIT: I think daylight saving time will mess this up, and there’s no obvious way around that. If you live somewhere that doesn’t do summer / winter time, it’ll be fine.