uiprotect 7.0.1__py3-none-any.whl → 7.1.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 +17 -1
- uiprotect/cli/__init__.py +2 -0
- uiprotect/cli/aiports.py +59 -0
- uiprotect/data/__init__.py +2 -0
- uiprotect/data/base.py +16 -10
- uiprotect/data/bootstrap.py +5 -3
- uiprotect/data/convert.py +2 -0
- uiprotect/data/devices.py +6 -0
- uiprotect/data/types.py +2 -0
- uiprotect/test_util/__init__.py +17 -0
- uiprotect/utils.py +1 -1
- {uiprotect-7.0.1.dist-info → uiprotect-7.1.0.dist-info}/METADATA +1 -1
- {uiprotect-7.0.1.dist-info → uiprotect-7.1.0.dist-info}/RECORD +16 -15
- {uiprotect-7.0.1.dist-info → uiprotect-7.1.0.dist-info}/LICENSE +0 -0
- {uiprotect-7.0.1.dist-info → uiprotect-7.1.0.dist-info}/WHEEL +0 -0
- {uiprotect-7.0.1.dist-info → uiprotect-7.1.0.dist-info}/entry_points.txt +0 -0
uiprotect/api.py
CHANGED
|
@@ -57,7 +57,7 @@ from .data import (
|
|
|
57
57
|
create_from_unifi_dict,
|
|
58
58
|
)
|
|
59
59
|
from .data.base import ProtectModelWithId
|
|
60
|
-
from .data.devices import Chime
|
|
60
|
+
from .data.devices import AiPort, Chime
|
|
61
61
|
from .data.types import IteratorCallback, ProgressCallback
|
|
62
62
|
from .exceptions import BadRequest, NotAuthorized, NvrError
|
|
63
63
|
from .utils import (
|
|
@@ -1268,6 +1268,14 @@ class ProtectApiClient(BaseApiClient):
|
|
|
1268
1268
|
"""
|
|
1269
1269
|
return cast(list[Chime], await self.get_devices(ModelType.CHIME, Chime))
|
|
1270
1270
|
|
|
1271
|
+
async def get_aiports(self) -> list[AiPort]:
|
|
1272
|
+
"""
|
|
1273
|
+
Gets the list of aiports straight from the NVR.
|
|
1274
|
+
|
|
1275
|
+
The websocket is connected and running, you likely just want to use `self.bootstrap.aiports`
|
|
1276
|
+
"""
|
|
1277
|
+
return cast(list[AiPort], await self.get_devices(ModelType.AIPORT, AiPort))
|
|
1278
|
+
|
|
1271
1279
|
async def get_viewers(self) -> list[Viewer]:
|
|
1272
1280
|
"""
|
|
1273
1281
|
Gets the list of viewers straight from the NVR.
|
|
@@ -1386,6 +1394,14 @@ class ProtectApiClient(BaseApiClient):
|
|
|
1386
1394
|
"""
|
|
1387
1395
|
return cast(Chime, await self.get_device(ModelType.CHIME, device_id, Chime))
|
|
1388
1396
|
|
|
1397
|
+
async def get_aiport(self, device_id: str) -> AiPort:
|
|
1398
|
+
"""
|
|
1399
|
+
Gets a AiPort straight from the NVR.
|
|
1400
|
+
|
|
1401
|
+
The websocket is connected and running, you likely just want to use `self.bootstrap.aiport[device_id]`
|
|
1402
|
+
"""
|
|
1403
|
+
return cast(AiPort, await self.get_device(ModelType.AIPORT, device_id, AiPort))
|
|
1404
|
+
|
|
1389
1405
|
async def get_viewer(self, device_id: str) -> Viewer:
|
|
1390
1406
|
"""
|
|
1391
1407
|
Gets a viewer straight from the NVR.
|
uiprotect/cli/__init__.py
CHANGED
|
@@ -17,6 +17,7 @@ from ..data import Version, WSPacket
|
|
|
17
17
|
from ..test_util import SampleDataGenerator
|
|
18
18
|
from ..utils import RELEASE_CACHE, get_local_timezone, run_async
|
|
19
19
|
from ..utils import profile_ws as profile_ws_job
|
|
20
|
+
from .aiports import app as aiports_app
|
|
20
21
|
from .base import CliContext, OutputFormatEnum
|
|
21
22
|
from .cameras import app as camera_app
|
|
22
23
|
from .chimes import app as chime_app
|
|
@@ -128,6 +129,7 @@ app.add_typer(doorlock_app, name="doorlocks")
|
|
|
128
129
|
app.add_typer(light_app, name="lights")
|
|
129
130
|
app.add_typer(sensor_app, name="sensors")
|
|
130
131
|
app.add_typer(viewer_app, name="viewers")
|
|
132
|
+
app.add_typer(aiports_app, name="aiports")
|
|
131
133
|
|
|
132
134
|
if backup_app is not None:
|
|
133
135
|
app.add_typer(backup_app, name="backup")
|
uiprotect/cli/aiports.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
from ..api import ProtectApiClient
|
|
9
|
+
from ..cli import base
|
|
10
|
+
from ..data import AiPort
|
|
11
|
+
|
|
12
|
+
app = typer.Typer(rich_markup_mode="rich")
|
|
13
|
+
|
|
14
|
+
ARG_DEVICE_ID = typer.Argument(
|
|
15
|
+
None, help="ID of AiPort device to select for subcommands"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class AiPortContext(base.CliContext):
|
|
21
|
+
devices: dict[str, AiPort]
|
|
22
|
+
device: AiPort | None = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
ALL_COMMANDS, DEVICE_COMMANDS = base.init_common_commands(app)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@app.callback(invoke_without_command=True)
|
|
29
|
+
def main(ctx: typer.Context, device_id: Optional[str] = ARG_DEVICE_ID) -> None:
|
|
30
|
+
"""
|
|
31
|
+
AiPort device CLI.
|
|
32
|
+
|
|
33
|
+
Returns full list of AiPorts without any arguments passed.
|
|
34
|
+
"""
|
|
35
|
+
protect: ProtectApiClient = ctx.obj.protect
|
|
36
|
+
context = AiPortContext(
|
|
37
|
+
protect=ctx.obj.protect,
|
|
38
|
+
device=None,
|
|
39
|
+
devices=protect.bootstrap.aiports,
|
|
40
|
+
output_format=ctx.obj.output_format,
|
|
41
|
+
)
|
|
42
|
+
ctx.obj = context
|
|
43
|
+
|
|
44
|
+
if device_id is not None and device_id not in ALL_COMMANDS:
|
|
45
|
+
if (device := protect.bootstrap.aiports.get(device_id)) is None:
|
|
46
|
+
typer.secho("Invalid aiport ID", fg="red")
|
|
47
|
+
raise typer.Exit(1)
|
|
48
|
+
ctx.obj.device = device
|
|
49
|
+
|
|
50
|
+
if not ctx.invoked_subcommand:
|
|
51
|
+
if device_id in ALL_COMMANDS:
|
|
52
|
+
ctx.invoke(ALL_COMMANDS[device_id], ctx)
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
if ctx.obj.device is not None:
|
|
56
|
+
base.print_unifi_obj(ctx.obj.device, ctx.obj.output_format)
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
base.print_unifi_dict(ctx.obj.devices)
|
uiprotect/data/__init__.py
CHANGED
|
@@ -10,6 +10,7 @@ from .base import (
|
|
|
10
10
|
from .bootstrap import Bootstrap
|
|
11
11
|
from .convert import create_from_unifi_dict
|
|
12
12
|
from .devices import (
|
|
13
|
+
AiPort,
|
|
13
14
|
Bridge,
|
|
14
15
|
Camera,
|
|
15
16
|
CameraChannel,
|
|
@@ -85,6 +86,7 @@ __all__ = [
|
|
|
85
86
|
"DEFAULT_TYPE",
|
|
86
87
|
"NVR",
|
|
87
88
|
"WS_HEADER_SIZE",
|
|
89
|
+
"AiPort",
|
|
88
90
|
"AnalyticsOption",
|
|
89
91
|
"AudioStyle",
|
|
90
92
|
"Bootstrap",
|
uiprotect/data/base.py
CHANGED
|
@@ -137,10 +137,12 @@ class ProtectBaseObject(BaseModel):
|
|
|
137
137
|
data.pop("api", None)
|
|
138
138
|
return cls(api=api, **data)
|
|
139
139
|
|
|
140
|
-
return cls.
|
|
140
|
+
return cls.model_construct(**data)
|
|
141
141
|
|
|
142
142
|
@classmethod
|
|
143
|
-
def
|
|
143
|
+
def model_construct(
|
|
144
|
+
cls, _fields_set: set[str] | None = None, **values: Any
|
|
145
|
+
) -> Self:
|
|
144
146
|
api: ProtectApiClient | None = values.pop("api", None)
|
|
145
147
|
(
|
|
146
148
|
unifi_objs,
|
|
@@ -152,19 +154,21 @@ class ProtectBaseObject(BaseModel):
|
|
|
152
154
|
) = cls._get_protect_model()
|
|
153
155
|
for key, value in values.items():
|
|
154
156
|
if has_unifi_objs and key in unifi_objs and isinstance(value, dict):
|
|
155
|
-
values[key] = unifi_objs[key].
|
|
157
|
+
values[key] = unifi_objs[key].model_construct(**value)
|
|
156
158
|
elif has_unifi_lists and key in unifi_lists and isinstance(value, list):
|
|
157
159
|
values[key] = [
|
|
158
|
-
unifi_lists[key].
|
|
160
|
+
unifi_lists[key].model_construct(**v) if isinstance(v, dict) else v
|
|
159
161
|
for v in value
|
|
160
162
|
]
|
|
161
163
|
elif has_unifi_dicts and key in unifi_dicts and isinstance(value, dict):
|
|
162
164
|
values[key] = {
|
|
163
|
-
k: unifi_dicts[key].
|
|
165
|
+
k: unifi_dicts[key].model_construct(**v)
|
|
166
|
+
if isinstance(v, dict)
|
|
167
|
+
else v
|
|
164
168
|
for k, v in value.items()
|
|
165
169
|
}
|
|
166
170
|
|
|
167
|
-
obj = super().
|
|
171
|
+
obj = super().model_construct(_fields_set=_fields_set, **values)
|
|
168
172
|
if api is not None:
|
|
169
173
|
obj._api = api
|
|
170
174
|
|
|
@@ -369,7 +373,7 @@ class ProtectBaseObject(BaseModel):
|
|
|
369
373
|
if isinstance(value, ProtectBaseObject):
|
|
370
374
|
value = value.unifi_dict()
|
|
371
375
|
elif isinstance(value, dict):
|
|
372
|
-
value = klass.
|
|
376
|
+
value = klass.model_construct({}).unifi_dict(data=value) # type: ignore[arg-type]
|
|
373
377
|
|
|
374
378
|
return value
|
|
375
379
|
|
|
@@ -390,7 +394,7 @@ class ProtectBaseObject(BaseModel):
|
|
|
390
394
|
return [
|
|
391
395
|
item.unifi_dict()
|
|
392
396
|
if isinstance(item, ProtectBaseObject)
|
|
393
|
-
else klass.
|
|
397
|
+
else klass.model_construct({}).unifi_dict(data=item) # type: ignore[arg-type]
|
|
394
398
|
for item in value
|
|
395
399
|
]
|
|
396
400
|
|
|
@@ -587,9 +591,11 @@ class ProtectModelWithId(ProtectModel):
|
|
|
587
591
|
self._update_sync = update_sync or UpdateSynchronization()
|
|
588
592
|
|
|
589
593
|
@classmethod
|
|
590
|
-
def
|
|
594
|
+
def model_construct(
|
|
595
|
+
cls, _fields_set: set[str] | None = None, **values: Any
|
|
596
|
+
) -> Self:
|
|
591
597
|
update_sync = values.pop("update_sync", None)
|
|
592
|
-
obj = super().
|
|
598
|
+
obj = super().model_construct(_fields_set=_fields_set, **values)
|
|
593
599
|
obj._update_sync = update_sync or UpdateSynchronization()
|
|
594
600
|
return obj
|
|
595
601
|
|
uiprotect/data/bootstrap.py
CHANGED
|
@@ -23,6 +23,7 @@ from .base import (
|
|
|
23
23
|
)
|
|
24
24
|
from .convert import MODEL_TO_CLASS, create_from_unifi_dict
|
|
25
25
|
from .devices import (
|
|
26
|
+
AiPort,
|
|
26
27
|
Bridge,
|
|
27
28
|
Camera,
|
|
28
29
|
Chime,
|
|
@@ -181,6 +182,7 @@ class Bootstrap(ProtectBaseObject):
|
|
|
181
182
|
sensors: dict[str, Sensor]
|
|
182
183
|
doorlocks: dict[str, Doorlock]
|
|
183
184
|
chimes: dict[str, Chime]
|
|
185
|
+
aiports: dict[str, AiPort]
|
|
184
186
|
last_update_id: str
|
|
185
187
|
|
|
186
188
|
# TODO:
|
|
@@ -426,7 +428,7 @@ class Bootstrap(ProtectBaseObject):
|
|
|
426
428
|
if updated_obj is None:
|
|
427
429
|
return None
|
|
428
430
|
|
|
429
|
-
old_obj = updated_obj.
|
|
431
|
+
old_obj = updated_obj.model_copy()
|
|
430
432
|
updated_data = {to_snake_case(k): v for k, v in data.items()}
|
|
431
433
|
updated_obj.update_from_dict(updated_data)
|
|
432
434
|
|
|
@@ -461,7 +463,7 @@ class Bootstrap(ProtectBaseObject):
|
|
|
461
463
|
if not (data := self.nvr.unifi_dict_to_dict(data)):
|
|
462
464
|
return None
|
|
463
465
|
|
|
464
|
-
old_nvr = self.nvr.
|
|
466
|
+
old_nvr = self.nvr.model_copy()
|
|
465
467
|
self.nvr = self.nvr.update_from_dict(data)
|
|
466
468
|
|
|
467
469
|
return WSSubscriptionMessage(
|
|
@@ -517,7 +519,7 @@ class Bootstrap(ProtectBaseObject):
|
|
|
517
519
|
# nothing left to process
|
|
518
520
|
return None
|
|
519
521
|
|
|
520
|
-
old_obj = obj.
|
|
522
|
+
old_obj = obj.model_copy()
|
|
521
523
|
obj = obj.update_from_dict(data)
|
|
522
524
|
|
|
523
525
|
if model_type is ModelType.EVENT:
|
uiprotect/data/convert.py
CHANGED
|
@@ -8,6 +8,7 @@ from uiprotect.data.base import ProtectModelWithId
|
|
|
8
8
|
|
|
9
9
|
from ..exceptions import DataDecodeError
|
|
10
10
|
from .devices import (
|
|
11
|
+
AiPort,
|
|
11
12
|
Bridge,
|
|
12
13
|
Camera,
|
|
13
14
|
Chime,
|
|
@@ -40,6 +41,7 @@ MODEL_TO_CLASS: dict[str, type[ProtectModel]] = {
|
|
|
40
41
|
ModelType.SENSOR: Sensor,
|
|
41
42
|
ModelType.DOORLOCK: Doorlock,
|
|
42
43
|
ModelType.CHIME: Chime,
|
|
44
|
+
ModelType.AIPORT: AiPort,
|
|
43
45
|
ModelType.KEYRING: Keyring,
|
|
44
46
|
ModelType.ULP_USER: UlpUser,
|
|
45
47
|
}
|
uiprotect/data/devices.py
CHANGED
|
@@ -976,6 +976,8 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
976
976
|
audio_settings: CameraAudioSettings | None = None
|
|
977
977
|
# requires 5.0.33+
|
|
978
978
|
is_third_party_camera: bool | None = None
|
|
979
|
+
# requires 5.1.78+
|
|
980
|
+
is_paired_with_ai_port: bool | None = None
|
|
979
981
|
# TODO: used for adopting
|
|
980
982
|
# apMac read only
|
|
981
983
|
# apRssi read only
|
|
@@ -3382,3 +3384,7 @@ class Chime(ProtectAdoptableDeviceModel):
|
|
|
3382
3384
|
raise BadRequest("Camera %s is not paired with chime", camera.id)
|
|
3383
3385
|
|
|
3384
3386
|
await self.queue_update(callback)
|
|
3387
|
+
|
|
3388
|
+
|
|
3389
|
+
class AiPort(Camera):
|
|
3390
|
+
paired_cameras: list[str]
|
uiprotect/data/types.py
CHANGED
|
@@ -124,6 +124,7 @@ class ModelType(str, UnknownValuesEnumMixin, enum.Enum):
|
|
|
124
124
|
DOORLOCK = "doorlock"
|
|
125
125
|
SCHEDULE = "schedule"
|
|
126
126
|
CHIME = "chime"
|
|
127
|
+
AIPORT = "aiport"
|
|
127
128
|
DEVICE_GROUP = "deviceGroup"
|
|
128
129
|
RECORDING_SCHEDULE = "recordingSchedule"
|
|
129
130
|
ULP_USER = "ulpUser"
|
|
@@ -173,6 +174,7 @@ class ModelType(str, UnknownValuesEnumMixin, enum.Enum):
|
|
|
173
174
|
ModelType.SENSOR,
|
|
174
175
|
ModelType.DOORLOCK,
|
|
175
176
|
ModelType.CHIME,
|
|
177
|
+
ModelType.AIPORT,
|
|
176
178
|
)
|
|
177
179
|
|
|
178
180
|
@classmethod
|
uiprotect/test_util/__init__.py
CHANGED
|
@@ -131,6 +131,7 @@ class SampleDataGenerator:
|
|
|
131
131
|
"sensor": len(bootstrap["sensors"]),
|
|
132
132
|
"doorlock": len(bootstrap["doorlocks"]),
|
|
133
133
|
"chime": len(bootstrap["chimes"]),
|
|
134
|
+
"aiport": len(bootstrap["aiports"]),
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
self.log("Generating event data...")
|
|
@@ -283,6 +284,7 @@ class SampleDataGenerator:
|
|
|
283
284
|
self.generate_sensor_data(),
|
|
284
285
|
self.generate_lock_data(),
|
|
285
286
|
self.generate_chime_data(),
|
|
287
|
+
self.generate_aiport_data(),
|
|
286
288
|
self.generate_bridge_data(),
|
|
287
289
|
self.generate_liveview_data(),
|
|
288
290
|
)
|
|
@@ -469,6 +471,21 @@ class SampleDataGenerator:
|
|
|
469
471
|
obj = await self.client.api_request_obj(f"chimes/{device_id}")
|
|
470
472
|
await self.write_json_file("sample_chime", obj)
|
|
471
473
|
|
|
474
|
+
async def generate_aiport_data(self) -> None:
|
|
475
|
+
objs = await self.client.api_request_list("aiports")
|
|
476
|
+
device_id: str | None = None
|
|
477
|
+
for obj_dict in objs:
|
|
478
|
+
device_id = obj_dict["id"]
|
|
479
|
+
if is_online(obj_dict):
|
|
480
|
+
break
|
|
481
|
+
|
|
482
|
+
if device_id is None:
|
|
483
|
+
self.log("No aiport found. Skipping aiport endpoints...")
|
|
484
|
+
return
|
|
485
|
+
|
|
486
|
+
obj = await self.client.api_request_obj(f"aiports/{device_id}")
|
|
487
|
+
await self.write_json_file("sample_aiport", obj)
|
|
488
|
+
|
|
472
489
|
async def generate_bridge_data(self) -> None:
|
|
473
490
|
objs = await self.client.api_request_list("bridges")
|
|
474
491
|
device_id: str | None = None
|
uiprotect/utils.py
CHANGED
|
@@ -572,7 +572,7 @@ def local_datetime(dt: datetime | None = None) -> datetime:
|
|
|
572
572
|
def log_event(event: Event) -> None:
|
|
573
573
|
from uiprotect.data import EventType
|
|
574
574
|
|
|
575
|
-
_LOGGER.debug("event WS msg: %s", event.
|
|
575
|
+
_LOGGER.debug("event WS msg: %s", event.model_dump())
|
|
576
576
|
if "smart" not in event.type.value:
|
|
577
577
|
return
|
|
578
578
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
uiprotect/__init__.py,sha256=Oz6i1tonIz4QWVnEPkbielJDJ3WQdwZVgYtjY4IwGAQ,636
|
|
2
2
|
uiprotect/__main__.py,sha256=C_bHCOkv5qj6WMy-6ELoY3Y6HDhLxOa1a30CzmbZhsg,462
|
|
3
3
|
uiprotect/_compat.py,sha256=HThmb1zQZCEssCxYYbQzFhJq8zYYlVaSnIEZabKc-6U,302
|
|
4
|
-
uiprotect/api.py,sha256=
|
|
5
|
-
uiprotect/cli/__init__.py,sha256=
|
|
4
|
+
uiprotect/api.py,sha256=EW_2s8FSxhwFykl4Vw_YhhjzC2AZVAZBDL-ha9yUBqg,69690
|
|
5
|
+
uiprotect/cli/__init__.py,sha256=gHo9G2WusvrWgnHhecT8Q2NLRXG0VS-rc9TKy4V5Kw8,8951
|
|
6
|
+
uiprotect/cli/aiports.py,sha256=wpEr2w_hY18CGpFiQM2Yc0FiVwG_1l2CzZhZLGNigvI,1576
|
|
6
7
|
uiprotect/cli/backup.py,sha256=ZiS7RZnJGKI8TJKLW2cOUzkRM8nyTvE5Ov_jZZGtvSM,36708
|
|
7
8
|
uiprotect/cli/base.py,sha256=GVHQMrI3thQ-4ixJlunTCfEMF90xCnt-bvRPMDupDss,7588
|
|
8
9
|
uiprotect/cli/cameras.py,sha256=YvvMccQEYG3Wih0Ix8tan1R1vfaJ6cogg6YKWLzMUV8,16973
|
|
@@ -14,25 +15,25 @@ uiprotect/cli/liveviews.py,sha256=GU5z-ZLRBXHyspDKiJpiv-kbaBcvxK_-K70rPoqx2Ms,18
|
|
|
14
15
|
uiprotect/cli/nvr.py,sha256=TwxEg2XT8jXAbOqv6gc7KFXELKadeItEDYweSL4_-e8,4260
|
|
15
16
|
uiprotect/cli/sensors.py,sha256=fQtcDJCVxs4VbAqcavgBy2ABiVxAW3GXtna6_XFBp2k,8153
|
|
16
17
|
uiprotect/cli/viewers.py,sha256=2cyrp104ffIvgT0wYGIO0G35QMkEbFe7fSVqLwDXQYQ,2171
|
|
17
|
-
uiprotect/data/__init__.py,sha256=
|
|
18
|
-
uiprotect/data/base.py,sha256=
|
|
19
|
-
uiprotect/data/bootstrap.py,sha256=
|
|
20
|
-
uiprotect/data/convert.py,sha256=
|
|
21
|
-
uiprotect/data/devices.py,sha256=
|
|
18
|
+
uiprotect/data/__init__.py,sha256=audwJBjxRiYdNPeYlP6iofFIOq3gyQzh6VpDsOCM2dQ,2964
|
|
19
|
+
uiprotect/data/base.py,sha256=LRqmK60PKeDFgP2k5qpVj93AxEvdfC6kLk0Cqvt1W5k,35481
|
|
20
|
+
uiprotect/data/bootstrap.py,sha256=2X5_ejlu1FnoL7RTeIJeR38yQQFMGzZlxN9l7l2fo8g,23294
|
|
21
|
+
uiprotect/data/convert.py,sha256=xEN878_hm0HZZCVYGwJSxcSp2as9zpkvsemVIibReOA,2628
|
|
22
|
+
uiprotect/data/devices.py,sha256=Ht9ANMG4TRxz6wYKYuWlTx8uGxGJJKMHa_PJRZ7g6HQ,113927
|
|
22
23
|
uiprotect/data/nvr.py,sha256=E18DgE0nXl9VZ_ULotTPcXSi3M1u3mWQsuZbY1gIajs,47490
|
|
23
|
-
uiprotect/data/types.py,sha256=
|
|
24
|
+
uiprotect/data/types.py,sha256=r09nuG3ZIsgld4Uo7fyBz_Nd6I4wNfyhfViX5ldp_LI,19138
|
|
24
25
|
uiprotect/data/user.py,sha256=Del5LUmt5uCfAQMI9-kl_GaKm085oTLjxmcCrlEKXxc,10526
|
|
25
26
|
uiprotect/data/websocket.py,sha256=m4EV1Qfh08eKOihy70ycViYgEQpeNSGZQJWdtGIYJDA,6791
|
|
26
27
|
uiprotect/exceptions.py,sha256=kgn0cRM6lTtgLza09SDa3ZiX6ue1QqHCOogQ4qu6KTQ,965
|
|
27
28
|
uiprotect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
29
|
uiprotect/release_cache.json,sha256=NamnSFy78hOWY0DPO87J9ELFCAN6NnVquv8gQO75ZG4,386
|
|
29
30
|
uiprotect/stream.py,sha256=MWiTRFIhUfFLPA_csSrKl5-SkUbPZ2VhDu0XW2oVr-U,4800
|
|
30
|
-
uiprotect/test_util/__init__.py,sha256=
|
|
31
|
+
uiprotect/test_util/__init__.py,sha256=HlQBgIgdtrvT-gQ5OWP92LbgVr_YzsD5NFImLRonUZk,19320
|
|
31
32
|
uiprotect/test_util/anonymize.py,sha256=f-8ijU-_y9r-uAbhIPn0f0I6hzJpAkvJzc8UpWihObI,8478
|
|
32
|
-
uiprotect/utils.py,sha256=
|
|
33
|
+
uiprotect/utils.py,sha256=q2YYQfxr0b3QEWMSP7SdpcJZbB4huEhpo8PbtnTbEFI,20481
|
|
33
34
|
uiprotect/websocket.py,sha256=tEyenqblNXHcjWYuf4oRP1E7buNwx6zoECMwpBr-jig,8191
|
|
34
|
-
uiprotect-7.0.
|
|
35
|
-
uiprotect-7.0.
|
|
36
|
-
uiprotect-7.0.
|
|
37
|
-
uiprotect-7.0.
|
|
38
|
-
uiprotect-7.0.
|
|
35
|
+
uiprotect-7.1.0.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
|
|
36
|
+
uiprotect-7.1.0.dist-info/METADATA,sha256=W8UXVUWhcruyMXTU9ajSMwJ_cuOj8_MLfHf-M1hRAGk,11142
|
|
37
|
+
uiprotect-7.1.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
38
|
+
uiprotect-7.1.0.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
|
|
39
|
+
uiprotect-7.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|