Skip to content

Commit 28d65c8

Browse files
committed
Revert back to old formation code, writing settings directly is unstable
1 parent fd86554 commit 28d65c8

File tree

6 files changed

+302
-148
lines changed

6 files changed

+302
-148
lines changed

tests/api/test_network_state.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import dataclasses
2+
3+
import pytest
4+
5+
from ..conftest import ALL_DEVICES, FORMED_DEVICES, BaseZStack1CC2531
6+
7+
pytestmark = [pytest.mark.asyncio]
8+
9+
10+
@pytest.mark.parametrize("to_device", ALL_DEVICES)
11+
@pytest.mark.parametrize("from_device", FORMED_DEVICES)
12+
async def test_state_transfer(from_device, to_device, make_connected_znp):
13+
formed_znp, _ = await make_connected_znp(server_cls=from_device)
14+
15+
await formed_znp.load_network_info()
16+
formed_znp.close()
17+
18+
empty_znp, _ = await make_connected_znp(server_cls=to_device)
19+
20+
await empty_znp.write_network_info(
21+
network_info=formed_znp.network_info,
22+
node_info=formed_znp.node_info,
23+
)
24+
await empty_znp.load_network_info()
25+
26+
# Z-Stack 1 devices can't have some security info read out
27+
if issubclass(from_device, BaseZStack1CC2531):
28+
assert formed_znp.network_info == dataclasses.replace(
29+
empty_znp.network_info, stack_specific={}
30+
)
31+
elif issubclass(to_device, BaseZStack1CC2531):
32+
assert (
33+
dataclasses.replace(formed_znp.network_info, stack_specific={})
34+
== empty_znp.network_info
35+
)
36+
else:
37+
assert formed_znp.network_info == empty_znp.network_info
38+
39+
assert formed_znp.node_info == empty_znp.node_info

tests/api/test_nvram.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ async def test_osal_writes_invalid(connected_znp):
1313

1414
# Passing in untyped integers is not allowed
1515
with pytest.raises(TypeError):
16-
await znp.nvram.osal_write(nvids.OsalNvIds.STARTUP_OPTION, 0xAB)
16+
await znp.nvram.osal_write(nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1, 0xAB)
1717

1818
# Neither is passing in an empty value
1919
with pytest.raises(ValueError):
20-
await znp.nvram.osal_write(nvids.OsalNvIds.STARTUP_OPTION, b"")
20+
await znp.nvram.osal_write(nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1, b"")
2121

2222
# Or a type that serializes to an empty value
2323
class Empty:
@@ -27,7 +27,7 @@ def serialize(self):
2727
assert Empty().serialize() == b""
2828

2929
with pytest.raises(ValueError):
30-
await znp.nvram.osal_write(nvids.OsalNvIds.STARTUP_OPTION, Empty())
30+
await znp.nvram.osal_write(nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1, Empty())
3131

3232

3333
@pytest.mark.parametrize(
@@ -41,7 +41,7 @@ def serialize(self):
4141
async def test_osal_write_existing(connected_znp, value):
4242
znp, znp_server = connected_znp
4343

44-
nvid = nvids.OsalNvIds.STARTUP_OPTION
44+
nvid = nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1
4545

4646
# The item is one byte long
4747
length_rsp = znp_server.reply_once_to(
@@ -65,7 +65,7 @@ async def test_osal_write_existing(connected_znp, value):
6565
async def test_osal_write_same_length(connected_znp):
6666
znp, znp_server = connected_znp
6767

68-
nvid = nvids.OsalNvIds.STARTUP_OPTION
68+
nvid = nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1
6969
value = b"\x01"
7070

7171
# The existing item is also one byte long so we will not recreate it
@@ -87,7 +87,7 @@ async def test_osal_write_same_length(connected_znp):
8787
await write_rsp
8888

8989

90-
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.STARTUP_OPTION])
90+
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1])
9191
@pytest.mark.parametrize("value", [b"\x01\x02"])
9292
@pytest.mark.parametrize("create", [True, False])
9393
async def test_osal_write_wrong_length(connected_znp, nvid, value, create):
@@ -130,7 +130,7 @@ async def test_osal_write_wrong_length(connected_znp, nvid, value, create):
130130
assert not write_rsp.done()
131131

132132

133-
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.STARTUP_OPTION])
133+
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1])
134134
@pytest.mark.parametrize("value", [b"test"])
135135
async def test_osal_write_bad_length(connected_znp, nvid, value):
136136
znp, znp_server = connected_znp
@@ -147,7 +147,7 @@ async def test_osal_write_bad_length(connected_znp, nvid, value):
147147
await length_rsp
148148

149149

150-
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.STARTUP_OPTION])
150+
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1])
151151
@pytest.mark.parametrize("value", [b"test"])
152152
async def test_osal_read_success(connected_znp, nvid, value):
153153
znp, znp_server = connected_znp
@@ -169,7 +169,7 @@ async def test_osal_read_success(connected_znp, nvid, value):
169169
assert result == value
170170

171171

172-
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.STARTUP_OPTION])
172+
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1])
173173
@pytest.mark.parametrize("value", [b"test" * 62 + b"x"]) # 248 + 1 bytes, needs two
174174
async def test_osal_read_long_success(connected_znp, nvid, value):
175175
znp, znp_server = connected_znp
@@ -197,7 +197,7 @@ async def test_osal_read_long_success(connected_znp, nvid, value):
197197
assert result == value
198198

199199

200-
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.STARTUP_OPTION])
200+
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1])
201201
async def test_osal_read_failure(connected_znp, nvid):
202202
znp, znp_server = connected_znp
203203

@@ -212,7 +212,7 @@ async def test_osal_read_failure(connected_znp, nvid):
212212
await length_rsp
213213

214214

215-
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.STARTUP_OPTION])
215+
@pytest.mark.parametrize("nvid", [nvids.OsalNvIds.HAS_CONFIGURED_ZSTACK1])
216216
async def test_osal_write_nonexistent(connected_znp, nvid):
217217
znp, znp_server = connected_znp
218218

tests/conftest.py

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,11 @@ async def inner(server_cls):
162162

163163
znp.nvram.align_structs = server_cls.align_structs
164164
znp.version = server_cls.version
165-
znp.capabilities = t.MTCapabilities(0)
165+
166+
if hasattr(znp_server, "ping_replier"):
167+
znp.capabilities = znp_server.ping_replier(None).Capabilities
168+
else:
169+
znp.capabilities = t.MTCapabilities(0)
166170

167171
return znp, znp_server
168172

@@ -455,7 +459,61 @@ def create_nib(self, _=None):
455459
self._nvram[ExNvIds.LEGACY][OsalNvIds.NWKKEY] = self.nvram_serialize(key_info)
456460

457461
def _default_nib(self):
458-
return const.DEFAULT_NIB.replace()
462+
return t.NIB(
463+
SequenceNum=0,
464+
PassiveAckTimeout=5,
465+
MaxBroadcastRetries=2,
466+
MaxChildren=0,
467+
MaxDepth=20,
468+
MaxRouters=0,
469+
dummyNeighborTable=0,
470+
BroadcastDeliveryTime=30,
471+
ReportConstantCost=0,
472+
RouteDiscRetries=0,
473+
dummyRoutingTable=0,
474+
SecureAllFrames=1,
475+
SecurityLevel=5,
476+
SymLink=1,
477+
CapabilityFlags=143,
478+
TransactionPersistenceTime=7,
479+
nwkProtocolVersion=2,
480+
RouteDiscoveryTime=5,
481+
RouteExpiryTime=30,
482+
nwkDevAddress=0xFFFE,
483+
nwkLogicalChannel=0,
484+
nwkCoordAddress=0xFFFE,
485+
nwkCoordExtAddress=t.EUI64.convert("00:00:00:00:00:00:00:00"),
486+
nwkPanId=0xFFFF,
487+
nwkState=t.NwkState.NWK_INIT,
488+
channelList=t.Channels.NO_CHANNELS,
489+
beaconOrder=15,
490+
superFrameOrder=15,
491+
scanDuration=0,
492+
battLifeExt=0,
493+
allocatedRouterAddresses=0,
494+
allocatedEndDeviceAddresses=0,
495+
nodeDepth=0,
496+
extendedPANID=t.EUI64.convert("00:00:00:00:00:00:00:00"),
497+
nwkKeyLoaded=False,
498+
spare1=t.NwkKeyDesc(
499+
KeySeqNum=0, Key=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
500+
),
501+
spare2=t.NwkKeyDesc(
502+
KeySeqNum=0, Key=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
503+
),
504+
spare3=0,
505+
spare4=0,
506+
nwkLinkStatusPeriod=60,
507+
nwkRouterAgeLimit=3,
508+
nwkUseMultiCast=False,
509+
nwkIsConcentrator=True,
510+
nwkConcentratorDiscoveryTime=120,
511+
nwkConcentratorRadius=10,
512+
nwkAllFresh=1,
513+
nwkManagerAddr=0x0000,
514+
nwkTotalTransmissions=0,
515+
nwkUpdateId=0,
516+
)
459517

460518
@reply_to(c.ZDO.ActiveEpReq.Req(DstAddr=0x0000, NWKAddrOfInterest=0x0000))
461519
def active_endpoints_request(self, req):
@@ -597,7 +655,22 @@ def nib(self, nib):
597655
self._nvram[ExNvIds.LEGACY][OsalNvIds.NIB] = self.nvram_serialize(nib)
598656

599657
@reply_to(c.SYS.ResetReq.Req(Type=t.ResetType.Soft))
600-
def reset_req(self, request):
658+
def reset_req(self, request, *, _handle_startup_reset=True):
659+
if (
660+
self._nvram.get(ExNvIds.LEGACY, {}).get(OsalNvIds.STARTUP_OPTION)
661+
is not None
662+
and _handle_startup_reset
663+
):
664+
startup, _ = t.StartupOptions.deserialize(
665+
self._nvram[ExNvIds.LEGACY][OsalNvIds.STARTUP_OPTION]
666+
)
667+
668+
if startup & t.StartupOptions.ClearState:
669+
self._create_network_nvram()
670+
self._nvram[ExNvIds.LEGACY][
671+
OsalNvIds.STARTUP_OPTION
672+
] = t.StartupOptions.NONE.serialize()
673+
601674
version = self.version_replier(None)
602675

603676
return c.SYS.ResetInd.Callback(
@@ -891,7 +964,9 @@ def connection_made(self):
891964
self._first_connection = False
892965

893966
# Z-Stack 3 devices send a callback when they're first used
894-
asyncio.get_running_loop().call_soon(self.send, self.reset_req(None))
967+
asyncio.get_running_loop().call_soon(
968+
self.send, self.reset_req(None, _handle_startup_reset=False)
969+
)
895970

896971

897972
class BaseLaunchpadCC26X2R1(BaseZStack3Device):

0 commit comments

Comments
 (0)