Skip to content

Commit 83e36fa

Browse files
committed
Test joins through a specific device and fix addressing bug
1 parent ffaa197 commit 83e36fa

File tree

7 files changed

+58
-17
lines changed

7 files changed

+58
-17
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ repos:
55
- id: debug-statements
66

77
- repo: https://github.com/psf/black
8-
rev: 22.1.0
8+
rev: 22.3.0
99
hooks:
1010
- id: black
1111

tests/application/test_joining.py

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,8 @@
1919
)
2020

2121

22-
@pytest.mark.parametrize(
23-
"device,fixed_joining_bug",
24-
[(d, False) for d in FORMED_DEVICES] + [(FormedLaunchpadCC26X2R1, True)],
25-
)
26-
async def test_permit_join(device, fixed_joining_bug, mocker, make_application):
27-
if fixed_joining_bug:
28-
mocker.patch.object(device, "code_revision", 20210708)
29-
22+
@pytest.mark.parametrize("device", FORMED_DEVICES)
23+
async def test_permit_join(device, mocker, make_application):
3024
app, znp_server = make_application(server_cls=device)
3125

3226
permit_join_coordinator = znp_server.reply_once_to(
@@ -70,7 +64,7 @@ async def test_permit_join(device, fixed_joining_bug, mocker, make_application):
7064
await permit_join_broadcast
7165
await permit_join_broadcast_raw
7266

73-
if fixed_joining_bug:
67+
if device.code_revision >= 20210708:
7468
assert not permit_join_coordinator.done()
7569
else:
7670
assert permit_join_coordinator.done()
@@ -101,6 +95,41 @@ async def test_join_coordinator(device, make_application):
10195
await app.shutdown()
10296

10397

98+
@pytest.mark.parametrize("device", [FormedLaunchpadCC26X2R1])
99+
async def test_join_device(device, make_application):
100+
ieee = t.EUI64.convert("EC:1B:BD:FF:FE:54:4F:40")
101+
nwk = 0x1234
102+
103+
app, znp_server = make_application(server_cls=device)
104+
device = app.add_initialized_device(ieee=ieee, nwk=nwk)
105+
106+
permit_join = znp_server.reply_once_to(
107+
request=c.ZDO.MgmtPermitJoinReq.Req(
108+
AddrMode=t.AddrMode.NWK, Dst=nwk, Duration=60, partial=True
109+
),
110+
responses=[
111+
c.ZDO.MgmtPermitJoinReq.Rsp(Status=t.Status.SUCCESS),
112+
c.ZDO.MgmtPermitJoinRsp.Callback(Src=nwk, Status=t.ZDOStatus.SUCCESS),
113+
c.ZDO.MsgCbIncoming.Callback(
114+
Src=nwk,
115+
IsBroadcast=t.Bool.false,
116+
ClusterId=32822,
117+
SecurityUse=0,
118+
TSN=6,
119+
MacDst=0x0000,
120+
Data=b"\x00",
121+
),
122+
],
123+
)
124+
125+
await app.startup(auto_form=False)
126+
await app.permit(node=ieee)
127+
128+
await permit_join
129+
130+
await app.shutdown()
131+
132+
104133
@pytest.mark.parametrize("device", FORMED_ZSTACK3_DEVICES)
105134
@pytest.mark.parametrize("permit_result", [None, asyncio.TimeoutError()])
106135
async def test_permit_join_with_key(device, permit_result, make_application, mocker):

tests/application/test_requests.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@
2121
)
2222

2323

24-
@pytest.mark.parametrize("device", FORMED_DEVICES)
24+
@pytest.mark.parametrize("device", [FormedLaunchpadCC26X2R1])
2525
async def test_chosen_dst_endpoint(device, make_application, mocker):
2626
app, znp_server = make_application(device)
2727
await app.startup(auto_form=False)
2828

29+
build = mocker.patch.object(type(app), "_zstack_build_id", mocker.PropertyMock())
30+
build.return_value = 20200708
31+
2932
cluster = mocker.Mock()
3033
cluster.endpoint.endpoint_id = 2
3134
cluster.endpoint.profile_id = zigpy.profiles.zll.PROFILE_ID

tests/application/test_startup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,23 @@
2020

2121
DEV_NETWORK_SETTINGS = {
2222
FormedLaunchpadCC26X2R1: (
23-
"CC1352/CC2652, Z-Stack 3.30+ (build 20200805)",
23+
f"CC1352/CC2652, Z-Stack 3.30+ (build {FormedLaunchpadCC26X2R1.code_revision})",
2424
15,
2525
t.Channels.from_channel_list([15]),
2626
0x4402,
2727
t.EUI64.convert("A2:BA:38:A8:B5:E6:83:A0"),
2828
t.KeyData.convert("4C:4E:72:B8:41:22:51:79:9A:BF:35:25:12:88:CA:83"),
2929
),
3030
FormedZStack3CC2531: (
31-
"CC2531, Z-Stack 3.0.x (build 20190425)",
31+
f"CC2531, Z-Stack 3.0.x (build {FormedZStack3CC2531.code_revision})",
3232
15,
3333
t.Channels.from_channel_list([15]),
3434
0xB6AB,
3535
t.EUI64.convert("62:92:32:46:3C:77:2D:B2"),
3636
t.KeyData.convert("6D:DE:24:EA:E2:85:52:B6:DE:29:56:EB:05:85:1A:FA"),
3737
),
3838
FormedZStack1CC2531: (
39-
"CC2531, Z-Stack Home 1.2 (build 20190608)",
39+
f"CC2531, Z-Stack Home 1.2 (build {FormedZStack1CC2531.code_revision})",
4040
11,
4141
t.Channels.from_channel_list([11]),
4242
0x1A62,

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,7 @@ def connection_made(self):
11111111
class BaseLaunchpadCC26X2R1(BaseZStack3Device):
11121112
version = 3.30
11131113
align_structs = True
1114-
code_revision = 20200805
1114+
code_revision = 20220219
11151115

11161116
def _create_network_nvram(self):
11171117
super()._create_network_nvram()

zigpy_znp/types/commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ def __init__(self, *, partial=False, **params):
345345
and not issubclass(param.type, enum.Enum),
346346

347347
isinstance(value, bytes)
348-
and issubclass(param.type, (t.ShortBytes, t.LongBytes)),
348+
and issubclass(param.type, (t.ShortBytes, t.LongBytes, t.Bytes)),
349349

350350
isinstance(value, list) and issubclass(param.type, list),
351351
isinstance(value, bool) and issubclass(param.type, t.Bool),

zigpy_znp/zigbee/application.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,13 @@ async def _send_request_raw(
12361236
# addressing another device. The router will receive the ZDO request and a
12371237
# device will try to join, but Z-Stack will never send the network key.
12381238
if cluster == zdo_t.ZDOCmd.Mgmt_Permit_Joining_req:
1239+
if dst_addr.mode == t.AddrMode.Broadcast:
1240+
# The coordinator responds to broadcasts
1241+
permit_addr = 0x0000
1242+
else:
1243+
# Otherwise, the destination device responds
1244+
permit_addr = dst_addr.address
1245+
12391246
await self._znp.request_callback_rsp(
12401247
request=c.ZDO.MgmtPermitJoinReq.Req(
12411248
AddrMode=dst_addr.mode,
@@ -1244,7 +1251,9 @@ async def _send_request_raw(
12441251
TCSignificance=data[2],
12451252
),
12461253
RspStatus=t.Status.SUCCESS,
1247-
callback=c.ZDO.MgmtPermitJoinRsp.Callback(Src=0x0000, partial=True),
1254+
callback=c.ZDO.MgmtPermitJoinRsp.Callback(
1255+
Src=permit_addr, partial=True
1256+
),
12481257
)
12491258
# Internally forward ZDO requests destined for the coordinator back to zigpy
12501259
# so we can send internal Z-Stack requests when necessary

0 commit comments

Comments
 (0)