Skip to content

Conversation

@raman325
Copy link
Owner

@raman325 raman325 commented Jan 5, 2026

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_code command (0x06) for reading codes
  • set_pin_code command (0x05) for setting codes
  • clear_pin_code command (0x07) for clearing codes

Push Updates (Battery Saving)

Subscribes directly to zigpy cluster events to receive real-time notifications:

  • programming_event_notification (0x21): Fires when PINs are added/deleted/changed → triggers coordinator refresh
  • operation_event_notification (0x20): Fires on lock/unlock with user ID → fires code slot event for automations

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:

  • Supported: Disables drift detection entirely (relies on push notifications)
  • Not supported: Enables 1-hour drift detection interval as fallback

Also adds "zha" to after_dependencies in manifest and zigpy to test dependencies.

Type of change

  • New feature (which adds functionality)

Additional information

  • This PR is related to issue: Adding support for additional lock integrations

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings January 5, 2026 04:18
@github-actions github-actions bot added the python Pull requests that update Python code label Jan 5, 2026
@raman325 raman325 added the enhancement New feature or request label Jan 5, 2026
@raman325 raman325 marked this pull request as draft January 5, 2026 04:23
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@raman325 raman325 force-pushed the feat/zha-provider branch 5 times, most recently from 2b84382 to f068ebb Compare January 5, 2026 21:09
@codecov
Copy link

codecov bot commented Jan 5, 2026

Codecov Report

❌ Patch coverage is 67.81116% with 75 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.56%. Comparing base (059c578) to head (d1ac920).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...onents/lock_code_manager/providers/zha/provider.py 66.20% 73 Missing ⚠️
...ponents/lock_code_manager/providers/zha/helpers.py 77.77% 2 Missing ⚠️

❌ 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

Impacted file tree graph

@@            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     
Flag Coverage Δ
python 93.35% <67.81%> (-2.65%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...components/lock_code_manager/providers/__init__.py 100.00% <100.00%> (ø)
...onents/lock_code_manager/providers/zha/__init__.py 100.00% <100.00%> (ø)
...omponents/lock_code_manager/providers/zha/const.py 100.00% <100.00%> (ø)
...ponents/lock_code_manager/providers/zha/helpers.py 77.77% <77.77%> (ø)
...onents/lock_code_manager/providers/zha/provider.py 66.20% <66.20%> (ø)

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@raman325 raman325 linked an issue Jan 9, 2026 that may be closed by this pull request
@github-actions github-actions bot added the dependencies Pull requests that update a dependency file label Jan 15, 2026
@raman325 raman325 force-pushed the feat/zha-provider branch 2 times, most recently from 6418603 to 0a02512 Compare January 15, 2026 19:23
raman325 and others added 7 commits January 15, 2026 14:43
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>
raman325 and others added 5 commits January 15, 2026 14:43
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file enhancement New feature or request python Pull requests that update Python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable the integration for Zigbee locks.

2 participants