Add ZHA (Zigbee Home Automation) lock provider#739
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds support for ZHA (Zigbee Home Automation) locks by implementing a new provider that interfaces with the zigpy DoorLock cluster (0x0101) for user code management.
Key changes:
- Implements polling-based user code synchronization with a 5-minute scan interval and 1-hour hard refresh interval
- Provides direct cluster access for get_pin_code, set_pin_code, and clear_pin_code operations
- Includes connection monitoring with 30-second check intervals
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| custom_components/lock_code_manager/providers/zha.py | New ZHA lock provider implementation with cluster-based user code management, connection checking, and polling configuration |
| custom_components/lock_code_manager/providers/init.py | Registers the new ZHALock provider in the integrations map |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
c73dd9c to
3bda7d1
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
2b84382 to
f068ebb
Compare
Codecov Report❌ Patch coverage is
❌ Your patch check has failed because the patch coverage (67.81%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #739 +/- ##
==========================================
- Coverage 96.04% 93.56% -2.48%
==========================================
Files 29 33 +4
Lines 2554 2768 +214
Branches 83 82 -1
==========================================
+ Hits 2453 2590 +137
- Misses 101 178 +77
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
40561f0 to
cc80f2a
Compare
6418603 to
0a02512
Compare
Add support for ZHA locks by accessing the zigpy DoorLock cluster (0x0101) directly. This enables user code management for Zigbee locks via: - get_pin_code command (0x06) for reading codes - set_pin_code command (0x05) for setting codes - clear_pin_code command (0x07) for clearing codes Uses polling mode (5 min interval) since ZHA doesn't support push updates for user codes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Subscribe to Door Lock cluster events directly via zigpy to receive: - programming_event_notification (0x21): PIN code added/deleted/changed → triggers coordinator refresh to sync new code state - operation_event_notification (0x20): lock/unlock with user ID → fires code slot event for automations This eliminates the need for 5-minute polling on locks that support these notifications, significantly reducing Zigbee traffic and improving battery life. Also adds zigpy to test dependencies. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Check programming event mask attributes to determine if the lock supports programming_event_notification. If not supported, enable 1-hour drift detection interval as fallback. This ensures locks that don't support programming events still get periodic code sync, while locks that do support them avoid unnecessary polling. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Convert providers/zha.py to providers/zha/ package - Use zigpy types directly (DoorLock.UserStatus, DoorLock.OperationEvent, etc.) - Keep only custom mappings in const.py (OPERATION_TO_LOCKED, OPERATION_SOURCE_NAMES) - Extract get_zha_gateway helper to helpers.py 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix get_zha_gateway helper to use HA's official get_zha_gateway_proxy - Fix _get_door_lock_cluster to access underlying zigpy device correctly (device_proxy.device is ZHA Device, .device again gets zigpy device) - Add comprehensive ZHA test fixtures adapted from HA core's ZHA tests - Add test_zha.py with 15 tests covering properties, cluster access, usercodes, push updates, and programming event detection - Fix _concurrent_requests_semaphore.max_value mock for gateway teardown 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Simplify redundant len(result) > 3 check (already checked >= 4) - Let LockDisconnected propagate without re-wrapping in exception handlers - Extract duplicated connection check logic into _get_connected_cluster helper - Add return type hint to get_zha_gateway function Note: Unused constants (USER_STATUS_*) were already addressed in previous commits. Test coverage exists in tests/providers/test_zha.py. The eq=False dataclass setting is intentional for identity-based comparison. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The ZHA integration has CONNECT_DELAY_S and RETRY_DELAY_S constants (both 1.0s) in radio_manager.py that are used for real hardware timing. These caused each ZHA test to spend ~1.1s in setup. Patching these to 0 in tests reduces: - ZHA tests: 18s → 3s - Full suite: 20s → 5.5s 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed Coroutine[None] to Awaitable[None] which is the correct type for async callables that return None. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The ZHA provider imports from homeassistant.components.zha which requires the zha package to be installed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The ZHA gateway's radio_concurrency property uses max_value in arithmetic operations. Using MagicMock caused TypeError when comparing MagicMock with int. Using a simple class ensures the value is an actual integer. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Newer versions of ZHA access max_concurrency instead of max_value. Add both attributes to support both old and new ZHA versions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
0a02512 to
40b0f52
Compare
Proposed change
Adds support for ZHA locks by accessing the zigpy DoorLock cluster (0x0101) directly. This enables user code management for Zigbee locks via:
get_pin_codecommand (0x06) for reading codesset_pin_codecommand (0x05) for setting codesclear_pin_codecommand (0x07) for clearing codesPush Updates (Battery Saving)
Subscribes directly to zigpy cluster events to receive real-time notifications:
This eliminates polling for locks that support these notifications, significantly reducing Zigbee traffic and improving battery life.
Capability Detection
Checks the lock's programming event mask attributes (
keypad_programming_event_mask,rf_programming_event_mask,rfid_programming_event_mask) to determine if it supports programming event notifications:Also adds "zha" to after_dependencies in manifest and zigpy to test dependencies.
Type of change
Additional information
🤖 Generated with Claude Code