Skip to content

Commit 55c4f79

Browse files
authored
Implement command priority (#240)
1 parent bc7e960 commit 55c4f79

File tree

4 files changed

+30
-5
lines changed

4 files changed

+30
-5
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ license = {text = "GPL-3.0"}
1515
requires-python = ">=3.8"
1616
dependencies = [
1717
"voluptuous",
18-
"zigpy>=0.60.0",
18+
"zigpy>=0.60.2",
1919
'async-timeout; python_version<"3.11"',
2020
]
2121

tests/test_api.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,3 +1031,17 @@ async def test_firmware_responding_with_wrong_type_with_correct_seq(
10311031
"Firmware responded incorrectly (Response is mismatched! Sent"
10321032
" <CommandId.aps_data_confirm: 4>, received <CommandId.version: 13>), retrying"
10331033
) in caplog.text
1034+
1035+
1036+
def test_get_command_priority(api):
1037+
assert (
1038+
api._get_command_priority(
1039+
deconz_api.Command(command_id=deconz_api.CommandId.write_parameter)
1040+
)
1041+
> api._get_command_priority(
1042+
deconz_api.Command(command_id=deconz_api.CommandId.update_neighbor)
1043+
)
1044+
> api._get_command_priority(
1045+
deconz_api.Command(command_id=deconz_api.CommandId.aps_data_request)
1046+
)
1047+
)

zigpy_deconz/api.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from asyncio import timeout as asyncio_timeout # pragma: no cover
1616

1717
from zigpy.config import CONF_DEVICE_PATH
18+
from zigpy.datastructures import PriorityLock
1819
from zigpy.types import (
1920
APSStatus,
2021
Bool,
@@ -419,7 +420,7 @@ def __init__(self, app: Callable, device_config: dict[str, Any]):
419420

420421
# [seq][cmd_id] = [fut1, fut2, ...]
421422
self._awaiting = collections.defaultdict(lambda: collections.defaultdict(list))
422-
self._command_lock = asyncio.Lock()
423+
self._command_lock = PriorityLock()
423424
self._config = device_config
424425
self._device_state = DeviceState(
425426
network_state=NetworkState2.OFFLINE,
@@ -489,6 +490,16 @@ def close(self):
489490
self._uart.close()
490491
self._uart = None
491492

493+
def _get_command_priority(self, command: Command) -> int:
494+
return {
495+
# The watchdog is fed using `write_parameter` and `get_device_state` so they
496+
# must take priority
497+
CommandId.write_parameter: 999,
498+
CommandId.device_state: 999,
499+
# APS data requests are retried and can be deprioritized
500+
CommandId.aps_data_request: -1,
501+
}.get(command.command_id, 0)
502+
492503
async def send_command(self, cmd, **kwargs) -> Any:
493504
while True:
494505
try:
@@ -557,7 +568,7 @@ async def _command(self, cmd, **kwargs):
557568
# connection was lost
558569
raise CommandError(Status.ERROR, "API is not running")
559570

560-
async with self._command_lock:
571+
async with self._command_lock(priority=self._get_command_priority(command)):
561572
seq = self._seq
562573

563574
LOGGER.debug("Sending %s%s (seq=%s)", cmd, kwargs, seq)

zigpy_deconz/zigbee/application.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class ControllerApplication(zigpy.application.ControllerApplication):
6464
{zigpy.config.CONF_DEVICE_BAUDRATE: 115200},
6565
]
6666

67-
_watchdog_period = 600 * 0.75
67+
_watchdog_period = 30
6868

6969
def __init__(self, config: dict[str, Any]):
7070
"""Initialize instance."""
@@ -85,7 +85,7 @@ async def _watchdog_feed(self):
8585
and self._api.firmware_version <= 0x26450900
8686
):
8787
await self._api.write_parameter(
88-
NetworkParameter.watchdog_ttl, int(self._watchdog_period / 0.75)
88+
NetworkParameter.watchdog_ttl, int(2 * self._watchdog_period)
8989
)
9090
else:
9191
await self._api.get_device_state()

0 commit comments

Comments
 (0)