Binary sensor not updating with time change

I have the following binary sensor which should return true if the current time falls in between the values of two input_datetime entities. If I set the “end” input_datetime to the current time the sensor reports True as expected. However, when the time moves past the end time the sensor still reports true.

I actually have an additional input_boolean as part of this binary_sensor (not shown) and if I turn it off and on after the time progresses the sensor reports the correct value.

Why isn’t the sensor updating every time “now().strftime(’%H%M’)” changes? Any ideas on how I can fix this?

    range_sensor:
      value_template: "{{

((states.input_datetime.starttime.attributes.timestamp  | timestamp_custom('%H%M', False) | int ) | int  <=  (now().strftime('%H%M')  | timestamp_custom('%H%M', False) | int)) and 

  ((states.input_datetime.endtime.attributes.timestamp  | timestamp_custom('%H%M', False) | int ) | int  >=  (now().strftime('%H%M')  | timestamp_custom('%H%M', False) | int)) }}"

You need to post your full code.
I suspect that you need to list sensor.time as an entity_id so that it checks the template every minute

Because it doesn’t change (in the way you think it does).

now() is a function, not an entity. An entity has a state that Home Assistant can monitor for changes. A function produces a result when executed and at no other time.

For more information see: Templates without entities using now()

You should be able to replace now() with as_timestamp(states(‘sensor.time’)) and get roughly the same result because sensor.time is an entity that will trigger the template to get recalculated.

What Steve said or add this to the Template Sensor’s configuration:

      entity_id: sensor.time

Now the template will be evaluated every minute because you’ve instructed Home Assistant to monitor the state-changes for sensor.time (which changes every minute).

Ensure you define sensor.time in your configuration file (see docs).

I posted the relevant code which just has the part checking to see if the current time is between two times, however here is the whole shebang


   mon_5:
      value_template: "{{ ((is_state('input_boolean.mon_5', 'on'))) and (now().strftime('%A') == 'Monday') and ((states.input_datetime.monstart_date_5.state  == states.input_datetime.monend_date_5.state) or ((states.input_datetime.monstart_date_5.attributes.timestamp  | timestamp_custom('%H%M', False) | int ) | int  <=  (now().strftime('%H%M')  | timestamp_custom('%H%M', False) | int)) and ((states.input_datetime.monend_date_5.attributes.timestamp  | timestamp_custom('%H%M', False) | int ) | int  >=  (now().strftime('%H%M')  | timestamp_custom('%H%M', False) | int))) }}"

In the template editor the following reports None

{{
as_timestamp(states('sensor.time'))
}}

Though the following shows 7:14 (I don’t know what it will report at 1pm, hopefully 13:00)

{{
states('sensor.time')
}}

In my configuration.yaml file I have

sensor: !include sensors.yaml

And in sensors.yaml I have, amongst other things


- platform: time_date
  display_options:
    - 'time'
    - 'date'
    - 'date_time'
    - 'date_time_iso'
    - 'time_date'
    - 'time_utc'
    - 'beat'

So far, all three responders have suggested that you incorporate sensor.time
So put : -

Into your sensor, in line with the value_template but above it.
When I get home I’ll look at the whole template and see if it can be optimised. But sometimes ‘optimising’ can make it less readable and so harder to maintain.
It may be best just to get it working, as your current template reflects the way ‘your’ mind works and so you’ll be more comfortable with that.

Why convert it to a time stamp? Just use it as a string
Eg “{{ states(time.sensor) == states(‘input_datetime.start_time’) [0:5]}}”
This gets rid of the seconds to allow a direct comparison

“{{ states(time.sensor) == states(‘input_datetime.start_time’) [0:5]}}”

One more issue however

How can I get the day of week from sensor.date?

{{ states(‘sensor.date’) }}

So that this returns Monday?

  1. The output of sensor.date is the date as a string (2019-10-28).
  2. Convert this date string into a datetime object using the strptime function.
  3. Use the resulting object’s strftime method to produce the day of week.

Long-hand, step-by-step version:

{% set date_string = states('sensor.date') %}
{% set datetime_object = strptime(date_string, '%Y-%m-%d') %}
{% set day_of_the_week = datetime_object.strftime('%A') %}
{{ day_of_the_week }}

All-in-one-line version:

{{ strptime(states('sensor.date'), '%Y-%m-%d').strftime('%A') }}

NOTE
This can be used to determine the ‘day of the week’ for any given date. Just replace states('sensor.date') with a date-string like '2019-10-31'.

1 Like

or just use : -
now().weekday()
This returns the weekday number, 0 being Monday, 6 being Sunday
This is quick, easy and compact; to use in templates, but if you need Monday or Mon use : -
as_timestamp(now()) | timestamp_custom(’%A’)
or
as_timestamp(now()) | timestamp_custom(’%a’)
You already have the update from sensor.time so you don’t need the update from sensor.date

Looking at your whole template I think you don’t need sensor.time as sensor.date will do (you don’t have any time values that I can see)
Anyway, I’m not sure (because I don’t have any input_datetime’s with dates so you will have to check and edit the text strings accordingly) but I’d go with : -

   mon_5:
      enitity_id: sensor.date
      value_template: "{{ (is_state('input_boolean.mon_5', 'on') and (now().weekday() == '0') and (states('input_datetime.monstart_date_5') == states('input_datetime.monend_date_5') or (states('input_datetime.monstart_date_5') <= states('sensor.date') <= states('input_datetime.monend_date_5'))) }}"

And I think you may be able to get away without the entity_id: bit too (as it’s in the template)

Edit: As I said, I can’t test this so you will have to test it yourself and feedback any issues - But it seems to me that you have here the following : -
Monday Binary enabled AND it’s a Monday AND ((start == end) OR (start <= today <= end))
Which seems odd to me, I’d have gone with
(Monday is enabled and it’s a Monday) or (it’s a Monday between these two dates)

   mon_5:
      enitity_id: sensor.date
      value_template: "{{is_state('input_boolean.mon_5', 'on') and (now().weekday() == '0') or (states('input_datetime.monstart_date_5') <= states('sensor.date') <= states('input_datetime.monend_date_5')) }}"

Edit2: I’ve messed up with the brackets here, so check the brackets carefully

This example should meet the requirements you’ve described.

The template determines if the current time (represented as a timestamp) falls within a start datetime and an end datetime (also represented as timestamps).

    range_sensor:
      entity_id:
        - sensor.time
      value_template: >
        {{ state_attr('input_datetime.starttime', 'timestamp') <= now().timestamp() <= state_attr('input_datetime.endtime', 'timestamp') }}

EDIT
Configuration was reduced to avoid redundancy.