uiprotect 1.13.0__tar.gz → 1.15.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.
- {uiprotect-1.13.0 → uiprotect-1.15.0}/PKG-INFO +1 -1
- {uiprotect-1.13.0 → uiprotect-1.15.0}/pyproject.toml +1 -1
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/data/base.py +36 -60
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/data/bootstrap.py +14 -16
- {uiprotect-1.13.0 → uiprotect-1.15.0}/LICENSE +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/README.md +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/__init__.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/__main__.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/api.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/__init__.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/backup.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/base.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/cameras.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/chimes.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/doorlocks.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/events.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/lights.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/liveviews.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/nvr.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/sensors.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/cli/viewers.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/data/__init__.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/data/convert.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/data/devices.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/data/nvr.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/data/types.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/data/user.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/data/websocket.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/exceptions.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/py.typed +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/release_cache.json +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/stream.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/test_util/__init__.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/test_util/anonymize.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/utils.py +0 -0
- {uiprotect-1.13.0 → uiprotect-1.15.0}/src/uiprotect/websocket.py +0 -0
|
@@ -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."""
|
|
@@ -9,7 +9,7 @@ from copy import deepcopy
|
|
|
9
9
|
from dataclasses import dataclass
|
|
10
10
|
from datetime import datetime
|
|
11
11
|
from functools import cache
|
|
12
|
-
from typing import TYPE_CHECKING, Any
|
|
12
|
+
from typing import TYPE_CHECKING, Any
|
|
13
13
|
|
|
14
14
|
from aiohttp.client_exceptions import ServerDisconnectedError
|
|
15
15
|
|
|
@@ -298,20 +298,20 @@ class Bootstrap(ProtectBaseObject):
|
|
|
298
298
|
|
|
299
299
|
def get_device_from_mac(self, mac: str) -> ProtectAdoptableDeviceModel | None:
|
|
300
300
|
"""Retrieve a device from MAC address."""
|
|
301
|
-
|
|
302
|
-
if ref is None:
|
|
303
|
-
return None
|
|
304
|
-
|
|
305
|
-
devices: dict[str, ProtectModelWithId] = getattr(self, ref.model.devices_key)
|
|
306
|
-
return cast(ProtectAdoptableDeviceModel, devices.get(ref.id))
|
|
301
|
+
return self._get_device_from_ref(self.mac_lookup.get(normalize_mac(mac)))
|
|
307
302
|
|
|
308
303
|
def get_device_from_id(self, device_id: str) -> ProtectAdoptableDeviceModel | None:
|
|
309
304
|
"""Retrieve a device from device ID (without knowing model type)."""
|
|
310
|
-
|
|
305
|
+
return self._get_device_from_ref(self.id_lookup.get(device_id))
|
|
306
|
+
|
|
307
|
+
def _get_device_from_ref(
|
|
308
|
+
self, ref: ProtectDeviceRef | None
|
|
309
|
+
) -> ProtectAdoptableDeviceModel | None:
|
|
311
310
|
if ref is None:
|
|
312
311
|
return None
|
|
313
|
-
|
|
314
|
-
|
|
312
|
+
devices_key = ref.model.devices_key
|
|
313
|
+
devices: dict[str, ProtectAdoptableDeviceModel] = getattr(self, devices_key)
|
|
314
|
+
return devices[ref.id]
|
|
315
315
|
|
|
316
316
|
def process_event(self, event: Event) -> None:
|
|
317
317
|
event_type = event.type
|
|
@@ -386,9 +386,8 @@ class Bootstrap(ProtectBaseObject):
|
|
|
386
386
|
def _process_remove_packet(
|
|
387
387
|
self, model_type: ModelType, packet: WSPacket
|
|
388
388
|
) -> WSSubscriptionMessage | None:
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
)
|
|
389
|
+
devices_key = model_type.devices_key
|
|
390
|
+
devices: dict[str, ProtectDeviceModel] | None = getattr(self, devices_key, None)
|
|
392
391
|
|
|
393
392
|
if devices is None:
|
|
394
393
|
return None
|
|
@@ -615,9 +614,8 @@ class Bootstrap(ProtectBaseObject):
|
|
|
615
614
|
if isinstance(device, NVR):
|
|
616
615
|
self.nvr = device
|
|
617
616
|
else:
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
)
|
|
617
|
+
devices_key = model_type.devices_key
|
|
618
|
+
devices: dict[str, ProtectModelWithId] = getattr(self, devices_key)
|
|
621
619
|
devices[device.id] = device
|
|
622
620
|
_LOGGER.debug("Successfully refresh model: %s %s", model_type, device_id)
|
|
623
621
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|