I’m trying to create an automation for my salt water pool chlorine generator. The time the chlorinator must be active and therefore generating chlorine is dependant on the temperature of the water. The hotter it is, the more chlorine is required.
So I want an automation that switches the chlorinator on at sunset and turns off some time later, where the time is determined by pool temp (deg C) * 12. IE for every degree the chlorinator runs for 12 minutes.
My config info is below.
The trouble is that I don’t seem to be able to use any sort of variable for timer duration. The config below, for example, gives the error: extra keys not allowed @ data['data_template']
Is there any other option?
I have a sensor that determines this time:
## Pool chlorinator time needed
- platform: template
sensors:
chlorinate_time:
value_template: >-
{% set time = (states('sensor.pool_temp')|float)|round * 720 %}
{% set minutes = ((time % 3600) / 60) | int %}
{% set hours = ((time % 86400) / 3600) | int %}
"{{ "%02d" | format(hours) }}:{{"%02d" | format(minutes)}}"
sensor.chlorinate_time returns a value like “02:36”
I have a timer set in configuration.yaml:
## timers
timer:
pool_pm:
And I have two automations (nb the chlorinator uses a climate integration as a hack, there is no pool chlorinator component):
- id: chlorinator-on-pm
alias: chlorinator-on-pm
description: 'Turn on pool chlorinator at sunset'
trigger:
- event: sunset
platform: sun
condition: []
action:
- service: climate.set_temperature
data:
entity_id: climate.chlorinator
temperature: 100
- service: timer.start
data_template:
entity_id: timer.pool_pm
duration: '{{states('sensor.chlorinate_time')}}'
- id: chlorinator-off-pm
alias: chlorinator-off-pm
description: Turn off pool chlorinator after temp-calc duration
trigger:
- event_data:
entity_id: timer.pool_pm
event_type: timer.finished
platform: event
condition: []
action:
- data:
entity_id: climate.chlorinator
temperature: 0
service: climate.set_temperature
Thanks @tom_l. I’m not sure that’s it. I’ve made the change so that sensor now gives the HH:MM:SS value but I get the same error. I’m not sure that the duration: field can accept a template entry.
Looking at the timer integration page I don’t believe the duration can be templated. Either that or it is failing because you are using single quotes in single quotes. This
duration: '{{states('sensor.chlorinate_time')}}'
Should be:
duration: "{{states('sensor.chlorinate_time')}}"
However due to the error message I think it is the former reason.
An alternative method would be to forget the timer and just use a template trigger to turn off the chlorine generator after the required time.
- id: chlorinator-off-pm
alias: chlorinator-off-pm
description: Turn off pool chlorinator after temp-calc duration
trigger:
platform: template
value_template: "{{ state_attr('climate.chlorinator', 'temperature')int = 100 }}"
for: "{{ states('sensor.chlorinate_time') }}" # assuming this has hh:mm:ss format
action:
service: climate.set_temperature
data:
entity_id: climate.chlorinator
temperature: 0
Due to some excellent work by one of the forum members, Phil Bruckner, you can use a template in for: for most (all?) triggers now.
As @tom_l said, the main problem is your template is not using quotes correctly.
duration: '{{states('sensor.chlorinate_time')}}'
needs to be
duration: "{{states('sensor.chlorinate_time')}}"
HH:MM format is acceptable.
And, yes, as @tom_l also said, you can use a templated for: option on most triggers now.
However, I think the easiest way is to just use a templated delay in a single automation:
- id: chlorinator-on-off
alias: chlorinator-on-off
description: 'Turn on pool chlorinator at sunset and off later'
trigger:
- event: sunset
platform: sun
condition: []
action:
- service: climate.set_temperature
data:
entity_id: climate.chlorinator
temperature: 100
- delay: "{{states('sensor.chlorinate_time')}}"
- data:
entity_id: climate.chlorinator
temperature: 0
service: climate.set_temperature
True, if HA restarts during the delay the chlorinator won’t be turned off. But I’m pretty sure the same would be true with your timer-based implementation. (I.e., I don’t think active timers will survive a HA restart.)
If you want the solution to work through a HA restart, then you’d probably need to save the stop time in an input_datetime or input_number (as a timestamp.) Then use a template trigger on the off automation that compares the current time (e.g., sensor.date_time) to the saved time.
Thanks all for your input. I’ll clean up my quotes and see if that works, just for my own education. I like the single automation option from @pnbruckner, looks clean. Thanks so much.
Finity, I understand ALL of your template, apart from the last line, can you describe the : - %02i’ | format(hours_left) bit, I can guess but I thought filters ran right to left ???
TIA (thanks in advance)
The last line actually contains two separate expressions, and each contains one filter. So right-to-left or left-to-right doesn’t really apply here. But, basically, filters are just another binary operator, and they have higher precedence than other binary operators. The filter takes what comes before it as its first “argument”, and then other arguments are supplied in parentheses. So:
'%02i' | format(hours_left)
just means to run the format filter, where the first argument is the string '%02i', and the second argument is the value of the variable hours_left. The format filter basically uses the first argument as the format string, and the remaining arguments as the values. So the above is effectively the same as the Python expression:
'%02i' % (hours_left)
For more details, see the docs on the format filter.
I should probably add, the filter operator is left-to-right associative. E.g.,
a | b | c
in this case a is “fed into” the b filter, and the result is “fed into” the c filter, like:
(a | b) | c
This, I suspect, is why the doc uses “pipe” terminology when describing filters.
Phil, thanks for the explanation (I really need to continue reading that python book and then do some ‘more’ coding (word clock — rubs hands))
I took time to respond as I needed to play with the expressions
What I didn’t get (cos I did guess correctly what it was used for) was why it wasn’t : -
take this number - filter it (pipe it) into a format of this type
eg - hours_left | format(‘%02i’)
many other pipe instructions are very right to left, like : - value [pipe] function → result
eg 3.1415926 | int, 2.17186 | float etc. but having played I see that this is not the case here
format_you_want_it_in (as text string) [pipe] value → result
But once again Petro has done it most concisely, though I do like your automation and the off time in an input_datetime is a very nice touch
Thanks Again - and also to @finity for his time manipulations (or should that be to Klogg ??? )
Hi all, this post is 2 years old but I found it as I had to solve the same problem. The hint of tom_l has actually helped me solve my problem. Just posting this as it may help others. For me, this works (in a HA script):