Skip to content

Commit

Permalink
Implement command priority (#602)
Browse files Browse the repository at this point in the history
  • Loading branch information
puddly authored Dec 20, 2023
1 parent 15b3223 commit 09b2782
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
25 changes: 23 additions & 2 deletions bellows/ezsp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from typing import Any, Callable, Generator
import urllib.parse

from zigpy.datastructures import PriorityDynamicBoundedSemaphore

if sys.version_info[:2] < (3, 11):
from async_timeout import timeout as asyncio_timeout # pragma: no cover
else:
Expand Down Expand Up @@ -39,6 +41,8 @@
NETWORK_OPS_TIMEOUT = 10
NETWORK_COORDINATOR_STARTUP_RESET_WAIT = 1

MAX_COMMAND_CONCURRENCY = 4


class EZSP:
_BY_VERSION = {
Expand All @@ -60,6 +64,7 @@ def __init__(self, device_config: dict):
self._ezsp_version = v4.EZSPv4.VERSION
self._gw = None
self._protocol = None
self._send_sem = PriorityDynamicBoundedSemaphore(value=MAX_COMMAND_CONCURRENCY)

self._stack_status_listeners: collections.defaultdict[
t.EmberStatus, list[asyncio.Future]
Expand Down Expand Up @@ -184,14 +189,30 @@ def close(self):
self._gw.close()
self._gw = None

def _command(self, name: str, *args: tuple[Any, ...]) -> asyncio.Future:
def _get_command_priority(self, name: str) -> int:
return {
# Deprioritize any commands that send packets
"setSourceRoute": -1,
"setExtendedTimeout": -1,
"sendUnicast": -1,
"sendMulticast": -1,
"sendBroadcast": -1,
# Prioritize watchdog commands
"nop": 999,
"readCounters": 999,
"readAndClearCounters": 999,
"getValue": 999,
}.get(name, 0)

async def _command(self, name: str, *args: tuple[Any, ...]) -> Any:
if not self.is_ezsp_running:
LOGGER.debug(
"Couldn't send command %s(%s). EZSP is not running", name, args
)
raise EzspError("EZSP is not running")

return self._protocol.command(name, *args)
async with self._send_sem(priority=self._get_command_priority(name)):
return await self._protocol.command(name, *args)

async def _list_command(self, name, item_frames, completion_frame, spos, *args):
"""Run a command, returning result callbacks as a list"""
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ dependencies = [
"click-log>=0.2.1",
"pure_pcapy3==1.0.1",
"voluptuous",
"zigpy>=0.60.0",
"zigpy>=0.60.2",
'async-timeout; python_version<"3.11"',
]

Expand Down

0 comments on commit 09b2782

Please sign in to comment.