Time to Leave for Work Sensor returning error

I am trying to create a sensor that will return a color based on how much time is left before I have to leave to get to work by a certain time according to the google map sensor.

The sensor shows as unavailable and I am getting the following error? Could someone help me figure out where I went astray. Many thanks
Not sure where the float is coming from:
TemplateError(‘TypeError: unsupported operand type(s) for +: ‘datetime.datetime’ and ‘float’’) while processing

    work_drive_time_color:
      value_template: >
        {% set arrival = '10:45' %}
        {% set travel_time = states('sensor.google_travel_time') | float / 60 %}
        
        {% set arrival = strptime(arrival, '%H:%M') %}
        {% set t = strptime(states.sensor.time.state,'%H:%M') %}
        {% set delta = arrival.hour + arrival.minute/60 - (t + travel_time) %}
        {% if delta*60 <= 15 and delta*60>=0 %}
          green
        {% elif  delta*60 <0  and delta*60 >= -10%}
          yellow
        {% elif delta*60 <= -10 %}
          red
        {% else %}
          off
        {% endif %} 

The variable t is a datetime object.

{% set t = strptime(states.sensor.time.state,'%H:%M') %}

The variable travel_time is a float value (numeric).

        {% set travel_time = states('sensor.google_travel_time') | float / 60 %}

The end of this template attempts to add a datetime object and a float which is not permitted.

{% set delta = arrival.hour + arrival.minute/60 - (t + travel_time) %}
                                                   ^^^^^^^^^^^^^^^

Which results in the error message:

unsupported operand type(s) for +: ‘datetime.datetime’ and ‘float

I think I understand what the template is attempting to do so I have converted it to consistently use datetime and timedelta objects. I assume travel_time is in minutes (if I’m wrong about that then the template will need adjustments). Try this version:

    work_drive_time_color:
      value_template: >
        {% set arrival = now().replace(hour=10, minute=45) %}
        {% set travel_time = states('sensor.google_travel_time') | float / 60 %}
        {% set delta = ((arrival - (now() + timedelta(minutes=travel_time))).seconds / 60) | round %}
        {% if 0 <= delta <= 15 %} green
        {% elif  -10 <= delta < 10 %} yellow
        {% elif delta <= -10 %} red
        {% else %} off
        {% endif %}

Here’s how this line works:

        {% set delta = ((arrival - (now() + timedelta(minutes=travel_time))).seconds / 60) | round %}

It adds travel_time in minutes to the current time. It does this by adding a timedelta object to a datetime object.

now() + timedelta(minutes=travel_time)

It subtracts that value (a datetime object) from the arrival time (also a a datetime object).

arrival - (now() + timedelta(minutes=travel_time))

The resulting value (a timedelta object) is reported in seconds then divided by 60 to get minutes:

(arrival - (now() + timedelta(minutes=travel_time))).seconds / 60

The entire result is rounded to zero decimal places.

((arrival - (now() + timedelta(minutes=travel_time))).seconds / 60) | round`

I am still soaking this up. Thank you immensely. I will have to review this a few more time times.

Based on your explanations that’s what I wanted to do. When I have 0-15 minutes to get to my job return green, When 0 to 10 minutes late yellow and everything else red .
I changed the time to in set to {% set arrival = now().replace(hour=14, minute=45) %}
which was 15 minutes early which I thought would have returned green but no luck. It actually turned green green it looks like when I would be 15 minutes late

I will check again later, as I am using my phone instead of my computer but I could not resist the urge to see where I went wrong.

Thanks so much

now() + timedelta(minutes=travel_time)

I thought I had to first convert the minutes into seconds to do the computations but it seems that by specifying minutes above it handles the calculations automatically.

Your explanations make sense and opened my mind. Thanks again

I wrote the template a long time ago and it worked at one point, however it didn’t use datetimes it used timestamps. The intent is to simply spit out a color based on how close we are to an arrival time. I was meaning to update the template in the thread, but I forgot.

I replied to the old post , but I thought since it was old I thought no one might be monitoring. Once it working I will post the completed code. Maybe it will help someone else. I think I am close :slight_smile:
Thanks for laying the ground work and inspiring me

pretty sure the travel times are in minutes, so

    work_drive_time_color:
      value_template: >
        {% set t = now() %}
        {% set arrival = t.replace(hour=10, minute=45) %}
        {% if arrival > t %}
          {% set travel_time = states('sensor.google_travel_time') | float %}
          {% set red = arrival - timedelta(minutes=travel_time + 5) %}
          {% set yellow = arrival - timedelta(minutes=travel_time + 10) %}
          {% if t > red %} red
          {% elif t > yellow %} yellow
          {% else%} green
          {% endif %}
        {% else %} off
        {% endif %}

EDIT: Was having a brainfart. Had to edit it.

Hi thanks again. It is not showing green for when there is 15 minutes to leave work, yellow for when I am 10 minutes late, and red for everything else.
Do the minutes for the current time (now()) need to be converted ? The current time is being added to the travel time and then the final value is converted to seconds

{% set delta = ((arrival - (now() + timedelta(minutes=travel_time))).seconds / 60) | round %}

But I see minutes travel was already converted to seconds:

{% set travel_time = states('sensor.google_travel_time') | float / 60 %}

How can I check the value of each variable or return them in the if else template so I could see the values. I feel I can tweak what you have if I could see the value of each variable. Thanks again.

That’s a conversion to hours, not seconds. Taking minutes to seconds would be multiplying by 60. 123 assumed the travel time sensor returns seconds when it returns minutes. Have you tried the template I supplied?

Thanks, I just tried yours and it is working. Is is possible to have the conditions evaluate based on the delta alone, so if delta =15 , elif delta=10, elif=5 etc… This will allow me to adapt it further for some other automations . Similar to the solution above?

Actually, the assumption I made was that sensor.google_travel_time reports in hours and the template converts it into minutes for travel_time. If that’s incorrect, and google_travel_time` is in minutes, change this line:

{% set travel_time = states('sensor.google_travel_time') | float / 60 %}

to this:

{% set travel_time = states('sensor.google_travel_time') | int %}

No conversion of the current time is needed. It’s a datetime object and that’s exactly how we want it for use in the calculation.

    work_drive_time_color:
      value_template: >
        {% set arrival = now().replace(hour=10, minute=45) %}
        {% set travel_time = states('sensor.google_travel_time') | int %}
        {% set delta = ((arrival - (now() + timedelta(minutes=travel_time))).seconds / 60) | round %}
        {% if 0 <= delta <= 15 %} green
        {% elif  -10 <= delta < 0 %} yellow
        {% elif delta <= -10 %} red
        {% else %} off
        {% endif %}

Here’s a test I performed using the Template Editor. Current time is 09:00, arrival time is 09:45 and travel_time is 30 minutes.

09:45 - (09:00 + 00:30) = 15 minutes

That result satisfies this if statement:

{% if 0 <= delta <= 15 %} green

and the reported result is green.


EDIT

I just spotted a typo I made in the first elif statement. :man_facepalming:

Change this:

{% elif  -10 <= delta < 10 %} yellow

to this:

{% elif  -10 <= delta < 0 %} yellow

I have already corrected it in the example contained in this post.

Wow, I had no idea about this template editor. Nice. Will have to look into this.
The green condition executes now then it goes straight to off once its <0. I thought the issues was the condition so I changed the condition for yellow and red but no luck

    work_drive_time_color:
      value_template: >
        {% set arrival = now().replace(hour=14, minute=35) %}
        {% set travel_time = states('sensor.google_travel_time') | int %}
        {% set delta = ((arrival - (now() + timedelta(minutes=travel_time))).seconds / 60) | round %}
        {% if 0 <= delta <= 15 %} green
        {% elif  -10 <= delta < 0 %} yellow
        {% elif delta <-10 %} red
        {% else %} off
        {% endif %}

Yeah, I now see what’s causing that. The calculation of delta never produces a negative value. The lowest value it produces is 1 and reports 1440 instead of going negative. You can see that for yourself in the Template Editor by adding {{ delta }} at the end of the entire template to see its value.

If you don’t want to wait for me to sort it out, go with Petro’s suggestion which checks if arrival time is greater than the current time before tackling the calculations.

Thanks, I have used his solution. At this point it was about learning and I like using the if elif directly on detla so I can can add additional conditions in the future if I wanted. . I will play with this as well but I do appreciate your efforts as learning about the template editor is a nice find :slight_smile:

Here’s the corrected version:

    work_drive_time_color:
      value_template: >
        {% set arrival = now().replace(hour=10, minute=45) %}
        {% set travel_time = states('sensor.google_travel_time') | int %}
        {% set t = arrival - timedelta(minutes=travel_time) %}
        {% set delta = (((t - now()).seconds if t >= now() else -(now() - t).seconds) / 60) | round %}
        {% if 0 <= delta <= 15 %} green
        {% elif  -10 <= delta < 0 %} yellow
        {% elif delta <= -10 %} red
        {% else %} off
        {% endif %}

Thank you very much. It is working now

You’re welcome!

Please consider marking my post (above) with the Solution tag. It will automatically place a check-mark next to the topic’s title which signals to other users that this topic has been resolved. It will also place a link below your first post that leads to the solution post. All of this helps users find answers to similar questions.