Skip to content

Commit 83872b1

Browse files
authored
Gracefully handle neighbors table filling up on startup (#237)
1 parent ecaf376 commit 83872b1

File tree

2 files changed

+38
-15
lines changed

2 files changed

+38
-15
lines changed

tests/test_application.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ async def test_force_remove(app):
354354
await app.force_remove(sentinel.device)
355355

356356

357-
async def test_restore_neighbours(app):
357+
async def test_restore_neighbours(app, caplog):
358358
"""Test neighbour restoration."""
359359

360360
# FFD, Rx on when idle
@@ -372,6 +372,10 @@ async def test_restore_neighbours(app):
372372
device_5 = app.add_device(nwk=0x0005, ieee=EUI64.convert("00:00:00:00:00:00:00:05"))
373373
device_5.node_desc = zdo_t.NodeDescriptor(2, 64, 128, 0xBEEF, 82, 82, 0, 82, 0)
374374

375+
# RFD, Rx off when idle (duplicate)
376+
device_6 = app.add_device(nwk=0x0005, ieee=EUI64.convert("00:00:00:00:00:00:00:06"))
377+
device_6.node_desc = zdo_t.NodeDescriptor(2, 64, 128, 0xBEEF, 82, 82, 0, 82, 0)
378+
375379
coord = MagicMock()
376380
coord.ieee = EUI64.convert("aa:aa:aa:aa:aa:aa:aa:aa")
377381

@@ -384,16 +388,33 @@ async def test_restore_neighbours(app):
384388
zdo_t.Neighbor(ieee=device_3.ieee),
385389
zdo_t.Neighbor(ieee=EUI64.convert("00:00:00:00:00:00:00:04")),
386390
zdo_t.Neighbor(ieee=device_5.ieee),
391+
zdo_t.Neighbor(ieee=device_6.ieee),
387392
]
388393

394+
max_neighbors = 1
395+
396+
def mock_add_neighbour(nwk, ieee, mac_capability_flags):
397+
nonlocal max_neighbors
398+
max_neighbors -= 1
399+
400+
if max_neighbors < 0:
401+
raise zigpy_deconz.exception.CommandError(
402+
deconz_api.Status.FAILURE, "Failure"
403+
)
404+
389405
p = patch.object(app, "_api", spec_set=zigpy_deconz.api.Deconz(None, None))
390406

391407
with p as api_mock:
392-
api_mock.add_neighbour = AsyncMock()
393-
await app.restore_neighbours()
408+
err = zigpy_deconz.exception.CommandError(deconz_api.Status.FAILURE, "Failure")
409+
api_mock.add_neighbour = AsyncMock(side_effect=[None, err, err, err])
410+
411+
with caplog.at_level(logging.DEBUG):
412+
await app.restore_neighbours()
413+
414+
assert caplog.text.count("Failed to add device to neighbor table") == 1
394415

395-
assert api_mock.add_neighbour.call_count == 1
396-
assert api_mock.add_neighbour.await_count == 1
416+
assert api_mock.add_neighbour.call_count == 2
417+
assert api_mock.add_neighbour.await_count == 2
397418

398419

399420
@patch("zigpy_deconz.zigbee.application.DELAY_NEIGHBOUR_SCAN_S", 0)

zigpy_deconz/zigbee/application.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -573,16 +573,18 @@ async def restore_neighbours(self) -> None:
573573
or descr.is_receiver_on_when_idle
574574
):
575575
continue
576-
LOGGER.debug(
577-
"Restoring %s/0x%04x device as direct child",
578-
device.ieee,
579-
device.nwk,
580-
)
581-
await self._api.add_neighbour(
582-
nwk=device.nwk,
583-
ieee=device.ieee,
584-
mac_capability_flags=descr.mac_capability_flags,
585-
)
576+
577+
LOGGER.debug("Restoring %s as direct child", device)
578+
579+
try:
580+
await self._api.add_neighbour(
581+
nwk=device.nwk,
582+
ieee=device.ieee,
583+
mac_capability_flags=descr.mac_capability_flags,
584+
)
585+
except zigpy_deconz.exception.CommandError as ex:
586+
assert ex.status == Status.FAILURE
587+
LOGGER.debug("Failed to add device to neighbor table: %s", ex)
586588

587589
async def _delayed_neighbour_scan(self) -> None:
588590
"""Scan coordinator's neighbours."""

0 commit comments

Comments
 (0)