Setting variables in 'choose'-blocks of automations

Hi,
I am cleaning up my code and try to combine multiple similar automations into one. For that, I want to use the new ‘Variables’ feature (v0.115).
The following…

automation:
  - id: test1
    trigger:
      #... some trigger
    variables: 
      messagetext: '--'
    action:
      - variables:
          messagetext: 'start'
      - service: notify.max
        data:
          title: 'Automation Test1'
          message: "{{ messagetext }}"

…works, I get a notification with text ‘start’.
But, if I put the setting of the variable inside a chooser block and use that variable later on:

automation:
  - id: test2
    trigger:
      #... some trigger
    variables: 
      messagetext: '--'
    action:
      - choose:
        - conditions:
          #do something Mondays
          - condition: time
            weekday:
              - mon
          sequence:
            - variables:
                messagetext: 'a Monday'
        default:
          #do something else 
          - variables:
              messagetext: 'another day'        
      - service: notify.max
        data:
          title: 'Automation Test2'
          message: "{{ messagetext }}"

…I get the notification message ‘–’.
In Jinja templates variables are always local or a namespace has to be set.
But how is that done here in automation actions?
In my understanding the defined variable should be accessible throughout the whole automation.

Thanks in advance for your input.
Max

1 Like

Did you ever get this working? I have the same issue

In brief, you can’t redefine the value of a variable like in the posted example.

The variable’s scope is constrained by where it’s defined in the automation. The assumption maxl67 made is that no matter where the variable is defined, it’s scope is always global (available everywhere within the ,action. However, that’s not how it works.

In the example, the variable messagetext is defined not just once but three times. The first time is outside of action and represents the one whose scope is global for the entire automation.

The second and third definitions are made within the conditions of a choose so their scope is constrained to the conditions.

Outside of conditions, like in the service call, the value of messagetext is determined by its first (global) definition.

1 Like

@Rob: no, I haven’t.
@Taras: Thanks for the good explanation.

It’s a pity, it would be useful to be able to alter a variable depending on a condition. For example I’d like to use today’s energy consumption value in an automation run before midnight, but use yesterday’s value if its before 1 AM:

  sequence:
    - variables:
        consumption: "{{ states('sensor.energy_today') | round(1) }}"
    - if:
        - condition: time
          before: "01:00:00"
      then:
        - variables:
            consumption: "{{ states('sensor.energy_yesterday') | round(1) }}"

very easy, nice to read - but it won’t work, cannot use the changed variable later, as its scope limits it to the then: branch…

Because of this, I have to use jinja template to set the variable dependig on the time, but it is much less friendly:

    - variables:
        consumption: >-
          {% if now().strftime("%H")+now().strftime("%M") < "0100"  %}
            {{ states('sensor.power_kwh_yesterday') | round(1) }}
          {% else %}
            {{ states('sensor.daily_energy') | round(1) }}
          {% endif %}

Especially so, if I have to change several variables on the same condition, like the word “today” or “yesterday” in another variable: then the only way to double the whole Jinja template rows for that variable…

1 Like
- variables:
    consumption: >-
      {{ states(iif(now() < today_at('01:00'), 'sensor.power_kwh_yesterday', 'sensor.daily_energy')) | round(1) }}
1 Like

I came across this issue while searching for the same problem as the OP. So I wanted to add to this discussion where I’m at on this, and see if anyone has any better ideas.

I was also trying to use a variable set by a complicated choose automation, and then use the variable later in the automation. It is unfortunate there doesn’t seem to be a way to do this with variables.

I suppose I can do this by setting an input_text helper, but I would then have to set that up separately, which is less clean. I would prefer a variable scoped for the automation as whole. I could also try and write my whole choose action as a template, but that is not clean either.

Another option is using one of the variable integrations from HACS, but I would prefer to used HA core functionality as much as possible to ensure long term stability.

Does anyone else think one of these is better than the other? Why?

You can put all your logic in the variable. Jinja is much more flexible than normal conditions. So just post the logic and we can help you write the template.

I have multiple variables that need to be set depending on the choose conditions. So I’d have to repeat the same if/else logic for every single variable.

No, you can put the logic into a variable and then use that variable in other variables.

All of the variables are independent of one another, so I can’t use the text of any of them in the others.

Post your code and I’ll show you.

Thanks @petro. I’ll take you up on this offer. I agree with @jimjames, especially this part:

I suppose I can do this by setting an input_text helper, but I would then have to set that up separately, which is less clean. I would prefer a variable scoped for the automation as whole.

I have a very simple use case, where I want to store the current position of my blinds (number between 0 and 100). Then change the blind position and then 1 minute later revert to the original blind position. Please note the pseudo-service local_input_number.set_value. This doesn’t exist but I’m looking for something like it:

- service: local_input_number.set_value
  data:
    name: prev_position
    value: state_attr('cover.kitchen_smart_blind', 'position')
- service: cover.set_cover_position
  data:
    position: 50
  target:
    entity_id: cover.kitchen_smart_blind
- delay:
    hours: 0
    minutes: 0
    seconds: 10
    milliseconds: 0
- service: cover.set_cover_position
  data:
    position: "{{prev_position}}"
  target:
    entity_id: cover.kitchen_smart_blind

How can I write this automation in a simple manner that doesn’t rely on globally accessible variables?

- variables:
    prev_position: >
      {{ state_attr('cover.kitchen_smart_blind', 'position') }}
- service: cover.set_cover_position
  data:
    position: 50
  target:
    entity_id: cover.kitchen_smart_blind
- delay:
    hours: 0
    minutes: 0
    seconds: 10
    milliseconds: 0
- service: cover.set_cover_position
  data:
    position: "{{prev_position}}"
  target:
    entity_id: cover.kitchen_smart_blind
1 Like

Awesome! I must have been using it wrong all along. Thank you!

I have the same issue. I’m trying to set the ac_mode and target_temp inside the choose but since the variables inside choose are local, it doesn’t update the initial variables. Code below, @petro let me know if you have any ideas? For now, going to use an input text variable

alias: "[Climate] Switch on Aircon TEST"
description: ""
triggers:
  - at: "07:00:00"
    trigger: time
conditions:
  - condition: state
    entity_id: input_boolean.holiday
    state: "off"
actions:
  - variables:
      forecast: "{{states('input_text.forecast') | from_json }}"
      ac_mode: "off"
      target_temp: "24"
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ forecast.temperature >= 27 }}"
        sequence:
          - variables:
              target_temp: "24"
              ac_mode: cool
          - action: notify.mobile_app_pixel_6
            metadata: {}
            data:
              title: Aircon automation
              message: >-
                Today is going to be a hot one! Max temperature of {{
                forecast.temperature }}, humidity of {{ forecast.humidity }}.
                Remember to pull the blinds and close the windows! Today's
                precipitation is {{ forecast.precipitation }} with a probability
                of {{ forecast.precipitation_probability }} and the UV Index is
                {{ forecast.uv_index }}
      - conditions:
          - condition: template
            value_template: "{{ forecast.temperature <= 15 }}"
        sequence:
          - variables:
              target_temp: "24"
              ac_mode: heat
          - action: notify.mobile_app_pixel_6
            metadata: {}
            data:
              title: Aircon automation
              message: >-
                Today is going to be a cold one! Max temperature of {{
                forecast.temperature }}, humidity of {{ forecast.humidity }}.
                Remember to open the blinds and close the windows! Today's
                precipitation is {{ forecast.precipitation }} with a probability
                of {{ forecast.precipitation_probability }} and the UV Index is
                {{ forecast.uv_index }}
      - conditions:
          - condition: template
            value_template: "{{ forecast.humidity >= 80 }}"
        sequence:
          - variables:
              target_temp: "24"
              ac_mode: dry
          - action: notify.mobile_app_pixel_6
            metadata: {}
            data:
              title: Aircon automation
              message: >-
                Today is going to be a humid one! Max temperature of {{
                forecast.temperature }}, humidity of {{ forecast.humidity }}.
                Remember to close the windows! Today's precipitation is {{
                forecast.precipitation }} with a probability of {{
                forecast.precipitation_probability }} and the UV Index is {{
                forecast.uv_index }}
    default:
      - action: notify.mobile_app_pixel_6
        metadata: {}
        data:
          message: >-
            No action as max temp of {{ forecast.temperature }} and humidity of
            {{ forecast.humidity }} within normal.  Today's precipitation is {{
            forecast.precipitation }} with a probability of {{
            forecast.precipitation_probability }} and the UV Index is {{
            forecast.uv_index }}
          title: Aircon Automation
      - stop: Within normal temperature range, no action to perform
  - metadata: {}
    data:
      hvac_mode: "{{ ac_mode }}"
    target:
      entity_id: climate.at2plus_ac_0
    action: climate.set_hvac_mode
  - metadata: {}
    data:
      fan_mode: low
    target:
      entity_id: climate.at2plus_ac_0
    action: climate.set_fan_mode
  - metadata: {}
    data:
      temperature: "{{ target_temp }}"
    target:
      device_id: d97874f1ab4def723560d917ebcc492c
    action: climate.set_temperature
  - target:
      entity_id:
        - fan.family
    data:
      percentage: 100
    action: fan.turn_on
  - target:
      entity_id:
        - fan.master
        - fan.bed4
        - fan.bed2
        - fan.bed3
    data:
      percentage: 50
    action: fan.turn_on
  - metadata: {}
    data:
      title: Turned on Aircon
      message: >-
        Aircon switched on as forecast temperature is {{ forecast.temperature
        }}. Aircon set to {{ mode }} and target temperature of {{ target_temp }}
    action: notify.mobile_app_pixel_6
  - wait_for_trigger:
      - at: "16:30:00"
        trigger: time
    enabled: false
  - device_id: d97874f1ab4def723560d917ebcc492c
    domain: climate
    entity_id: f61fe36d5d44a0576f7ecbe809d58a31
    type: set_hvac_mode
    hvac_mode: "off"
    enabled: false
mode: single