Skip to content

Support APS_Encryption transmit option - #738

Merged
puddly merged 2 commits into
zigpy:devfrom
TheJulianJES:tjj/aps-encryption-tx-option
Jul 28, 2026
Merged

Support APS_Encryption transmit option#738
puddly merged 2 commits into
zigpy:devfrom
TheJulianJES:tjj/aps-encryption-tx-option

Conversation

@TheJulianJES

Copy link
Copy Markdown
Contributor

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.

Related zigpy PR that requires this (but bellows doesn't require a new zigpy version):

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.
Copilot AI review requested due to automatic review settings July 28, 2026 18:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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_ENCRYPTION when TransmitOptions.APS_Encryption is 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.

Comment thread bellows/zigbee/application.py
Comment thread tests/test_application.py
@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.54%. Comparing base (89750d1) to head (6401d18).

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@zigpy-review-bot zigpy-review-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Verified the mapping and the surrounding logic — correct, minimal, and well tested. Approving.

What I checked

  • t.EmberApsOption.APS_OPTION_ENCRYPTION is 0x0020 (bellows/types/named.py:946), matching EmberZNet's EMBER_APS_OPTION_ENCRYPTION — right constant.
  • Placement is right: an independent if after the source-routing / force-route-discovery / route-discovery if/elif/else chain, so it composes with all three branches, and before the ACK block without disturbing the APS_OPTION_RETRY logic.
  • 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:875 sets ENABLE_SECURITY ungated as well), and in practice zigpy only ever sets APS_Encryption for unicasts (zigpy#1867 sets it in ControllerApplication.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_ERROR and NO_LINK_KEY_RECEIVED are already mapped to their sl_Status equivalents (bellows/types/named.py:1718, :1721), so an NCP rejection surfaces as a normal DeliveryError.
  • Tests: test_send_packet_unicast_aps_encryption asserts the full resulting option set rather than just the new bit — good. tests/test_application.py passes 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.

@puddly
puddly merged commit cd25d97 into zigpy:dev Jul 28, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants