How to set a variable inside automation loop?

Hi!

This is probably a really stupid question for beginners, but at the moment I’m stumped and can’t get any further:

I have an automation. I want a variable whose value is false by default to be set to true after the first run and then remain true. But when I look at it, the variable is always false. What is my error here?

alias: Benachrichtigung - Fenster geöffnet
description: ""
triggers:
  - type: opened
    device_id: xxx
    entity_id: xxx
    domain: binary_sensor
    trigger: device
conditions: []
actions:
  - variables:
      test1: false
  - repeat:
      sequence:
        - if:
            - condition: or
              conditions:
                - condition: numeric_state
                  entity_id: weather.home
                  attribute: temperature
                  enabled: false
                  above: input_number.contact_sensor_notification_disable_temperature
                - condition: state
                  entity_id: input_boolean.contact_sensor_notification_disable_by_user
                  state: "on"
                  enabled: true
          then: []
          else:
            - device_id: xxx
              domain: mobile_app
              type: notify
              title: "Fenster "
              message: Wurde geöffnet
              enabled: false
            - action: notify.alexa_media_alexa_arbeitszimmer
              data:
                data: {}
                message: >-
                  Wert 1 {{ contact_sensor_notification_disable_temperature_hint
                  }}, Wert 2 {{ test1 }}
        - variables:
            test1: true
        - delay:
            hours: 0
            minutes: 0
            seconds: 5
            milliseconds: 0
      while:
        - type: is_open
          condition: device
          device_id: xxx
          entity_id: xxx
          domain: binary_sensor
          enabled: true
mode: single

Could you give us an idea of what the automation is supposed to achieve? The first if seems to be redundant.

1 Like

Sure! :slight_smile: It’s for a automation where I want to play a notification at predefined intervals that a window is open.

However, there is a specific scenario where this should not happen: If the outside temperature has exceeded a certain temperature, only a warning should be played at the beginning that no announcements will be made due to excessive temperatures.
However, the loop should continue to run silently because it is possible, for example, that the window is open until the evening when the temperature drops again. In this case, the notification should be played when the temperature falls below this level.

To prevent the notification that it is too warm being played all the time, I would like to set a flag from false to true after the notification has been played. The notification should only be played if the flag is set to false, if it is true it should be skipped.

In general: I would be interested in how I can define a variable within the automation, the content of which I can then set and use again and again with the set value.

Ah, and sorry: The above example does not correspond to what I ultimately want to achieve. It’s just a quick and dirty example. As written, the goal is to understand how I can set and use a variable.

OK, I see.

Well, if there are conditions under which you don’t want the automation to run, they need to go in the conditions block immediately after the trigger, not in the actions block. This is what the conditions block is for - to stop the automation under certain circumstances.

As for repeating notifications at intervals, you might look at the Alert integration, which does exactly that.

To catch the outside temperature being high enough not to need an alert, and/or a drop in temperature after the window has been open for some time, I personally would probably use separate automations, with the temperature as the trigger and the state of the window in the condition block. There’s no particular benefit in cramming everything into one automation, and after a few months (when you’ve forgotten what you were trying to do :roll_eyes:) it can make maintenance much harder.

My understanding of variables is that they are not global - they only work in templates in the following action Edit: It’s much more complicated than this - see below - and that makes them less useful than you might expect.

If you need global variables, you might look at an integration like Variables+History

Edit: Great advice below, however I would add that looping and long delays in automations are not a good idea - they can easily be interrupted by restarts etc.

2 Likes

Try setting the variables at the top with no ident like this…

alias: Benachrichtigung - Fenster geöffnet
description: ""
variables:
  var001: 1234
  var002: 5678
triggers:
  - type: opened
    device_id: xxx
    entity_id: xxx
    domain: binary_sensor
    trigger: device
conditions: []
actions:
  - repeat:
      sequence:

As previous responses have noted, you are running into a scoping issue.

In automations, YAML variables can be defined multiple places, their scope depends on where they are defined.

trigger_variables:
  var_1: true #script-wide (only Limited Templates and static values allowed)
trigger:
  - platform: template
    value_template: "{{ states('binary_sensor.x') | bool == var_1 }}"
    variables:
      var_2: "{{ false }}" #script-wide but, if you have multiple triggers, this value applies only when this specific trigger initiates the automation
variables:
  var_3: "{{ true }}" #script-wide
condition:
  - variables:
      var_4: "{{ true }}" #local to condition block
action:
  - variables:
      var_5: "{{ true }}" #local to action block
  - choose:
      - conditions: 
          - condition: template
            value_template: "{{ var_2 }}" 
        sequence:
          - variables:
              var_6: "{{ false }}" #local to this Option of this Choose action    

* Variables will be populated with values roughly in the order I have numbered above.

One workaround for variables inside repeat actions is to set the value to an appropriate Helper or Trigger-based template sensor through an action.

Example using OP's sample automation
alias: Benachrichtigung - Fenster geöffnet
description: ""
triggers:
  - type: opened
    device_id: xxx
    entity_id: xxx
    domain: binary_sensor
    trigger: device
conditions: []
actions:
  - action: input_boolean.turn_off
    target:
      entity_id: input_boolean.fenster_notification_running
  - repeat:
      sequence:
        - variables:
            test1: "{{ states('input_boolean.fenster_notification_running')|bool }}"
        - if:
            - condition: or
              conditions:
                - condition: numeric_state
                  entity_id: weather.home
                  attribute: temperature
                  enabled: false
                  above: input_number.contact_sensor_notification_disable_temperature
                - condition: state
                  entity_id: input_boolean.contact_sensor_notification_disable_by_user
                  state: "on"
                  enabled: true
          then: []  #You can't leave this blank and expect the automation to work reliably
          else:
            - device_id: xxx
              domain: mobile_app
              type: notify
              title: "Fenster "
              message: Wurde geöffnet
              enabled: false
            - action: notify.alexa_media_alexa_arbeitszimmer
              data:
                data: {}
                message: >-
                  Wert 1 {# The variable that follows is undefined #}{{contact_sensor_notification_disable_temperature_hint}},
                  Wert 2 {{ test1 }} 
        - action: input_boolean.turn_on
          target:
            entity_id: input_boolean.fenster_notification_running
        - delay:
            hours: 0
            minutes: 0
            seconds: 5
            milliseconds: 0
      while:
        - type: is_open
          condition: device
          device_id: xxx
          entity_id: xxx
          domain: binary_sensor
          enabled: true
mode: single
3 Likes

Thanks all for your responses.

@jackjourneyman Thank you for this insights! This helps me, learn more about the possibilities of HA :slight_smile: So far, as you already write, i wouldn’t use the alert. As you write, it feels like hidden code and made it hards, have everything important at one place. Also I think, I haven’t the flexibility, i want.

About script syntax, I’ve tried this:

alias: Benachrichtigung - Fenster geöffnet
description: ""
triggers:
  - type: opened
    device_id: xxx
    entity_id: xxx
    domain: binary_sensor
    trigger: device
conditions: []
actions:
  - repeat:
      sequence:
        - variables:
            test: 0
        - if:
            - condition: or
              conditions:
                - condition: numeric_state
                  entity_id: weather.home
                  attribute: temperature
                  enabled: false
                  above: input_number.contact_sensor_notification_disable_temperature
                - condition: state
                  entity_id: input_boolean.contact_sensor_notification_disable_by_user
                  state: "on"
                  enabled: true
          then:
            - variables:
                test: "{{ test + 1 }}"
          else:
            - device_id: xxx
              domain: mobile_app
              type: notify
              title: "Fenster "
              message: Wurde geöffnet
              enabled: false
            - action: notify.alexa_media_alexa_arbeitszimmer
              data:
                data: {}
                message: >-
                  Wert ist {{ test }}
            - variables:
                test: "{{ test + 1 }}"
        - delay:
            hours: 0
            minutes: 0
            seconds: 5
            milliseconds: 0
      while:
        - type: is_open
          condition: device
          device_id: xxx
          entity_id: xxx
          domain: binary_sensor
          enabled: true
mode: single

Related to the sample under Script Syntax - Home Assistant i understand it so far, that the value of test should increase every round with 1. But the message contains always 0.

Actually, I would have expected these announcements at appropriate intervals:

  • Wert ist null
  • Wert ist eins
  • Wert ist zwei

You mentioned the additional component. But should it be really necessary, install a additional component for set and change a variable inside a process?
As I understand it, this should be more of a basic functionality?

About the loops: Are there perhaps other ideas on how to implement this well?
It could also be an automation that is called up at certain intervals as long as a sensor indicates the open status. As you write, working with the loop is not a good approach, as I have also realised. I had scenarios where too many runs were probably running uncontrolled.

An automation like this would trigger every 30 minutes but only continue if the window was open:

triggers:
  - trigger: time_pattern
    minutes: /30
conditions:
  - condition: state
    entity_id: binary_sensor.window_open
    state: "on"
actions: 

etc. etc.

You can’t overwrite variables. So it will not increment the variable.

If you are looking for a way to count the runs through the loop, that is already built in using the repeat variable.

Okay, but I understand the sample code on that side, that this is possible

It’s not possible, that example code is telling you that it’s not possible. It’s showing you how the scoping works in HA.

I echo that.

@prodigy7 you should avoid long-running automations. An alternative to @jackjourneyman’s suggestion is to start a timer and have a second automation trigger on its finished event. Long-running automations isn’t robust against restarts. Also look at the alert integration.

I have drawn a rough flowchart of how it works in my current home automation system (FHEM):

I can imagine that because HA has different approaches, I have to rethink things. I would like to learn that. How can I implement the process here so that it works for each individual sensor (window)? Presumably as a blueprint. But it would probably make sense to build an automation once and then transfer it to a blueprint, wouldn’t it?