uiprotect 3.5.0__tar.gz → 3.6.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-3.5.0 → uiprotect-3.6.0}/PKG-INFO +1 -1
- {uiprotect-3.5.0 → uiprotect-3.6.0}/pyproject.toml +1 -1
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/data/devices.py +53 -65
- {uiprotect-3.5.0 → uiprotect-3.6.0}/LICENSE +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/README.md +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/__init__.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/__main__.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/api.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/__init__.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/backup.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/base.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/cameras.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/chimes.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/doorlocks.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/events.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/lights.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/liveviews.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/nvr.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/sensors.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/cli/viewers.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/data/__init__.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/data/base.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/data/bootstrap.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/data/convert.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/data/nvr.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/data/types.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/data/user.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/data/websocket.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/exceptions.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/py.typed +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/release_cache.json +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/stream.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/test_util/__init__.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/test_util/anonymize.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/utils.py +0 -0
- {uiprotect-3.5.0 → uiprotect-3.6.0}/src/uiprotect/websocket.py +0 -0
|
@@ -1107,18 +1107,16 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1107
1107
|
|
|
1108
1108
|
@property
|
|
1109
1109
|
def last_ring_event(self) -> Event | None:
|
|
1110
|
-
if self.last_ring_event_id is None:
|
|
1110
|
+
if (last_ring_event_id := self.last_ring_event_id) is None:
|
|
1111
1111
|
return None
|
|
1112
|
-
|
|
1113
|
-
return self._api.bootstrap.events.get(self.last_ring_event_id)
|
|
1112
|
+
return self._api.bootstrap.events.get(last_ring_event_id)
|
|
1114
1113
|
|
|
1115
1114
|
@property
|
|
1116
1115
|
def last_smart_detect_event(self) -> Event | None:
|
|
1117
1116
|
"""Get the last smart detect event id."""
|
|
1118
|
-
if self.last_smart_detect_event_id is None:
|
|
1117
|
+
if (last_smart_detect_event_id := self.last_smart_detect_event_id) is None:
|
|
1119
1118
|
return None
|
|
1120
|
-
|
|
1121
|
-
return self._api.bootstrap.events.get(self.last_smart_detect_event_id)
|
|
1119
|
+
return self._api.bootstrap.events.get(last_smart_detect_event_id)
|
|
1122
1120
|
|
|
1123
1121
|
@property
|
|
1124
1122
|
def hdr_mode_display(self) -> Literal["auto", "off", "always"]:
|
|
@@ -1151,20 +1149,19 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1151
1149
|
@property
|
|
1152
1150
|
def last_smart_audio_detect_event(self) -> Event | None:
|
|
1153
1151
|
"""Get the last smart audio detect event id."""
|
|
1154
|
-
if
|
|
1152
|
+
if (
|
|
1153
|
+
last_smart_audio_detect_event_id := self.last_smart_audio_detect_event_id
|
|
1154
|
+
) is None:
|
|
1155
1155
|
return None
|
|
1156
|
-
|
|
1157
|
-
return self._api.bootstrap.events.get(self.last_smart_audio_detect_event_id)
|
|
1156
|
+
return self._api.bootstrap.events.get(last_smart_audio_detect_event_id)
|
|
1158
1157
|
|
|
1159
1158
|
def get_last_smart_audio_detect_event(
|
|
1160
1159
|
self,
|
|
1161
1160
|
smart_type: SmartDetectAudioType,
|
|
1162
1161
|
) -> Event | None:
|
|
1163
1162
|
"""Get the last smart audio detect event for given type."""
|
|
1164
|
-
event_id
|
|
1165
|
-
if event_id is None:
|
|
1163
|
+
if (event_id := self.last_smart_audio_detect_event_ids.get(smart_type)) is None:
|
|
1166
1164
|
return None
|
|
1167
|
-
|
|
1168
1165
|
return self._api.bootstrap.events.get(event_id)
|
|
1169
1166
|
|
|
1170
1167
|
@property
|
|
@@ -1186,7 +1183,6 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1186
1183
|
"""
|
|
1187
1184
|
if self.use_global:
|
|
1188
1185
|
return self._api.bootstrap.nvr.is_global_recording_enabled
|
|
1189
|
-
|
|
1190
1186
|
return self.recording_settings.mode is not RecordingMode.NEVER
|
|
1191
1187
|
|
|
1192
1188
|
@property
|
|
@@ -1218,7 +1214,6 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1218
1214
|
"""Get active recording settings."""
|
|
1219
1215
|
if self.use_global and self._api.bootstrap.nvr.global_camera_settings:
|
|
1220
1216
|
return self._api.bootstrap.nvr.global_camera_settings.recording_settings
|
|
1221
|
-
|
|
1222
1217
|
return self.recording_settings
|
|
1223
1218
|
|
|
1224
1219
|
@property
|
|
@@ -1226,7 +1221,6 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1226
1221
|
"""Get active smart detection settings."""
|
|
1227
1222
|
if self.use_global and self._api.bootstrap.nvr.global_camera_settings:
|
|
1228
1223
|
return self._api.bootstrap.nvr.global_camera_settings.smart_detect_settings
|
|
1229
|
-
|
|
1230
1224
|
return self.smart_detect_settings
|
|
1231
1225
|
|
|
1232
1226
|
@property
|
|
@@ -1234,9 +1228,8 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1234
1228
|
"""Get active smart detection types."""
|
|
1235
1229
|
if self.use_global:
|
|
1236
1230
|
return set(self.smart_detect_settings.object_types).intersection(
|
|
1237
|
-
|
|
1231
|
+
self.feature_flags.smart_detect_types,
|
|
1238
1232
|
)
|
|
1239
|
-
|
|
1240
1233
|
return set(self.smart_detect_settings.object_types)
|
|
1241
1234
|
|
|
1242
1235
|
@property
|
|
@@ -1244,7 +1237,7 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1244
1237
|
"""Get active audio detection types."""
|
|
1245
1238
|
if self.use_global:
|
|
1246
1239
|
return set(self.smart_detect_settings.audio_types or []).intersection(
|
|
1247
|
-
|
|
1240
|
+
self.feature_flags.smart_detect_audio_types or [],
|
|
1248
1241
|
)
|
|
1249
1242
|
|
|
1250
1243
|
return set(self.smart_detect_settings.audio_types or [])
|
|
@@ -1504,8 +1497,11 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1504
1497
|
audio_type = smart_type.audio_type
|
|
1505
1498
|
return (
|
|
1506
1499
|
audio_type is not None
|
|
1507
|
-
and
|
|
1508
|
-
|
|
1500
|
+
and (
|
|
1501
|
+
smart_detect_audio_types := self.feature_flags.smart_detect_audio_types
|
|
1502
|
+
)
|
|
1503
|
+
is not None
|
|
1504
|
+
and audio_type in smart_detect_audio_types
|
|
1509
1505
|
)
|
|
1510
1506
|
|
|
1511
1507
|
def _is_audio_enabled(self, smart_type: SmartDetectObjectType) -> bool:
|
|
@@ -1535,8 +1531,9 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1535
1531
|
return (
|
|
1536
1532
|
self.is_recording_enabled
|
|
1537
1533
|
and bool(self.active_audio_detect_types)
|
|
1538
|
-
and self.last_smart_audio_detect_event
|
|
1539
|
-
|
|
1534
|
+
and (last_smart_audio_detect_event := self.last_smart_audio_detect_event)
|
|
1535
|
+
is not None
|
|
1536
|
+
and last_smart_audio_detect_event.end is None
|
|
1540
1537
|
)
|
|
1541
1538
|
|
|
1542
1539
|
# region Smoke Alarm
|
|
@@ -1903,28 +1900,25 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1903
1900
|
|
|
1904
1901
|
@property
|
|
1905
1902
|
def is_high_fps_enabled(self) -> bool:
|
|
1906
|
-
return self.video_mode
|
|
1903
|
+
return self.video_mode is VideoMode.HIGH_FPS
|
|
1907
1904
|
|
|
1908
1905
|
@property
|
|
1909
1906
|
def is_video_ready(self) -> bool:
|
|
1910
1907
|
return (
|
|
1911
|
-
self.feature_flags.lens_type
|
|
1912
|
-
|
|
1913
|
-
)
|
|
1908
|
+
lens_type := self.feature_flags.lens_type
|
|
1909
|
+
) is None or lens_type is not LensType.NONE
|
|
1914
1910
|
|
|
1915
1911
|
@property
|
|
1916
1912
|
def has_removable_lens(self) -> bool:
|
|
1917
1913
|
return (
|
|
1918
|
-
self.feature_flags.hotplug
|
|
1919
|
-
|
|
1920
|
-
)
|
|
1914
|
+
hotplug := self.feature_flags.hotplug
|
|
1915
|
+
) is not None and hotplug.video is not None
|
|
1921
1916
|
|
|
1922
1917
|
@property
|
|
1923
1918
|
def has_removable_speaker(self) -> bool:
|
|
1924
1919
|
return (
|
|
1925
|
-
self.feature_flags.hotplug
|
|
1926
|
-
|
|
1927
|
-
)
|
|
1920
|
+
hotplug := self.feature_flags.hotplug
|
|
1921
|
+
) is not None and hotplug.audio is not None
|
|
1928
1922
|
|
|
1929
1923
|
@property
|
|
1930
1924
|
def has_mic(self) -> bool:
|
|
@@ -1933,11 +1927,11 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1933
1927
|
@property
|
|
1934
1928
|
def has_color_night_vision(self) -> bool:
|
|
1935
1929
|
if (
|
|
1936
|
-
self.feature_flags.hotplug is not None
|
|
1937
|
-
and
|
|
1938
|
-
and
|
|
1930
|
+
(hotplug := self.feature_flags.hotplug) is not None
|
|
1931
|
+
and (extender := hotplug.extender) is not None
|
|
1932
|
+
and (is_attached := extender.is_attached) is not None
|
|
1939
1933
|
):
|
|
1940
|
-
return
|
|
1934
|
+
return is_attached
|
|
1941
1935
|
|
|
1942
1936
|
return False
|
|
1943
1937
|
|
|
@@ -1955,14 +1949,14 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
1955
1949
|
index, _ = self.get_privacy_zone()
|
|
1956
1950
|
if index is None:
|
|
1957
1951
|
zone_id = 0
|
|
1958
|
-
|
|
1959
|
-
|
|
1952
|
+
privacy_zones = self.privacy_zones
|
|
1953
|
+
if len(privacy_zones) > 0:
|
|
1954
|
+
zone_id = privacy_zones[-1].id + 1
|
|
1960
1955
|
|
|
1961
|
-
|
|
1956
|
+
privacy_zones.append(CameraZone.create_privacy_zone(zone_id))
|
|
1962
1957
|
|
|
1963
1958
|
def remove_privacy_zone(self) -> None:
|
|
1964
1959
|
index, _ = self.get_privacy_zone()
|
|
1965
|
-
|
|
1966
1960
|
if index is not None:
|
|
1967
1961
|
self.privacy_zones.pop(index)
|
|
1968
1962
|
|
|
@@ -2521,22 +2515,18 @@ class Camera(ProtectMotionDeviceModel):
|
|
|
2521
2515
|
|
|
2522
2516
|
async def stop_audio(self) -> None:
|
|
2523
2517
|
"""Stop currently playing audio."""
|
|
2524
|
-
stream
|
|
2525
|
-
if stream is None:
|
|
2518
|
+
if (stream := self.talkback_stream) is None:
|
|
2526
2519
|
raise StreamError("No audio playing to stop")
|
|
2527
|
-
|
|
2528
2520
|
await stream.stop()
|
|
2529
2521
|
|
|
2530
2522
|
def can_read_media(self, user: User) -> bool:
|
|
2531
2523
|
if self.model is None:
|
|
2532
2524
|
return True
|
|
2533
|
-
|
|
2534
2525
|
return user.can(self.model, PermissionNode.READ_MEDIA, self)
|
|
2535
2526
|
|
|
2536
2527
|
def can_delete_media(self, user: User) -> bool:
|
|
2537
2528
|
if self.model is None:
|
|
2538
2529
|
return True
|
|
2539
|
-
|
|
2540
2530
|
return user.can(self.model, PermissionNode.DELETE_MEDIA, self)
|
|
2541
2531
|
|
|
2542
2532
|
# region PTZ
|
|
@@ -2818,10 +2808,9 @@ class Sensor(ProtectAdoptableDeviceModel):
|
|
|
2818
2808
|
@property
|
|
2819
2809
|
def camera(self) -> Camera | None:
|
|
2820
2810
|
"""Paired Camera will always be none if no camera is paired"""
|
|
2821
|
-
if self.camera_id is None:
|
|
2811
|
+
if (camera_id := self.camera_id) is None:
|
|
2822
2812
|
return None
|
|
2823
|
-
|
|
2824
|
-
return self._api.bootstrap.cameras[self.camera_id]
|
|
2813
|
+
return self._api.bootstrap.cameras[camera_id]
|
|
2825
2814
|
|
|
2826
2815
|
@property
|
|
2827
2816
|
def is_tampering_detected(self) -> bool:
|
|
@@ -2839,25 +2828,28 @@ class Sensor(ProtectAdoptableDeviceModel):
|
|
|
2839
2828
|
|
|
2840
2829
|
@property
|
|
2841
2830
|
def is_motion_sensor_enabled(self) -> bool:
|
|
2842
|
-
return self.mount_type
|
|
2831
|
+
return self.mount_type is not MountType.LEAK and self.motion_settings.is_enabled
|
|
2843
2832
|
|
|
2844
2833
|
@property
|
|
2845
2834
|
def is_alarm_sensor_enabled(self) -> bool:
|
|
2846
|
-
return self.mount_type
|
|
2835
|
+
return self.mount_type is not MountType.LEAK and self.alarm_settings.is_enabled
|
|
2847
2836
|
|
|
2848
2837
|
@property
|
|
2849
2838
|
def is_light_sensor_enabled(self) -> bool:
|
|
2850
|
-
return self.mount_type
|
|
2839
|
+
return self.mount_type is not MountType.LEAK and self.light_settings.is_enabled
|
|
2851
2840
|
|
|
2852
2841
|
@property
|
|
2853
2842
|
def is_temperature_sensor_enabled(self) -> bool:
|
|
2854
2843
|
return (
|
|
2855
|
-
self.mount_type
|
|
2844
|
+
self.mount_type is not MountType.LEAK
|
|
2845
|
+
and self.temperature_settings.is_enabled
|
|
2856
2846
|
)
|
|
2857
2847
|
|
|
2858
2848
|
@property
|
|
2859
2849
|
def is_humidity_sensor_enabled(self) -> bool:
|
|
2860
|
-
return
|
|
2850
|
+
return (
|
|
2851
|
+
self.mount_type is not MountType.LEAK and self.humidity_settings.is_enabled
|
|
2852
|
+
)
|
|
2861
2853
|
|
|
2862
2854
|
@property
|
|
2863
2855
|
def is_leak_sensor_enabled(self) -> bool:
|
|
@@ -2869,31 +2861,27 @@ class Sensor(ProtectAdoptableDeviceModel):
|
|
|
2869
2861
|
|
|
2870
2862
|
@property
|
|
2871
2863
|
def last_motion_event(self) -> Event | None:
|
|
2872
|
-
if self.last_motion_event_id is None:
|
|
2864
|
+
if (last_motion_event_id := self.last_motion_event_id) is None:
|
|
2873
2865
|
return None
|
|
2874
|
-
|
|
2875
|
-
return self._api.bootstrap.events.get(self.last_motion_event_id)
|
|
2866
|
+
return self._api.bootstrap.events.get(last_motion_event_id)
|
|
2876
2867
|
|
|
2877
2868
|
@property
|
|
2878
2869
|
def last_contact_event(self) -> Event | None:
|
|
2879
|
-
if self.last_contact_event_id is None:
|
|
2870
|
+
if (last_contact_event_id := self.last_contact_event_id) is None:
|
|
2880
2871
|
return None
|
|
2881
|
-
|
|
2882
|
-
return self._api.bootstrap.events.get(self.last_contact_event_id)
|
|
2872
|
+
return self._api.bootstrap.events.get(last_contact_event_id)
|
|
2883
2873
|
|
|
2884
2874
|
@property
|
|
2885
2875
|
def last_value_event(self) -> Event | None:
|
|
2886
|
-
if self.last_value_event_id is None:
|
|
2876
|
+
if (last_value_event_id := self.last_value_event_id) is None:
|
|
2887
2877
|
return None
|
|
2888
|
-
|
|
2889
|
-
return self._api.bootstrap.events.get(self.last_value_event_id)
|
|
2878
|
+
return self._api.bootstrap.events.get(last_value_event_id)
|
|
2890
2879
|
|
|
2891
2880
|
@property
|
|
2892
2881
|
def last_alarm_event(self) -> Event | None:
|
|
2893
|
-
if self.last_alarm_event_id is None:
|
|
2882
|
+
if (last_alarm_event_id := self.last_alarm_event_id) is None:
|
|
2894
2883
|
return None
|
|
2895
|
-
|
|
2896
|
-
return self._api.bootstrap.events.get(self.last_alarm_event_id)
|
|
2884
|
+
return self._api.bootstrap.events.get(last_alarm_event_id)
|
|
2897
2885
|
|
|
2898
2886
|
@property
|
|
2899
2887
|
def is_leak_detected(self) -> bool:
|
|
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
|
|
File without changes
|