Skip to content

Commit

Permalink
feat: avoid linear searches to process websocket packets (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored Jun 10, 2024
1 parent 83608b9 commit 86d5f19
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 4 deletions.
7 changes: 5 additions & 2 deletions src/uiprotect/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1075,7 +1075,10 @@ async def get_events(

for event_dict in response:
# ignore unknown events
if "type" not in event_dict or event_dict["type"] not in EventType.values():
if (
"type" not in event_dict
or event_dict["type"] not in EventType.values_set()
):
_LOGGER.debug("Unknown event type: %s", event_dict)
continue

Expand All @@ -1086,7 +1089,7 @@ async def get_events(
continue

if (
event.type.value in EventType.device_events()
event.type.value in EventType.device_events_set()
and event.score >= self._minimum_score
):
events.append(event)
Expand Down
4 changes: 2 additions & 2 deletions src/uiprotect/data/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ def process_ws_packet(
if action["newUpdateId"] is not None:
self.last_update_id = action["newUpdateId"]

if action["modelKey"] not in ModelType.values():
if action["modelKey"] not in ModelType.values_set():
_LOGGER.debug("Unknown model type: %s", action["modelKey"])
self._create_stat(packet, [], True)
return None
Expand All @@ -577,7 +577,7 @@ def process_ws_packet(
if action["modelKey"] == ModelType.NVR.value:
return self._process_nvr_update(packet, data, ignore_stats)
if (
action["modelKey"] in ModelType.bootstrap_models()
action["modelKey"] in ModelType.bootstrap_models_set()
or action["modelKey"] == ModelType.EVENT.value
):
return self._process_device_update(
Expand Down
20 changes: 20 additions & 0 deletions src/uiprotect/data/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import enum
from collections.abc import Callable, Coroutine
from functools import cache
from typing import Any, Literal, Optional, TypeVar, Union

from packaging.version import Version as BaseVersion
Expand Down Expand Up @@ -58,11 +59,17 @@ class ValuesEnumMixin:
_values_normalized: dict[str, str] | None = None

@classmethod
@cache
def values(cls) -> list[str]:
if cls._values is None:
cls._values = [e.value for e in cls] # type: ignore[attr-defined]
return cls._values

@classmethod
@cache
def values_set(cls) -> set[str]:
return set(cls.values())

@classmethod
def _missing_(cls, value: Any) -> Any | None:
if cls._values_normalized is None:
Expand Down Expand Up @@ -103,6 +110,7 @@ class ModelType(str, UnknownValuesEnumMixin, enum.Enum):
UNKNOWN = "unknown"

@staticmethod
@cache
def bootstrap_models() -> tuple[str, ...]:
# TODO:
# legacyUFV
Expand All @@ -121,6 +129,11 @@ def bootstrap_models() -> tuple[str, ...]:
ModelType.CHIME.value,
)

@staticmethod
@cache
def bootstrap_models_set() -> set[str]:
return set(ModelType.bootstrap_models())


@enum.unique
class EventType(str, ValuesEnumMixin, enum.Enum):
Expand Down Expand Up @@ -204,6 +217,7 @@ class EventType(str, ValuesEnumMixin, enum.Enum):
RECORDING_OFF = "recordingOff"

@staticmethod
@cache
def device_events() -> list[str]:
return [
EventType.MOTION.value,
Expand All @@ -212,6 +226,12 @@ def device_events() -> list[str]:
]

@staticmethod
@cache
def device_events_set() -> set[str]:
return set(EventType.device_events())

@staticmethod
@cache
def motion_events() -> list[str]:
return [EventType.MOTION.value, EventType.SMART_DETECT.value]

Expand Down

0 comments on commit 86d5f19

Please sign in to comment.