uiprotect 1.12.0__py3-none-any.whl → 1.12.1__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/data/base.py CHANGED
@@ -61,6 +61,9 @@ RECENT_EVENT_MAX = timedelta(seconds=30)
61
61
  EVENT_PING_INTERVAL = timedelta(seconds=3)
62
62
  EVENT_PING_INTERVAL_SECONDS = EVENT_PING_INTERVAL.total_seconds()
63
63
 
64
+ _EMPTY_EVENT_PING_BACK: dict[Any, Any] = {}
65
+
66
+
64
67
  _LOGGER = logging.getLogger(__name__)
65
68
 
66
69
 
@@ -788,7 +791,7 @@ class ProtectModelWithId(ProtectModel):
788
791
 
789
792
  def _emit_message(self, updated: dict[str, Any]) -> None:
790
793
  """Emits fake WS message for ProtectApiClient to process."""
791
- if updated == {}:
794
+ if _is_ping_back := updated is _EMPTY_EVENT_PING_BACK:
792
795
  _LOGGER.debug("Event ping callback started for %s", self.id)
793
796
 
794
797
  if self.model is None:
@@ -817,7 +820,9 @@ class ProtectModelWithId(ProtectModel):
817
820
 
818
821
  message = self._api.bootstrap.process_ws_packet(
819
822
  WSPacket(action_frame.packed + data_frame.packed),
823
+ is_ping_back=_is_ping_back,
820
824
  )
825
+
821
826
  if message is not None:
822
827
  self._api.emit_message(message)
823
828
 
@@ -876,7 +881,7 @@ class ProtectDeviceModel(ProtectModelWithId):
876
881
  self._callback_ping = loop.call_later(
877
882
  EVENT_PING_INTERVAL_SECONDS,
878
883
  self._emit_message,
879
- {},
884
+ _EMPTY_EVENT_PING_BACK,
880
885
  )
881
886
 
882
887
  async def set_name(self, name: str | None) -> None:
@@ -451,7 +451,15 @@ class Bootstrap(ProtectBaseObject):
451
451
  action: dict[str, Any],
452
452
  data: dict[str, Any],
453
453
  ignore_stats: bool,
454
+ is_ping_back: bool,
454
455
  ) -> WSSubscriptionMessage | None:
456
+ """
457
+ Process a device update packet.
458
+
459
+ If is_ping_back is True, the packet is an empty packet
460
+ that was generated internally as a result of an event
461
+ that will expire and result in a state change.
462
+ """
455
463
  remove_keys = (
456
464
  STATS_AND_IGNORE_DEVICE_KEYS if ignore_stats else IGNORE_DEVICE_KEYS
457
465
  )
@@ -462,7 +470,7 @@ class Bootstrap(ProtectBaseObject):
462
470
  if model_type is ModelType.CAMERA and "lastMotion" in data:
463
471
  del data["lastMotion"]
464
472
  # nothing left to process
465
- if not data:
473
+ if not data and not is_ping_back:
466
474
  self._create_stat(packet, None, True)
467
475
  return None
468
476
 
@@ -476,6 +484,12 @@ class Bootstrap(ProtectBaseObject):
476
484
 
477
485
  obj = devices[action_id]
478
486
  data = obj.unifi_dict_to_dict(data)
487
+
488
+ if not data and not is_ping_back:
489
+ # nothing left to process
490
+ self._create_stat(packet, None, True)
491
+ return None
492
+
479
493
  old_obj = obj.copy()
480
494
  obj = obj.update_from_dict(deepcopy(data))
481
495
 
@@ -513,6 +527,7 @@ class Bootstrap(ProtectBaseObject):
513
527
  packet: WSPacket,
514
528
  models: set[ModelType] | None = None,
515
529
  ignore_stats: bool = False,
530
+ is_ping_back: bool = False,
516
531
  ) -> WSSubscriptionMessage | None:
517
532
  """Process a WS packet."""
518
533
  action = packet.action_frame.data
@@ -521,17 +536,16 @@ class Bootstrap(ProtectBaseObject):
521
536
  action = deepcopy(action)
522
537
  data = deepcopy(data)
523
538
 
524
- new_update_id: str = action["newUpdateId"]
539
+ new_update_id: str | None = action["newUpdateId"]
525
540
  if new_update_id is not None:
526
541
  self.last_update_id = new_update_id
527
542
 
528
543
  model_key: str = action["modelKey"]
529
- if model_key not in ModelType.values_set():
544
+ if (model_type := ModelType.from_string(model_key)) is ModelType.UNKNOWN:
530
545
  _LOGGER.debug("Unknown model type: %s", model_key)
531
546
  self._create_stat(packet, None, True)
532
547
  return None
533
548
 
534
- model_type = ModelType.from_string(model_key)
535
549
  if models and model_type not in models:
536
550
  self._create_stat(packet, None, True)
537
551
  return None
@@ -540,7 +554,7 @@ class Bootstrap(ProtectBaseObject):
540
554
  if action_action == "remove":
541
555
  return self._process_remove_packet(model_type, packet)
542
556
 
543
- if not data:
557
+ if not data and not is_ping_back:
544
558
  self._create_stat(packet, None, True)
545
559
  return None
546
560
 
@@ -552,11 +566,7 @@ class Bootstrap(ProtectBaseObject):
552
566
  return self._process_nvr_update(packet, data, ignore_stats)
553
567
  if model_type in ModelType.bootstrap_models_types_and_event_set:
554
568
  return self._process_device_update(
555
- model_type,
556
- packet,
557
- action,
558
- data,
559
- ignore_stats,
569
+ model_type, packet, action, data, ignore_stats, is_ping_back
560
570
  )
561
571
  except (ValidationError, ValueError) as err:
562
572
  self._handle_ws_error(action, err)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 1.12.0
3
+ Version: 1.12.1
4
4
  Summary: Python API for Unifi Protect (Unofficial)
5
5
  Home-page: https://github.com/uilibs/uiprotect
6
6
  License: MIT
@@ -14,8 +14,8 @@ 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=apIXKZHL6dbyXTT4C4lkyo4M-Nf_DwsVXoXBL5jcXVo,37574
18
- uiprotect/data/bootstrap.py,sha256=pAb-JC_AatYPldfefiMqdZ3_6Ftngcmd2asAMw66XLE,21486
17
+ uiprotect/data/base.py,sha256=yzGm5RCeo9AqmgArWC8O7LhBp_Qxz1XSel3xRyhNAbM,37718
18
+ uiprotect/data/bootstrap.py,sha256=wjRFVrv1rOFVDcij6ZYm7dzMe0iz6AqYciQozC-J2TI,21893
19
19
  uiprotect/data/convert.py,sha256=8h6Il_DhMkPRDPj9F_rA2UZIlTuchS3BQD24peKpk2A,2185
20
20
  uiprotect/data/devices.py,sha256=Nq3bOko5PFf5LvEBoD4JV8kmbq50laRdh3VHMWX7t-0,111809
21
21
  uiprotect/data/nvr.py,sha256=XC4NO1c_Mom-hIpzj9ksKFcgKbHd6ToqWjkgzxJ1PJY,47636
@@ -30,8 +30,8 @@ uiprotect/test_util/__init__.py,sha256=d2g7afa0LSdixQ0kjEDYwafDFME_UlW2LzxpamZ2B
30
30
  uiprotect/test_util/anonymize.py,sha256=f-8ijU-_y9r-uAbhIPn0f0I6hzJpAkvJzc8UpWihObI,8478
31
31
  uiprotect/utils.py,sha256=6OLY8hNiCzk418PjJJIlFW7jjPzVt1vxBKEzBSqMeTk,18418
32
32
  uiprotect/websocket.py,sha256=IzDPyqbzrkOMREvahN-e2zdvVD0VABSCWy6jSoCwOT0,7299
33
- uiprotect-1.12.0.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
34
- uiprotect-1.12.0.dist-info/METADATA,sha256=wPRYZLr1EpqqtUnuenaK3Z-iEdmDqA4YnHCvJG5NQAY,10985
35
- uiprotect-1.12.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
- uiprotect-1.12.0.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
37
- uiprotect-1.12.0.dist-info/RECORD,,
33
+ uiprotect-1.12.1.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
34
+ uiprotect-1.12.1.dist-info/METADATA,sha256=tQiyGoMyj_g6AQLes0kHr4TWIXfENceZ_ksLycnREqI,10985
35
+ uiprotect-1.12.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
+ uiprotect-1.12.1.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
37
+ uiprotect-1.12.1.dist-info/RECORD,,