Hi very bright peoples,
I am trying to set up a template calculation that starts my pool the correct number of hours before I want to go swimming.
So I have set up the variables:
In input_numbers.yaml
pool_temp_calc:
name: Calculate heating duration
initial: off
icon: mdi:calculator
In input_datetime.yaml
pool_end_time:
name: Pool end time
has_date: false
has_time: true
And in automations.yaml
- alias: Turn pool on at calculated time
trigger:
platform: template
value_template: '{{ (as_timestamp(states.sensor.time.state)) == (as_timestamp(states.input_datetime.pool_end_time.state)) - (((states.input_number.pool_desired_temp ā sensor.wirelesstag_pool_temp_temperature)/0.5)*3600) }}
condition:
condition: state
entity_id: input_boolean.pool_temp_calc
state: 'on'
action:
- service: switch.turn_on
data:
entity_id:
- switch.fibaro_system_fgs223_double_relay_switch
- switch.fibaro_system_fgs223_double_relay_switch_2
The 0.5 is used because the heater heats up the pool at 0.5 deg/hour.
I am turning my head into mush trying to work out how to calculate the trigger.
So far I think I have understood that:
āstates.sensor.time.stateā is better to use than ānow()ā because the latter is dependent on being triggered
āas_timestamp()ā is needed to convert standard time formats into seconds so that times can be used in calculations.
However I just canāt work out how to get the calculation to work. I havenāt even been able to get āas_timestamp(states.sensor.time.state)ā to work in the Template Editor. The result returned states āNoneā.
Did you configure sensor.time? Itās based on the Time and Date integration which requires you to configure the sensor before it can become available for use.
In your second automation you are comparing strings. In the first you are trying to compare timestamps butā¦
Put this in the developer tools template editor:
{{ as_timestamp(states.sensor.time.state) }}
You will see it returns None. Without the date you can not return a timestamp. You will have the same problem with the input_datetime.
I use the binary sensor definition below to trigger these sorts of automations. It adds todayās date to the input_datetime and compares it to now(). The function now() wonāt trigger updates of the sensor template so the entity sensor.time is used for this. It updates the template every minute.
- platform: template
sensors:
pool_start_time_active:
friendly_name: "Pool Start Time Active"
entity_id:
- sensor.time # required to update now()
- input_datetime.pool_start_time
value_template: >-
{% set d = now().strftime("%Y-%m-%d ") %}
{% set t = now().timestamp() %}
{% set pool_time_active = strptime(d + states('input_datetime.pool_start_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{{ pool_time_active < t < ( pool_time_active + 300) }}
This binary sensor will be on for five minutes beginning at your input_datetime setting.
Be careful trying to use {{ pool_time_active = t }} as there may be a fraction of a second difference between the calculation of t and the calculation of the input_datetime timestamp. And timestamps include fractions of seconds.
Your automation trigger becomes:
- alias: Turn pool on at calculated time
trigger:
platform: state
entity_id: binary_sensor.pool_start_time_active
to: 'on'
FYI you can also use this template to check if the time is between a range set by two input_datetimes. e.g.
- platform: template
sensors:
dining_heating_am_automation_time_active:
friendly_name: "Dining AM Automation Time Active"
entity_id:
- sensor.time # required to update now()
- input_datetime.dining_am_on_time
- input_datetime.dining_am_off_time
value_template: >-
{% set d = now().strftime("%Y-%m-%d ") %}
{% set t = now().timestamp() %}
{% set am_start = strptime(d + states('input_datetime.dining_am_on_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{% set am_end = strptime(d + states('input_datetime.dining_am_off_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{{ am_start <= t <= am_end }}
Thanks very much and apologies for the delay, life has got in the way. I will get back to you guys when I am looking at HA again. This looks very helpful and I appreciate your input.
Thank you all for your input with helping me understand the time formatting.
I have now got the set up to work. There were a few bumps along the way - please bear in mind I am new to this and not a programmer.
Based on @tom_lās advice I set up the sensor template as instructed. However the automation trigger would not work until I realised the entity was sensor.pool_start_time_active and not binary_sensor.pool_start_time_active. And then that the state was ātrueā rather than āonā. And after much head scratching (in fact the answer became apparent to me as I started this contribution which was going to be a request for more help) that the state has to be capitalised ie āTrueā.
Thank you @tom_l for your advice, and thank you @finity for pointing me to the comprehensive resource on formatting.
Here is the template sensor (with an extra 30 mins added on to the duration for āsafetyā:
calc_pool_pump_active:
friendly_name: "Calculated pool pump active"
entity_id:
- sensor.time # required to update now()
- input_datetime.routine_pool_end_time
- sensor.wirelesstag_pool_temp_temperature
- input_number.pool_desired_temp
value_template: >-
{% set d = now().strftime("%Y-%m-%d ") %}
{% set t = now().timestamp() %}
{% set dur = ((((((states.input_number.pool_desired_temp.state | float) - (states.sensor.wirelesstag_pool_temp_temperature.state | float ))/0.5)) * 3600) | int ) + (30*60) %}
{% set pool_start = strptime(d + states('input_datetime.routine_pool_end_time'), '%Y-%m-%d %H:%M:%S').timestamp() - dur %}
{% set pool_end = strptime(d + states('input_datetime.routine_pool_end_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{{ pool_start <= t <= pool_end }}
Here is the automation:
#Pool pump turns on at routine_pool_start_time
- alias: "Pool pump on"
trigger:
platform: state
entity_id: sensor.calc_pool_pump_active
to: 'True'
action:
- service: switch.turn_on
data:
entity_id: switch.fibaro_system_fgs223_double_relay_switch_2
- service: switch.turn_on
data:
entity_id: switch.fibaro_system_fgs223_double_relay_switch
- service: notify.paul_dev_email
data_template:
title: 'Pool Notification'
message: "Pool pump turned on. Pool temp is {{states('sensor.wirelesstag_pool_temp_temperature')}}"
- service: notify.paul_pushbullet
data:
message: 'Pool pump turned on'
Hello again!
I woke up this morning thinking how I could build into the calculation of how long the pool pump has to be on to raise the temperature to the desired level a variable that reflected how the external temperature affected the speed of raising the temperature.
I estimate that when the external temperature is above 20deg, the rate of rise in the pool is 0.5deg/hour. Between 10 and 20deg it is 0.35deg/hour. And below that it is 0.2deg/hour.
I have tried the following:
calc_pool_pump_active:
friendly_name: "Calculated pool pump active"
entity_id:
- sensor.time # required to update now()
- input_datetime.routine_pool_end_time
- sensor.wirelesstag_pool_temp_temperature
- input_number.pool_desired_temp
- sensor.nibe_47186_40004 #outdoor temp
value_template: >-
{% set d = now().strftime("%Y-%m-%d ") %}
{% set t = now().timestamp() %}
{% set p = (if(sensor.nibe_47186_40004 | float) > 20) %}
'0.5'
{% elif(10 <= (sensor.nibe_47186_40004 | float) <= 20) %}
'0.35'
{% else %}
'0.2'
{% endif %}
{% set dur = ((((((states.input_number.pool_desired_temp.state | float) - (states.sensor.wirelesstag_pool_temp_temperature.state | float ))/(p | float))) * 3600) | int ) + (30*60) %}
{% set pool_start = strptime(d + states('input_datetime.routine_pool_end_time'), '%Y-%m-%d %H:%M:%S').timestamp() - dur %}
{% set pool_end = strptime(d + states('input_datetime.routine_pool_end_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{{ pool_start <= t <= pool_end }}
But the added part does not work. I have tried to put it into the template tool, but I get an error Error rendering template: TemplateSyntaxError: Encountered unknown tag 'elif'.
I have tidied up the template sensor and added explanations of what is being done. Remove the explanations after value_template: >- : because all the comments were included in the result causing the sensor to show in HA as āUnknownā.
calc_pool_pump_active:
friendly_name: "Calculated pool pump active"
entity_id:
- sensor.time # required to update now()
- input_datetime.routine_pool_end_time
- sensor.wirelesstag_pool_temp_temperature
- input_number.pool_desired_temp
- sensor.outside_temp
value_template: >-
{% set d = now().strftime("%Y-%m-%d ") %} #set today's date
{% set t = now().timestamp() %} #set now as timestamp (number of seconds since epoch i.e. January 1, 1970)
{% set n = states('sensor.outside_temp')|float %} #set the outside temp as a number
{% set p = 0.45 if n > 5 else 0.3 %} #set the rate of temp rise (with the heating running) in deg/hour depending on the outside temp
{% set dur = ((states.input_number.pool_desired_temp.state | float - states.sensor.wirelesstag_pool_temp_temperature.state | float )/(p) * 3600) | int %} #set the number of seconds for pool to get to the desired temp
{% set pool_start = strptime(d ~ states('input_datetime.routine_pool_end_time'), '%Y-%m-%d %H:%M:%S').timestamp() - dur %} #add today's date to the pool start time and express as a timestamp
{% set pool_end = strptime(d ~ states('input_datetime.routine_pool_end_time'), '%Y-%m-%d %H:%M:%S').timestamp() %} #add today's date to the pool end time and express as a timestamp
{{ pool_start <= t <= pool_end }} #compare now with the pool start and pool end times with the result either 'True' or 'False'
There are places in your template where you are concatenating strings and using the plus operator (+) to do it.
The plus operator is for performing numeric addition but if the values arenāt numeric it performs a string concatenation. The use of a plus operator in this manner can sometimes lead to an unexpected result . Thatās why thereās another operator, the tilde (~), used for the sole purpose of concatenating strings.
Instead of this:
d + states('input_datetime.routine_pool_end_time')
do this:
d ~ states('input_datetime.routine_pool_end_time')
Thank you @123 for the explanation of + and ~. I have edited my previous reply to reflect this. That helps me understand what is going on in the d + states('input_datetime.routine_pool_end_time') part of the expression ie strings rather than numbers.
My plan is to have the heater turn on automatically two hours before my (or my gfs) alarm rings.
Iām getting that value from the app.
What I tried so far:
{{
states.sensor.lenovo_tb_j616x_next_alarm
-
states.input_datetime.2 # helper with 2 hours
}}
TypeError: unsupported operand type(s) for -: 'TemplateState' and 'TemplateState'
Doesnāt work and gives me the error I posted.
I tried a ton from here, canāt get it to work even with localtime, etc.
In the end my plan would be:
If person.hans is true and states.sensor.lenovo_tb_j616x_next_alarm < states.sensor.in2023_next_alarm
set helper to states.sensor.lenovo_tb_j616x_next_alarm - 2 hours
elseif person.gretel is true and states.sensor.in2023_next_alarm < states.sensor.lenovo_tb_j616x_next_alarm
set helper to states.sensor.in2023_next_alarm - 2 hours
else set helper to false
Access the state of an entity with e.g. {{ states('sensor.lenovo_tb_j616x_next_alarm') }}
All states are strings and may need converting to datetime objects, numbers etc in order to process them
With that, and using the docs, have another go and come back with at least partially-working code if you get stuck. Weāll also need to know what the states of the sensors youāre using look like, either from the template editor or with screenshots like this: