Skip to content
raman325 edited this page Jun 10, 2026 · 3 revisions

Z-Wave Integration

Lock Code Manager supports Z-Wave locks via the Z-Wave JS integration in Home Assistant.

How It Works

Z-Wave locks store PIN codes in numbered user code slots. Lock Code Manager reads, sets, and clears these codes via the Z-Wave JS driver. Most Z-Wave locks support push updates — when a code is used or changed, the lock notifies Home Assistant immediately.

Some Z-Wave locks mask PIN codes (returning **** instead of the actual value). Lock Code Manager handles this transparently — masked codes are treated as "occupied but unreadable" and the configured PIN is shown in the sensor display.

User Credential CC vs User Code CC

Z-Wave locks expose codes through one of two command classes:

  • User Code CC (UC) — the older slot-only model: a slot holds a PIN with no user concept. LCM addresses these by slot number directly. No on-lock identity tag is needed (there is no name field).
  • User Credential CC (U3C) — the newer Z-Wave Plus v2 model: each PIN belongs to a named user. As of LCM 4.0.0, LCM tags its own U3C users with lcm:<slot>:<friendly name> in the user-name field — so a slot-3 user named "Alice" appears on the lock as lcm:3:Alice. This lets LCM coexist with other controllers managing their own users on the same lock.

For U3C locks, two consequences worth knowing:

  • Lock-side user_id is no longer pinned to the LCM slot. Previously LCM created users at user_id == slot; now Z-Wave auto-allocates a free user_id and LCM discovers the user by walking the lock's user list for the tag. You may see the on-lock user_id differ from the LCM slot, which is expected.
  • Existing installs migrate seamlessly. On the first write to a slot after upgrade, LCM scans for an untagged user at the old user_id == slot position; if found, it adopts that user (preserving its credentials) and rewrites its name to the new tagged form. No PIN re-entry needed.

UC locks are unchanged by this — they have no user name field to tag.

LCM uses the Z-Wave JS unified access_control API (introduced in node-zwave-js 15.23.4+) for both command classes; the same Python code path serves UC and U3C locks.

Requirements

  • The Z-Wave JS integration configured in Home Assistant
  • A Z-Wave lock with user code support

Supported Operations

Operation Supported Notes
Set PIN Via Z-Wave JS set_lock_usercode service
Clear PIN Via Z-Wave JS clear_lock_usercode service
Read PIN Varies Some locks return actual PINs, others mask them
Push updates Real-time notifications for code changes and usage
Code slot events Reports which code was used to unlock

Features

  • Push updates: Code changes and lock operations are reported in real time (no polling delay)
  • Code slot events: The pin_used event entity fires when a specific code is used, enabling automations like the Slot Usage Limiter blueprint
  • Duplicate code detection: Detects when a lock rejects a code because it duplicates an existing one
  • Drift detection: Periodically verifies codes on the lock match the configured values

Limitations

  • Masked PINs: Some Z-Wave locks (e.g. certain Schlage models via Z-Wave) mask PIN values. Lock Code Manager cannot read the actual PIN back but handles sync correctly.
  • Lock-specific behavior: Different Z-Wave lock brands may handle user code slots differently (e.g. slot numbering, status reporting).

Troubleshooting

Codes not syncing

Check that the Z-Wave JS integration is loaded and the lock entity is available. Verify the lock's node is not in a failed state in the Z-Wave JS control panel.

"Code rejected" errors

The lock rejected the PIN. Common causes: PIN too short/long for the lock, duplicate PIN already on another slot, or the slot is firmware-disabled.

Masked PINs showing as "unknown"

This is normal for locks that mask their codes. The code sensor shows the configured PIN for display purposes. The sync indicator assumes the code is correct after a successful set.

Clone this wiki locally