Skip to content

Fix bug that prevented just the coordinator from permitting joins #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions tests/application/test_joining.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,29 @@ async def test_permit_join(device, fixed_joining_bug, mocker, make_application):
await app.shutdown()


@pytest.mark.parametrize("device", FORMED_DEVICES)
async def test_join_coordinator(device, make_application):
app, znp_server = make_application(server_cls=device)

# Handle us opening joins on the coordinator
permit_join_coordinator = znp_server.reply_once_to(
request=c.ZDO.MgmtPermitJoinReq.Req(
AddrMode=t.AddrMode.NWK, Dst=0x0000, Duration=60, partial=True
),
responses=[
c.ZDO.MgmtPermitJoinReq.Rsp(Status=t.Status.SUCCESS),
c.ZDO.MgmtPermitJoinRsp.Callback(Src=0x0000, Status=t.ZDOStatus.SUCCESS),
],
)

await app.startup(auto_form=False)
await app.permit(node=app.ieee)

await permit_join_coordinator

await app.shutdown()


@pytest.mark.parametrize("device", FORMED_ZSTACK3_DEVICES)
@pytest.mark.parametrize("permit_result", [None, asyncio.TimeoutError()])
async def test_permit_join_with_key(device, permit_result, make_application, mocker):
Expand Down
19 changes: 13 additions & 6 deletions zigpy_znp/zigbee/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ def model(self):
model = "CC2538" if self.application._znp.nvram.align_structs else "CC2531"
version = "Home 1.2" if self.application._znp.version == 1.2 else "3.0.x"

build = self.application._version_rsp.CodeRevision

return f"{model}, Z-Stack {version} (build {build})"
return f"{model}, Z-Stack {version} (build {self.application._zstack_build_id})"


class ControllerApplication(zigpy.application.ControllerApplication):
Expand Down Expand Up @@ -328,7 +326,7 @@ async def _startup(self, auto_form=False, force_form=False, read_only=False):
LOGGER.info("Network settings")
LOGGER.info(" Model: %s", self.zigpy_device.model)
LOGGER.info(" Z-Stack version: %s", self._znp.version)
LOGGER.info(" Z-Stack build id: %s", self._version_rsp.CodeRevision)
LOGGER.info(" Z-Stack build id: %s", self._zstack_build_id)
LOGGER.info(" Max concurrent requests: %s", max_concurrent_requests)
LOGGER.info(" Channel: %s", self.channel)
LOGGER.info(" PAN ID: 0x%04X", self.pan_id)
Expand Down Expand Up @@ -704,10 +702,11 @@ async def permit(self, time_s=60, node=None):

# 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.
# also permitting joins. This also needs to happen if we're permitting joins
# through the coordinator itself.
#
# Fixed in https://github.com/Koenkk/Z-Stack-firmware/commit/efac5ee46b9b437
if time_s == 0 or self._version_rsp.CodeRevision < 20210708:
if time_s == 0 or self._zstack_build_id < 20210708 or node == self.ieee:
response = await self._znp.request_callback_rsp(
request=c.ZDO.MgmtPermitJoinReq.Req(
AddrMode=t.AddrMode.NWK,
Expand Down Expand Up @@ -979,6 +978,14 @@ async def on_af_message(self, msg: c.AF.IncomingMsg.Callback) -> None:
# Internal methods #
####################

@property
def _zstack_build_id(self) -> t.uint32_t:
"""
Z-Stack build ID, more recently the build date.
"""

return self._version_rsp.CodeRevision

@property
def zigpy_device(self) -> zigpy.device.Device:
"""
Expand Down