uiprotect 1.11.1__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 +7 -2
- uiprotect/data/bootstrap.py +28 -20
- {uiprotect-1.11.1.dist-info → uiprotect-1.12.1.dist-info}/METADATA +1 -1
- {uiprotect-1.11.1.dist-info → uiprotect-1.12.1.dist-info}/RECORD +7 -7
- {uiprotect-1.11.1.dist-info → uiprotect-1.12.1.dist-info}/LICENSE +0 -0
- {uiprotect-1.11.1.dist-info → uiprotect-1.12.1.dist-info}/WHEEL +0 -0
- {uiprotect-1.11.1.dist-info → uiprotect-1.12.1.dist-info}/entry_points.txt +0 -0
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:
|
uiprotect/data/bootstrap.py
CHANGED
|
@@ -56,6 +56,7 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
56
56
|
MAX_SUPPORTED_CAMERAS = 256
|
|
57
57
|
MAX_EVENT_HISTORY_IN_STATE_MACHINE = MAX_SUPPORTED_CAMERAS * 2
|
|
58
58
|
STATS_KEYS = {
|
|
59
|
+
"eventStats",
|
|
59
60
|
"storageStats",
|
|
60
61
|
"stats",
|
|
61
62
|
"systemInfo",
|
|
@@ -394,8 +395,7 @@ class Bootstrap(ProtectBaseObject):
|
|
|
394
395
|
|
|
395
396
|
device_id: str = packet.action_frame.data["id"]
|
|
396
397
|
self.id_lookup.pop(device_id, None)
|
|
397
|
-
device
|
|
398
|
-
if device is None:
|
|
398
|
+
if (device := devices.pop(device_id, None)) is None:
|
|
399
399
|
return None
|
|
400
400
|
self.mac_lookup.pop(normalize_mac(device.mac), None)
|
|
401
401
|
|
|
@@ -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
|
|
|
@@ -486,19 +500,17 @@ class Bootstrap(ProtectBaseObject):
|
|
|
486
500
|
elif model_type is ModelType.CAMERA:
|
|
487
501
|
if TYPE_CHECKING:
|
|
488
502
|
assert isinstance(obj, Camera)
|
|
489
|
-
if "last_ring" in data and obj.last_ring:
|
|
490
|
-
is_recent
|
|
491
|
-
_LOGGER.debug("last_ring for %s (%s)", obj.id, is_recent)
|
|
492
|
-
if is_recent:
|
|
503
|
+
if "last_ring" in data and (last_ring := obj.last_ring):
|
|
504
|
+
if is_recent := last_ring + RECENT_EVENT_MAX >= utc_now():
|
|
493
505
|
obj.set_ring_timeout()
|
|
506
|
+
_LOGGER.debug("last_ring for %s (%s)", obj.id, is_recent)
|
|
494
507
|
elif model_type is ModelType.SENSOR:
|
|
495
508
|
if TYPE_CHECKING:
|
|
496
509
|
assert isinstance(obj, Sensor)
|
|
497
|
-
if "alarm_triggered_at" in data and obj.alarm_triggered_at:
|
|
498
|
-
is_recent
|
|
499
|
-
_LOGGER.debug("alarm_triggered_at for %s (%s)", obj.id, is_recent)
|
|
500
|
-
if is_recent:
|
|
510
|
+
if "alarm_triggered_at" in data and (trigged_at := obj.alarm_triggered_at):
|
|
511
|
+
if is_recent := trigged_at + RECENT_EVENT_MAX >= utc_now():
|
|
501
512
|
obj.set_alarm_timeout()
|
|
513
|
+
_LOGGER.debug("alarm_triggered_at for %s (%s)", obj.id, is_recent)
|
|
502
514
|
|
|
503
515
|
devices[action_id] = obj
|
|
504
516
|
self._create_stat(packet, data, False)
|
|
@@ -515,6 +527,7 @@ class Bootstrap(ProtectBaseObject):
|
|
|
515
527
|
packet: WSPacket,
|
|
516
528
|
models: set[ModelType] | None = None,
|
|
517
529
|
ignore_stats: bool = False,
|
|
530
|
+
is_ping_back: bool = False,
|
|
518
531
|
) -> WSSubscriptionMessage | None:
|
|
519
532
|
"""Process a WS packet."""
|
|
520
533
|
action = packet.action_frame.data
|
|
@@ -523,17 +536,16 @@ class Bootstrap(ProtectBaseObject):
|
|
|
523
536
|
action = deepcopy(action)
|
|
524
537
|
data = deepcopy(data)
|
|
525
538
|
|
|
526
|
-
new_update_id: str = action["newUpdateId"]
|
|
539
|
+
new_update_id: str | None = action["newUpdateId"]
|
|
527
540
|
if new_update_id is not None:
|
|
528
541
|
self.last_update_id = new_update_id
|
|
529
542
|
|
|
530
543
|
model_key: str = action["modelKey"]
|
|
531
|
-
if
|
|
544
|
+
if (model_type := ModelType.from_string(model_key)) is ModelType.UNKNOWN:
|
|
532
545
|
_LOGGER.debug("Unknown model type: %s", model_key)
|
|
533
546
|
self._create_stat(packet, None, True)
|
|
534
547
|
return None
|
|
535
548
|
|
|
536
|
-
model_type = ModelType.from_string(model_key)
|
|
537
549
|
if models and model_type not in models:
|
|
538
550
|
self._create_stat(packet, None, True)
|
|
539
551
|
return None
|
|
@@ -542,7 +554,7 @@ class Bootstrap(ProtectBaseObject):
|
|
|
542
554
|
if action_action == "remove":
|
|
543
555
|
return self._process_remove_packet(model_type, packet)
|
|
544
556
|
|
|
545
|
-
if not data:
|
|
557
|
+
if not data and not is_ping_back:
|
|
546
558
|
self._create_stat(packet, None, True)
|
|
547
559
|
return None
|
|
548
560
|
|
|
@@ -554,11 +566,7 @@ class Bootstrap(ProtectBaseObject):
|
|
|
554
566
|
return self._process_nvr_update(packet, data, ignore_stats)
|
|
555
567
|
if model_type in ModelType.bootstrap_models_types_and_event_set:
|
|
556
568
|
return self._process_device_update(
|
|
557
|
-
model_type,
|
|
558
|
-
packet,
|
|
559
|
-
action,
|
|
560
|
-
data,
|
|
561
|
-
ignore_stats,
|
|
569
|
+
model_type, packet, action, data, ignore_stats, is_ping_back
|
|
562
570
|
)
|
|
563
571
|
except (ValidationError, ValueError) as err:
|
|
564
572
|
self._handle_ws_error(action, err)
|
|
@@ -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=
|
|
18
|
-
uiprotect/data/bootstrap.py,sha256=
|
|
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.
|
|
34
|
-
uiprotect-1.
|
|
35
|
-
uiprotect-1.
|
|
36
|
-
uiprotect-1.
|
|
37
|
-
uiprotect-1.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|