ZHA: User code management on Zigbee door locks

A couple of quick questions on your script.

lock: YOUR.LOCK_DEVICE

Is that an entity or device ID?

And I feel like a total newb for this one, but what the heck is a device_id and where do I find it?

@flyize Configuration → Devices → /choose your lock/, then you’ll see it’s ID in the URL

1 Like

@vilord I just found a bug, related to ZHA Yale locks - actual user code slots on the lock are shifted by 1, compared to what is handled by ZHA functions. I.e. if I set up a code for user #1 via yale keypad (master code, 1, 2, 1 /user slot #/, code) - it actually corresponds to slot #2 handled via zha calls (clear, set, enable, disable).

As a side node - I also have one Z-wave Yale lock, where it handles all the slots correctly (i.e. slot #1 on the lock = slot #1 in zwave lock calls).

Hey Vlad, is that bug still a thing?

I just installed my first zigbee lock, a yale assure SL (branded as a lockwood tlock here in australia)

I set up the first few codes via the panel itself and then found this thread. Managed to get @jkuntz805 dashboard working without too much trouble and have configured 2 more codes through home assistant using it.

It seems the codes created from the panel started at 1 for the master code and counted up. on the surface, (to a noob like me) it seems okay. maybe i’m missing something? Just wanted to check I didn’t have to watch out for a gotcha.

Master code is NOT the same as User1 code. I have 3 Zigbee + 1 Zwave Yale locks and initially configured all of them via keypad. Master as master, User1 for me, User2 for my wife etc.

When I tried to reset the code for me (User1) via the above dashboard. I was able to get with new code to Zwave lock, but not to any Zigbee. When I reset code for User2, it propagated to User2 on Zwave lock (as expected), but to User1 instead of User2 on all Zigbee locks.

I ended up with the following workaround for Yale Zigbee locks (+1 increment while calling zha functions)

add_code:
  alias: Add Lock Code
  variables:
    codeslot: "{{ states('input_text.codeslot') | int }}"
    usercode: "{{ states('input_text.usercode') | int }}"
  sequence:
  - service: zwave_js.set_lock_usercode
    target:
      device_id: <yale_zwave_lock_id>
    data:
      code_slot: '{{ codeslot }}'
      usercode: '{{ usercode }}'
  - service: zha.set_lock_user_code
    data:
      code_slot: '{{ codeslot+1 }}'
      user_code: '{{ usercode }}'
    target:
      device_id:
        - <yale1_zigbee_lock_id>
        - <yale2_zigbee_lock_id>
        - <yale3_zigbee_lock_id>
  - service: notify.my_mobile
    data:
      title: 'YALE LOCKS - USER CODE UPDATED'
      message: 'Slot #{{ codeslot }} was updated with user code {{ usercode }}'
  mode: single
clear_code:
  alias: Clear Lock Code
  variables:
    codeslot: "{{ states('input_text.codeslot') | int }}"
    usercode: "{{ states('input_text.usercode') | int }}" # Unused
  sequence:
  - service: zwave_js.clear_lock_usercode
    target:
      device_id: <yale_zwave_lock_id>
    data:
      code_slot: '{{ codeslot }}'
  - service: zha.clear_lock_user_code
    data:
      code_slot: '{{ codeslot+1 }}'
    target:
      device_id:
        - <yale1_zigbee_lock_id>
        - <yale2_zigbee_lock_id>
        - <yale3_zigbee_lock_id>
  - service: notify.my_mobile
    data:
      title: 'YALE LOCKS - USER CODE DELETED'
      message: 'User code was deleted from slot #{{ codeslot }}'
  mode: single

Just to contribute with something quite easy, but useful (at least for me).

It’s a single use code. Meaning it gets cleared after a single use.

Considering you installed the custom Lovelace text input row* mentioned by @jkuntz805:

Create an input text for your single use code

Input Text - Single Use Code

In your configuration.yaml, add this input_text.

input_text:
##Input do código temporário da porta
  singleusecode:
    name: Single Use Code
    initial: 0000

Create a script that sets the user code and notifies you

Script - Set new lock code and notify

Important: I’m using codeslot 100, since I probably won’t create 100 codes in this lifetime. Which also means in this workflow, only 1 single use code is possible. Please check your lock max number of codes to see if 100 is usable.

alias: Add Single Use Code
sequence:
  - service: zha.set_lock_user_code
    target:
#Easiest way to locate your device ID is through the Call Service on Developer Tools, selecting zha.set_lock_user_code, selecting your device and checking the YAML editor
      device_id: yourDeviceID
    data:
      code_slot: '100'
      user_code: '{{ states(''input_text.singleusecode'') | int }}'
  - service: notify.your_phone_goes_here
    data:
      message: Um código de uso único foi criado.
      title: Novo código - Porta da Frente
      data:
#This part is only valid for Android devices. For some reason, I need this or the notification won't show unless I unlock my phone. This sets the notification priority as urgent. In case you need it, check documentation for iOS settings on priority.
        ttl: 0
        priority: high
mode: single
icon: mdi:key-plus

Create a card to input your single use code and run the script

Lovelace Card

You can place this in a lovelace card, editing it in YAML mode.

type: vertical-stack
cards:
  - type: entities
    header:
      image: https://www.ryadel.com/wp-content/uploads/2017/11/IT-Security.jpg
      type: picture
    show_header_toggle: false
    entities:
      - type: custom:text-input-row
        entity: input_text.singleusecode
      - entity: script.add_single_use_code
        icon: mdi:key-plus

Create an automation that deletes the code when used and notifies you

Automation to delete used code and send notification

This was created for a Yale YRD256 lock with Zigbee. It’s probably the same for a few other Yale Locks with Zigbee. For your lock, you might want to check which args you should use to detect Unlocking on the trigger and the code slot args to use on the condition. You can check this by listening to zha_event on Developer Tools and unlocking your door through the keypad to check for the event info.

alias: Fechadura - Deleta Single Use Code
trigger:
  - platform: event
    event_type: zha_event
    event_data:
#You can find the device_ieee on your Zigbee integration.
      device_ieee: 00:00:00:00:00:00:00:00
      args:
        operation: Unlock
condition:
  - condition: template
    value_template: '{{ trigger.event.data.args.code_slot == 100 }}'
action:
  - service: zha.clear_lock_user_code
    target:
      device_id: yourDeviceID
    data:
      code_slot: '100'
  - service: notify.your_phone_goes_here
    data:
      title: Porta da Frente
      message: Código de Uso Único foi utilizado e apagado.
      data:
        ttl: 0
        priority: high
mode: single

That’s it. I made a few comments along the way to help people that - like me - are noobs.

Hope someone finds it helpful.

** btw if you didn’t install the custom elements, easiest way is through HACS. It’s available there.

2 Likes

Hi all, @VladStar sorry for that bug… it seems like kwikset vs yale handles the slot numbers differently, I didn’t run into that with my kwikset locks.
@Bruno_Dantas this is great! Glad to see you’re able to leverage all the functions and put them together into this! A perfect use for the integration.

1 Like

Thanks @jkuntz805 ! I was able to implement this card in my dashboard and update the scripts to reflect service calls to Hubitat, so it’s easy-peasy to add new codes and looks pretty too!

Background: I use Hubitat to connect to all my Zigbee and Zwave devices, so the usual OTS integrations like KeyMaster probably won’t work to manage locks without significant effort since I don’t have any Zwave services in HA. My Yale Zigbee lock was the last thing still on SmartThings, as the Hubitat UI for lock code management isn’t very wife friendly. But now I’m off ST and wife will be content.

For any other Hubitat users who come through this thread, I am using the Hubitat integration to HA through Maker API. It’s fairly trivial to add/remove codes for any lock in Hubitat using this card, with only slight modification of the associated scripts (I’m not a developer).

Feature Request: Ideally, all codes added through these scripts get logged to a file, which is then read by the Lock Codes display section of the card to reflect current users/codes without having to manually update a static list.

Another aspect of user code management is the ability to read back a user PIN code - even though it’s kind of icky from a security standpoint, but the spec allows it.

It is fairly simple on Yale locks to get user codes by issuing a cluster command, the argument is the “user_id”:

service: zha.issue_zigbee_cluster_command
data:
  ieee: 00:00:00:00:00:00:00:00
  endpoint_id: 1
  cluster_id: 257
  command: 6
  command_type: server
  args: 1

Unfortunately it looks like zha has no support for turning the reply into a zha_event, is there any interest in adding support for this? Right now the only way is to get the pin code value is to enable debug logging and grep for get_ping in the logs.

Edit: reading the ZHA component source, it looks like almost everything is there to read a pin code, there are just a couple of callbacks missing, is anyone working on this?

2 Likes

I would be interested in being able to retrieve pins. Could be handy for my single use codes if I forget them.

https://github.com/firstof9/keymaster/tree/zha-support It seems like firstof9 is working on zha support in keymaster

1 Like

This is super useful thanks. Reopening old thread sorry, but wanted to check on the Code Slot format - are they just any integer from 1 to ? I’ve only configured the master code on the unit itself so far. Using Yale Assure SL if they are lock-dependent… Thanks

1 Like

Yes, it’s just a number. My Schlage, for example, has 30 code slots available.

1 Like

Was ZHA pin support ever implemented?
If not what are your current workarounds?
Thx

I am still using this:

1 Like

Thank you.

But still no way to retrieve/read the existing pin codes right?

To the best of my knowledge - correct

1 Like

services now support returning data. Any chance of getting a get_pin_code service implemented?

1 Like

See another topic that I’ve created in the past. Cluster command (that supposed to get a pin code from the Yale locks) still isn’t working in 2023.10.5.