pyezvizapi 1.0.2.8__tar.gz → 1.0.2.9__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 pyezvizapi might be problematic. Click here for more details.
- {pyezvizapi-1.0.2.8/pyezvizapi.egg-info → pyezvizapi-1.0.2.9}/PKG-INFO +1 -1
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/api_endpoints.py +1 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/client.py +132 -30
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9/pyezvizapi.egg-info}/PKG-INFO +1 -1
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/setup.py +1 -1
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/LICENSE +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/LICENSE.md +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/MANIFEST.in +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/README.md +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/__init__.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/__main__.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/camera.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/cas.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/constants.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/exceptions.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/light_bulb.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/models.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/mqtt.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/test_cam_rtsp.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/test_mqtt.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi/utils.py +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi.egg-info/SOURCES.txt +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi.egg-info/dependency_links.txt +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi.egg-info/entry_points.txt +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi.egg-info/requires.txt +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/pyezvizapi.egg-info/top_level.txt +0 -0
- {pyezvizapi-1.0.2.8 → pyezvizapi-1.0.2.9}/setup.cfg +0 -0
|
@@ -39,6 +39,7 @@ API_ENDPOINT_DETECTION_SENSIBILITY = "/api/device/configAlgorithm"
|
|
|
39
39
|
API_ENDPOINT_DETECTION_SENSIBILITY_GET = "/api/device/queryAlgorithmConfig"
|
|
40
40
|
API_ENDPOINT_SENSITIVITY = "/v3/devconfig/v1/sensitivity/"
|
|
41
41
|
API_ENDPOINT_SET_DEFENCE_SCHEDULE = "/api/device/defence/plan2"
|
|
42
|
+
API_ENDPOINT_DEVICE_SWITCH_STATUS_LEGACY = "/api/device/switchStatus"
|
|
42
43
|
API_ENDPOINT_CAM_ENCRYPTKEY = "/api/device/query/encryptkey"
|
|
43
44
|
API_ENDPOINT_OFFLINE_NOTIFY = "/api/device/notify/switch"
|
|
44
45
|
API_ENDPOINT_CANCEL_ALARM = "/api/device/cancelAlarm"
|
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from collections.abc import Callable
|
|
5
|
+
from collections.abc import Callable, Mapping
|
|
6
6
|
from datetime import datetime
|
|
7
7
|
import hashlib
|
|
8
8
|
import json
|
|
9
9
|
import logging
|
|
10
10
|
from typing import Any, ClassVar, TypedDict, cast
|
|
11
|
-
import urllib.parse
|
|
12
11
|
from uuid import uuid4
|
|
13
12
|
|
|
14
13
|
import requests
|
|
@@ -28,6 +27,7 @@ from .api_endpoints import (
|
|
|
28
27
|
API_ENDPOINT_DEVCONFIG_BY_KEY,
|
|
29
28
|
API_ENDPOINT_DEVICE_BASICS,
|
|
30
29
|
API_ENDPOINT_DEVICE_STORAGE_STATUS,
|
|
30
|
+
API_ENDPOINT_DEVICE_SWITCH_STATUS_LEGACY,
|
|
31
31
|
API_ENDPOINT_DEVICE_SYS_OPERATION,
|
|
32
32
|
API_ENDPOINT_DEVICES,
|
|
33
33
|
API_ENDPOINT_DO_NOT_DISTURB,
|
|
@@ -648,26 +648,103 @@ class EzvizClient:
|
|
|
648
648
|
self._ensure_ok(json_output, "Could not get unified message list")
|
|
649
649
|
return json_output
|
|
650
650
|
|
|
651
|
+
def set_switch_v3(
|
|
652
|
+
self,
|
|
653
|
+
serial: str,
|
|
654
|
+
switch_type: int,
|
|
655
|
+
enable: bool | int,
|
|
656
|
+
channel: int = 0,
|
|
657
|
+
max_retries: int = 0,
|
|
658
|
+
) -> dict:
|
|
659
|
+
"""Update a device switch via the v3 endpoint."""
|
|
660
|
+
|
|
661
|
+
if max_retries > MAX_RETRIES:
|
|
662
|
+
raise PyEzvizError("Can't gather proper data. Max retries exceeded.")
|
|
663
|
+
|
|
664
|
+
enable_flag = 1 if bool(enable) else 0
|
|
665
|
+
path = (
|
|
666
|
+
f"{API_ENDPOINT_DEVICES}{serial}/{channel}/{enable_flag}/"
|
|
667
|
+
f"{switch_type}{API_ENDPOINT_SWITCH_STATUS}"
|
|
668
|
+
)
|
|
669
|
+
payload = self._request_json(
|
|
670
|
+
"PUT",
|
|
671
|
+
path,
|
|
672
|
+
retry_401=True,
|
|
673
|
+
max_retries=max_retries,
|
|
674
|
+
)
|
|
675
|
+
self._ensure_ok(payload, "Could not set the switch")
|
|
676
|
+
return payload
|
|
677
|
+
|
|
678
|
+
def set_switch_legacy(
|
|
679
|
+
self,
|
|
680
|
+
serial: str,
|
|
681
|
+
switch_type: int,
|
|
682
|
+
enable: bool | int,
|
|
683
|
+
channel: int = 0,
|
|
684
|
+
max_retries: int = 0,
|
|
685
|
+
) -> dict:
|
|
686
|
+
"""Fallback legacy switch endpoint used by older firmware."""
|
|
687
|
+
|
|
688
|
+
if max_retries > MAX_RETRIES:
|
|
689
|
+
raise PyEzvizError("Can't gather proper data. Max retries exceeded.")
|
|
690
|
+
|
|
691
|
+
payload = self._request_json(
|
|
692
|
+
"POST",
|
|
693
|
+
API_ENDPOINT_DEVICE_SWITCH_STATUS_LEGACY,
|
|
694
|
+
data={
|
|
695
|
+
"serial": serial,
|
|
696
|
+
"enable": "1" if bool(enable) else "0",
|
|
697
|
+
"type": str(switch_type),
|
|
698
|
+
"channel": str(channel),
|
|
699
|
+
},
|
|
700
|
+
retry_401=True,
|
|
701
|
+
max_retries=max_retries,
|
|
702
|
+
)
|
|
703
|
+
self._ensure_ok(payload, "Could not set the switch (legacy)")
|
|
704
|
+
return payload
|
|
705
|
+
|
|
706
|
+
def set_switch(
|
|
707
|
+
self,
|
|
708
|
+
serial: str,
|
|
709
|
+
switch_type: int,
|
|
710
|
+
enable: bool | int,
|
|
711
|
+
channel: int = 0,
|
|
712
|
+
max_retries: int = 0,
|
|
713
|
+
) -> dict:
|
|
714
|
+
"""Try the v3 switch endpoint, falling back to the legacy API if needed."""
|
|
715
|
+
|
|
716
|
+
try:
|
|
717
|
+
return self.set_switch_v3(
|
|
718
|
+
serial, switch_type, enable, channel, max_retries=max_retries
|
|
719
|
+
)
|
|
720
|
+
except PyEzvizError as first_error:
|
|
721
|
+
try:
|
|
722
|
+
return self.set_switch_legacy(
|
|
723
|
+
serial, switch_type, enable, channel, max_retries=max_retries
|
|
724
|
+
)
|
|
725
|
+
except PyEzvizError:
|
|
726
|
+
raise first_error from None
|
|
727
|
+
|
|
651
728
|
def switch_status(
|
|
652
729
|
self,
|
|
653
730
|
serial: str,
|
|
654
731
|
status_type: int,
|
|
655
|
-
enable: int,
|
|
732
|
+
enable: bool | int,
|
|
656
733
|
channel_no: int = 0,
|
|
657
734
|
max_retries: int = 0,
|
|
658
735
|
) -> bool:
|
|
659
736
|
"""Camera features are represented as switches. Switch them on or off."""
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
737
|
+
|
|
738
|
+
target_state = bool(enable)
|
|
739
|
+
self.set_switch(
|
|
740
|
+
serial,
|
|
741
|
+
status_type,
|
|
742
|
+
target_state,
|
|
743
|
+
channel=channel_no,
|
|
666
744
|
max_retries=max_retries,
|
|
667
745
|
)
|
|
668
|
-
self._ensure_ok(json_output, "Could not set the switch")
|
|
669
746
|
if self._cameras.get(serial):
|
|
670
|
-
self._cameras[serial]["switches"][status_type] =
|
|
747
|
+
self._cameras[serial]["switches"][status_type] = target_state
|
|
671
748
|
return True
|
|
672
749
|
|
|
673
750
|
def switch_status_other(
|
|
@@ -793,36 +870,61 @@ class EzvizClient:
|
|
|
793
870
|
serial, value=f'{{"mode":{mode}}}', key="display_mode"
|
|
794
871
|
)
|
|
795
872
|
|
|
796
|
-
def
|
|
873
|
+
def set_dev_config_kv(
|
|
797
874
|
self,
|
|
798
875
|
serial: str,
|
|
799
|
-
|
|
876
|
+
channel: int,
|
|
800
877
|
key: str,
|
|
878
|
+
value: Mapping[str, Any] | str | bytes | float | bool,
|
|
801
879
|
max_retries: int = 0,
|
|
802
|
-
) ->
|
|
803
|
-
"""
|
|
880
|
+
) -> dict:
|
|
881
|
+
"""Update a device configuration key/value pair via devconfig."""
|
|
882
|
+
|
|
804
883
|
if max_retries > MAX_RETRIES:
|
|
805
884
|
raise PyEzvizError("Can't gather proper data. Max retries exceeded.")
|
|
806
885
|
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
886
|
+
if isinstance(value, Mapping):
|
|
887
|
+
value_payload = json.dumps(value, separators=(",", ":"))
|
|
888
|
+
elif isinstance(value, bytes):
|
|
889
|
+
value_payload = value.decode()
|
|
890
|
+
elif isinstance(value, bool):
|
|
891
|
+
value_payload = "1" if value else "0"
|
|
892
|
+
elif isinstance(value, (int, float)):
|
|
893
|
+
value_payload = str(value)
|
|
894
|
+
else:
|
|
895
|
+
value_payload = str(value)
|
|
811
896
|
|
|
812
|
-
|
|
897
|
+
data = {
|
|
898
|
+
"key": key,
|
|
899
|
+
"value": value_payload,
|
|
900
|
+
}
|
|
813
901
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
902
|
+
payload = self._request_json(
|
|
903
|
+
"PUT",
|
|
904
|
+
f"{API_ENDPOINT_DEVCONFIG_BY_KEY}{serial}/{channel}/op",
|
|
905
|
+
data=data,
|
|
906
|
+
retry_401=True,
|
|
907
|
+
max_retries=max_retries,
|
|
908
|
+
)
|
|
909
|
+
self._ensure_ok(payload, "Could not set devconfig key")
|
|
910
|
+
return payload
|
|
820
911
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
912
|
+
def set_device_config_by_key(
|
|
913
|
+
self,
|
|
914
|
+
serial: str,
|
|
915
|
+
value: Any,
|
|
916
|
+
key: str,
|
|
917
|
+
max_retries: int = 0,
|
|
918
|
+
) -> bool:
|
|
919
|
+
"""Change value on device by setting key."""
|
|
825
920
|
|
|
921
|
+
self.set_dev_config_kv(
|
|
922
|
+
serial,
|
|
923
|
+
1,
|
|
924
|
+
key,
|
|
925
|
+
value,
|
|
926
|
+
max_retries=max_retries,
|
|
927
|
+
)
|
|
826
928
|
return True
|
|
827
929
|
|
|
828
930
|
def set_device_feature_by_key(
|
|
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
|