Automation data_template IF-statement help

I have an automation that updates a input_datetime entity.
Every minute this gets updated with the latest sensor data.
Sometimes a sensors fails, when this happens I want to have a ‘safe’ value for that sensor.

My automation looks like this:

- id: update_alarm
  alias: Update alarm
  trigger:
    platform: time_pattern
    minutes: '/1'

  action:
  - service: input_datetime.set_datetime
    entity_id: input_datetime.alarmclock
    data_template:
      date: >
        {% if is_state('sensor.travel_time', 'unknown') %}
          "{{ (as_timestamp(states('sensor.calendar_event')) | int - 5400) | timestamp_custom('%Y-%m-%d', true) }}"
        {% else %}
          "{{ (as_timestamp(states('sensor.calendar_event')) | int - (states('sensor.travel_time') | int * 60) - 3300) | timestamp_custom('%Y-%m-%d', true) }}"
        {% endif %}
      time: >
        {% if is_state('sensor.travel_time', 'unknown') %}
          "{{ (as_timestamp(states('sensor.calendar_event')) | int - 5400) | timestamp_custom('%H:%M:%S', true) }}"
        {% else %}
          "{{ (as_timestamp(states('sensor.calendar_event')) | int - (states('sensor.travel_time') | int * 60) - 3300) | timestamp_custom('%H:%M:%S', true) }}"
        {% endif %}

When I paste the data_template code in the Template Editor, I get the correct result.
However, when the automation runs, it seems that the IF statement is always FALSE.

Couple things:

First, when you declare a multiline template, remove the quotation marks around the template. They are only required with single line templates.

Second, the “true” in your timestamp_custom filter sets the timezone as GMT-0. Is that correct for your application?

Please paste these lines into Template Editor and let me know if it produces the same results as your templates:

{% set ce = as_timestamp(states('sensor.calendar_event')) | int %}
{% set t_t = states('sensor.travel_time') | int * 60 %}
{% set tt = t_t - 3300 if t_t > 0 else 5400 %}
Date is:  {{ (ce - tt) | timestamp_custom('%Y-%m-%d', true) }}
Time is:  {{ (ce - tt) | timestamp_custom('%H:%M:%S', true) }}

Is it necessary for the automation to trigger every minute? Wouldn’t it be more efficient to have it trigger whenever sensor.calendar_event or sensor.travel_time changes state?

For example, this will trigger whenever either of the two sensors changes state and at the beginning of each day (using sensor.date).

  trigger:
    - platform: state
      entity_id:
        - sensor.calendar_event
        - sensor.travel_time
        - sensor.date

@walrus_parka: The removal of the quotation marks did the trick. Thanx for that.

@123: I’ve tried to simplify my code before, but the configuration file validator keeps saying my yaml code isn’t correct. So that’s why I did the ‘quick and dirty’ way of multiple if-statements for each attribute.
The code you proposed is definitely better, and does the trick in the template editor.
But: how do I implement this in the data_template of my automation. Because just copy pasting the proposed code gives me config-errors.

What the triggering goes: I’ve set this to time based 1-minute for testing purposes. This needs finetuning, and your proposal for monitoring state changes is something I would like to implement.
But first get the code running properly :slight_smile:

Like this:

- id: update_alarm
  alias: 'Update alarm'
  trigger:
  - platform: state
    entity_id:
      - sensor.calendar_event
      - sensor.travel_time
      - sensor.date
  action:
  - service: input_datetime.set_datetime
    entity_id: input_datetime.alarmclock
    data_template:
      date: >
        {% set ce = as_timestamp(states('sensor.calendar_event')) | int %}
        {% set t_t = states('sensor.travel_time') | int * 60 %}
        {% set tt = t_t - 3300 if t_t > 0 else 5400 %}
        {{ (ce - tt) | timestamp_custom('%Y-%m-%d', true) }}
      time: >
        {% set ce = as_timestamp(states('sensor.calendar_event')) | int %}
        {% set t_t = states('sensor.travel_time') | int * 60 %}
        {% set tt = t_t - 3300 if t_t > 0 else 5400 %}
        {{ (ce - tt) | timestamp_custom('%H:%M:%S', true) }}

For testing purposes, you can change the trigger to the 1-minute time_pattern you’ve been using.

You may have noticed the template does not check for sensor.travel_time being ‘unknown’. If it is then the int filter simply returns 0. The template checks if the value is greater than 0 when determining how it will perform the calculation.

ah, I had it the other way around.
Thought you could set the variable once, just below data_template and re-use it for date and time entities.

The template has a scope (the boundaries of its influence and operation) and its not everything lying below data_template but just to the option itself. Therefore the template for the date option is separate from the template for time.

I’ve learned that you can created global macros for Jinja2 templates (the macros are stored in a file) but this capability is not supported by Home Assistant’s implementation of Jinja2.

You can create a macro within a template but its scope is limited to that template.