zigpy-deconz 0.25.2__tar.gz → 0.25.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {zigpy_deconz-0.25.2/zigpy_deconz.egg-info → zigpy_deconz-0.25.3}/PKG-INFO +1 -1
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/tests/test_application.py +1 -1
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/tests/test_network_state.py +103 -6
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz/zigbee/application.py +14 -7
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3/zigpy_deconz.egg-info}/PKG-INFO +1 -1
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/COPYING +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/LICENSE +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/README.md +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/pyproject.toml +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/setup.cfg +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/setup.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/tests/test_api.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/tests/test_exception.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/tests/test_send_receive.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/tests/test_types.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/tests/test_uart.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/tests/test_utils.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz/__init__.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz/api.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz/config.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz/exception.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz/types.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz/uart.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz/utils.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz/zigbee/__init__.py +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz.egg-info/SOURCES.txt +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz.egg-info/dependency_links.txt +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz.egg-info/requires.txt +0 -0
- {zigpy_deconz-0.25.2 → zigpy_deconz-0.25.3}/zigpy_deconz.egg-info/top_level.txt +0 -0
|
@@ -556,7 +556,7 @@ async def test_reset_network_info(app):
|
|
|
556
556
|
app.form_network = AsyncMock()
|
|
557
557
|
await app.reset_network_info()
|
|
558
558
|
|
|
559
|
-
app.form_network.
|
|
559
|
+
app.form_network.assert_called_once_with(fast=True)
|
|
560
560
|
|
|
561
561
|
|
|
562
562
|
async def test_energy_scan_conbee_2(app):
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Test `load_network_info` and `write_network_info` methods."""
|
|
2
2
|
|
|
3
3
|
import importlib.metadata
|
|
4
|
+
from unittest.mock import ANY, call
|
|
4
5
|
|
|
5
6
|
import pytest
|
|
6
|
-
from zigpy.exceptions import
|
|
7
|
+
from zigpy.exceptions import CannotWriteNetworkSettings, NetworkNotFormed
|
|
7
8
|
import zigpy.state as app_state
|
|
8
9
|
import zigpy.types as t
|
|
9
10
|
import zigpy.zdo.types as zdo_t
|
|
@@ -70,28 +71,55 @@ def network_info(node_info):
|
|
|
70
71
|
@patch.object(application, "CHANGE_NETWORK_POLL_TIME", 0.001)
|
|
71
72
|
@patch.object(application, "CHANGE_NETWORK_STATE_DELAY", 0.001)
|
|
72
73
|
@pytest.mark.parametrize(
|
|
73
|
-
|
|
74
|
+
(
|
|
75
|
+
"channel_mask",
|
|
76
|
+
"channel",
|
|
77
|
+
"security_level",
|
|
78
|
+
"fw_supports_fc",
|
|
79
|
+
"logical_type",
|
|
80
|
+
"tx_counter",
|
|
81
|
+
"should_error",
|
|
82
|
+
),
|
|
74
83
|
[
|
|
84
|
+
# FW supports frame counter
|
|
75
85
|
(
|
|
76
86
|
t.Channels.from_channel_list([15]),
|
|
77
87
|
15,
|
|
78
88
|
0,
|
|
79
89
|
True,
|
|
80
90
|
zdo_t.LogicalType.Coordinator,
|
|
91
|
+
39009277,
|
|
92
|
+
False,
|
|
93
|
+
),
|
|
94
|
+
# FW doesn't support but we're writing blank settings (tx_counter == 0)
|
|
95
|
+
(
|
|
96
|
+
t.Channels.from_channel_list([15]),
|
|
97
|
+
15,
|
|
98
|
+
5,
|
|
99
|
+
False,
|
|
100
|
+
zdo_t.LogicalType.Coordinator,
|
|
101
|
+
0,
|
|
102
|
+
False,
|
|
81
103
|
),
|
|
104
|
+
# FW doesn't support and we're writing real settings (should error)
|
|
82
105
|
(
|
|
83
106
|
t.Channels.from_channel_list([15]),
|
|
84
107
|
15,
|
|
85
108
|
0,
|
|
86
109
|
False,
|
|
87
110
|
zdo_t.LogicalType.Coordinator,
|
|
111
|
+
39009277,
|
|
112
|
+
True,
|
|
88
113
|
),
|
|
114
|
+
# Additional test cases with FW support
|
|
89
115
|
(
|
|
90
116
|
t.Channels.from_channel_list([15, 20]),
|
|
91
117
|
15,
|
|
92
118
|
5,
|
|
93
119
|
True,
|
|
94
120
|
zdo_t.LogicalType.Coordinator,
|
|
121
|
+
39009277,
|
|
122
|
+
False,
|
|
95
123
|
),
|
|
96
124
|
(
|
|
97
125
|
t.Channels.from_channel_list([15, 20, 25]),
|
|
@@ -99,8 +127,18 @@ def network_info(node_info):
|
|
|
99
127
|
5,
|
|
100
128
|
True,
|
|
101
129
|
zdo_t.LogicalType.Router,
|
|
130
|
+
39009277,
|
|
131
|
+
False,
|
|
132
|
+
),
|
|
133
|
+
(
|
|
134
|
+
None,
|
|
135
|
+
15,
|
|
136
|
+
5,
|
|
137
|
+
True,
|
|
138
|
+
zdo_t.LogicalType.Coordinator,
|
|
139
|
+
39009277,
|
|
140
|
+
False,
|
|
102
141
|
),
|
|
103
|
-
(None, 15, 5, True, zdo_t.LogicalType.Coordinator),
|
|
104
142
|
],
|
|
105
143
|
)
|
|
106
144
|
async def test_write_network_info(
|
|
@@ -112,6 +150,8 @@ async def test_write_network_info(
|
|
|
112
150
|
security_level,
|
|
113
151
|
fw_supports_fc,
|
|
114
152
|
logical_type,
|
|
153
|
+
tx_counter,
|
|
154
|
+
should_error,
|
|
115
155
|
):
|
|
116
156
|
"""Test that network info is correctly written."""
|
|
117
157
|
|
|
@@ -137,13 +177,14 @@ async def test_write_network_info(
|
|
|
137
177
|
channel=channel,
|
|
138
178
|
channel_mask=channel_mask,
|
|
139
179
|
security_level=security_level,
|
|
180
|
+
network_key=network_info.network_key.replace(tx_counter=tx_counter),
|
|
140
181
|
)
|
|
141
182
|
|
|
142
183
|
node_info = node_info.replace(logical_type=logical_type)
|
|
143
184
|
|
|
144
|
-
if
|
|
185
|
+
if should_error:
|
|
145
186
|
with pytest.raises(
|
|
146
|
-
|
|
187
|
+
CannotWriteNetworkSettings,
|
|
147
188
|
match=(
|
|
148
189
|
"Please upgrade your adapter firmware. Firmware version 0x26580700 does"
|
|
149
190
|
" not support writing the network key frame counter, which is required"
|
|
@@ -166,7 +207,9 @@ async def test_write_network_info(
|
|
|
166
207
|
for call in app._api.write_parameter.await_args_list
|
|
167
208
|
}
|
|
168
209
|
|
|
169
|
-
|
|
210
|
+
# Only check frame counter if firmware supports it
|
|
211
|
+
if fw_supports_fc:
|
|
212
|
+
assert params["nwk_frame_counter"] == (network_info.network_key.tx_counter,)
|
|
170
213
|
|
|
171
214
|
if node_info.logical_type == zdo_t.LogicalType.Coordinator:
|
|
172
215
|
assert params["aps_designed_coordinator"] == (1,)
|
|
@@ -328,3 +371,57 @@ async def test_load_network_info(
|
|
|
328
371
|
assert app.state.network_info == network_info
|
|
329
372
|
|
|
330
373
|
assert app.state.node_info == node_info.replace(**node_state_changes)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
@patch.object(application, "CHANGE_NETWORK_POLL_TIME", 0.001)
|
|
377
|
+
@patch.object(application, "CHANGE_NETWORK_STATE_DELAY", 0.001)
|
|
378
|
+
async def test_form_network_fast_without_frame_counter_support(app): # noqa: F811
|
|
379
|
+
"""Test that form_network(fast=True) works when FW doesn't support frame counter."""
|
|
380
|
+
|
|
381
|
+
async def write_parameter(param, *args):
|
|
382
|
+
if param == zigpy_deconz.api.NetworkParameter.nwk_frame_counter:
|
|
383
|
+
raise zigpy_deconz.exception.CommandError(
|
|
384
|
+
"Command is unsupported",
|
|
385
|
+
status=zigpy_deconz.api.Status.UNSUPPORTED,
|
|
386
|
+
command=None,
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
app._change_network_state = AsyncMock()
|
|
390
|
+
app._api.write_parameter = AsyncMock(side_effect=write_parameter)
|
|
391
|
+
app.backups = AsyncMock()
|
|
392
|
+
app.backups.restore_backup = AsyncMock()
|
|
393
|
+
|
|
394
|
+
# This should not raise an error because fast=True sets form_quickly
|
|
395
|
+
await app.form_network(fast=True)
|
|
396
|
+
|
|
397
|
+
# Verify that restore_backup was called with create_new=False (due to fast=True)
|
|
398
|
+
assert app.backups.restore_backup.mock_calls == [
|
|
399
|
+
call(backup=ANY, counter_increment=0, allow_incomplete=True, create_new=False)
|
|
400
|
+
]
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
@patch.object(application, "CHANGE_NETWORK_POLL_TIME", 0.001)
|
|
404
|
+
@patch.object(application, "CHANGE_NETWORK_STATE_DELAY", 0.001)
|
|
405
|
+
async def test_reset_network_info_without_frame_counter_support(app): # noqa: F811
|
|
406
|
+
"""Test that reset_network_info works even when FW doesn't support frame counter."""
|
|
407
|
+
|
|
408
|
+
async def write_parameter(param, *args):
|
|
409
|
+
if param == zigpy_deconz.api.NetworkParameter.nwk_frame_counter:
|
|
410
|
+
raise zigpy_deconz.exception.CommandError(
|
|
411
|
+
"Command is unsupported",
|
|
412
|
+
status=zigpy_deconz.api.Status.UNSUPPORTED,
|
|
413
|
+
command=None,
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
app._change_network_state = AsyncMock()
|
|
417
|
+
app._api.write_parameter = AsyncMock(side_effect=write_parameter)
|
|
418
|
+
app.backups = AsyncMock()
|
|
419
|
+
app.backups.restore_backup = AsyncMock()
|
|
420
|
+
|
|
421
|
+
# Should not raise an error because reset_network_info calls form_network(fast=True)
|
|
422
|
+
await app.reset_network_info()
|
|
423
|
+
|
|
424
|
+
# Verify that restore_backup was called once (via form_network)
|
|
425
|
+
assert app.backups.restore_backup.mock_calls == [
|
|
426
|
+
call(backup=ANY, counter_increment=0, allow_incomplete=True, create_new=False)
|
|
427
|
+
]
|
|
@@ -180,7 +180,7 @@ class ControllerApplication(zigpy.application.ControllerApplication):
|
|
|
180
180
|
|
|
181
181
|
async def reset_network_info(self):
|
|
182
182
|
# TODO: There does not appear to be a way to factory reset a Conbee
|
|
183
|
-
await self.form_network()
|
|
183
|
+
await self.form_network(fast=True)
|
|
184
184
|
|
|
185
185
|
async def write_network_info(self, *, network_info, node_info):
|
|
186
186
|
try:
|
|
@@ -189,12 +189,19 @@ class ControllerApplication(zigpy.application.ControllerApplication):
|
|
|
189
189
|
)
|
|
190
190
|
except zigpy_deconz.exception.CommandError as ex:
|
|
191
191
|
assert ex.status == Status.UNSUPPORTED
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
192
|
+
|
|
193
|
+
# If we are resetting the adapter or forming a brand new network, we can
|
|
194
|
+
# skip this check
|
|
195
|
+
if not (
|
|
196
|
+
network_info.stack_specific.get("form_quickly", False)
|
|
197
|
+
or network_info.network_key.tx_counter == 0
|
|
198
|
+
):
|
|
199
|
+
fw_version = f"{int(self._api.firmware_version):#010x}"
|
|
200
|
+
raise zigpy.exceptions.CannotWriteNetworkSettings(
|
|
201
|
+
f"Please upgrade your adapter firmware. Firmware version"
|
|
202
|
+
f" {fw_version} does not support writing the network key frame"
|
|
203
|
+
f" counter, which is required for migration to succeed."
|
|
204
|
+
)
|
|
198
205
|
|
|
199
206
|
if node_info.logical_type == zdo_t.LogicalType.Coordinator:
|
|
200
207
|
await self._api.write_parameter(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|