How to trigger automation BEFORE set time?

Thanks for replies, I have been trying to get this to work without success. Also apologies if this went into wrong thread :confused: I have been here for a while, yes, but I set up all my automations back in the day and then left them as they were as everything worked perfect :slight_smile: But now because I installed new version of Home Assistant and switched to SSD drive, and because I eventually decided to build everything up from scratch, I thought that using Lovelace in everything was… simpler and also preferred method of using HASS nowadays (no need to worry about formatting etc), but I guess that’s not the case…

For me, this automation for my car heater is the only thing I cannot get to work. And it seems like now even my old code doesn’t work anymore when I just paste it into configuration.yaml. AhmadK, I had that sensor.alarm_clock3_time_long in my old code and it worked. But let’s focus on my new code as it’s tidier :slight_smile: and the code that Jer78 kindly typed.

This is what I have in sensors now:

sensor:
  - platform: template
    sensors:  
      alarm_clock3_time:
        value_template: >
          {% set h = states('input_number.alarm_clock3_hour') | int %}
          {% set m = states('input_number.alarm_clock3_minute') | int %}
          {{ '{0:0=2d}:{1:0=2d}'.format(h, m) }}

Then, this is the automation part, the code Jer78 provided (I gave in and put this in configuration.yaml, as it is much clearer compared to Lovelace automation when things are a bit complicated like in this automation…):

automation: !include automations.yaml
automation old: !include_dir_merge_list automations

automation old:
  - alias: 'Turn Car on'
    initial_state: on
    trigger:
      platform: time_pattern
      minutes: '/1'
      seconds: '0'
    condition:
      condition: or
      conditions:
        - condition: template
          value_template:  >-
            {% set temp = states.sensor.sonoffth3_am2301_temperature.state %}
            {% set d = now().strftime("%m/%d/%Y ") %}
            {% set t = strptime(d+states.sensor.alarm_clock3_time.state,"%m/%d/%Y %H:%M") %}
            {% if states('sensor.time') == ( as_timestamp(t) - 180*60 )|timestamp_custom('%H:%M') and temp >= -10 %}true{%else%}false{% endif %}
    action:
      - service: switch.turn_on
        entity_id: switch.sonoffpow3_2
      - delay: '03:00:00'
      - service: switch.turn_off
        entity_id: switch.sonoffpow3_2

I have to say that I have no clue about those time conversions and there is probably a simple reason why this automation never triggers… Note that I changed condition for temperature to above -10 so it would trigger when I want (it’s warmer than that now :slight_smile: ).

No, absolutely not. I was merely explaining why Jer78 did what he did and why it did not ‘tick’ all your boxes. No blame to be placed, just an alternate perspective. :smiley:

Okay, Jer78 is Canadian so he’s probably at work now, give me 10 mins and I’ll sit down at a workstation. I can explain what I think can be optimised and what I think is redundant.
A couple of questions though : - you have two input numbers set up, one for hours and one for minutes - why ? - I mean you could just use an input datetime ? Then there’s the creation of this sensor in the first place (my own method would use a binary sensor but that was a completely different path and there are many ways to skin a cat) Jer78’s method sets an automation that fires every minute, tests conditions and then determines actions. You merely use you ‘set time’ in here.
How do you present this in your front end ?
Some people like to use input number sliders because it’s easier when used from a phone (for instance) so your two input number 's may be valid for your usage.
Another point, say its -11 at -3hrs but it’s -7 at -2hrs and -4 at -1hrs - what do you think should happen ?
Oh and does this only run on weekdays?

But my ‘boxes’ were addressed to the OP :wink:
Anyway, no worries.

Hello Mutt,

Here’s how it looks like in my front end (or the idea, I will clean it later when it works :slight_smile: ):
sliders

So yes, that’s why I use two input numbers. I set time when I want to leave home, and then automation warms up my car as needed beforehand. As for creating the sensor, I thought that’s what needs to be done so I can form time from hour and minute values? And then I could use alarm_clock3_time for something else as well if needed.

I am not 100% sure I understand why automation needs to be fired every minute (well, I guess it isn’t as like you said, there are many ways to skin a cat :slight_smile: ), but if I have understood right, somehow using that method I can get by using only one automation instead of three that I used to have (1: start heater 3 hours earlier if temperature is below -10, 2: start heater 2 hours earlier if temperature is between -10 and -5 and 3: start heater 1 hour earlier if temperature is between -5 and +2)? That would be great :slight_smile:

This is meant to run whenever I want, not only weekdays, earlier I just toggled automation on or off as needed. As for your point about if temperature changes like that… Yes, earlier none of my three automations fired in case of your scenario, but luckily that didn’t happen often :slight_smile:

Solved this awhile back

EDIT: The whole thread has about 80 different ways to solve the problem.

This being the final condition i believe.

Oh, thank you petro! I don’t know how I didn’t find THAT thread since OP there wants to do exactly the same as me, but maybe that’s because I started to search for Lovelace solutions…

And I am sure there are many different ways to solve this problem, but to me they all seem overly complicated considering that it’s pretty simple thing I want to achieve, just trigger something early based instead of delayed, and I thought as time has passed, Lovelace introduced quite a while back already etc etc, that there would be some simple solution to this kind of problem already that I just wasn’t aware of :slight_smile: Well, maybe one day there will be “negative delay” in HASS out-of-box :slight_smile:

Anyway, I am going to read that thread now and return back if (and hopefully when!) I get my automation working.

What you want to do is not simple. Anytime you want to do something dynamically in any software package, it changes the process from simple to complex.

And yet there are only “50 ways to leave your lover” :rofl:

1 Like

All right, I have tried pretty much everything here and although configuration seems always to be okay, the automation just does not trigger. So I figured out I should use template editor and test those things that I suspect might cause problems. I ended up using code that @Jer78 gave because that seems to give right values for me, for example this template here:

value_template:  >-
  {% set temp = states.sensor.sonoffth3_am2301_temperature.state %}
  {% set d = now().strftime("%m/%d/%Y ") %}
 {% set t = strptime(d+states.sensor.alarm_clock3_time.state,"%m/%d/%Y %H:%M") %}
 {% if states('sensor.time') == ( as_timestamp(t) - 180*60 )|timestamp_custom('%H:%M') and temp >= -10 %}true{%else%}false{% endif %}

I get right values from every variable until last line. see here:

Now, when sensor.time is exactly three hours before set time (that is, when this automation should trigger), template editor just returns “unknown error rendering template”. When that minute passes, template shows values again. So I think there’s something wrong with that if-statement but I have no idea what it is… :confused:

read the errors from your logs. Also your spacing is off. And you’re comparing a string to a float. This can also be optimized.

value_template:  >-
  {% set temp = states('sensor.sonoffth3_am2301_temperature') | float %}
  {% set time = as_timestamp((now().date() ~ 'T' ~ states('sensor.alarm_clock3_time') ~':00') | timestamp_custom('%H:%M') %}
  {{ states('sensor.time') == t and temp > -10 }}

All right, I have some errors in my logs but I assume that’s because of one binary sensor experiment still active (that error fires off once every minute). I will comment that part out, and probably everything else regarding this as well, as I am quitting for today I think :confused: 80 ways to do this and I cannot get even one way to work, great…

Spacing was off only in my post, in configuration.yaml it is right.

I tried that value_template provided by @petro but that gives strange error when I try to validate my code. It says: "Invalid config for [automation]: invalid template (TemplateSyntaxError: unexpected ‘}’, expected ‘)’) for dictionary value @ data[‘trigger’][0][‘value_template’]. Got None. (See /config/configuration.yaml, line 230). "

Well, on line 230 there is nothing but empty line :confused: When I comment out those three lines under that value_template, then my code is valid again. But those rows are on lines 262-264…

Post your entire code.

All right, here goes… I only edited out parts that are not relevant, for example recorded includes etc… And cleaned all the code that was commented out anyway. Also, there still might be some remains from my tests, for example that input_datetime…

# Alarm clock
input_number:
  alarm_clock_hour:
    initial: 6
    min: 0
    max: 23
    step: 1
  alarm_clock_minute:
    initial: 58
    min: 0
    max: 59
    step: 1
  kesto:
    initial: 32
    min: 0
    max: 60

# My car heater
  alarm_clock2_hour:
    initial: 7
    min: 0
    max: 23
    step: 1
  alarm_clock2_minute:
    initial: 30
    min: 0
    max: 59
    step: 1

# Her car heater
  alarm_clock3_hour:
    initial: 6
    min: 0
    max: 23
    step: 1
  alarm_clock3_minute:
    initial: 50
    min: 0
    max: 59
    step: 1

# Kahvinkeitin
  kahvinkeitin_hour:
    initial: 6
    min: 0
    max: 23
    step: 1
  kahvinkeitin_minute:
    initial: 10
    min: 0
    max: 59
    step: 1

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

sensor:
  - platform: mitemp_bt
    mac: 'XX:XX:XX:XX:XX'
    name: Xiaomei sensori 1
    force_update: true
    median: 1
    monitored_conditions:
      - temperature
      - humidity
      - battery


  - platform: time_date
    display_options:
      - 'time'
      - 'date'


  - platform: template
    sensors:
      alarm_clock_time:
        value_template: >
          {% set h = states('input_number.alarm_clock_hour') | int %}
          {% set m = states('input_number.alarm_clock_minute') | int %}
          {{ '{0:0=2d}:{1:0=2d}'.format(h, m) }}

      alarm_clock2_time:
        value_template: >
          {% set h = states('input_number.alarm_clock2_hour') | int %}
          {% set m = states('input_number.alarm_clock2_minute') | int %}
          {{ '{0:0=2d}:{1:0=2d}'.format(h, m) }}

      alarm_clock3_time:
        value_template: >
          {% set h = states('input_number.alarm_clock3_hour') | int %}
          {% set m = states('input_number.alarm_clock3_minute') | int %}
          {{ '{0:0=2d}:{1:0=2d}'.format(h, m) }}

      kahvinkeitin_time:
        value_template: >
          {% set h = states('input_number.kahvinkeitin_hour') | int %}
          {% set m = states('input_number.kahvinkeitin_minute') | int %}
          {{ '{0:0=2d}:{1:0=2d}'.format(h, m) }}

automation: !include automations.yaml
automation old: !include_dir_merge_list automations

automation old:
  - alias: 'Car heater test'
    trigger:
      - platform: template
        value_template:  >-
          {% set temp = states('sensor.sonoffth3_am2301_temperature') | float %}
          {% set time = as_timestamp((now().date() ~ 'T' ~ states('sensor.alarm_clock2_time') ~':00') | timestamp_custom('%H:%M') %}
          {{ states('sensor.time') == t and temp > -10 }}

    condition:
      condition: and
      conditions:
        - condition: numeric_state
          entity_id: sensor.sonoffth3_am2301_temperature
          above: -10
    action:
      - service: switch.turn_on
        entity_id: switch.sonoffpow3_2
      - delay: '02:00:00'
      - service: switch.turn_off
        entity_id: switch.sonoffpow3_2


switch:
  - platform: wake_on_lan
    mac: "XX-XX-XX-XX-XX-XX"
    name: TheKone hereille
    host: 192.168.0.11
    broadcast_address: 192.168.0.255

group: !include groups.yaml
#automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

So, I have managed to do all other automations via Lovelace, but for this car heater thing I went back to configuration.yaml.

Your first problem is that you have two automation olds. can’t have that.

Second I think the issue is that date() doesn’t return a string so try this:

          {% set temp = states('sensor.sonoffth3_am2301_temperature') | float %}
          {% set time = as_timestamp((now().date() | string ~ 'T' ~ states('sensor.alarm_clock2_time') ~':00') | timestamp_custom('%H:%M') %}
          {{ states('sensor.time') == t and temp > -10 }}

Actually that’s how I had it in my old configuration.yaml and after tinkering with it for a while, the only way it actually works. The first two are include lines, and they have to be right there so that I can see both manual and Lovelace automations on my frontend.

I tried your code but I think there is something wrong with the formatting (and it bugs me because I cannot figure out why. So my automation is now like this:

automation old:
  - alias: 'My car test'
    trigger:
      - platform: template
        value_template:  >-
          {% set temp = states('sensor.sonoffth3_am2301_temperature') | float %}
          {% set time = as_timestamp((now().date() | string ~ 'T' ~ states('sensor.alarm_clock2_time') ~':00') | timestamp_custom('%H:%M') %}
          {{ states('sensor.time') == t and temp > -10 }}

    condition:
      condition: and
      conditions:
        - condition: numeric_state
          entity_id: sensor.sonoffth3_am2301_temperature
          above: -10
    action:
      - service: switch.turn_on
        entity_id: switch.sonoffs203
      - delay: '02:00:00'
      - service: switch.turn_off
        entity_id: switch.sonoffs203

And check config returns error: Invalid config for [automation]: invalid template (TemplateSyntaxError: unexpected ‘}’, expected ‘)’) for dictionary value @ data[‘trigger’][0][‘value_template’]. Got None. (See /config/configuration.yaml, line 229).

Also I am not sure how HASS counts those lines as line 229 is empty line just before that first automation include line. When I comment out those three lines in template, configuration is valid again.

By the way, shouldn’t the last line be a comparison between sensor.time and the time that is 1-3 hours before now? Temperature is already covered in conditions.

put that value_template in Developer Tools → Template and see what it says in HA log.

I believe that’s the way it works unfortunately. From my experience sometimes it cannot point you to a string with error and refers to the line a file with error is included in configuration.yaml

p.s this

automation: !include automations.yaml
automation old: !include_dir_merge_list automations

looks weird. HA accepts that (just tried) but to avoid any confusion I’d rather have all automations in automations and remove automation completely (and rename automation old to just automation), but that’s me.

It says pretty much the same: Error rendering template: TemplateSyntaxError: unexpected ‘}’, expected ‘)’

Yes, I have noticed that too, but in this case, the problematic code is in configuration.yaml.

That’s how home assistant documentation advices to use it.: Automation editor - Home Assistant

My Lovelace-created automations (all those work flawlessly) are in automations.yaml, and that’s why I have to include that. But because this complex automation seemingly needs to be in configuration.yaml, I have to use that automation_old, so that will be included as well. Tried without, and then HA couldn’t see this automation anymore.

Remove one of the “(” after as_timestamp like this:

{% set time = as_timestamp(now().date() | string ~ 'T' ~ states('sensor.alarm_clock2_time') ~':00') | timestamp_custom('%H:%M') %}

2 Likes

Thank you Burningstone, that did the trick! Although I am not sure what is that “t” in third line of that template: In template editor, it returns “false” even when time is exactly the same as sensor.alarm_clock2_time (if I have understood right, it SHOULD return “true” when those times are the same, and temperature is above -10 (that is true as well).

Of course, what I wanted was that automation would trigger 1-3 hours before based on temperature, but for now I would just like to see “true” in that template editor :smiley: