Change an input_boolean once a certain point in time has come

I’m trying to do something that I thought would be really simple:
Set a boolean to ‘true’ or ‘on’ when a certain point in time has gone by - can’t seem to figure it out.

I have a sensor that calculates when my sprinklers should run next time from the time the ran previously:

- platform: template
  sensors:
    sprinkler_next_runval:
      friendly_name: Sprinkler Next Runval
      value_template: '{{ ((states.input_datetime.sprinkler_last_runtime.attributes["timestamp"]) + (3600 * 24 * (states.sensor.sprinkler_offset_in_days.state | float) - 60)) }}'

Once this time has come I want to indicate that it is now an option to run the sprinklers again by using a simple automation (I still want to check a few conditions, though, like accumulated precipitation over the last 7 days and that it’s actually not during the middle of the day).

I have spent the last two days trying to make this work, but I can’t, the trigger doesn’t seem to work in my setup:

- alias: Set Time to Water State
  trigger:
    platform: template
    value_template: "{{ ((as_timestamp(now()) | float) > ((states.sensor.sprinkler_next_runval.state) | float)) }}"
  action:
    - service: homeassistant.turn_on
      entity_id: input_boolean.time_to_water

If I test it in the template editor it works fine, as part of the automation it does not.
Anybody out the who can help?

I seem to remember reading something about the use of .state in a template (I’m pretty inexperienced, hope I’m helping here).

Are you sure the value you need is stored in states.sensor.sprinkler_next_runval.state ? Shouldn’t you get rid of the last part ‘.state’ ?

Thanks for the tip.

But that’s what I get for looking at '{{ (states.sensor.sprinkler_next_runval.state) }}' in the template editor:

‘1522028700.0’

And that’s what I get when I take the .state out, i.e using: '{{ (states.sensor.sprinkler_next_runval) }}':

‘<template state sensor.sprinkler_next_runval=1522028700.0; friendly_name=Sprinkler Next Runval @ 2018-03-25T18:44:27.648788-07:00>’

Try an intermediate variable

Untested:

- alias: Set Time to Water State
  trigger:
    platform: template
    value_template: >-
      {% set next_runval = states('sensor.sprinkler_next_runval') | float %}
      {{ as_timestamp(now()) | float > next_runval }}
  action:
    - service: homeassistant.turn_on
      entity_id: input_boolean.time_to_water

Tried everything that was suggested here and then some, so far to no avail.

Looks like now() does not trigger an automation reliably :frowning:

I’m currently setting up the trigger, i.e. were now passing the new earliest time, to be used as a condition, i.e. have we now passed the earliest time already, and am setting up a new trigger to check for this condition every so often.

- alias: Set Time to Water State
  trigger:
    platform: time
    hours: '/1'
    minutes: 00
    seconds: 00
  condition:
    condition: and 
    conditions:
      - condition: state
        entity_id: input_boolean.time_to_water
        state: 'off'
      - condition: template
        value_template: >-
          {% set next_runval = states('sensor.sprinkler_next_runval') | float %}
          {% set now_val = as_timestamp(now()) | float %}
          {{ now_val > next_runval }}
  action:
    - service: homeassistant.turn_on
      entity_id: input_boolean.time_to_water

You might make use of the input_datetime:

The example automation compares the input_datetime sensor with a time sensor.

So basically, don’t compare with now(), but instead with sensor.time.

try

value_template: ‘{{ states.sensor.time.state >= (states.sensor.sprinkler_next_runval.attributes.timestamp | int | timestamp_custom("%H:%M", False)) }}’

Thanks for the hints - tired it again, but didn’t work either.
I have now come to the conclusion that comparing something to the current time simply doesn’t work as a trigger.

I use now() all the time for triggers in my automations with no issues. I know it sounds dumb, but try changing your filter from float to int.

For example, this trigger has been running perfectly:

  trigger:
    - platform: template
      value_template: '{{ (( as_timestamp( states.sun.sun.attributes.next_dusk ) | int ) - 600) < ( as_timestamp( now() ) | int ) }}'

Also, are you sure you are getting correct timestamps in a epoch format? I would recommend you test out in the template editor

{{ ( states.sensor.sprinkler_next_runval.state | float ) }}
{{ ( as_timestamp( now() ) | int ) }}

And then go to https://www.epochconverter.com/ and copy the intergier timestamps in and see if the times/dates are as expected.

Thanks @will,

When I put this in the template editor

{% set next_runval = states('sensor.sprinkler_next_runval') | int %}
{% set now_val = as_timestamp(now()) | int %}
{{ now_val }}
{{ next_runval }}
{{ now_val > next_runval }}

The output on the right hand side of the screen shows this:

1522107268
1522107360
False

It does not update the output for {{ now_val }} at all, it stays at the same value, so does the indication of the result: False

Only when I make a change in the template editor, e.g. by simply adding a ' at the end of any line the displayed values change once.

I’m completely baffled - and glad that it works for you.

Just for the record, here is the last config I tried:

######################################################################
- alias: Set Time to Water State
  trigger:
    platform: template
    value_template: >-
      {% set next_runval = states('sensor.sprinkler_next_runval') | int %}
      {% set now_val = as_timestamp(now()) | int %}
      {{ now_val > next_runval }}
  action:
    - service: homeassistant.turn_on
      entity_id: input_boolean.time_to_water

With me sensor being defined as a timestamp:

- platform: template
  sensors:
    sprinkler_next_runval:
      friendly_name: Sprinkler Next Runval
      value_template: '{{ ((states.input_datetime.sprinkler_last_runtime.attributes["timestamp"]) + ((3600 * 24 * (states.sensor.sprinkler_offset_in_days.state | float)) - 60)) }}'

image

So the now() value is only evaluated once in the template editor so it shouldn’t update unless the template editor recompiles the template.

Also, the automations evaluate the automation templates every x number of milliseconds (not sure what it is, 100, 500, 2000, etc.). So when you use now() in your logic you need to make sure you aren’t setting the comparison to close, for example, if you did:

1522107360 == as_timestamp ( now() ) | int

That would not fire every time because the automation task would of had to evaluate the automation at the exact second now() equalued 1522107360. So you want to make sure you are always using a comparison that has a larger window.

Try this top code instead:

{% set next_runval = states('sensor.sprinkler_next_runval') | int %}
{% set now_val = as_timestamp( now() ) | int %}
{{ now_val }}
{{ next_runval }}
{{ next_runval < now_val }}

Because the time is always increasing but your next run time is static I would recommend basing the trigger when now is greater than next_runval.This way, if the automation engine fires 2000 or 10000ms late, your automation will still be picked up. With the way you originally wrote the code, you created a 1m and 26s window in which the statement would evaluate as true, otherwise, it would always be false (which isn’t your intention).

So I can’t check if your sensors are giving out the correct output but I did check your math and everything looks great.

I used a timestamp of 3/25/18 at 12:00:00 and I got a next run time of 3/27/18 at 11:59:00 (assuming your offset in days = 2)

{{ ( 1521979200 + ( (3600 * 24 * (2) ) - 60) ) }}

Try rewriting your automation trigger to be the following and see if it works:

  trigger:
    platform: template
    value_template: ( states.sensor.sprinkler_next_runval.state | int ) < ( as_timestamp( now() ) | int )

- platform: template
  sensors:
    sprinkler_next_runval:
      friendly_name: Sprinkler Next Runval
      value_template: '{{ (( states.input_datetime.sprinkler_last_runtime.attributes["timestamp"]  | int) + ((3600 * 24 * (states.sensor.sprinkler_offset_in_days.state | int)) - 60)) }}'

I changed the comparison order, changed the states() to the states object, and I changed your floats to int (which shouldn’t make a difference but why use a float when you need an integer - save yourself 8 bytes of RAM :grinning:). Keep in mind, this might not run at the exact second you want, it might run a few seconds later but it should work once the automation task evaluator runs through everything.

I hope this fixes your issue.

1 Like

Thanks for all your effort @will - highly appreciated.

I ended up not using the boolean at all - I’m using the comparison of now() with the next_run_val in a condition to evaluate it only once, at the time the sprinklers should com on (or not).

I think I tried to over-complicate it it, but am sure the occasion will come up eventually where I want to use now() as a trigger.

Thanks everybody for chiming in.