Changing Variables in Script Conditionals

Hello all, new user here, I have an access control system that allows scanning RFID cards to open/close an overhead door. My existing system uses a custom VB .NET application to do an SQL lookup, confirm the tag is authorized, then actuates the door and sends me a text if a flag is set in the DB. However, Verizon is now deeming all my text notifications to myself as spam and started blocking them. I’ve decided to go down the Home Assistant rabbit hole, but I’ve hit a snag. It looks like doing a DB lookup from HA is out of the cards, so I tried hard coding the tags in a script but I’m having some trouble wrapping my head around variables in scripts. Here is the script I’ve put together, but it doesn’t work.

alias: RFID Test
sequence:
  - variables:
      tag_name: unknown
      grant_access: false
      send_note: false
  - choose:
      - conditions:
          - condition: state
            state: "0123456789"
            entity_id: sensor.test_rfid_reader
        sequence:
          - variables:
              tag_name: Test Card Good
              grant_access: true
      - conditions:
          - condition: state
            state: "1234567890"
            entity_id: sensor.test_rfid_reader
        sequence:
          - variables:
              tag_name: Test Keychain Good
              grant_access: true
              send_note: true
  - if:
      - "{{ grant_access }}"
    then:
      - service: mqtt.publish
        data:
          topic: TEST/COMMAND
          payload: ACTUATE
    else:
      - service: mqtt.publish
        data:
          topic: TEST/COMMAND
          payload: DENY
        alias: Unauthorized Tag
      - service: notify.mobile_app_pixel_7
        data:
          message: Access DENIED to tag {{states('sensor.test_rfid_reader')}}
          title: Alert
          data:
            ttl: 0
            priority: high
  - if:
      - "{{ send_note }}"
    then:
      - service: notify.mobile_app_pixel_7
        data:
          message: Access GRANTED to tag {{ tag_name }}
          title: Alert
          data:
            ttl: 0
            priority: high
mode: single

Then I stumbled upon this statement in the docs “Variables have local scope. This means that if a variable is changed in a nested sequence block, that change will not be visible in an outer sequence block.” SO what’s the point of variables if you can’t modify them in a conditional? Will I have to create a choose option with the appropriate publish and notify services for each and every tag number? (there are dozens of them so I’m hoping not)
Thanks

There may be better ways, but what I would do is to split this into two scripts. In your conditions, instead of setting variables, you’d call the second script with the variables’ values as a payload:

…
  - choose:
      - conditions:
          - condition: state
            state: "0123456789"
            entity_id: sensor.test_rfid_reader
        sequence:
          - service: script.verify_access
            data:
              tag_name: Test Card Good
              grant_access: true

Then in your new script:

verify_access:
  sequence:
  - if:
      - "{{ grant_access }}"
    then:
      - service: mqtt.publish
        data:
          topic: TEST/COMMAND
          payload: ACTUATE
…

The issue is the Choose actions…

alias: RFID Test
sequence:
  - variables:
      tag_id: "{{ states('sensor.test_rfid_reader') }}"
      tags:
        "0123456789": 
            tag_name: Test Card Good
            grant_access: true
        "1234567890":
            tag_name: Test Keychain Good
            grant_access: true
            send_note: true
      grant_access: |- 
        {{ iif( tag_id in tags and tags.get(tag_id).grant_access is defined, tags.get(tag_id).grant_access, false, false) }}
      send_note: |- 
        {{ iif( tag_id in tags and tags.get(tag_id).send_note is defined, tags.get(tag_id).send_note, false, false) }}
      tag_name: |-
        {{ iif( tag_id in tags and tags.get(tag_id).tag_name is defined, tags.get(tag_id).tag_name, 'No Name') }}
  - if:
      - "{{ grant_access }}"
    then:
      - service: mqtt.publish
        data:
          topic: TEST/COMMAND
          payload: ACTUATE
    else:
      - service: mqtt.publish
        data:
          topic: TEST/COMMAND
          payload: DENY
        alias: Unauthorized Tag
      - service: notify.mobile_app_pixel_7
        data:
          message: Access DENIED to tag {{ tag_id }}
          title: Alert
          data:
            ttl: 0
            priority: high
  - if:
      - "{{ send_note }}"
    then:
      - service: notify.mobile_app_pixel_7
        data:
          message: Access GRANTED to tag {{ tag_name }}
          title: Alert
          data:
            ttl: 0
            priority: high
mode: single

I will have to keep this in mind, I didn’t see a way to pass parameters to scripts when called only a “Response Variable” which I’d read to mean the called script can return a value to the calling script. I wish there was better documentation.

This works great, I was trying to figure out how to define a dataset in yaml but all my searches returned nil. Now if only I could find a way to pull the dataset out of SQL…

So in this case, the keys under “- variables” are considered to be in the same block as the “- if” statements, so they are referencing the same instance of the variable then I guess?

Thanks

Yes, all the keys defined in “variables” are script-level, so they are available everywhere in the script. Also, all the logic you were attempting in the Choose action is handled while populating the variables section so it isn’t necessary to pass it along to another script for processing.