Automation with datetime (trigger based on self defined time-helper) not working

Dear all, I have been searching and trying but failing. I guess it is simple but I am not getting it.

I want to trigger an action based on a date/time that I am calculating with helpers.

  1. my automation:
alias: test my own time helper 
description: ""
triggers:
  - trigger: time
    at: sensor.haus_start_auto_laden_mit_haus_batterie
conditions: []
actions:
  - action: notify.persistent_notification
    metadata: {}
    data:
      message: Trigger based on my own helpers
mode: single
  1. my template (and I guess I am doing something awfully wrong here);
template:
  -sensor:
      - name: "Haus - Start Auto-Laden mit Haus Batterie"
        device_class: "timestamp"
        state: >
          {{ states.sensor.sun_next_rising.state | as_datetime +  timedelta(minutes=-210) - timedelta(minutes=float(states.sensor.haus_verfugbare_auto_lade_dauer.state)) }}

When testing the helpers they all give me correct values but the automation is never triggered.

Any tip for me (still rookie)?

Most likely your template sensor and the compare to time aren’t matching up so the trigger will not initiate.

Look at both outputs in Developer Tools

1 Like

do you mean not matching from a format point of view or matching state wise, i.e. the value (date and time) my sonsor is holding is never caught by the automation for some reason?

here is what my sensor holds:

Is it an issue that it is of type string (in the template I set it to class timestamp, but I guess that is irrelevant if the value itself is not properly set)?

Yes, the compare for the trigger is most likely not matching your sensor output

For example, look at the values in Developer Tools like this

           Your code   {{ states.sensor.sun_next_rising.state | as_datetime + ..... }} 
system  date and time  {{now()}}   

You have to find a comparable format or common denominator

1 Like

Not a perfect match to your existing sensor, but it’s one way to have a common denominator

{{(states.sensor.sun_next_rising.state|as_timestamp) | int(0)== ( states.sensor.xxxxx.last_changed |as_timestamp) | int(0) }}

{{(states.sensor.sun_next_rising.state|as_timestamp) | int(0)}}
{{( states.sensorxxxx.last_changed |as_timestamp) | int(0)}}

1 Like

Thanks. there is a difference in the output; now() also returns milliseconds (i guess)

I will research on how to do the formatting of my sensor to match the one of now() or follow your approach with defining as int.

However, I want to zoom out again: Shouldn’t the format be completely irrelevant when using a time sensor in an automation where the trigger condition is a time(stamp)? I mean why would I need to take care of the formating of something that has many faces (as in many formats :slight_smile: ) while always being the same thing: a point in time

Sure but you are comparing your customized time sensor output against a time stamp and saying they have to match. - trigger: time has to equal at: sensor.haus_start_auto_laden_mit_haus_batterie

Format and output type matters a whole bunch. You can’t compare a number to a letter, correct?

A=2 will never be true…

A string will never equal a number and that logic applies to time and dates.

Time is probably close to the most difficult to compare. It also brings in how often the timestamp is reported. I just would avoid it if other triggers are available.

When you added math (+,-,float) with this, the standard format went out the window

{{ states.sensor.sun_next_rising.state | as_datetime + timedelta(minutes=-210) - timedelta(minutes=float(states.sensor.haus_verfugbare_auto_lade_dauer.state)) }}

I hear you :slight_smile: and I get your point. I guess I was hoping there is some magic happening defining my sensor as timestampt to convert it to a date_time-object and makes sure, that it can be compared to other time objects without the formating of it. But I also get your point: A != 2

I will try for some hours now and post an update. Thanks already (I will edit this post with real update so that this forum is not turning into a chat).

The chat is ok if it gives clarity at the same time. A summary of your solution would be ideal.

here we go:

  1. formating the output of my sensor to match what now() has as standard output:

My code for testing

{% set test = states.sensor.sun_next_rising.state | as_datetime +  timedelta(minutes=-210) - timedelta(minutes=float(states.sensor.haus_verfugbare_auto_lade_dauer.state)) %}

value of my sensor
{{ test.strftime('%Y-%m-%d %H:%M:%S.%f+02:00') }} 

value of now()
{{now() }}

Results match pretty good:

  1. I put the same code to my template.yaml
template:
  - sensor:
      - name: "Haus - Start Auto-Laden mit Haus Batterie"
        device_class: "timestamp"
        state: >
          {% set temp = states.sensor.sun_next_rising.state | as_datetime +  timedelta(minutes=-210) - timedelta(minutes=float(states.sensor.haus_verfugbare_auto_lade_dauer.state)) %}
          {{ temp.strftime('%Y-%m-%d %H:%M:%S.%f+02:00') }} 

but please see what the entity has as value: it has a different format (but is timewise the same considering the offset seen in 1)

  1. the novice’s question: Even if the format of the sensor value matches to what we assume is used in the automation when checking: “is it now the time as defined in the sensor, then do something”: how would homeassist find a match even with milliseconds when doing he comparison? I guess I still don’t understand how the trigger is working:

is there an digestible explaination? :slight_smile:

Thanks.

I played around: working for me:

  1. template definition:
template
  - sensor
    - name: "Haus - Start Auto-Laden mit Haus Batterie"
            device_class: timestamp
            state: >
              {{ states.sensor.sun_next_rising.state | as_datetime + timedelta(minutes=60) - timedelta(minutes=float(states.sensor.haus_verfugbare_auto_lade_dauer.state))}}

  1. Automation (for testing only a notification)
alias: Auto_Nachts_AutoLaden
description: ""
triggers:
  - trigger: time
    at: sensor.haus_start_auto_laden_mit_haus_batterie
conditions: []
actions:
  - action: notify.persistent_notification
    metadata: {}
    data:
      message: Ladung in der Nacht gestartet
mode: single

the only difference I can see is the usage of

... timedelta(minutes=-210) ...

i.e. a negative value in my code that is not working; rest of code looks identical.
The core learning for me: I need to convert the value of the sensor for the next sun-rise to a datetime-object by using as_datetime. Only then the automation using a time as trigger is working.

Thanks @LiQuid_cOOled for your guidance.

As noted in the “States” section of the Templating docs LiQuid_cOOled linked to earlier, you should avoid using the state-object method shown above, unless it is necessary.

A better option would be:

template:
  - sensor:
      - name: "Haus - Start Auto-Laden mit Haus Batterie"
        device_class: timestamp
        state: >
          {% set min_offset = states('sensor.haus_verfugbare_auto_lade_dauer') | float(0)  %}
          {{ states('sensor.sun_next_rising') | as_datetime + timedelta(minutes= (60 - min_offset)) }}

thanks @Didgeridrew

I’m still a bit buffled. Both of you point me to a page where I don’t find the hints you want me to see.

Could you tell me why the state-object method (that I am using) should be avoided?

One difference I see between your code snippet an mine:

  • mine:
states.sensor.sun_next_rising.state | as_datetime
  • yours:
states('sensor.sun_next_rising') | as_datetime

when testing both return the same output:
2025-04-19 04:23:01+00:00

ChatGPT tells me: the second option is better as it never throws an error, e.g. in cases the sensor doesn’t exist.

Is this the difference you are referring to?

It’s in the section “States” in a box marked “Warning”…

In some cases these errors can cause entities to get stuck in unknown or unavailable state after restart. That means they can cause knock-on issues in both the frontend as well as in your scripts and automations if they are used there.

1 Like

ok got it now - thanks - I learned quite a bit from this thread.

Also: @Didgeridrew your code snippet is working great. And to give you the well deserved credit I set your input as solution.