diff --git a/tests/application/test_joining.py b/tests/application/test_joining.py index b9f645b0..065646e4 100644 --- a/tests/application/test_joining.py +++ b/tests/application/test_joining.py @@ -9,36 +9,25 @@ import zigpy_znp.types as t import zigpy_znp.commands as c -from ..conftest import FORMED_DEVICES, FORMED_ZSTACK3_DEVICES, CoroutineMock +from ..conftest import ( + FORMED_DEVICES, + FORMED_ZSTACK3_DEVICES, + CoroutineMock, + FormedLaunchpadCC26X2R1, +) pytestmark = [pytest.mark.asyncio] -@pytest.mark.parametrize("device", FORMED_DEVICES) -async def test_permit_join(device, make_application): - app, znp_server = make_application(server_cls=device) - - # Handle the startup permit join clear - znp_server.reply_once_to( - request=c.ZDO.MgmtPermitJoinReq.Req( - AddrMode=t.AddrMode.NWK, Dst=0x0000, Duration=0, partial=True - ), - responses=[ - c.ZDO.MgmtPermitJoinReq.Rsp(Status=t.Status.SUCCESS), - c.ZDO.MgmtPermitJoinRsp.Callback(Src=0x0000, Status=t.ZDOStatus.SUCCESS), - ], - override=True, - ) +@pytest.mark.parametrize( + "device,fixed_joining_bug", + [(d, False) for d in FORMED_DEVICES] + [(FormedLaunchpadCC26X2R1, True)], +) +async def test_permit_join(device, fixed_joining_bug, mocker, make_application): + if fixed_joining_bug: + mocker.patch.object(device, "code_revision", 20210708) - znp_server.reply_once_to( - request=c.ZDO.MgmtPermitJoinReq.Req( - AddrMode=t.AddrMode.Broadcast, Dst=0xFFFC, Duration=0, partial=True - ), - responses=[ - c.ZDO.MgmtPermitJoinReq.Rsp(Status=t.Status.SUCCESS), - c.ZDO.MgmtPermitJoinRsp.Callback(Src=0x0000, Status=t.ZDOStatus.SUCCESS), - ], - ) + app, znp_server = make_application(server_cls=device) # Handle us opening joins on the coordinator permit_join_coordinator = znp_server.reply_once_to( @@ -65,8 +54,14 @@ async def test_permit_join(device, make_application): await app.startup(auto_form=False) await app.permit(time_s=10) - await permit_join_coordinator - await permit_join_broadcast + if fixed_joining_bug: + await permit_join_broadcast + + # Joins should not have been opened on the coordinator + assert not permit_join_coordinator.done() + else: + await permit_join_coordinator + await permit_join_broadcast await app.shutdown() diff --git a/tests/conftest.py b/tests/conftest.py index 4ea90878..bb9cf9fd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -722,6 +722,7 @@ def zdo_route_check(self, request): class BaseZStack1CC2531(BaseZStackDevice): align_structs = False version = 1.2 + code_revision = 20190608 @reply_to(c.SYS.OSALNVRead.Req(partial=True)) @reply_to(c.SYS.OSALNVReadExt.Req(partial=True)) @@ -766,7 +767,7 @@ def version_replier(self, request): MajorRel=2, MinorRel=6, MaintRel=3, - CodeRevision=20190608, + CodeRevision=self.code_revision, BootloaderBuildType=c.sys.BootloaderBuildType.BUILT_AS_BIN, BootloaderRevision=0, ) @@ -963,6 +964,7 @@ def connection_made(self): class BaseLaunchpadCC26X2R1(BaseZStack3Device): version = 3.30 align_structs = True + code_revision = 20200805 def create_nib(self, _=None): super().create_nib() @@ -1034,7 +1036,7 @@ def version_replier(self, request): MajorRel=2, MinorRel=7, MaintRel=1, - CodeRevision=20200805, + CodeRevision=self.code_revision, BootloaderBuildType=c.sys.BootloaderBuildType.NON_BOOTLOADER_BUILD, BootloaderRevision=0xFFFFFFFF, ) @@ -1070,6 +1072,7 @@ def led_responder(self, req): class BaseZStack3CC2531(BaseZStack3Device): version = 3.0 align_structs = False + code_revision = 20190425 def create_nib(self, _=None): super().create_nib() @@ -1100,7 +1103,7 @@ def version_replier(self, request): MajorRel=2, MinorRel=7, MaintRel=2, - CodeRevision=20190425, + CodeRevision=self.code_revision, BootloaderBuildType=c.sys.BootloaderBuildType.BUILT_AS_BIN, BootloaderRevision=0, ) diff --git a/zigpy_znp/zigbee/application.py b/zigpy_znp/zigbee/application.py index 1eac10f7..edfac966 100644 --- a/zigpy_znp/zigbee/application.py +++ b/zigpy_znp/zigbee/application.py @@ -699,12 +699,12 @@ async def permit(self, time_s=60, node=None): LOGGER.info("Permitting joins for %d seconds", time_s) + # If joins were permitted through a specific router, older Z-Stack builds + # did not allow the key to be distributed unless the coordinator itself was + # also permitting joins. + # + # Fixed in https://github.com/Koenkk/Z-Stack-firmware/commit/efac5ee46b9b437 if time_s == 0 or self._version_rsp.CodeRevision < 20210708: - # If joins were permitted through a specific router, older Z-Stack builds - # did not allow the key to be distributed unless the coordinator itself was - # also permitting joins. - # - # Fixed in https://github.com/Koenkk/Z-Stack-firmware/commit/efac5ee46b9b437 response = await self._znp.request_callback_rsp( request=c.ZDO.MgmtPermitJoinReq.Req( AddrMode=t.AddrMode.NWK, @@ -716,10 +716,10 @@ async def permit(self, time_s=60, node=None): callback=c.ZDO.MgmtPermitJoinRsp.Callback(Src=0x0000, partial=True), ) - if response.Status != t.Status.SUCCESS: - raise RuntimeError(f"Failed to permit joins on the coordinator: {response}") + if response.Status != t.Status.SUCCESS: + raise RuntimeError(f"Failed to permit joins on coordinator: {response}") - return await super().permit(time_s=time_s, node=node) + await super().permit(time_s=time_s, node=node) async def permit_ncp(self, time_s: int) -> None: """