59 lines
2.9 KiB
Markdown
59 lines
2.9 KiB
Markdown
# Door Locks & Codes
|
||
|
||
<overview>
|
||
Two Kwikset HC620 Z-Wave (zwave_js) keypad locks:
|
||
`lock.lodge_front_door_lock` (node 3) and `lock.bunkhouse_frontdoor_lock`
|
||
(node 8). Each supports user-code slots 1–250; the automation and "Lock
|
||
Management" Lovelace view manage shared logical slots 1–8 via helpers:
|
||
`input_text.lock_slotN_user`, `input_text.lock_slotN_code`,
|
||
`input_boolean.lock_slotN_lodge_enabled`, and
|
||
`input_boolean.lock_slotN_bunkhouse_enabled` (N = 1–8).
|
||
Slot 1 = Fritz family, 2 = cleaner, 4 = carpenter, 5 = backup.
|
||
Legacy `input_boolean.lock_slotN_enabled` helpers remain but are unwired and
|
||
hidden from the dashboard.
|
||
</overview>
|
||
|
||
<sync>
|
||
All code changes go through `script.lock_sync_slot` (fields: `slot` 1–8), the
|
||
single source of truth. Per slot and door it refreshes the User Code CC cache,
|
||
then writes the validated slot code when enabled or calls
|
||
`zwave_js.clear_lock_usercode` when disabled. Every Z-Wave call uses
|
||
`continue_on_error`, so one door never blocks the other.
|
||
|
||
- `script.lock_sync_all_codes` — warns (persistent + `notify.mobile_app_donavan_s_iphone_16_pro`)
|
||
if a lock's `*_node_status` sensor isn't alive/asleep, then runs
|
||
`lock_sync_slot` for slots 1–8.
|
||
- `automation.lock_slot_N_sync_both_locks` (×8, alias "Sync Door Codes") —
|
||
trigger on either door's enabled toggle OR the slot's `_code` helper →
|
||
`lock_sync_slot` for that slot.
|
||
- `automation.lock_codes_full_sync_self_heal` — full sync daily 04:00 and
|
||
10 min after HA start, so transient failures heal within a day.
|
||
|
||
An HC620 clear is confirmed by a refreshed `in_use: false` readback. Do not
|
||
overwrite disabled slots with the family PIN: the lock rejects a duplicate PIN
|
||
without changing the slot even when the service call returns successfully.
|
||
</sync>
|
||
|
||
<troubleshooting>
|
||
Error `userCode for code slot N not found` from `zwave_js.set_lock_usercode`
|
||
= Z-Wave JS value cache has no userCode value for that slot, NOT a lock or code
|
||
problem. The sync script's pre-`get` prevents it; manual fix:
|
||
`zwave_js.invoke_cc_api {device_id, command_class: "99", method_name: "get", parameters: [N]}`
|
||
then re-run the sync.
|
||
|
||
Bunkhouse lock (Z-Wave node 8) intermittently returns `ZW1405 - node failed to
|
||
decode the message` on commands (seen 2026-07-05 on unlock + usercode set).
|
||
Sync tolerates it (continue_on_error + daily self-heal retries); if it
|
||
persists, suspect S2/RF health on that lock.
|
||
</troubleshooting>
|
||
|
||
<backup>
|
||
Scripts/automations/dashboards/helper-definitions are mirrored to
|
||
`dfritz/home-assistant` repo under `lodge/` (API export — the lodge HA has no
|
||
SSH). Nightly Gitea Actions workflow `.gitea/workflows/backup-ha.yaml` IN THIS
|
||
SKILL REPO (secrets `HA_TOKEN` + `GIT_TOKEN` on skills/thelonglakelodge; ops
|
||
lacks rights to put secrets on dfritz/home-assistant) exports and pushes only
|
||
on change; failure emails via action/notify-email. Manual run: the workflow's
|
||
`workflow_dispatch`, or `HA_TOKEN=... lodge/backup.sh` in the mirror repo.
|
||
</backup>
|