uiprotect 3.7.0__py3-none-any.whl → 4.0.0__py3-none-any.whl

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.

uiprotect/api.py CHANGED
@@ -1815,7 +1815,6 @@ class ProtectApiClient(BaseApiClient):
1815
1815
  except (
1816
1816
  TimeoutError,
1817
1817
  asyncio.TimeoutError,
1818
- asyncio.CancelledError,
1819
1818
  aiohttp.ServerDisconnectedError,
1820
1819
  client_exceptions.ClientError,
1821
1820
  ) as err:
uiprotect/data/base.py CHANGED
@@ -647,7 +647,7 @@ class ProtectModelWithId(ProtectModel):
647
647
  await self._update_sync.event.wait()
648
648
  self._update_sync.event.clear()
649
649
  return
650
- except (TimeoutError, asyncio.TimeoutError, asyncio.CancelledError):
650
+ except (TimeoutError, asyncio.TimeoutError):
651
651
  async with self._update_sync.lock:
652
652
  # Important! Now that we have the lock, we yield to the event loop so any
653
653
  # updates from the websocket are processed before we generate the diff
@@ -464,13 +464,6 @@ class Bootstrap(ProtectBaseObject):
464
464
  if TYPE_CHECKING:
465
465
  assert isinstance(obj, Event)
466
466
  self.process_event(obj)
467
- elif model_type is ModelType.CAMERA:
468
- if TYPE_CHECKING:
469
- assert isinstance(obj, Camera)
470
- if "last_ring" in data and (last_ring := obj.last_ring):
471
- if is_recent := last_ring + RECENT_EVENT_MAX >= utc_now():
472
- obj.set_ring_timeout()
473
- _LOGGER.debug("last_ring for %s (%s)", obj.id, is_recent)
474
467
  elif model_type is ModelType.SENSOR:
475
468
  if TYPE_CHECKING:
476
469
  assert isinstance(obj, Sensor)
@@ -560,34 +553,38 @@ class Bootstrap(ProtectBaseObject):
560
553
  model_type, action, data, ignore_stats, is_ping_back
561
554
  )
562
555
  except (ValidationError, ValueError) as err:
563
- self._handle_ws_error(action, err)
556
+ self._handle_ws_error(action_action, model_type, action, err)
564
557
 
565
558
  _LOGGER.debug(
566
559
  "Unexpected bootstrap model type deviceadoptedfor update: %s", model_key
567
560
  )
568
561
  return None
569
562
 
570
- def _handle_ws_error(self, action: dict[str, Any], err: Exception) -> None:
563
+ def _handle_ws_error(
564
+ self,
565
+ action_action: str,
566
+ model_type: ModelType,
567
+ action: dict[str, Any],
568
+ err: Exception,
569
+ ) -> None:
571
570
  msg = ""
572
- if action["modelKey"] == "event":
573
- msg = f"Validation error processing event: {action['id']}. Ignoring event."
571
+ device_id: str = action["id"]
572
+ if model_type is ModelType.EVENT:
573
+ msg = f"Validation error processing event: {device_id}. Ignoring event."
574
574
  else:
575
- try:
576
- model_type = ModelType.from_string(action["modelKey"])
577
- device_id: str = action["id"]
578
- task = asyncio.create_task(self.refresh_device(model_type, device_id))
579
- self._refresh_tasks.add(task)
580
- task.add_done_callback(self._refresh_tasks.discard)
581
- except (ValueError, IndexError):
582
- msg = f"{action['action']} packet caused invalid state. Unable to refresh device."
583
- else:
584
- msg = f"{action['action']} packet caused invalid state. Refreshing device: {model_type} {device_id}"
575
+ task = asyncio.create_task(self.refresh_device(model_type, device_id))
576
+ self._refresh_tasks.add(task)
577
+ task.add_done_callback(self._refresh_tasks.discard)
578
+ msg = (
579
+ f"{action_action} packet caused invalid state. "
580
+ f"Refreshing device: {model_type} {device_id}"
581
+ )
585
582
  _LOGGER.debug("%s Error: %s", msg, err)
586
583
 
587
584
  async def refresh_device(self, model_type: ModelType, device_id: str) -> None:
588
585
  """Refresh a device in the bootstrap."""
589
586
  try:
590
- if model_type == ModelType.NVR:
587
+ if model_type is ModelType.NVR:
591
588
  device: ProtectModelWithId = await self._api.get_nvr()
592
589
  else:
593
590
  device = await self._api.get_device(model_type, device_id)
@@ -595,7 +592,6 @@ class Bootstrap(ProtectBaseObject):
595
592
  ValidationError,
596
593
  TimeoutError,
597
594
  asyncio.TimeoutError,
598
- asyncio.CancelledError,
599
595
  ClientError,
600
596
  ServerDisconnectedError,
601
597
  ):
uiprotect/data/devices.py CHANGED
@@ -977,7 +977,6 @@ class Camera(ProtectMotionDeviceModel):
977
977
  last_smart_detect_event_ids: dict[SmartDetectObjectType, str] = {}
978
978
  last_smart_audio_detect_event_ids: dict[SmartDetectAudioType, str] = {}
979
979
  talkback_stream: TalkbackStream | None = None
980
- _last_ring_timeout: datetime | None = PrivateAttr(None)
981
980
 
982
981
  @classmethod
983
982
  @cache
@@ -1845,12 +1844,6 @@ class Camera(ProtectMotionDeviceModel):
1845
1844
  # endregion
1846
1845
  # endregion
1847
1846
 
1848
- @property
1849
- def is_ringing(self) -> bool:
1850
- if self._last_ring_timeout is None:
1851
- return False
1852
- return utc_now() < self._last_ring_timeout
1853
-
1854
1847
  @property
1855
1848
  def chime_type(self) -> ChimeType:
1856
1849
  if self.chime_duration.total_seconds() == 0.3:
@@ -1935,10 +1928,6 @@ class Camera(ProtectMotionDeviceModel):
1935
1928
 
1936
1929
  return False
1937
1930
 
1938
- def set_ring_timeout(self) -> None:
1939
- self._last_ring_timeout = utc_now() + EVENT_PING_INTERVAL
1940
- self._event_callback_ping()
1941
-
1942
1931
  def get_privacy_zone(self) -> tuple[int | None, CameraZone | None]:
1943
1932
  for index, zone in enumerate(self.privacy_zones):
1944
1933
  if zone.name == PRIVACY_ZONE_NAME:
uiprotect/utils.py CHANGED
@@ -201,11 +201,14 @@ def to_camel_case(name: str) -> str:
201
201
  return name
202
202
 
203
203
 
204
+ _EMPTY_UUID = UUID("0" * 32)
205
+
206
+
204
207
  def convert_unifi_data(value: Any, field: ModelField) -> Any:
205
208
  """Converts value from UFP data into pydantic field class"""
206
209
  type_ = field.type_
207
210
 
208
- if type_ == Any:
211
+ if type_ is Any:
209
212
  return value
210
213
 
211
214
  shape = field.shape
@@ -222,7 +225,7 @@ def convert_unifi_data(value: Any, field: ModelField) -> Any:
222
225
  return ip_address(value)
223
226
  except ValueError:
224
227
  return value
225
- if type_ == datetime:
228
+ if type_ is datetime:
226
229
  return from_js_time(value)
227
230
  if type_ in _CREATE_TYPES or _is_enum_type(type_):
228
231
  # cannot do this check too soon because some types cannot be used in isinstance
@@ -230,8 +233,8 @@ def convert_unifi_data(value: Any, field: ModelField) -> Any:
230
233
  return value
231
234
  # handle edge case for improperly formatted UUIDs
232
235
  # 00000000-0000-00 0- 000-000000000000
233
- if type_ == UUID and value == _BAD_UUID:
234
- value = "0" * 32
236
+ if type_ is UUID and value == _BAD_UUID:
237
+ return _EMPTY_UUID
235
238
  return type_(value)
236
239
 
237
240
  return value
@@ -574,7 +577,7 @@ def log_event(event: Event) -> None:
574
577
  )
575
578
  smart_settings = camera.smart_detect_settings
576
579
  for smart_type in event.smart_detect_types:
577
- is_audio = event.type == EventType.SMART_AUDIO_DETECT
580
+ is_audio = event.type is EventType.SMART_AUDIO_DETECT
578
581
  if is_audio:
579
582
  if smart_type.audio_type is None:
580
583
  return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 3.7.0
3
+ Version: 4.0.0
4
4
  Summary: Python API for Unifi Protect (Unofficial)
5
5
  Home-page: https://github.com/uilibs/uiprotect
6
6
  Author: UI Protect Maintainers
@@ -1,6 +1,6 @@
1
1
  uiprotect/__init__.py,sha256=UdpRSSLSy7pdDfTKf0zRIfy6KRGt_Jv-fMzYWgibbG4,686
2
2
  uiprotect/__main__.py,sha256=C_bHCOkv5qj6WMy-6ELoY3Y6HDhLxOa1a30CzmbZhsg,462
3
- uiprotect/api.py,sha256=QBKgvSWxqcYBYIHSz6_nq-AaZW99r8jciknKpfRKZvo,67621
3
+ uiprotect/api.py,sha256=8zfSeqDKArG2pbvImqibQx4HrMi_y06fYXrgcwYztCc,67585
4
4
  uiprotect/cli/__init__.py,sha256=1MO8rJmjjAsfVx2x01gn5DJo8B64xdPGo6gRVJbWd18,8868
5
5
  uiprotect/cli/backup.py,sha256=ZiS7RZnJGKI8TJKLW2cOUzkRM8nyTvE5Ov_jZZGtvSM,36708
6
6
  uiprotect/cli/base.py,sha256=k-_qGuNT7br0iV0KE5F4wYXF75iyLLjBEckTqxC71xM,7591
@@ -14,10 +14,10 @@ uiprotect/cli/nvr.py,sha256=TwxEg2XT8jXAbOqv6gc7KFXELKadeItEDYweSL4_-e8,4260
14
14
  uiprotect/cli/sensors.py,sha256=fQtcDJCVxs4VbAqcavgBy2ABiVxAW3GXtna6_XFBp2k,8153
15
15
  uiprotect/cli/viewers.py,sha256=2cyrp104ffIvgT0wYGIO0G35QMkEbFe7fSVqLwDXQYQ,2171
16
16
  uiprotect/data/__init__.py,sha256=OcfuJl2qXfHcj_mdnrHhzZ5tEIZrw8auziX5IE7dn-I,2938
17
- uiprotect/data/base.py,sha256=yACpt6l-7Kl3iVp419XX8O1z7196fJN333v03QQn5j4,35146
18
- uiprotect/data/bootstrap.py,sha256=EWl8zWo3zSN7HWMTgcoWr3UI9WE62Mi6FJ33DTqWTII,21128
17
+ uiprotect/data/base.py,sha256=fSD5H3jAp8M-0VbvOsFkohJwbzuUaytQxxF4nbWOVKg,35122
18
+ uiprotect/data/bootstrap.py,sha256=p7A9YGi2zktgBkVVIVlFh372K2qnlec5Z7wRc8Jd0ps,20598
19
19
  uiprotect/data/convert.py,sha256=8h6Il_DhMkPRDPj9F_rA2UZIlTuchS3BQD24peKpk2A,2185
20
- uiprotect/data/devices.py,sha256=DrHjLmIbkOneWSMoqN6W8EL9zdspY8YM2RM8_dHA2RI,110185
20
+ uiprotect/data/devices.py,sha256=46qYESXE9gcrtlNn1wuYzIM6We3S_8--KT0xA465JIY,109813
21
21
  uiprotect/data/nvr.py,sha256=kPEfFNi_gQHLBEA1JOgTjfnDb6BuPDDjZy6PMzLPR60,46749
22
22
  uiprotect/data/types.py,sha256=3CocULpkdTgF4is1nIEDYIlwf2EOkNNM7L4kJ7NkAwM,17654
23
23
  uiprotect/data/user.py,sha256=YvgXJKV4_y-bm0eySWz9f_ie9aR5lpVn17t9H0Pix8I,6998
@@ -28,10 +28,10 @@ uiprotect/release_cache.json,sha256=NamnSFy78hOWY0DPO87J9ELFCAN6NnVquv8gQO75ZG4,
28
28
  uiprotect/stream.py,sha256=McV3XymKyjn-1uV5jdQHcpaDjqLS4zWyMASQ8ubcyb4,4924
29
29
  uiprotect/test_util/__init__.py,sha256=whiOUb5LfDLNT3AQG6ISiKtAqO2JnhCIdFavhWDK46M,18718
30
30
  uiprotect/test_util/anonymize.py,sha256=f-8ijU-_y9r-uAbhIPn0f0I6hzJpAkvJzc8UpWihObI,8478
31
- uiprotect/utils.py,sha256=3SJFF8qs1Jz8t3mD8qwc1hFSocolFjdXI_v4yVlC7o4,20088
31
+ uiprotect/utils.py,sha256=G0WkMXpCky2Cc4jynFDFFxAcVaZX4F01OXKa6cx9pho,20121
32
32
  uiprotect/websocket.py,sha256=D5DZrMzo434ecp8toNxOB5HM193kVwYw42yEcg99yMw,8029
33
- uiprotect-3.7.0.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
34
- uiprotect-3.7.0.dist-info/METADATA,sha256=Qt-uh6bPO1A4Sj3Exbg7zH5HE8zUHsaUYM0pOCnnERo,10969
35
- uiprotect-3.7.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
- uiprotect-3.7.0.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
37
- uiprotect-3.7.0.dist-info/RECORD,,
33
+ uiprotect-4.0.0.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
34
+ uiprotect-4.0.0.dist-info/METADATA,sha256=a16c68d2xebwOqT_oEz0SNVp99Ml9FKYxpB9EmrNcQ4,10969
35
+ uiprotect-4.0.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
+ uiprotect-4.0.0.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
37
+ uiprotect-4.0.0.dist-info/RECORD,,