Skip to content

Commit ce8a126

Browse files
authored
Fail adapter migration if the IEEE cannot be written (#672)
* Fail adapter migration if the IEEE address cannot be written * Add a unit test
1 parent a7db28e commit ce8a126

2 files changed

Lines changed: 85 additions & 7 deletions

File tree

bellows/zigbee/application.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -364,15 +364,18 @@ async def write_network_info(
364364
elif not stack_specific.get(
365365
"i_understand_i_can_update_eui64_only_once_and_i_still_want_to_do_it"
366366
):
367-
LOGGER.warning(
368-
"Current node's IEEE address (%s) does not match the backup's (%s)",
369-
current_eui64,
370-
node_info.ieee,
367+
_, _, version = await self._get_board_info()
368+
raise ControllerError(
369+
f"Please upgrade your adapter firmware. The adapter IEEE address"
370+
f" needs to be replaced and firmware {version!r} does not support"
371+
f" writing it multiple times."
371372
)
372373
elif not await ezsp.can_burn_userdata_custom_eui64():
373-
LOGGER.error(
374-
"Current node's IEEE address has already been written once. It"
375-
" cannot be written again without fully erasing the chip with JTAG."
374+
_, _, version = await self._get_board_info()
375+
raise ControllerError(
376+
f"Please upgrade your adapter firmware. The adapter IEEE address"
377+
f" has been overwritten and firmware {version!r} does not support"
378+
f" writing it a second time."
376379
)
377380
else:
378381
await ezsp.write_custom_eui64(node_info.ieee, burn_into_userdata=True)

tests/test_application.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,3 +2155,78 @@ async def test_packet_capture_failure(app: ControllerApplication) -> None:
21552155
with pytest.raises(zigpy.exceptions.ControllerException):
21562156
async for packet in app.packet_capture(channel=15):
21572157
pass
2158+
2159+
2160+
async def test_migration_failure_eui64_overwrite_confirmation(
2161+
app: ControllerApplication,
2162+
zigpy_backup: zigpy.backups.NetworkBackup,
2163+
) -> None:
2164+
app._ezsp.can_rewrite_custom_eui64 = AsyncMock(return_value=False)
2165+
2166+
# Migration explicitly fails if we need to write the EUI64 but the adapter treats it
2167+
# as a write-once operation
2168+
with pytest.raises(
2169+
zigpy.exceptions.ControllerException,
2170+
match=(
2171+
"Please upgrade your adapter firmware. The adapter IEEE address needs to be"
2172+
" replaced and firmware 'Mock version' does not support writing it multiple"
2173+
" times."
2174+
),
2175+
):
2176+
with patch.object(app, "_reset"):
2177+
await app.write_network_info(
2178+
node_info=zigpy_backup.node_info.replace(
2179+
ieee=t.EUI64.convert("aa:aa:aa:aa:aa:aa:aa:aa")
2180+
),
2181+
network_info=zigpy_backup.network_info,
2182+
)
2183+
2184+
# Even if we opt in, if the adapter doesn't support it, we can't do anything
2185+
with patch.object(app, "_reset"), patch.object(
2186+
app._ezsp, "write_custom_eui64", wraps=app._ezsp.write_custom_eui64
2187+
), patch.object(app._ezsp, "can_burn_userdata_custom_eui64", return_value=False):
2188+
with pytest.raises(
2189+
zigpy.exceptions.ControllerException,
2190+
match=(
2191+
"Please upgrade your adapter firmware. The adapter IEEE address has"
2192+
" been overwritten and firmware 'Mock version' does not support writing"
2193+
" it a second time."
2194+
),
2195+
):
2196+
await app.write_network_info(
2197+
node_info=zigpy_backup.node_info.replace(
2198+
ieee=t.EUI64.convert("aa:aa:aa:aa:aa:aa:aa:aa")
2199+
),
2200+
network_info=zigpy_backup.network_info.replace(
2201+
stack_specific={
2202+
"ezsp": {
2203+
**zigpy_backup.network_info.stack_specific["ezsp"],
2204+
"i_understand_i_can_update_eui64_only_once_and_i_still_want_to_do_it": True,
2205+
}
2206+
}
2207+
),
2208+
)
2209+
2210+
assert app._ezsp.write_custom_eui64.mock_calls == []
2211+
2212+
# It works if everything is correct
2213+
with patch.object(app, "_reset"), patch.object(
2214+
app._ezsp, "write_custom_eui64"
2215+
), patch.object(app._ezsp, "can_burn_userdata_custom_eui64", return_value=True):
2216+
await app.write_network_info(
2217+
node_info=zigpy_backup.node_info.replace(
2218+
ieee=t.EUI64.convert("aa:aa:aa:aa:aa:aa:aa:aa")
2219+
),
2220+
network_info=zigpy_backup.network_info.replace(
2221+
stack_specific={
2222+
"ezsp": {
2223+
**zigpy_backup.network_info.stack_specific["ezsp"],
2224+
"i_understand_i_can_update_eui64_only_once_and_i_still_want_to_do_it": True,
2225+
}
2226+
}
2227+
),
2228+
)
2229+
2230+
assert app._ezsp.write_custom_eui64.mock_calls == [
2231+
call(t.EUI64.convert("aa:aa:aa:aa:aa:aa:aa:aa"), burn_into_userdata=True)
2232+
]

0 commit comments

Comments
 (0)