What is the problem with strings in this?

The below code works, but it is not what I want to have. The idea is to enter in a six digit user pass code followed by a one digit numeral. The first six characters are the passcode and the last character is what garage door to open or close.

However, I have one user code that starts with a zero and another that starts with a number other than zero. The one with a zero works and the one with a number does not. If I pre-pend a zero to both codes then they both work which is the code I have below but I would rather have the user codes of: “012340” and “123462” because that matches the door lock codes.

I had to jimmy around with the door numbers too, as ‘1’, ‘2’, and ‘3’ in the YAML would not work either.

I’ve tried all manner of workarounds without any success. I can accept the door codes being numeral, but really would like a non-zero string of numbers to be treated as a string by the automation without having to pre-pend the zero.

For the record, the event listener does show the entered numbers as a string being received.

Any help would be greatly appreciated. If it is a dummy request - me being the dummy - feel free to virtually slap me.

Environment is:

  • Installation method Home Assistant OS
  • Core 2026.3.1
  • Supervisor 2026.03.0
  • Operating System 17.1
  • Frontend 20260304.0
alias: Automation - Keypad Garage Control
description: Handles user codes + door number with explicit Open/Close actions
triggers:
  - event_type: zwave_js_notification
    event_data:
      node_id: 142
      command_class: 111
    trigger: event
conditions:
  - condition: template
    value_template: "{{ entered_code in valid_user_codes }}"
actions:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ entered_door == 1 }}"
        sequence:
          - choose:
              - conditions:
                  - condition: state
                    entity_id: cover.garage_01
                    state: closed
                sequence:
                  - action: cover.open_cover
                    target:
                      entity_id: cover.garage_01
              - conditions:
                  - condition: state
                    entity_id: cover.garage_01
                    state: open
                sequence:
                  - action: cover.close_cover
                    target:
                      entity_id: cover.garage_01
      - conditions:
          - condition: template
            value_template: "{{ entered_door == 2 }}"
        sequence:
          - choose:
              - conditions:
                  - condition: state
                    entity_id: cover.garage_02
                    state: closed
                sequence:
                  - action: cover.open_cover
                    target:
                      entity_id: cover.garage_02
              - conditions:
                  - condition: state
                    entity_id: cover.garage_02
                    state: open
                sequence:
                  - action: cover.close_cover
                    target:
                      entity_id: cover.garage_02
      - conditions:
          - condition: template
            value_template: "{{ entered_door == 3 }}"
        sequence:
          - choose:
              - conditions:
                  - condition: state
                    entity_id: cover.garage_03
                    state: closed
                sequence:
                  - action: cover.open_cover
                    target:
                      entity_id: cover.garage_03
              - conditions:
                  - condition: state
                    entity_id: cover.garage_03
                    state: open
                sequence:
                  - action: cover.close_cover
                    target:
                      entity_id: cover.garage_03
mode: parallel
variables:
  valid_user_codes:
    - "0012340"
    - "0123462"
  entered_string: "{{ (trigger.event.data.event_data | string) | trim }}"
  entered_code: "{{ entered_string[:-1] }}"
  entered_door: "{{ entered_string[-1:] | string }}"

Can you post the Trace? I think the issue is your index slicing…

Also, you can condense that significantly:

alias: Automation - Keypad Garage Control
description: Handles user codes + door number with explicit Open/Close actions
triggers:
  - event_type: zwave_js_notification
    event_data:
      node_id: 142
      command_class: 111
    trigger: event
variables:
  valid_user_codes:
    - "0012340"
    - "0123462"
  entered_string: "{{ (trigger.event.data.event_data | string) | trim }}"
  door: "cover.garage_0{{ entered_string[-1] | string }}"
conditions:
  - condition: template
    value_template: "{{ entered_string in valid_user_codes }}"
actions:
  - action: cover.{{'open' if is_state(door,'closed') else 'close'}}_cover
    target:
      entity_id: "{{door}}"
mode: parallel

Long shot, try adding “string” filter to the template condition:

In my experience with this yaml/jinja annoyance: whenever you need to use a numeric variable as a string, you should cast it to a string. In other words, casting in the variable definition isn’t always enough.

I tested it with this script
sequence:
  - variables:
      valid_user_codes:
        - "012340"
        - "123462"
      entered_string: 1234621
      entered_code: "{{ (entered_string|string)[:-1] }}"
      entered_door: "{{ (entered_string|string)[-1:] }}"
      ret:
        entered_string: "{{ entered_string }}"
        entered_code: "{{ entered_code }}"
        entered_door: "{{ entered_door }}"
        valid: "{{ entered_code|string in valid_user_codes }}"
  - stop: ""
    response_variable: ret
alias: test

entered_string is numeric (worst case scenario). You can run this in Developer Tools, Actions to see the output. Without the |string filter, the code is never valid. Also, if the script response doesn’t apper, just retry 2-3 times.

entered_string is likely not a string, so all the slicing won’t work. Home assistant types top level variables. Meaning, things that are strings but look like numbers will be typed as a number.

To get around this, make complex variable outputs. Assuming you update to @Didgeridrew’s suggestion…

alias: Automation - Keypad Garage Control
description: Handles user codes + door number with explicit Open/Close actions
triggers:
  - event_type: zwave_js_notification
    event_data:
      node_id: 142
      command_class: 111
    trigger: event
variables:
  valid_user_codes:
    - "0012340"
    - "0123462"
  entered: "{{ dict(code=(trigger.event.data.event_data | string) | trim) }}"
  door: "cover.garage_0{{ entered.code[-1] | string }}"
conditions:
  - condition: template
    value_template: "{{ entered.code in valid_user_codes }}"
actions:
  - action: cover.{{'open' if is_state(door,'closed') else 'close'}}_cover
    target:
      entity_id: "{{door}}"
mode: parallel
1 Like

Going to mark petro’s response as the answer. While their YAML did not work, the dictionary approach was the key. As well, a Kudos to Didgeridrew in providing a far more concise block of code that the others built on.

Here is what I have wound up with and both six digit codes now work.

alias: Automation - Keypad Garage Control
description: Handles user codes + door number with explicit Open/Close actions
triggers:
  - event_type: zwave_js_notification
    event_data:
      node_id: 142
      command_class: 111
    trigger: event
conditions:
  - condition: template
    value_template: "{{ entered['code'] in valid_user_codes }}"
actions:
  - action: "cover.{{'open' if is_state(entered['door'], 'closed') else 'close'}}_cover"
    target:
      entity_id: "{{ entered['door'] }}"
variables:
  valid_user_codes:
    - "012340"
    - "123456"
  entered: |-
    {{ dict(
      code=(trigger.event.data.event_data | string | trim)[:-1],
      door='cover.garage_0' ~ (trigger.event.data.event_data | string | trim)[-1:]
    ) }}
mode: parallel

You don’t have to use the [‘code’] notation for this. You can use entered.code and entered.door to avoid dealing with termination and quoting

Understood - however, several different AI chatboxes I ran it past commented that a Jinja2-rendered dict is less reliable using dot notation as opposed to bracket notation and as you might have guessed, I am not an advanced YAML user so if the suggestion offered works I’m fine with using it - especially since I have run into similar issues using dot notation as opposed to bracketed notation with SQL queries in other work I have done so it made sense when it was mentioned.

It’s not less reliable. There are a few gotcha’s that you just need to avoid:

  1. don’t start keys with numbers.
  2. don’t use the keys clear, copy, fromkeys, get, items, keys, pop, popitem, setdefault, update, and values.

well in my case I have more than half a dozen users where four started with 4 digit door codes (schlage FE599 lock sets) and when I switched them out for Kwikset with 6-8 digt codes most of those users opted to simply add zeroes to make up the extra two digits, but the other two are new since the Schlage locks were replaced and both opted to use a number other than zero for their first digit.

So the path of least resistance is to use the same codes for this automation which maintains consistency and which makes it less likely I am going to get a call at odd hours asking me to remind them what their code is.

And honestly, I fail to see any good reason other than poor/lazy programming why any assortment of alpha-numeric characters shouldn’t be perfectly fine to use. Any decent programming language lets the coder cast a string of all numbers as a string regardless of what the first character is without having to go through all manner of hoops to make that happen.

And you completely miss understood what I said. You can’t use the dot notation i.e. something.something if you use a number as the first thing in your key. e.g. something.9something isn’t possible. This is a restriction in literally all coding languages. The number restriction isn’t about what you put in the dictionary, it’s what key you use. In your case, you are using the word code and the word door for your keys, so this should have no impact on what you’re doing.

And what Petro said applies to the keys. It doesn’t affect at all what you can use as the values (so it’s not applicable.to your point about codes and leading zeroes). Either way, you’re completely fine using bracket notation. It’s just more conventional to avoid it where possible, paradigm-wise.