Time range condition template

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.

1 Like

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. :persevere:

Just as well I have a copy.

Thanks petro!

Needless to say, I feel like a bit of an idiot.

1 Like

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.

2 Likes

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 }}
1 Like

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}}