uiprotect 0.9.0__tar.gz → 0.10.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.9.0 → uiprotect-0.10.0}/PKG-INFO +1 -1
  2. {uiprotect-0.9.0 → uiprotect-0.10.0}/pyproject.toml +1 -1
  3. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/data/bootstrap.py +22 -15
  4. {uiprotect-0.9.0 → uiprotect-0.10.0}/LICENSE +0 -0
  5. {uiprotect-0.9.0 → uiprotect-0.10.0}/README.md +0 -0
  6. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/__init__.py +0 -0
  7. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/__main__.py +0 -0
  8. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/api.py +0 -0
  9. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/__init__.py +0 -0
  10. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/backup.py +0 -0
  11. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/base.py +0 -0
  12. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/cameras.py +0 -0
  13. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/chimes.py +0 -0
  14. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/doorlocks.py +0 -0
  15. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/events.py +0 -0
  16. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/lights.py +0 -0
  17. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/liveviews.py +0 -0
  18. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/nvr.py +0 -0
  19. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/sensors.py +0 -0
  20. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/cli/viewers.py +0 -0
  21. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/data/__init__.py +0 -0
  22. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/data/base.py +0 -0
  23. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/data/convert.py +0 -0
  24. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/data/devices.py +0 -0
  25. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/data/nvr.py +0 -0
  26. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/data/types.py +0 -0
  27. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/data/user.py +0 -0
  28. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/data/websocket.py +0 -0
  29. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/exceptions.py +0 -0
  30. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/py.typed +0 -0
  31. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/release_cache.json +0 -0
  32. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/stream.py +0 -0
  33. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/test_util/__init__.py +0 -0
  34. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/test_util/anonymize.py +0 -0
  35. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/utils.py +0 -0
  36. {uiprotect-0.9.0 → uiprotect-0.10.0}/src/uiprotect/websocket.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 0.9.0
3
+ Version: 0.10.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.9.0"
3
+ version = "0.10.0"
4
4
  description = "Python API for Unifi Protect (Unofficial)"
5
5
  authors = ["UI Protect Maintainers <ui@koston.org>"]
6
6
  license = "MIT"
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import asyncio
6
6
  import logging
7
+ from collections.abc import Iterable
7
8
  from copy import deepcopy
8
9
  from dataclasses import dataclass
9
10
  from datetime import datetime
@@ -337,7 +338,7 @@ class Bootstrap(ProtectBaseObject):
337
338
  def _create_stat(
338
339
  self,
339
340
  packet: WSPacket,
340
- keys_set: list[str],
341
+ keys_set: Iterable[str] | None,
341
342
  filtered: bool,
342
343
  ) -> None:
343
344
  if self.capture_ws_stats:
@@ -346,7 +347,7 @@ class Bootstrap(ProtectBaseObject):
346
347
  model=packet.action_frame.data["modelKey"],
347
348
  action=packet.action_frame.data["action"],
348
349
  keys=list(packet.data_frame.data),
349
- keys_set=keys_set,
350
+ keys_set=[] if keys_set is None else list(keys_set),
350
351
  size=len(packet.raw),
351
352
  filtered=filtered,
352
353
  ),
@@ -389,7 +390,9 @@ class Bootstrap(ProtectBaseObject):
389
390
  return None
390
391
 
391
392
  updated = obj.dict()
392
- self._create_stat(packet, list(updated), False)
393
+
394
+ self._create_stat(packet, updated, False)
395
+
393
396
  return WSSubscriptionMessage(
394
397
  action=WSAction.ADD,
395
398
  new_update_id=self.last_update_id,
@@ -415,7 +418,7 @@ class Bootstrap(ProtectBaseObject):
415
418
  return None
416
419
  self.mac_lookup.pop(device.mac.lower().replace(":", ""), None)
417
420
 
418
- self._create_stat(packet, [], False)
421
+ self._create_stat(packet, None, False)
419
422
  return WSSubscriptionMessage(
420
423
  action=WSAction.REMOVE,
421
424
  new_update_id=self.last_update_id,
@@ -433,25 +436,25 @@ class Bootstrap(ProtectBaseObject):
433
436
  _remove_stats_keys(data)
434
437
  # nothing left to process
435
438
  if not data:
436
- self._create_stat(packet, [], True)
439
+ self._create_stat(packet, None, True)
437
440
  return None
438
441
 
439
442
  # for another NVR in stack
440
443
  nvr_id = packet.action_frame.data.get("id")
441
444
  if nvr_id and nvr_id != self.nvr.id:
442
- self._create_stat(packet, [], True)
445
+ self._create_stat(packet, None, True)
443
446
  return None
444
447
 
445
448
  data = self.nvr.unifi_dict_to_dict(data)
446
449
  # nothing left to process
447
450
  if not data:
448
- self._create_stat(packet, [], True)
451
+ self._create_stat(packet, None, True)
449
452
  return None
450
453
 
451
454
  old_nvr = self.nvr.copy()
452
455
  self.nvr = self.nvr.update_from_dict(deepcopy(data))
453
456
 
454
- self._create_stat(packet, list(data), False)
457
+ self._create_stat(packet, data, False)
455
458
  return WSSubscriptionMessage(
456
459
  action=WSAction.UPDATE,
457
460
  new_update_id=self.last_update_id,
@@ -478,7 +481,7 @@ class Bootstrap(ProtectBaseObject):
478
481
  del data["lastMotion"]
479
482
  # nothing left to process
480
483
  if not data:
481
- self._create_stat(packet, [], True)
484
+ self._create_stat(packet, None, True)
482
485
  return None
483
486
 
484
487
  key = f"{model_type}s"
@@ -492,12 +495,14 @@ class Bootstrap(ProtectBaseObject):
492
495
  data = obj.unifi_dict_to_dict(data)
493
496
  old_obj = obj.copy()
494
497
  obj = obj.update_from_dict(deepcopy(data))
495
- now = utc_now()
498
+ now: datetime | None = None
496
499
 
497
500
  if isinstance(obj, Event):
498
501
  self.process_event(obj)
499
502
  elif isinstance(obj, Camera):
500
503
  if "last_ring" in data and obj.last_ring:
504
+ if now is None:
505
+ now = utc_now()
501
506
  is_recent = obj.last_ring + RECENT_EVENT_MAX >= now
502
507
  _LOGGER.debug("last_ring for %s (%s)", obj.id, is_recent)
503
508
  if is_recent:
@@ -507,6 +512,8 @@ class Bootstrap(ProtectBaseObject):
507
512
  and "alarm_triggered_at" in data
508
513
  and obj.alarm_triggered_at
509
514
  ):
515
+ if now is None:
516
+ now = utc_now()
510
517
  is_recent = obj.alarm_triggered_at + RECENT_EVENT_MAX >= now
511
518
  _LOGGER.debug("alarm_triggered_at for %s (%s)", obj.id, is_recent)
512
519
  if is_recent:
@@ -514,7 +521,7 @@ class Bootstrap(ProtectBaseObject):
514
521
 
515
522
  devices[action["id"]] = obj
516
523
 
517
- self._create_stat(packet, list(data), False)
524
+ self._create_stat(packet, data, False)
518
525
  return WSSubscriptionMessage(
519
526
  action=WSAction.UPDATE,
520
527
  new_update_id=self.last_update_id,
@@ -555,18 +562,18 @@ class Bootstrap(ProtectBaseObject):
555
562
 
556
563
  if action["modelKey"] not in ModelType.values_set():
557
564
  _LOGGER.debug("Unknown model type: %s", action["modelKey"])
558
- self._create_stat(packet, [], True)
565
+ self._create_stat(packet, None, True)
559
566
  return None
560
567
 
561
568
  if len(models) > 0 and ModelType(action["modelKey"]) not in models:
562
- self._create_stat(packet, [], True)
569
+ self._create_stat(packet, None, True)
563
570
  return None
564
571
 
565
572
  if action["action"] == "remove":
566
573
  return self._process_remove_packet(packet, data)
567
574
 
568
575
  if data is None or len(data) == 0:
569
- self._create_stat(packet, [], True)
576
+ self._create_stat(packet, None, True)
570
577
  return None
571
578
 
572
579
  try:
@@ -593,7 +600,7 @@ class Bootstrap(ProtectBaseObject):
593
600
  except (ValidationError, ValueError) as err:
594
601
  self._handle_ws_error(action, err)
595
602
 
596
- self._create_stat(packet, [], True)
603
+ self._create_stat(packet, None, True)
597
604
  return None
598
605
 
599
606
  def _handle_ws_error(self, action: dict[str, Any], err: Exception) -> None:
File without changes
File without changes