Help with an automation based on commute times

I’m looking to copy over an automation I was using in smarttthings. Quite simply I want to change the color of a hue bulb in the morning based on how heavy traffic is. I’m using Google Maps Travel Time sensor. It provides two values that I would be using. Duration is the normal time and duration_in_traffic is the current estimated time

This is what I was doing with ST
So this was my math. I divided DURATION by 6 lets call that my delay time.

Then I had three possible scenarios if duration_in_traffic less than or equal to DURATION + delay trigger then set light to green. Example. Normal commute is 30 minutes. Delay time would be 5 minutes. duration_in_traffic is 33 minutes that day. It’s less than 35 minutes, so commute is “normal”. Set light to green

If duration_in_traffic was in the range of (DURATION + delay time) and (DURATION + 2*delay time) then set light to orange. Example using same delay time. Lets say today duration in traffic comes back as 39 minutes. The value is between 35 amd 40 minutes, so light would be set to orange.

If duration_in_traffic was greater than (DURATION + 2*delay trigger) then set light to red.
Example, same delay time. Today duration_in_traffic is 45 minutes, that’s above 40, so light gets set to red. I also had this send me a notification just in case I was not near the light.

Now just to figure out the script/automation.

I would run this each morning starting about the time I woke up, and it would refresh the light color every 5 minutes. Or in this case it could just be on change to the Google Maps Travel Time sensor changes.

I found this to be nice and subtle, but very nice. Helped me to think, I need to get moving. and maybe leave early

What yaml do you currently have?

So far, just the sensors. I have two work locations, my wife has one. We leave at different times, so when I ran this on ST, I ran it for about 30 minutes (0700-0730) with her data, and then (0730-0800) with my data. I go to work 1 every day except Tuesday. I figure if I can get the basic logic down, I can work on conditions later for the days of the week or the person.

sensor:
  # person1s commute to home
  - platform: google_travel_time
    name: person1s Time to Home
    api_key: xxx
    origin: device_tracker.person1s_iphone
    destination: zone.home

  # person2s commute to Home
  - platform: google_travel_time
    name: person2's Time to Home
    api_key: xxx
    origin: device_tracker.person2s_iphone
    destination: zone.home	
	
  # Commute to work1
  - platform: google_travel_time
    name: Time to work1
    api_key: xxx
    origin: device_tracker.person1s_iphone
    destination: zone.work1    

	# Commute to work2
  - platform: google_travel_time
    name: Time to work 2
    api_key: xxx
    origin: device_tracker.person1s_iphone
    destination: zone.work2

	# Commute to work 3
  - platform: google_travel_time
    name: Time to work 3 person2
    api_key: xxx
    origin: device_tracker.person2s_iphone
    destination: zone.work3

So you always executed the automation between 7 am and 730 am? or was this triggered by you pressing a button or what?

Also, what are you running this on? rPi3?

I had it scheduled to run M-F at those times. I’m running home assistant on Umbuntu 17.10.

Can your hardware handle taxing processes? Reason I ask is that these run every x minutes can be taxing to your hardware. The way home assistant is built is that you will always be triggering every x minutes, but a condition will restrict the automation from executing. So the hardware is still running logic every x minutes to verify if it can execute.

If this is all well and good, you should look into automations:

A basic automation for something like this would be:

automation 3:
  trigger:
    platform: time
    minutes: '/5' 
  condition:
    condtition: template
    value_template: "{{ now().hour == 7 and 0 <= now().minute <= 30 }}"
  action:
    service: light.turn_on
    data_template: >
      brightness: 255
      color: >
        {% set drive_time = state('sensor.time_to_work1') %}
        {% if 0 <= drive_time <= 30 %}
          green
        {% elif 30 < drive_time <= 40 %}
          orange
        .... more logic here blah blah blah
        {% else %}
           white # in case the drive time isn't inside any of these if statements
        {% endif %}

Here is another doc for conditions:

You don’t have to use the condition I wrote, you could avoid templating “{{ curly bracket crap }}” by using the documentation above to come up with your own condition.

Wow, thanks great info. my hardware is 4-5 year old I3 processor and 4gb ram. SSD hard drive.

Could I use some other logic to turn this off when not being used to avoid taxing the hardware?

Also rather than static values for the compare (30, 40, etc), I was hoping to expose some of the other data in the sensor (duration, specifically). I’m probably just being picky, but I like the idea of a simple and reusable automation, that could be used by anyone with little to no modification.

So if I understand this part

        {% set drive_time = state('sensor.time_to_work1') %}

That is setting a variable based on the current state. How do I pull “duration” from the sensor?

Would this work

        {% set delay_time = state('sensor.time_to_work1'.attributes.duration') %}

But then I’d like that value to be divided by 6. Can I do that in the set_delay time statement?

Thanks for the help, this really has got me understanding much better so far

No, you need to use a different function. All that templating stuff is covered here:

This is what you should use:

{% set drive_time = state_attr('sensor.time_to_work1','duration') %}

Thanks, I’ll dig into the templating. I think I need to figure out a value template.

        {% set drive_time = state('sensor.time_to_work1') %}
        {% set delay_time = state_attr('sensor.time_to_work1','duration') %}

I know this is not right, but this is the logic I think.

        {% set drive_time = state('sensor.time_to_work1') %}
	{% set delay_time = state_attr('sensor.time_to_work1','duration') %}
        {% if 0 <= drive_time <= (Drive_time + (delay_time/6)) %}
          green
        {% elif (Drive_time + (delay_time/6)) < drive_time <= (Drive_time + ((delay_time/6)*2)) %}
          orange
        {% elif (Drive_time + ((delay_time/6)*2)) < drive_time  %}
          Red

I do understand this would not work as is. Need to figure out that value template. Thanks again, got some reading to do. :slight_smile:

You know I’ve been playing a learning a lot this week. I had a thought. I have 5 of these google traffic sensors. it’s my understanding that they update every 5 minutes anyway, right?

So I could just do something like this

  trigger:
  - platform: state
    entity_id: sensor.time_to_work_1
  condition:
    condtition: template
    value_template: "{{ now().hour == 7 and 0 <= now().minute <= 30 }}"

then the logic of course. :slight_smile: Then it would update my lights on the same schedule.

So, I think I’m closer, but the amount of { and ( make me think this may be to much

- condition: template
        value_template: "{{ states.sensor.time_to_work1.state  < (state_attr('sensor.time_to_work1','duration') | float + (state_attr('sensor.time_to_work1','duration')/6) }}"
		
- condition: template
        value_template: "{{ (state_attr('sensor.time_to_work1','duration') | float + (state_attr('sensor.time_to_work1','duration')/6) < states.sensor.time_to_work1.state < (state_attr('sensor.time_to_work1','duration') | float + (state_attr('sensor.time_to_work1','duration')/6)*2) }}"
		
- condition: template
        value_template: "{{ state_attr('sensor.time_to_work1','duration'  > (state_attr('sensor.time_to_work1','duration') | float + (state_attr('sensor.time_to_work1','duration')/6)*2) }}"

I believe if I got it right
states.sensor.time_to_work1.state should be my actual commute
and
state_attr(‘sensor.time_to_work1’,‘duration’) should be the “normal Commute”

So in the 1st line
current commute must be less than normal commute + normal commute divided by 6
2nd line
current commute is between (normal commute + normal commute divided by 6 ) and (normal commute + (normal commute divided by 6) times 2)
3rd line
current commute is greater than (normal commute + (normal commute divided by 6) times 2)

What do you think? too much? Just popped into my head.

Sorry, have been out of town. The templates look good i think. But you have them as conditions? Are you trying to used them as conditions or as a template sensor? My memory is foggy

Thanks,

I wanted to use the logic you provided

action:
    service: light.turn_on
    data_template: >
      brightness: 255
      color: >
        {% set drive_time = state('sensor.time_to_work1') %}
        {% if 0 <= drive_time <= 30 %}
          green
        {% elif 30 < drive_time <= 40 %}
          orange
        .... more logic here blah blah blah
        {% else %}
           white # in case the drive time isn't inside any of these if statements
        {% endif %}

but use the math above for the colors.

Green would be : "{{ states.sensor.time_to_work1.state  < (state_attr('sensor.time_to_work1','duration') | float + (state_attr('sensor.time_to_work1','duration')/6) }}"
		
Orange would be  "{{ (state_attr('sensor.time_to_work1','duration') | float + (state_attr('sensor.time_to_work1','duration')/6) < states.sensor.time_to_work1.state < (state_attr('sensor.time_to_work1','duration') | float + (state_attr('sensor.time_to_work1','duration')/6)*2) }}"
		
RED would be "{{ state_attr('sensor.time_to_work1','duration'  > (state_attr('sensor.time_to_work1','duration') | float + (state_attr('sensor.time_to_work1','duration')/6)*2) }}"

I’m not sure how to select the color based on the math. Heck, I’m not even sure my math is right, or would work as it’s written, haha.

Thanks again for the help, I’ve already learned a lot.

You have 2 option to get the color on your light: Build it in your action as a template or make a template sensor.

Placing it in the conditions won’t really help because then your automation won’t fire if your conditions aren’t met.

The logic I wrote above is an example of ‘build it in your action as a template’. I think that is the route you want to go. So instead of making them conditions, make the if, elif, elif, and else inside the template.