Trigger on time influenced by temperature

Hi,

I’m fairly new to Home Assistant and after setting up some sensors etc. I have started dipping my toes into automation. Apart from configuring some “simple” automations I followed an existing example for how to create an alarm clock that can send a push notification…and got it working.

Now I want to create a new automation that should trigger on a time that is based on a given time, like an alarm clock, but depending on the outside temperature the actual trigger time should be X minutes ahead of the given time. It is supposed to turn on an electrical car heater and to be eco friendly it should be enabled as short as possible and the time you set is the time that the car should be warm and ready.

Example:

  • Departure time is set to 8:00
  • If the outside temp is 0 to -5 the trigger time should be 7:00 (1 hour before)
  • If the outside temp is -5 to -10 the trigger time should be 6:45 (1 hour 15 mins before)
  • If the outside temp is -10 to -15 the trigger time should be 6:30 (1 hour 30 mins before)

Does this make sense?
If so, any ideas on how I can go about to achieve something like this?

I guess if you have an alarm clock that you are familiar with the time sensor and the template trigger ?

Your rule can be adding 2mn per degree below zero (which would also remove 2mn per degree above 0)
You’ll need :

  • one time sensor : sensor.time
- platform: time_date
  display_options:
    - 'time'
  • one input_datetime that has only time (not date), and contains your wake up time (8:00 in your example) (or you can put 28800 instead in the trigger)
  • one input_number that contains the outside temp (or any weather source, for instance yweather, that would be sensor.yweather_temperature)

Your template trigger would look like this, of course depending on the name of the objects needed :

trigger:
    - platform: template
      value_template: "{{ ((states.input_datetime.alarm_clock.attributes['timestamp']) - ( 3600 - (states.input_number.temperature| int * 120))) | timestamp_custom('%H:%M', False) ) == ( states.sensor.time.state ) }} "

I’m using this to start heater or light several minutes before wake up time : warm bathroom, progressive light in the bedroom…

Somewhat…I just started looking at automations and followed a guide for how to create an alarm clock with a UI where you have sliders to set hour and minute. And I got that working…so now i’m interested in learning more :slight_smile:

Your suggestion looks great…thanks…just what I had in mind. I already have this functionality in the remote switch i’m going to control. But the UI for that is not user-friendly so I was hoping to create something better in HA, either by doing it like this, or with a form where I just ask for the time and when you enable it it posts the required http request to the remote switch.

I played a bit with it last night but there is something wrong with the value_template because the configuration was not valid. But I will go over it again tonight and see if I can find out what was wrong, most likey something on my end :stuck_out_tongue:

So I will revisit my config again and if I still fail to make it work I will post my config.

You can try the template in the developer tools, “templates” icon. This way, you can test different options before altering the actual configuration. You don’t have to restart everytime neither.
Maybe there’s one ‘)’ too many after 120 in my example ? :thinking:

Thats the very old way of doing it (circa early 2017). There is a input_datetime component that makes a digital clock in the UI.

The configuration is simple and it makes the automation work exactly like @Mister_Slowhand described.

input datetime configuration.

input_datetime:
  departure_time:
    name: Input with both date and time
    has_time: true
    initial: "08:00"

time sensor

- platform: time_date
  display_options:
    - 'time'

template sensor (for easy automations)

You’ll need to rename

'sensor.temperature'

in this template.

binary_sensor:
  - platform: template
    sensors:
      start_car_charge:
        friendly_name: Car Flag
        value_template: >
          {% set temperature = states('sensor.temperature') | float %}
          {% set time_now = states('sensor.time') %}
          {% set departure_time = state_attr('input_datetime.departure_time','timestamp') %}
          {% set base_offset = 60*60 %}
          {% set increment = 15*60 %}
          {% if temperature > -5 %}
            {{ (departure_time-base_offset) | timestamp_custom('%H:%M', False) == time_now }}
          {% elif -10 < temperature <= -5 %}
             {{ (departure_time-base_offset-increment) | timestamp_custom('%H:%M', False) == time_now }}
          {% else %}
             {{ (departure_time-base_offset-increment*2) | timestamp_custom('%H:%M', False) == time_now }}
          {% endif %}

Automation

You’ll have to change the service and entity id for the car_heater. That will depend on what platform you use for the car heater implementation.

- alias:  Turn on car heater
  trigger:
    - platform: state
      entity_id: sensor.start_car_charge
      to: 'on'
      from: 'off'
  condition:
    - condition: state
      entity_id: switch.car_heater
      state: 'off'
  action:
    - service: switch.turn_on
      entity_id: switch.car_heater

- alias:  Turn off car heater
  trigger:
    - platform: template
      value_template: >
        {{ states('sensor.time') == state_attr('input_datetime.departure_time','timestamp') | timestamp_custom('%H:%M', False) }}
  condition:
    - condition: state
      entity_id: switch.car_heater
      state: 'on'
  action:
    - service: switch.turn_off
      entity_id: switch.car_heater
4 Likes

Many thanks to both of you…I now have a working concept that I can fine tune to my needs :slight_smile:

@petro Your example almost worked straight away…there was just one slight error in the automation part. There is a reference to sensor.start_car_charge, but it should be binary_sensor.start_car_charge. Once I change that, and my other references, it started working.

@Mister_Slowhand I liked your way of gradually changing the start time instead of having fixed intervals. So i’m going to give try to change what I have into that now.

There is a pretty steep learning curve with HA…but i’m starting to grasp bits of the automation part so now I can start experimenting a bit more. But first I need to try to make something nice with Lovelace out of what I already have.

Be careful using @Mister_Slowhand’s method, it will trigger more than once if the temperature rises. You can combine his trigger into the sensor template to avoid that. Or use a condition to check and see if you’re already charging.

1 Like

Yes, if I go that route there will be some “protection” for multiple triggers.

But right now I need to tackle the datetime input. It is definitely not user friendly, at least not on a mobile device. Unless there is a way, in Lovelace, to make it use the mobile native controls for date/time/number input, aka. a “spinner”?

Yes, if the temperature raises more than 2°/mn there would be several calls. Is this something possible ? (I guess it could)
If so, is there a problem to turn on your switch several times ? I have automations, for instance to turn the heater off, that can run on several conditions : window open, people leaving home, temperature increase etc etc… So I call the climate.turn_off even if its already off. It’s not a big deal. As long as you have a discrete on/off, not only a toggle action, this is fine.

If it’s a problem to turn on several times, you can prevent this by adding a condition on the current status.
And if you don’t have the status of your switch available, you can use the last_triggered attribute to ensure it won’t run twice a day.
Or last option, you set a “lock” input_boolean at first start every day, and unset it at 8:00. (I have that for my alarm clock : any modification to the time locks the clock, so it prevents setting the default hour if a manual modification has been done, and at the alarm time, I unset the lock)

He could also just check and see if the car is already charging?

Hi. Nice solution! I started implementing mines based on @petro suggestions.
Basically what I need is to turn on car heater electric switch depending on outside temperature. The colder temperature - earlier car heater should start.

Currently it looks like following:

Code in this section
    binary_sensor:
      - platform: template
        sensors:
          start_car_heat:
            friendly_name: Car Heating flag
            value_template: >
              {% set temperature = states('sensor.yr_temperature') | float %}
              {% set time_now = states('sensor.time') %}
              {% set departure_time = (7*60*60) + (0*60) %} {# 07:00  #}
              {% set increment = 60*60 %} {# Decrease time start by one hour every temperature period below (time is in seconds) #}
              {% if temperature > 5.5 %}
                {% set multiply = 0 %}
              {% elif 5.5 >= temperature > -5 %}
                {% set multiply = 1 %}
              {% elif -5 >= temperature > -10 %}
                {% set multiply = 2 %}
              {% elif -10 >= temperature > -15 %}
                {% set multiply = 3 %}
              {% else %}
                {% set multiply = 4 %}
              {% endif %}

              {% if multiply == 0 %}
              {{ False }}
              {% else %}
              {{ (departure_time-increment*multiply) | timestamp_custom('%H:%M', False) == time_now }}
              {% endif %}

tl; dr version of timings and temperature:
Leave at 07:00.

(… , 5.5) no trigger at all
[5.5, -5) trigger at 06:00
[-5, -10) trigger at 05:00
[-10, -15) trigger at 04:00
[-15, …) trigger at 03:00

What I don’t like is that possibility that it won’t be triggered.
Example:
At 04:00 we are having -9.9 degrees (no trigger)
At 05:00 we are having -10.1 degrees (again no trigger)

Am I right, or missing something?

Additional question: how often this binary_sensor logic is being executed?

not true, it will charge for 1 hour. (6:00)

Yep

Nope 5:45, charge time for 1 hour 15 minutes

Nope 5:15, charge time for 1 hour 45 minutes

Nope, it will always trigger. the minimum time is 1 hour.


The template updates once per minute. If the temperature is greater than -5 degrees, the charge time is an hour. Between -5 and -10, it will be 1 hour 15 minutes. For each 5 degrees below -10, it will add a half hour to the charge time.

There is never a day in which it will not trigger. All temperature ranges are covered.


I should clarify, there is a chance of no-triggers. That is if the temperature drops between charge times. I.E. Your charge time is set to fire in 5 minutes but he temperature drops and causes the template to change to 10 minutes in the past.

I had slight different logic for heater. I think I made mistake hiding code in section:

Anyway I will try to think out something. :slight_smile:

Ah didn’t see the code. You can modify this to work and you won’t have the non-trigger issue that I described:

Step 1: Use sensor.date_time. You may need to add it to your configuration.

Step 2: Use this template

    binary_sensor:
      - platform: template
        sensors:
          start_car_heat:
            friendly_name: Car Heating flag
            value_template: >
              {% set temperature = states('sensor.yr_temperature') | float %}
              {% set time_now = states('sensor.date_time') %}
              {% set ts_now = as_timestamp(strptime(time_now, '%Y-%m-%d, %H:%M')) %}
              {% set midnight = states('sensor.date_time').split(',')[0]+', 00:00' %}
              {% set ts_midnight = as_timestamp(strptime(midnight, '%Y-%m-%d, %H:%M')) %}
              {% set departure_time = ts_midnight+7*60*60 %}
              {% set increment = 60*60 %}
              {% if temperature > 5.5 %}
                {% set multiply = 0 %}
              {% elif 5.5 >= temperature > -5 %}
                {% set multiply = 1 %}
              {% elif -5 >= temperature > -10 %}
                {% set multiply = 2 %}
              {% elif -10 >= temperature > -15 %}
                {% set multiply = 3 %}
              {% else %}
                {% set multiply = 4 %}
              {% endif %}
              {% if multiply == 0 %}
              {{ False }}
              {% else %}
              {{ (departure_time-increment*multiply) <= time_now <= departure_time }}
              {% endif %}

This should trigger anytime between your multiplied time and your departure time if the time is between that window.

1 Like

Neat! Thank you a lot

Only one little adjustment on this small part:

should be
{{ (departure_time-increment*multiply) <= ts_now <= departure_time }}

I am also wondering if this would not overload RPi running every minute 24x7. There are some heavier string split operations and etc. I think I will implement additional check to check if this is “expected car heating period”.

Thanks again!

1 Like

It might. Not sure how you can make a sensor that updates every 15 minutes though. If you have any sensor that updates in a period of 15 minutes, you can remove the references to sensor.date_time and sensor.time and use now(). Just make sure you attach the 15 minute update sensor to the template using the entity_id field.

I was thinking about really simple solution. Execute all of our logic in this if

{% if "03:00" <= states('sensor.time') <= "07:00" %}

Else return false. Maybe I whould also add check if car automation pre-heating automation is enabled

I couldn’t fully understand that “sensor pdates every 15 minutes” thing due too my little experience with HA :-).

You can’t compare strings like that. greater than or less than does not work on strings the way you think it does. That’s why we have to convert them to timestamps. For example 9 > 10 as strings.

Yep I know that. But time strings in time format without /am should be good afaik. The thing that there,that I didn’t know how to convert them to stamps :slight_smile: