This wouldn’t be a pain in the ass if they just supplied a timestamp with today’s date. I have no idea why anyone would want a timestamp that isn’t useful when dealing with the current time.
That’s because internally it’s converted to a datetime.datetime, datetime.date or datetime.time, and when a datetime.datetime or datetime.time is converted to a string (which happens when the state is written to the state machine), it always shows HH:MM:SS (or I suppose HH:MM:SS.microsecond if the time’s microseconds is not zero.)
Another option: Subtract the date from the current time.
{% set t = now().timestamp()-strptime(now().strftime("%Y-%m-%d 00:00:00"),"%Y-%m-%d %H:%M:%S").timestamp() %}
result
- id: lounge_aircon_auto_on
alias: 'Lounge Room Aircon Scheduled On'
hide_entity: false
trigger:
- platform: state # AM on time trigger
entity_id:
- binary_sensor.lounge_ac_heat_required
- binary_sensor.lounge_ac_cool_required
to: 'on'
condition:
- condition: state # Only if AC is off (prevents oscillation between heat and cool mode if temperature over/undershoots set point)
entity_id: input_select.lounge_ac_mode
state: 'off'
- condition: template
value_template: >
{% set t = now().timestamp()-strptime(now().strftime("%Y-%m-%d 00:00:00"),"%Y-%m-%d %H:%M:%S").timestamp() %}
{% set am_start = state_attr('input_datetime.lounge_ac_am_on_time','timestamp') %}
{% set am_end = state_attr('input_datetime.lounge_ac_am_off_time','timestamp') %}
{% set pm_start = state_attr('input_datetime.lounge_ac_pm_on_time','timestamp') %}
{% set pm_end = state_attr('input_datetime.lounge_ac_pm_off_time','timestamp') %}
{{ am_start <= t <= am_end or pm_start <= t <= pm_end }}
- condition: or # And only if workday not tested or if is a workday
conditions:
- condition: state
entity_id: input_boolean.lounge_ac_workday
state: 'off'
- condition: state
entity_id: binary_sensor.workday_sensor
state: 'on'
action:
- condition: template
value_template: >
# verify that the temperature is actually different so that the option in the next
# action is always populated.
{{ states.sensor.aeotec_lounge_temperature.state != states.input_number.lounge_ac_heat_temp_set.state }}
- service: input_select.select_option
data_template:
entity_id: input_select.lounge_ac_mode
option: >
{% if states.sensor.aeotec_lounge_temperature.state < states.input_number.lounge_ac_heat_temp_set.state %}
Normal Heat
{% elif states.sensor.aeotec_lounge_temperature.state > states.input_number.lounge_ac_cool_temp_set.state %}
Normal Cool
{% endif %}
Thanks @petro.
I had to add two triggers for the case that heat/cool required is already true when the on times roll around and also put my extra temperature conditions back in for this.
Also the condition you added in the action section is not required as this is taken care of in the following template sensors:
- platform: template
sensors:
lounge_ac_heat_required:
friendly_name: "Lounge AC Heat Required"
value_template: >-
{{ states('sensor.aeotec_lounge_temperature') < states('input_number.lounge_ac_heat_temp_set') }}
lounge_ac_cool_required:
friendly_name: "Lounge AC Cool Required"
value_template: >-
{{ states('sensor.aeotec_lounge_temperature') > states('input_number.lounge_ac_cool_temp_set') }}
Spoke too soon. This is still giving me trouble.
For the following template sensors:
- platform: template
sensors:
lounge_ac_am_automation_time_active:
friendly_name: "Lounge AM Automation Time Active"
entity_id:
- sensor.time # required to update now()
- input_datetime.lounge_ac_am_on_time
- input_datetime.lounge_ac_am_off_time
- input_boolean.lounge_ac_am_automation
value_template: >-
{% set d = now().strftime("%Y-%m-%d ") %}
{% set t = now().timestamp() %}
{% set am_start = strptime(d + states('input_datetime.lounge_ac_am_on_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{% set am_end = strptime(d + states('input_datetime.lounge_ac_am_off_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{{ (am_start <= t <= am_end) and is_state('input_boolean.lounge_ac_am_automation', 'on') }}
lounge_ac_pm_automation_time_active:
friendly_name: "Lounge PM Automation Time Active"
entity_id:
- sensor.time # required to update now()
- input_datetime.lounge_ac_pm_on_time
- input_datetime.lounge_ac_pm_off_time
- input_boolean.lounge_ac_pm_automation
value_template: >-
{% set d = now().strftime("%Y-%m-%d ") %}
{% set t = now().timestamp() %}
{% set pm_start = strptime(d + states('input_datetime.lounge_ac_pm_on_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{% set pm_end = strptime(d + states('input_datetime.lounge_ac_pm_off_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{{ (pm_start <= t <= pm_end) and is_state('input_boolean.lounge_ac_pm_automation', 'on') }}
In the front end the sensors change from :
to
Exactly when they should.
However this automation never fires:
- id: lounge_aircon_auto_off
alias: 'Lounge Room Aircon Scheduled Off'
trigger:
- platform: state # AM or PM off time trigger
entity_id:
- binary_sensor.lounge_ac_am_automation_time_active
- binary_sensor.lounge_ac_pm_automation_time_active
to: 'off'
condition:
- condition: template # Only if AC is on
value_template: "{{ not is_state('input_select.lounge_ac_mode.state', 'Off') }}"
- condition: or # And only if workday not tested or if workday
conditions:
- condition: state
entity_id: input_boolean.lounge_ac_workday
state: 'off'
- condition: state
entity_id: binary_sensor.workday_sensor
state: 'on'
action:
- service: input_select.select_option
data_template:
entity_id: input_select.lounge_ac_mode
option: 'Off'
Looking at the template editor I see this before the event:
and this after:
I even tried my original sensors (with @pnbruckner 's suggestions):
- platform: template
sensors:
lounge_ac_am_automation_time_active:
friendly_name: "Lounge AM Automation Time Active"
entity_id:
- sensor.time # required to update now()
- input_datetime.lounge_ac_am_on_time
- input_datetime.lounge_ac_am_off_time
- input_boolean.lounge_ac_am_automation
value_template: >-
{{ (states.input_datetime.lounge_ac_am_on_time.attributes.timestamp <= (now().second + (now().minute * 60) + (now().hour * 3600)) <= states.input_datetime.lounge_ac_am_off_time.attributes.timestamp) and is_state('input_boolean.lounge_ac_am_automation', 'on') }}
lounge_ac_pm_automation_time_active:
friendly_name: "Lounge PM Automation Time Active"
entity_id:
- sensor.time # required to update now()
- input_datetime.lounge_ac_pm_on_time
- input_datetime.lounge_ac_pm_off_time
- input_boolean.lounge_ac_pm_automation
value_template: >-
{{ (states.input_datetime.lounge_ac_pm_on_time.attributes.timestamp <= (now().second + (now().minute * 60) + (now().hour * 3600)) <= states.input_datetime.lounge_ac_pm_off_time.attributes.timestamp) and is_state('input_boolean.lounge_ac_pm_automation', 'on') }}
I see the same thing. The state changes in the front end and the template editor exactly when it should but the automation never fires.
The reason I’m using template sensors is because I have to trigger on or test this condition in multiple automations and it does not seem efficient to keep having to write the long hand templates everywhere.
What events are happening in your logs? The automation looks good.
Excellent suggestion. Why didn’t I look there? I l only looked at the error log.
The automation is actually firing according to the log book. However my AC is not changing state when the input_select that controls it changes state… Hardware problem perhaps?
I logged into the web interface for the device that controls the AC unit - I can control it fine. So not that.
Oh bugger! I accidentally deleted the automation that manually controls the AC unit via an input_select when tidying up all the time/temperature automations.
Just as well I have a copy.
Thanks petro!
Needless to say, I feel like a bit of an idiot.
We’ve all been there…
So one last question, do you see any advantage or disadvantage for using either one of these templates? They both work and both do the same thing:
{% set timestamp_no_date = (now().second + (now().minute * 60) + (now().hour * 3600)) %}
{{ (states.input_datetime.lounge_ac_pm_on_time.attributes.timestamp <= timestamp_no_date <= states.input_datetime.lounge_ac_pm_off_time.attributes.timestamp)
and is_state('input_boolean.lounge_ac_pm_automation', 'on') }}
or
{% set d = now().strftime("%Y-%m-%d ") %}
{% set t = now().timestamp() %}
{% set pm_start = strptime(d + states('input_datetime.lounge_ac_pm_on_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{% set pm_end = strptime(d + states('input_datetime.lounge_ac_pm_off_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
{{ (pm_start <= t <= pm_end) and is_state('input_boolean.lounge_ac_pm_automation', 'on') }}
Nope, either are fine. Personally, I avoid using states.domain.entity.attributes.attr
. Only because of startup issues and errors when those devices haven’t been created. If you use state_attr('domain.entity','attr')
your templates will return results at all times if you convert them to the proper type. I.E. state_attr('domain.entity','attr') | int
will convert the result to 0 if domain.entity doesn’t exist yet. Then your template will still resolve to a false/off state and no errors will be produced in the logs.
Ok so
states.input_datetime.lounge_ac_pm_on_time.attributes.timestamp
Is easy enough to convert to state_attr() format:
state_attr('input_datetime.lounge_ac_am_off_time', 'timestamp')
| float
However one template that is glitching for me on start up is:
{{ states('sensor.aeotec_lounge_temperature') > states('input_number.lounge_ac_cool_temp_set') }}
But I am not sure how to represent with state_attr() - or even if I should.
Just convert the states into floats and it will default to zero when ‘undefined’ is returned during startup:
{{ states('sensor.aeotec_lounge_temperature') | float > states('input_number.lounge_ac_cool_temp_set') | float }}
would that apply too for the mold indicator, which uses an entity_id, and always errors out on startup:
# https://home-assistant.io/components/sensor.mold_indicator/
- platform: mold_indicator
name: Schimmel sensor
indoor_temp_sensor: sensor.temperatuur_living
indoor_humidity_sensor: sensor.luchtvochtigheid_living
outdoor_temp_sensor: sensor.rsd_temperature
calibration_factor: 1.16
as do several other statistics sensors
The sensors themselves error or templates that use them?
I think the sensors themselves, that together make up the Mold indicator. see the log:
2018-09-18 23:32:00 ERROR (SyncWorker_3) [homeassistant.components.sensor.mold_indicator] Unable to parse sensor temperature: unknown
2018-09-18 23:32:00 ERROR (SyncWorker_18) [homeassistant.components.sensor.mold_indicator] Unable to parse sensor humidity: unknown
2018-09-18 23:32:02 ERROR (MainThread) [homeassistant.components.sensor.statistics] mean requires at least one data point
2018-09-18 23:32:02 ERROR (MainThread) [homeassistant.components.sensor.statistics] variance requires at least two data points
2018-09-18 23:32:02 ERROR (MainThread) [homeassistant.components.sensor.statistics] variance requires at least two data points
tha last 3 lines are from a statistics sensor, that apparently isnt initialized yet either.
and, an ever returning error:
2018-09-18 23:35:54 ERROR (MainThread) [homeassistant.core] Error doing job: Future exception was never retrieved
Traceback (most recent call last):
File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.6/site-packages/homeassistant/util/__init__.py", line 325, in wrapper
result = method(*args, **kwargs)
TypeError: update() takes 1 positional argument but 2 were given
2018-09-18 23:35:54 ERROR (MainThread) [homeassistant.core] Error doing job: Future exception was never retrieved
Traceback (most recent call last):
File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.6/site-packages/homeassistant/util/__init__.py", line 325, in wrapper
result = method(*args, **kwargs)
TypeError: update() takes 1 positional argument but 2 were given
2018-09-18 23:35:54 ERROR (MainThread) [homeassistant.core] Error doing job: Future exception was never retrieved
Traceback (most recent call last):
File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.6/site-packages/homeassistant/util/__init__.py", line 325, in wrapper
result = method(*args, **kwargs)
TypeError: update() takes 1 positional argument but 2 were given
2018-09-18 23:35:54 ERROR (MainThread) [homeassistant.core] Error doing job: Future exception was never retrieved
Traceback (most recent call last):
File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.6/site-packages/homeassistant/util/__init__.py", line 325, in wrapper
result = method(*args, **kwargs)
TypeError: update() takes 1 positional argument but 2 were given
No idea where and how to start looking for that one…
I see start up mold sensor these errors too. Unfortunately that’s not something we have control over (as it is the component itself that has start up dependency problems).
will see if I can raise an issue on this, thanx for adding to the report.
see: https://github.com/home-assistant/home-assistant/issues/16733
Yeah, it doesn’t look like this is normal startup errors related to templates. What’s odd about these errors is that it doesn’t appear to come from the mold indicator. Have you turned on debug logging to view what the component is outputting?
No not yet. did that before once, and it almost halted my system… Other than setting debug globally, could I set it to a separate component, based on this log output?
Hmm. These are still occasionally glitching at start-up.
- platform: template
sensors:
lounge_ac_heat_required:
friendly_name: "Lounge AC Heat Required"
value_template: >-
{{ states('sensor.aeotec_lounge_temperature') | float < states('input_number.lounge_ac_heat_temp_set') | float }}
lounge_ac_cool_required:
friendly_name: "Lounge AC Cool Required"
value_template: >-
{{ states('sensor.aeotec_lounge_temperature') | float > states('input_number.lounge_ac_cool_temp_set') | float}}