Support APS_Encryption transmit option - #738
Conversation
Maps `zigpy.types.TransmitOptions.APS_Encryption` onto EmberZNet's `APS_OPTION_ENCRYPTION` APS frame option, so packets that require APS encryption (e.g. the Zigbee Direct Configuration cluster) are actually sent encrypted with the link key shared with the destination.
There was a problem hiding this comment.
Pull request overview
Adds support for Zigpy’s TransmitOptions.APS_Encryption by mapping it to EmberZNet’s APS_OPTION_ENCRYPTION, ensuring APS-encrypted packets are sent using the destination link key (e.g., for Zigbee Direct Configuration traffic).
Changes:
- Set
EmberApsFrame.options |= APS_OPTION_ENCRYPTIONwhenTransmitOptions.APS_Encryptionis requested. - Add a unit test validating the APS option bit is set for unicast sends when APS encryption is requested.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
bellows/zigbee/application.py |
Adds mapping from Zigpy transmit option APS_Encryption to Ember APS frame encryption option. |
tests/test_application.py |
Adds a unicast send test asserting APS_OPTION_ENCRYPTION is applied when requested. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #738 +/- ##
=======================================
Coverage 99.54% 99.54%
=======================================
Files 64 64
Lines 4203 4205 +2
=======================================
+ Hits 4184 4186 +2
Misses 19 19 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
zigpy-review-bot
left a comment
There was a problem hiding this comment.
Verified the mapping and the surrounding logic — correct, minimal, and well tested. Approving.
What I checked
t.EmberApsOption.APS_OPTION_ENCRYPTIONis0x0020(bellows/types/named.py:946), matching EmberZNet'sEMBER_APS_OPTION_ENCRYPTION— right constant.- Placement is right: an independent
ifafter the source-routing / force-route-discovery / route-discoveryif/elif/elsechain, so it composes with all three branches, and before the ACK block without disturbing theAPS_OPTION_RETRYlogic. - The flag is set regardless of address mode, so it also reaches
send_multicast/send_broadcast. That matches zigpy-znp (zigpy_znp/zigbee/application.py:875setsENABLE_SECURITYungated as well), and in practice zigpy only ever setsAPS_Encryptionfor unicasts (zigpy#1867 sets it inControllerApplication.request()), so there's nothing worth gating on here. - Failure modes stay legible when no link key is available with the destination:
EmberStatus.APS_ENCRYPTION_ERRORandNO_LINK_KEY_RECEIVEDare already mapped to theirsl_Statusequivalents (bellows/types/named.py:1718,:1721), so an NCP rejection surfaces as a normalDeliveryError. - Tests:
test_send_packet_unicast_aps_encryptionasserts the full resulting option set rather than just the new bit — good.tests/test_application.pypasses locally (111 passed) and CI is green.
The two Copilot threads are false positives
Both claim zigpy.types.TransmitOptions.APS_Encryption may not exist at the zigpy>=0.87.0 floor and suggest a getattr() guard plus a skip-if-missing test. It does exist there — git show 0.87.0:zigpy/types/named.py has APS_Encryption = 1 << 1 (the member has been in TransmitOptions since zigpy#1043, long before 0.87.0). So the PR description's "doesn't require a new zigpy version" is accurate, and no getattr() defensiveness is warranted. I'd dismiss both threads (bellows is pull-only for me, so I can't resolve them myself).
Optional follow-up, not for this PR
bellows still doesn't report APS encryption on the receive side: _handle_frame() (bellows/zigbee/application.py:731) builds the ZigbeePacket without tx_options, even though aps_frame.options is right there; zigpy-znp mirrors it (tx_options=APS_Encryption if msg.SecurityUse else NONE). Nothing in zigpy reads tx_options off received packets today, so this is purely a consistency nit for whenever a consumer appears.
Maps
zigpy.types.TransmitOptions.APS_Encryptiononto EmberZNet'sAPS_OPTION_ENCRYPTIONAPS frame option, so packets that require APS encryption (e.g. the Zigbee Direct Configuration cluster) are actually sent encrypted with the link key shared with the destination.Related zigpy PR that requires this (but bellows doesn't require a new zigpy version):