uiprotect 0.10.0__tar.gz → 0.11.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of uiprotect might be problematic. Click here for more details.

Files changed (36) hide show
  1. {uiprotect-0.10.0 → uiprotect-0.11.0}/PKG-INFO +1 -1
  2. {uiprotect-0.10.0 → uiprotect-0.11.0}/pyproject.toml +1 -1
  3. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/data/bootstrap.py +26 -40
  4. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/data/websocket.py +9 -3
  5. {uiprotect-0.10.0 → uiprotect-0.11.0}/LICENSE +0 -0
  6. {uiprotect-0.10.0 → uiprotect-0.11.0}/README.md +0 -0
  7. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/__init__.py +0 -0
  8. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/__main__.py +0 -0
  9. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/api.py +0 -0
  10. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/__init__.py +0 -0
  11. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/backup.py +0 -0
  12. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/base.py +0 -0
  13. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/cameras.py +0 -0
  14. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/chimes.py +0 -0
  15. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/doorlocks.py +0 -0
  16. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/events.py +0 -0
  17. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/lights.py +0 -0
  18. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/liveviews.py +0 -0
  19. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/nvr.py +0 -0
  20. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/sensors.py +0 -0
  21. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/cli/viewers.py +0 -0
  22. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/data/__init__.py +0 -0
  23. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/data/base.py +0 -0
  24. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/data/convert.py +0 -0
  25. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/data/devices.py +0 -0
  26. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/data/nvr.py +0 -0
  27. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/data/types.py +0 -0
  28. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/data/user.py +0 -0
  29. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/exceptions.py +0 -0
  30. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/py.typed +0 -0
  31. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/release_cache.json +0 -0
  32. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/stream.py +0 -0
  33. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/test_util/__init__.py +0 -0
  34. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/test_util/anonymize.py +0 -0
  35. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/utils.py +0 -0
  36. {uiprotect-0.10.0 → uiprotect-0.11.0}/src/uiprotect/websocket.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 0.10.0
3
+ Version: 0.11.0
4
4
  Summary: Python API for Unifi Protect (Unofficial)
5
5
  Home-page: https://github.com/uilibs/uiprotect
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "uiprotect"
3
- version = "0.10.0"
3
+ version = "0.11.0"
4
4
  description = "Python API for Unifi Protect (Unofficial)"
5
5
  authors = ["UI Protect Maintainers <ui@koston.org>"]
6
6
  license = "MIT"
@@ -41,7 +41,6 @@ from .types import EventType, FixSizeOrderedDict, ModelType
41
41
  from .user import Group, User
42
42
  from .websocket import (
43
43
  WSAction,
44
- WSJSONPacketFrame,
45
44
  WSPacket,
46
45
  WSSubscriptionMessage,
47
46
  )
@@ -169,6 +168,10 @@ class ProtectDeviceRef(ProtectBaseObject):
169
168
  id: str
170
169
 
171
170
 
171
+ _ModelType_NVR_value = ModelType.NVR.value
172
+ _ModelType_Event_value = ModelType.EVENT.value
173
+
174
+
172
175
  class Bootstrap(ProtectBaseObject):
173
176
  auth_user_id: str
174
177
  access_key: str
@@ -495,15 +498,12 @@ class Bootstrap(ProtectBaseObject):
495
498
  data = obj.unifi_dict_to_dict(data)
496
499
  old_obj = obj.copy()
497
500
  obj = obj.update_from_dict(deepcopy(data))
498
- now: datetime | None = None
499
501
 
500
502
  if isinstance(obj, Event):
501
503
  self.process_event(obj)
502
504
  elif isinstance(obj, Camera):
503
505
  if "last_ring" in data and obj.last_ring:
504
- if now is None:
505
- now = utc_now()
506
- is_recent = obj.last_ring + RECENT_EVENT_MAX >= now
506
+ is_recent = obj.last_ring + RECENT_EVENT_MAX >= utc_now()
507
507
  _LOGGER.debug("last_ring for %s (%s)", obj.id, is_recent)
508
508
  if is_recent:
509
509
  obj.set_ring_timeout()
@@ -512,9 +512,7 @@ class Bootstrap(ProtectBaseObject):
512
512
  and "alarm_triggered_at" in data
513
513
  and obj.alarm_triggered_at
514
514
  ):
515
- if now is None:
516
- now = utc_now()
517
- is_recent = obj.alarm_triggered_at + RECENT_EVENT_MAX >= now
515
+ is_recent = obj.alarm_triggered_at + RECENT_EVENT_MAX >= utc_now()
518
516
  _LOGGER.debug("alarm_triggered_at for %s (%s)", obj.id, is_recent)
519
517
  if is_recent:
520
518
  obj.set_alarm_timeout()
@@ -541,51 +539,40 @@ class Bootstrap(ProtectBaseObject):
541
539
  models: set[ModelType] | None = None,
542
540
  ignore_stats: bool = False,
543
541
  ) -> WSSubscriptionMessage | None:
544
- if models is None:
545
- models = set()
546
-
547
- if not isinstance(packet.action_frame, WSJSONPacketFrame):
548
- _LOGGER.debug(
549
- "Unexpected action frame format: %s",
550
- packet.action_frame.payload_format,
551
- )
552
-
553
- if not isinstance(packet.data_frame, WSJSONPacketFrame):
554
- _LOGGER.debug(
555
- "Unexpected data frame format: %s",
556
- packet.data_frame.payload_format,
557
- )
558
-
542
+ """Process a WS packet."""
559
543
  action, data = self._get_frame_data(packet)
560
- if action["newUpdateId"] is not None:
561
- self.last_update_id = action["newUpdateId"]
544
+ new_update_id: str = action["newUpdateId"]
545
+ if new_update_id is not None:
546
+ self.last_update_id = new_update_id
562
547
 
563
- if action["modelKey"] not in ModelType.values_set():
564
- _LOGGER.debug("Unknown model type: %s", action["modelKey"])
548
+ model_key: str = action["modelKey"]
549
+ if model_key not in ModelType.values_set():
550
+ _LOGGER.debug("Unknown model type: %s", model_key)
565
551
  self._create_stat(packet, None, True)
566
552
  return None
567
553
 
568
- if len(models) > 0 and ModelType(action["modelKey"]) not in models:
554
+ if models and ModelType(model_key) not in models:
569
555
  self._create_stat(packet, None, True)
570
556
  return None
571
557
 
572
- if action["action"] == "remove":
558
+ action_action: str = action["action"]
559
+ if action_action == "remove":
573
560
  return self._process_remove_packet(packet, data)
574
561
 
575
- if data is None or len(data) == 0:
562
+ if not data:
576
563
  self._create_stat(packet, None, True)
577
564
  return None
578
565
 
579
566
  try:
580
- if action["action"] == "add":
567
+ if action_action == "add":
581
568
  return self._process_add_packet(packet, data)
582
-
583
- if action["action"] == "update":
584
- if action["modelKey"] == ModelType.NVR.value:
569
+ if action_action == "update":
570
+ if model_key == _ModelType_NVR_value:
585
571
  return self._process_nvr_update(packet, data, ignore_stats)
572
+
586
573
  if (
587
- action["modelKey"] in ModelType.bootstrap_models_set()
588
- or action["modelKey"] == ModelType.EVENT.value
574
+ model_key in ModelType.bootstrap_models_set()
575
+ or model_key == _ModelType_Event_value
589
576
  ):
590
577
  return self._process_device_update(
591
578
  packet,
@@ -593,13 +580,12 @@ class Bootstrap(ProtectBaseObject):
593
580
  data,
594
581
  ignore_stats,
595
582
  )
596
- _LOGGER.debug(
597
- "Unexpected bootstrap model type deviceadoptedfor update: %s",
598
- action["modelKey"],
599
- )
600
583
  except (ValidationError, ValueError) as err:
601
584
  self._handle_ws_error(action, err)
602
585
 
586
+ _LOGGER.debug(
587
+ "Unexpected bootstrap model type deviceadoptedfor update: %s", model_key
588
+ )
603
589
  self._create_stat(packet, None, True)
604
590
  return None
605
591
 
@@ -7,6 +7,7 @@ import enum
7
7
  import struct
8
8
  import zlib
9
9
  from dataclasses import dataclass
10
+ from functools import cache, cached_property
10
11
  from typing import TYPE_CHECKING, Any
11
12
 
12
13
  import orjson
@@ -62,6 +63,7 @@ class BaseWSPacketFrame:
62
63
  raise NotImplementedError
63
64
 
64
65
  @staticmethod
66
+ @cache
65
67
  def klass_from_format(format_raw: int) -> type[BaseWSPacketFrame]:
66
68
  payload_format = ProtectWSPayloadFormat(format_raw)
67
69
 
@@ -174,13 +176,15 @@ class WSJSONPacketFrame(BaseWSPacketFrame):
174
176
 
175
177
 
176
178
  class WSPacket:
179
+ """Class to handle a unifi protect websocket packet."""
180
+
177
181
  _raw: bytes
178
182
  _raw_encoded: str | None = None
179
183
 
180
184
  _action_frame: BaseWSPacketFrame | None = None
181
185
  _data_frame: BaseWSPacketFrame | None = None
182
186
 
183
- def __init__(self, data: bytes):
187
+ def __init__(self, data: bytes) -> None:
184
188
  self._raw = data
185
189
 
186
190
  def decode(self) -> None:
@@ -190,7 +194,7 @@ class WSPacket:
190
194
  self._action_frame.length,
191
195
  )
192
196
 
193
- @property
197
+ @cached_property
194
198
  def action_frame(self) -> BaseWSPacketFrame:
195
199
  if self._action_frame is None:
196
200
  self.decode()
@@ -200,7 +204,7 @@ class WSPacket:
200
204
 
201
205
  return self._action_frame
202
206
 
203
- @property
207
+ @cached_property
204
208
  def data_frame(self) -> BaseWSPacketFrame:
205
209
  if self._data_frame is None:
206
210
  self.decode()
@@ -220,6 +224,8 @@ class WSPacket:
220
224
  self._action_frame = None
221
225
  self._data_frame = None
222
226
  self._raw_encoded = None
227
+ self.__dict__.pop("data_frame", None)
228
+ self.__dict__.pop("action_frame", None)
223
229
 
224
230
  @property
225
231
  def raw_base64(self) -> str:
File without changes
File without changes