Variable scope in automation - not clear what's wrong

Hi all,

This is a script that supposed to send a reminder for the bin, specifying in the notification the correct between recycling and composte.

For some reason that i cannot get now, the variable bin is not overridden despite the proper branch of the choose is activated during the script. The notification is always sent considering the initial value of bin ( = "XYZ" )

The trace debugging does not show any variable changed during that execution ( infact )

what is wrong ?

Thanks in advance.

alias: Garbage bin reminder
description: ""
variables:
  bin: "XYZ"
# trigger: [left empty to remove complexity]
action:
  - choose:
      - conditions:
          - condition: state
            entity_id: sensor.recycling
            attribute: days
            state: 1
        sequence:
          - variables:
              bin: "{{ state_attr('sensor.recycling', 'friendly_name') }}"
      - conditions:
          - condition: state
            entity_id: sensor.wast_and_composte
            attribute: days
            state: 1
        sequence:
          - variables:
              bin: "{{ state_attr('sensor.wast_and_composte', 'friendly_name') }}"
  - service: input_boolean.turn_on
    data: {}
    target:
      entity_id: input_boolean.bin_reminder
  - repeat:
      while:
        - condition: state
          entity_id: input_boolean.bin_reminder
          state: "on"
      sequence:
        - service: notify.internal_notification_group
          data:
            message: Bin Reminder
            title: "Hey Remember the {{ bin }} bin for tomorrow"
        - delay:
            hours: 0
           minutes: 10
            seconds: 0
            milliseconds: 0
mode: single

The variable’s scope is local to where it is defined, if you define it inside the Choose it’s only available in the Choose.

action:
  - variables:
      bin: >
        {% if is_state_attr('sensor.recycling', 'days', 1) %}
        {{ state_attr('sensor.recycling', 'friendly_name') }}
        {% elif is_state_attr('sensor.wast_and_composte', 'days', 1) %}
        {{ state_attr('sensor.wast_and_composte', 'friendly_name') }}
        {% endif %}
  - service: input_boolean.turn_on
    data: {}
    target:
      entity_id: input_boolean.bin_reminder
  - repeat:
      while:
        - condition: state
          entity_id: input_boolean.bin_reminder
          state: "on"
      sequence:
        - service: notify.internal_notification_group
          data:
            message: Bin Reminder
            title: "Hey Remember the {{ bin }} bin for tomorrow"
        - delay:
            hours: 0
            minutes: 10
            seconds: 0
            milliseconds: 0
mode: single

1 Like

You actually pretty much made an exact copy of the example of how scopes work from the documentation pages. :slight_smile:

Hey Drew, thanks for the suggestion.
I thought defining the variable at the larger scope (bin: “XYZ” - line 4 in my script) would have allow any block to access it in the script ( like any other programming language ).

OK. That reduce significantly the flexibility you can have with the building blocks. ( and also the readability ).

Thanks,
David.

Yeah, it is annoying, but you can often define a namespace and use that.

{% set ns = namespace(counter=0) %}
{% for x in y %}
	{% ns.counter=ns.counter+1 %}
{% end %}
{{ ns.counter }}

It is accessible anywhere else in the automation. By “accessible”, I mean readable.

What you can’t do is redefine its value afterwards. For example, line 15 in your automation is effectively defining a new local variable (with the same name as the global variable bin) whose scope is limited to the sequence where it’s defined. It’s not redefining the global bin variable.

1 Like

Hi Taras,
i see, them it seems it’s more a global constant than a global variable.
Any way, there might be some explanation behind that … not complaining.

Thanks everyone for helping.