uiprotect 1.12.1__py3-none-any.whl → 1.14.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 +6 -8
- uiprotect/data/base.py +36 -60
- uiprotect/websocket.py +6 -5
- {uiprotect-1.12.1.dist-info → uiprotect-1.14.0.dist-info}/METADATA +1 -1
- {uiprotect-1.12.1.dist-info → uiprotect-1.14.0.dist-info}/RECORD +8 -8
- {uiprotect-1.12.1.dist-info → uiprotect-1.14.0.dist-info}/LICENSE +0 -0
- {uiprotect-1.12.1.dist-info → uiprotect-1.14.0.dist-info}/WHEEL +0 -0
- {uiprotect-1.12.1.dist-info → uiprotect-1.14.0.dist-info}/entry_points.txt +0 -0
uiprotect/api.py
CHANGED
|
@@ -228,6 +228,7 @@ class BaseApiClient:
|
|
|
228
228
|
|
|
229
229
|
@property
|
|
230
230
|
def ws_url(self) -> str:
|
|
231
|
+
"""Get Websocket URL."""
|
|
231
232
|
url = f"wss://{self._host}"
|
|
232
233
|
if self._port != 443:
|
|
233
234
|
url += f":{self._port}"
|
|
@@ -267,7 +268,7 @@ class BaseApiClient:
|
|
|
267
268
|
|
|
268
269
|
if self._websocket is None:
|
|
269
270
|
self._websocket = Websocket(
|
|
270
|
-
self.
|
|
271
|
+
self.get_websocket_url,
|
|
271
272
|
_auth,
|
|
272
273
|
verify=self._verify_ssl,
|
|
273
274
|
timeout=self._ws_timeout,
|
|
@@ -626,9 +627,6 @@ class BaseApiClient:
|
|
|
626
627
|
self._websocket = None
|
|
627
628
|
|
|
628
629
|
websocket = await self.get_websocket()
|
|
629
|
-
# important to make sure WS URL is always current
|
|
630
|
-
websocket.url = self.ws_url
|
|
631
|
-
|
|
632
630
|
if not websocket.is_connected:
|
|
633
631
|
self._last_ws_status = False
|
|
634
632
|
with contextlib.suppress(
|
|
@@ -638,6 +636,10 @@ class BaseApiClient:
|
|
|
638
636
|
):
|
|
639
637
|
await websocket.connect()
|
|
640
638
|
|
|
639
|
+
def get_websocket_url(self) -> str:
|
|
640
|
+
"""Get Websocket URL."""
|
|
641
|
+
return self.ws_url
|
|
642
|
+
|
|
641
643
|
async def async_disconnect_ws(self) -> None:
|
|
642
644
|
"""Disconnect from Websocket."""
|
|
643
645
|
if self._websocket is None:
|
|
@@ -861,10 +863,6 @@ class ProtectApiClient(BaseApiClient):
|
|
|
861
863
|
models=self._subscribed_models,
|
|
862
864
|
ignore_stats=self._ignore_stats,
|
|
863
865
|
)
|
|
864
|
-
# update websocket URL after every message to ensure the latest last_update_id
|
|
865
|
-
if self._websocket is not None:
|
|
866
|
-
self._websocket.url = self.ws_url
|
|
867
|
-
|
|
868
866
|
if processed_message is None:
|
|
869
867
|
return
|
|
870
868
|
|
uiprotect/data/base.py
CHANGED
|
@@ -485,68 +485,44 @@ class ProtectBaseObject(BaseModel):
|
|
|
485
485
|
|
|
486
486
|
return new_data
|
|
487
487
|
|
|
488
|
-
def
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
api: ProtectApiClient | None,
|
|
492
|
-
) -> dict[str, Any]:
|
|
493
|
-
data["api"] = api
|
|
494
|
-
unifi_objs_sets = self._get_protect_objs_set()
|
|
495
|
-
has_unifi_objs = bool(unifi_objs_sets)
|
|
496
|
-
unifi_lists_sets = self._get_protect_lists_set()
|
|
497
|
-
has_unifi_lists = bool(unifi_lists_sets)
|
|
498
|
-
unifi_dicts_sets = self._get_protect_dicts_set()
|
|
499
|
-
has_unifi_dicts = bool(unifi_dicts_sets)
|
|
500
|
-
for key, value in data.items():
|
|
501
|
-
if has_unifi_objs and key in unifi_objs_sets and isinstance(value, dict):
|
|
502
|
-
value["api"] = api
|
|
503
|
-
elif (
|
|
504
|
-
has_unifi_lists and key in unifi_lists_sets and isinstance(value, list)
|
|
505
|
-
):
|
|
506
|
-
for item in value:
|
|
507
|
-
if isinstance(item, dict):
|
|
508
|
-
item["api"] = api
|
|
509
|
-
elif (
|
|
510
|
-
has_unifi_dicts and key in unifi_dicts_sets and isinstance(value, dict)
|
|
511
|
-
):
|
|
512
|
-
for item in value.values():
|
|
513
|
-
if isinstance(item, dict):
|
|
514
|
-
item["api"] = api
|
|
488
|
+
def update_from_dict(cls: ProtectObject, data: dict[str, Any]) -> ProtectObject:
|
|
489
|
+
"""
|
|
490
|
+
Updates current object from a cleaned UFP JSON dict.
|
|
515
491
|
|
|
516
|
-
|
|
492
|
+
The api client is injected into each dict for any child
|
|
493
|
+
UFP objects that are detected.
|
|
494
|
+
"""
|
|
495
|
+
unifi_objs = cls._get_protect_objs()
|
|
496
|
+
has_unifi_objs = bool(unifi_objs)
|
|
497
|
+
unifi_lists = cls._get_protect_lists()
|
|
498
|
+
has_unifi_lists = bool(unifi_lists)
|
|
517
499
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
setattr(
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
del data["api"]
|
|
545
|
-
|
|
546
|
-
for key in data:
|
|
547
|
-
setattr(self, key, convert_unifi_data(data[key], self.__fields__[key]))
|
|
548
|
-
|
|
549
|
-
return self
|
|
500
|
+
api = cls._api
|
|
501
|
+
_fields = cls.__fields__
|
|
502
|
+
unifi_obj: ProtectBaseObject | None
|
|
503
|
+
if "api" in data:
|
|
504
|
+
del data["api"]
|
|
505
|
+
value: Any
|
|
506
|
+
|
|
507
|
+
for key, item in data.items():
|
|
508
|
+
if has_unifi_objs and key in unifi_objs and isinstance(item, dict):
|
|
509
|
+
if (unifi_obj := getattr(cls, key)) is not None:
|
|
510
|
+
value = unifi_obj.update_from_dict(item)
|
|
511
|
+
else:
|
|
512
|
+
value = None
|
|
513
|
+
elif has_unifi_lists and key in unifi_lists and isinstance(item, list):
|
|
514
|
+
klass = unifi_lists[key]
|
|
515
|
+
value = [
|
|
516
|
+
klass(**i, api=api) if isinstance(i, dict) else i
|
|
517
|
+
for i in item
|
|
518
|
+
if i is not None and isinstance(i, (dict, ProtectBaseObject))
|
|
519
|
+
]
|
|
520
|
+
else:
|
|
521
|
+
value = convert_unifi_data(item, _fields[key])
|
|
522
|
+
|
|
523
|
+
setattr(cls, key, value)
|
|
524
|
+
|
|
525
|
+
return cls
|
|
550
526
|
|
|
551
527
|
def dict_with_excludes(self) -> dict[str, Any]:
|
|
552
528
|
"""Returns a dict of the current object without any UFP objects converted to dicts."""
|
uiprotect/websocket.py
CHANGED
|
@@ -45,7 +45,7 @@ class Websocket:
|
|
|
45
45
|
|
|
46
46
|
def __init__(
|
|
47
47
|
self,
|
|
48
|
-
|
|
48
|
+
get_url: Callable[[], str],
|
|
49
49
|
auth_callback: CALLBACK_TYPE,
|
|
50
50
|
*,
|
|
51
51
|
timeout: int = 30,
|
|
@@ -53,7 +53,7 @@ class Websocket:
|
|
|
53
53
|
verify: bool = True,
|
|
54
54
|
) -> None:
|
|
55
55
|
"""Init Websocket."""
|
|
56
|
-
self.
|
|
56
|
+
self.get_url = get_url
|
|
57
57
|
self.timeout_interval = timeout
|
|
58
58
|
self.backoff = backoff
|
|
59
59
|
self.verify = verify
|
|
@@ -85,14 +85,15 @@ class Websocket:
|
|
|
85
85
|
return True
|
|
86
86
|
|
|
87
87
|
async def _websocket_loop(self, start_event: asyncio.Event) -> None:
|
|
88
|
-
|
|
88
|
+
url = self.get_url()
|
|
89
|
+
_LOGGER.debug("Connecting WS to %s", url)
|
|
89
90
|
self._headers = await self._auth(self._should_reset_auth)
|
|
90
91
|
|
|
91
92
|
session = self._get_session()
|
|
92
93
|
# catch any and all errors for Websocket so we can clean up correctly
|
|
93
94
|
try:
|
|
94
95
|
self._ws_connection = await session.ws_connect(
|
|
95
|
-
|
|
96
|
+
url,
|
|
96
97
|
ssl=None if self.verify else False,
|
|
97
98
|
headers=self._headers,
|
|
98
99
|
)
|
|
@@ -104,7 +105,7 @@ class Websocket:
|
|
|
104
105
|
break
|
|
105
106
|
self._reset_timeout()
|
|
106
107
|
except ClientError:
|
|
107
|
-
_LOGGER.exception("Websocket disconnect error: %s",
|
|
108
|
+
_LOGGER.exception("Websocket disconnect error: %s", url)
|
|
108
109
|
finally:
|
|
109
110
|
_LOGGER.debug("Websocket disconnected")
|
|
110
111
|
self._increase_failure()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
uiprotect/__init__.py,sha256=llnQNtiBfwQG8IkQXovvFz4LZeFjrJx7XdmmUhu3a9E,289
|
|
2
2
|
uiprotect/__main__.py,sha256=C_bHCOkv5qj6WMy-6ELoY3Y6HDhLxOa1a30CzmbZhsg,462
|
|
3
|
-
uiprotect/api.py,sha256=
|
|
3
|
+
uiprotect/api.py,sha256=zVKTMieBqx3EM1sex5zzAj2J2k4pUlQQ_xF8nE6AS5s,66339
|
|
4
4
|
uiprotect/cli/__init__.py,sha256=sSLW9keVQOkgFcMW18HTDjRrt9sJ0KWjn9DJDA6f9Pc,8658
|
|
5
5
|
uiprotect/cli/backup.py,sha256=ZiS7RZnJGKI8TJKLW2cOUzkRM8nyTvE5Ov_jZZGtvSM,36708
|
|
6
6
|
uiprotect/cli/base.py,sha256=zpTm2kyJe_GLixnv3Uadke__iRLh64AEwQzp-2hqS7g,7730
|
|
@@ -14,7 +14,7 @@ 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=
|
|
17
|
+
uiprotect/data/base.py,sha256=OWKeMWk7n5VaHF_meTt2Ykw7H9zx6U47u-P2vLNDWzE,36627
|
|
18
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
|
|
@@ -29,9 +29,9 @@ uiprotect/stream.py,sha256=McV3XymKyjn-1uV5jdQHcpaDjqLS4zWyMASQ8ubcyb4,4924
|
|
|
29
29
|
uiprotect/test_util/__init__.py,sha256=d2g7afa0LSdixQ0kjEDYwafDFME_UlW2LzxpamZ2BC0,18556
|
|
30
30
|
uiprotect/test_util/anonymize.py,sha256=f-8ijU-_y9r-uAbhIPn0f0I6hzJpAkvJzc8UpWihObI,8478
|
|
31
31
|
uiprotect/utils.py,sha256=6OLY8hNiCzk418PjJJIlFW7jjPzVt1vxBKEzBSqMeTk,18418
|
|
32
|
-
uiprotect/websocket.py,sha256=
|
|
33
|
-
uiprotect-1.
|
|
34
|
-
uiprotect-1.
|
|
35
|
-
uiprotect-1.
|
|
36
|
-
uiprotect-1.
|
|
37
|
-
uiprotect-1.
|
|
32
|
+
uiprotect/websocket.py,sha256=JHI_2EZeRPqPyQopsBZS0dr3tu0HaTiqeLazfBXhW_8,7339
|
|
33
|
+
uiprotect-1.14.0.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
|
|
34
|
+
uiprotect-1.14.0.dist-info/METADATA,sha256=3CmROnNdNIJkOFAIRb0Ha13iqu67iKaJY0jKIcJdbcQ,10985
|
|
35
|
+
uiprotect-1.14.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
36
|
+
uiprotect-1.14.0.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
|
|
37
|
+
uiprotect-1.14.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|