Variable/condition evaluation

For automations and scripts that have been queued - when are conditions and variables evaluated?
At the moment of trigger or moment of execution?

If i’m not mistaken, conditions are the filter that sits between the trigger and the action.

That is certainly one place for conditions, and those conditions are obviously evaluated at trigger time. I’m referring to variables and conditions in the action section.

If an automation instance is triggered but sits in a queued state for 5 minutes, are the conditions in the action section and variables evaluated at the time of trigger, or 5 minutes later at the time of execution?

I need a value at time the automation is executed. For variables we can obviously redeclare them at the beginning of the action block to force them to reevaluate. I’m basically asking if this is necessary for variables and what happens with conditions (in the action block).

I don’t know the answer but I can offer you my best guess.

The mode option is used to control the execution of scripts and automations when they are called when already busy (i.e. how to handle the situation when the first execution is still busy when a second execution is requested).

That implies mode governs the action of an automation (which adheres to the same syntax as a script).

In other words, the automation’s trigger and condition are evaluated and then the action is executed in the manner dictated by mode. If the action is currently busy, and mode is queued, the second instance of the action is added to the queue.

Given this behavior, whatever variables defined outside the action were computed at the moment it triggered. The same is true for the condition because it had to have evaluated the condition to determine if the action should be queued (you can only get to the action by first evaluating the condition).

Anyway, that’s my hypothesis. I suggest creating an experiment to test it.

2 Likes

Exactly what I did when I didn’t get a response earlier.

- id: test_automation
  alias: test automation
  initial_state: true
  mode: queued
  variables:
    test: "{{ states('input_boolean.radio_on') }}"
  trigger:
      - platform: state
        entity_id: input_boolean.led_alert
        to: 'on'

  action:
    - service: system_log.write
      data:
        message: "Radio {{ states('input_boolean.radio_on') }}.  Variable {{ test }}."

    - service: input_boolean.turn_off
      entity_id: input_boolean.radio_on

    - delay:
        minutes: 1

    - service: system_log.write
      data:
        message: "I'm done. Radio {{ states('input_boolean.radio_on') }}. Variable {{ test }}."

    - condition: state
      entity_id: input_boolean.radio_on
      state: 'off'

    - service: system_log.write
      data:
        message: The radio is now off!

Started with the radio boolean on.

Triggered automation.
Radio on. Variable on.

Boolean turns off in automation.
Triggered automation again.

Results from first automation.

I'm done. Radio off. Variable on.
The radio is now off!

Second instance runs.
Radio off. Variable off.

Manually turned the radio boolean on.

Second instance completes.
I'm done. Radio on. Variable off.

So thank you for your educated and as it turns out, correct guess.

Variables are evaluated at trigger time and conditions within the action block are evaluated at run time. So the fix for that is as I suggested, reset the variables within the action block so they get reevaluated at runtime. (I suppose I should have included that in the experiment, but I’m confident that will work.)

1 Like

Variables defined outside the action have global scope can be referenced by condition and action. If the variable if not needed by the condition, only the action, then I would define it in the action exclusively.

1 Like

I didn’t realize that was possible! I got into the habit of always declaring them outside of the action when they were introduced and never thought twice about it. Thanks for that tidbit!

FWIW, here’s one of the more complicated automations I’ve created recently. It’s part of a system to restoring active timers that were interrupted by a restart. Before the advent of variables, it would not be possible to write this as a YAML automation (the original version was a python_script). It serves as an example of how variables can be used.

  • The modes variable, whose scope is the entire action, is defined once, outside the repeat. It could be defined outside the action but it’s not used anywhere other than within the action so that’s where I chose to define it.

  • The mode and timers_text variables are defined within the repeat and are redefined every repetition (just twice in all because count is 2).

  • The timers variable is defined within choose and is based on the timers_text variable.

  • The remaining three variables, t, id, and d, are defined within a nested repeat and their values are based on other variables.

- alias: 'Timers Restore'
  mode: single
  trigger:
    platform: homeassistant
    event: start
  action:
  - variables:
      modes:
      - active
      - paused
  - repeat:
      count: 2
      sequence:
      - variables:
          mode: '{{ modes[repeat.index-1] }}'
          timers_text: "{{ states('input_text.timers_' ~ mode) }}"
      - choose:
        - conditions: '{{ timers_text | length > 0 }}'
          sequence:
          - variables:
              timers: "{{ timers_text.split(',') }}"
          - repeat:
              count: '{{ timers | count }}'
              sequence:
              - variables:
                  t: '{{ timers[repeat.index-1].split() }}'
                  id: 'timer.{{t[0]}}'
                  d: "{{ t[1]|int - (now().timestamp()|int if mode == 'active' else 0) }}"
              - condition: template
                value_template: '{{ d > 0 }}'
              - service: timer.start
                data:
                  entity_id: '{{ id }}'
                  duration: '{{ d }}'
              - condition: template
                value_template: "{{ mode == 'paused' }}"
              - service: timer.pause
                data:
                  entity_id: '{{ id }}'

Funny you brought that up. I saw that thread a few days ago and bookmarked it. I’ve been meaning to try it out. My own solution was a little bit… messy, so I ended up nuking it.

Aside question - how did you get the folds with the hidden text in that post? That really makes long posts a lot more readable!

In the menu, click the gear icon. The first choice is Hide Details.

Screenshot from 2021-02-14 17-03-23

It creates a markdown summary section.

1 Like