SOLVED: Time trigger with input_datetime not working

HASS version 0.84.5 running and “in principle” everything runs fine but I’ve been having a hell of a time trying to turn switches on/off on a schedule (time based, every day). I’ve read the forum up and down and the following seems to have worked for most people:

input_datetime:
  switch_on:
    has_time: true
    has_date: false
    initial: '21:30'
  switch_off:
    has_time: true
    has_date: false
    initial: '23:30'

And in automations.yaml:

  - alias: switch_on
    trigger:
      - platform: template
        value_template: "{{ states.sensor.time.state == (states.input_datetime.switch_on.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
    action:
      - service: homeassistant.turn_on
        entity_id: switch.my_switch

  - alias: switch_off
    trigger:
      - platform: template
        value_template: "{{ states.sensor.time.state == (states.input_datetime.switch_off.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
    action:
      - service: homeassistant.turn_off
        entity_id: switch.my_switch

But these never, ever fire. In my desperation, I resorted to this, even clunkier construct I found in an old post:

sensor:
# Time with seconds
  - platform: command_line
    name: time_seconds
    scan_interval: 0.5
    command: date +"%T"

with the following value template as trigger:

value_template: "{{ states('sensor.time_seconds') == (states.input_datetime.switch_on.attributes.timestamp | int | timestamp_custom('%H:%M:%S', False)) }}"

These triggers at least work, but at the expense of having HASS execute a shell command twice a second and “spamming” my log.

What’s the trick to make these work with the builtin time sensor?

Are you sure that initial: '23:30' is actually 11:30 or is it 23 minutes and 30 seconds after midnight?

You’d want to verify that first.

Go check it in the template editor:

states('input_datetime.switch_on')

If that truely is HH:MM, then this template should work as a trigger:

      - platform: template
        value_template: "{{ states.sensor.time.state == states.input_datetime.switch_on.state }}"

If that doesn’t work, post the output of states('input_datetime.switch_on') from the template editor and I can help you build an equation that will work.

1 Like

Thanks. Yes, I verified that the initial XX:YY values are really taken as HH:MM as intended, not 00:MM:SS.

In the template editor (just learned about that, very useful!), with

{{ states("input_datetime.switch_on") }}
{{ states("input_datetime.switch_off") }}

I get

21:30:00
23:30:00

But

{{ states("sensor.time.state") }}
{{ states("sensor.time") }}

returns

unknown
unknown

!

OMG, it’s this one here, right?

1 Like

YES! After enabling the sensor, both

{{ states("sensor.time") }}
{{ states.sensor.time.state }}

return, e.g.

13:44

Feel stupid now, but I sure learned a lot! Thanks for the help!

BTW because the time from input_datetime has the “:00” at the end while the sensor.time.state, doesn’t, the final value template looks as follows:

value_template: "{{ states.sensor.time.state == states.input_datetime.switch_off.state[0:5] }}"

The [0:5] gets the first five characters and discards the “:00” at the end.

2 Likes

Yep that should work!

I have a similar question, but instead of a trigger I want to use the input time in a condition so that the automation does not fire before or after a certain time. Can I use something like

  - platform: template
    value_template: "{{ states('sensor.time') >= (states.input_datetime.time_off.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"

Would that work?

No because the 2 objects are strings. You need to convert them both into numerical values. The simplest way to get there would be this (without getting into crazy formatting).

  - platform: template
    value_template: "{{ states.sensor.time.last_updated >= (states.input_datetime.time_off.attributes.timestamp | int }}"

But be warned. This will trigger every minute (on the minute) after the datetime has been reached. A safe way to approach the situation would be to add a timerange:

  - platform: template
    value_template: > 
     {% set trigger_time = states.input_datetime.time_off.attributes.timestamp | int %}
     {% set offset = 30 %}
     {{ trigger_time - 30 <= states.sensor.time.last_updated <= trigger_time + 30 }}"

This essentially creates a minute window (that starts on the 30 second mark) in which the event can occur. It should only fire once.

Thanks, @petro! As I want to limit my automation ot certain times, I will not use the time as trigger but only as a condition, so the problem with firing every minute should not occcur. Thanks for the example though!

I just changed it according to your first example and at least it throws no errors so far, I think there was still an unneeded “(” though. :wink:

One thing I noticed after asking (at least if I’m not mistaken): Conditions do not use “platform”.
So all in all it looks like this:
- condition: template value_template: "{{ states.sensor.time.last_updated >= states.input_datetime.time_off.attributes.timestamp | int }}"

By tomorrow I should know if it works. :slight_smile:

Yah, I think thats a copy/paste error.

Yes conditions don’t use platform. For the most part, the word ‘platform’ is replaced with ‘condition’ for conditions. This works for most platform → condition. It does not work for all of them, so it’s typically best to consult the condition documentation.

I just tested it and it is not working (yet). Trying to narrow it down I did some testing and removed conditions/triggers, but it’s still not working in this simplified form. The trigger and the action both work in other automations, so I guess I still have an error in the conditions…

- id: coffee
  trigger:
  - entity_id: device_tracker.phone
    platform: state
    to: home
  condition:
  - condition: state
    entity_id: 'input_boolean.coffee'
    state: 'on'
  - condition: state
    entity_id: 'binary_sensor.workday_sensor'
    state: 'on'
  - condition: template
    value_template: "{{ states.sensor.time.last_updated >= states.input_datetime.time_workday_on.attributes.timestamp | int }}"
  - condition: template
    value_template: "{{ states.sensor.time.last_updated < states.input_datetime.time_workday_off.attributes.timestamp | int }}"
  action:
  - service: switch.turn_on
    entity_id: switch.coffee

Previously, I also had the conditions nested in an “and”, but according to the webinterface “condition: and” is not supported. Is that correct?

All lists of conditions are treated as and, so it’s not necessary.


Your automation isn’t working because you forgot .timestamp() on the datetime objects. Which was because I forgot it originally!

  - condition: template
    value_template: "{{ states.sensor.time.last_updated.timestamp() >= states.input_datetime.time_workday_on.attributes.timestamp | int }}"
  - condition: template
    value_template: "{{ states.sensor.time.last_updated.timestamp() < states.input_datetime.time_workday_off.attributes.timestamp | int }}"

Also, if you are using this as a condition, you don’t even need to use the states.sensor.time. That’s only needed for triggers and template sensors. You can just use now()

  - condition: template
    value_template: "{{ now().timestamp() >= states.input_datetime.time_workday_on.attributes.timestamp | int }}"
  - condition: template
    value_template: "{{ now().timestamp() < states.input_datetime.time_workday_off.attributes.timestamp | int }}"

and if you want to be super crafty, you can do this in one template.

  - condition: template
    value_template: "{{  states.input_datetime.time_workday_on.attributes.timestamp | int <= now().timestamp() < states.input_datetime.time_workday_off.attributes.timestamp | int }}"

You’re fogiven. :joy:

Thank you so much! An example like this be in the docs (if it’s in there, it’s hidden quite well I would say :wink:).

It is still not working though. Do you have an example what now().timestamp() looks like as a value? Is it given as UNIX timestamp? Looking at the entities I noticed that the inputs are specified as “seconds of the day” (I defined them to be w/o date). Would now().second give me the same “format” (e.g. would it be 18000 or 0 at exactly 5 am)?

I played a bit more with it and there seems to be a difference between the timestamps I would guess.
This on its own works:

  - condition: template
    value_template: "{{ now().timestamp() >= states.input_datetime.time_workday_on.attributes.timestamp | int }}"

It stops working when I add the second time. But if I change the comparison to “>=” as well instead of “<” (just for fun), the automation is triggered, even if “now” is 20:20 and time_workday_off is set to 22:00. So (just guessing) I would say “now” is UNIX time and my inputs are “seconds of the day”.


I don’t think this is “the way to go”, but I finally got it to work the way I wanted (not very handy though):

now().hour * 3600 + now().minute * 60 + now().second
1 Like

I Made a template sensor:

  - platform: template
    sensors:
      vacation_sensor:
        friendly_name: 'Vacation Sensor'
        entity_id: sensor.time_date
        value_template: >
          {% if state_attr('input_datetime.vacation_departure', 'timestamp') | int <= now().timestamp() and state_attr('input_datetime.vacation_arrival', 'timestamp') | int > now().timestamp() -%}
            On Vacation!
          {% elif state_attr('input_datetime.vacation_arrival', 'timestamp') | int <= state_attr('input_datetime.vacation_departure', 'timestamp') | int -%}
            Error!
          {%- else -%}
            Not On Vacation
          {%- endif %}
        icon_template: >
          {% if state_attr('input_datetime.vacation_departure', 'timestamp') | int <= now().timestamp() and state_attr('input_datetime.vacation_arrival', 'timestamp') | int > now().timestamp() -%}
            mdi:airplane
          {% elif state_attr('input_datetime.vacation_arrival', 'timestamp') | int <= state_attr('input_datetime.vacation_departure', 'timestamp') | int -%}
            mdi:alert-circle
          {%- else -%}
            mdi:home
          {%- endif %}

58%20AM
04%20AM
38%20AM
Then use it in node red as a condition.

I also have it notify me every 2 minutes if there’s an error as the sensor gets updated every minute and I could miss it and reverse the dates accidentally:

Can also use yaml:

  condition:
      condition: state
      entity_id: sensor.vacation_sensor
      state: 'On Vacation!'

Hope it helps.

1 Like

Hey @RevelRob

First I want to say above looks great! Immediately started using it when I found it :smile:
I only wondered how you made the date / time notation on arrival and departure.

image
It looks very different in my lovelace view. (I have the text in Dutch)

Hey @klaasnicolaas
Glad you’re using it!
I’m not sure what you mean exactly. Do you mean how I got it to show both date and time?
If so, you have to make sure that has_date and has_time are both set to true: https://www.home-assistant.io/components/input_datetime/
Hope that helps.

Is not quite what I meant.

I mean the date format, in yours the sensor is written out as mm-dd-yyyy
In my overview the format is: yyyy-mm-dd I wondered how I can get this adjusted.