pyezvizapi 1.0.2.8__py3-none-any.whl → 1.0.2.9__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 pyezvizapi might be problematic. Click here for more details.

@@ -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"
pyezvizapi/client.py CHANGED
@@ -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
- if max_retries > MAX_RETRIES:
661
- raise PyEzvizError("Can't gather proper data. Max retries exceeded.")
662
- json_output = self._request_json(
663
- "PUT",
664
- f"{API_ENDPOINT_DEVICES}{serial}/{channel_no}/{enable}/{status_type}{API_ENDPOINT_SWITCH_STATUS}",
665
- retry_401=True,
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] = bool(enable)
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 set_device_config_by_key(
873
+ def set_dev_config_kv(
797
874
  self,
798
875
  serial: str,
799
- value: Any,
876
+ channel: int,
800
877
  key: str,
878
+ value: Mapping[str, Any] | str | bytes | float | bool,
801
879
  max_retries: int = 0,
802
- ) -> bool:
803
- """Change value on device by setting key."""
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
- params = {"key": key, "value": value}
808
- params_str = urllib.parse.urlencode(
809
- params, safe="}{:"
810
- ) # not encode curly braces and colon
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
- full_url = f"https://{self._token['api_url']}{API_ENDPOINT_DEVCONFIG_BY_KEY}{serial}/1/op"
897
+ data = {
898
+ "key": key,
899
+ "value": value_payload,
900
+ }
813
901
 
814
- # EZVIZ api request needs {}: in the url, but requests lib doesn't allow it
815
- # so we need to manually prepare it
816
- req_prep = requests.Request(
817
- method="PUT", url=full_url, headers=self._session.headers
818
- ).prepare()
819
- req_prep.url = full_url + "?" + params_str
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
- req = self._send_prepared(req_prep, retry_401=True, max_retries=max_retries)
822
- json_output = self._parse_json(req)
823
- if not self._meta_ok(json_output):
824
- raise PyEzvizError(f"Could not set config key '${key}': Got {json_output})")
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(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyezvizapi
3
- Version: 1.0.2.8
3
+ Version: 1.0.2.9
4
4
  Summary: Pilot your Ezviz cameras
5
5
  Home-page: https://github.com/RenierM26/pyEzvizApi/
6
6
  Author: Renier Moorcroft
@@ -1,9 +1,9 @@
1
1
  pyezvizapi/__init__.py,sha256=IDnIN_nfIISVwuy0cVBh4wspgAav6MuOJCQGajjyU3g,1881
2
2
  pyezvizapi/__main__.py,sha256=9uttTuOfO22tzyomJIV8ebFJ-G-YUNDYOadZ_0AgdNA,20925
3
- pyezvizapi/api_endpoints.py,sha256=Wn3FtwFChoi4wAymnVCbEtFg-8B01_gKCMc6zNa2mE8,2814
3
+ pyezvizapi/api_endpoints.py,sha256=yC-pSKJ6-JLeoSlF73EOR-i3JNxnf-UR41-Bwd8bkm4,2884
4
4
  pyezvizapi/camera.py,sha256=Pl5oIEdrFcv1Hz5sQI1IyyJIDCMjOjQdtExgKzmLoK8,22102
5
5
  pyezvizapi/cas.py,sha256=3zHe-_a0KchCmGeAj1of-pV6oMPRUmSCIiDqBFsTK8A,6025
6
- pyezvizapi/client.py,sha256=LHl00HcAO339KBYS1y4Focgr35mHYpgLiLEnNePv0_A,76202
6
+ pyezvizapi/client.py,sha256=Kc2r8KyXaOZII8GXnfy6Ae0FrV5IhAFv8eccry-SxVk,78800
7
7
  pyezvizapi/constants.py,sha256=wSX5nxjZU_8zjedjoPaEjPrF1ddFptox2g_isD_Ku74,12621
8
8
  pyezvizapi/exceptions.py,sha256=8rmxEUQdrziqMe-M1SeeRd0HtP2IDQ2xpJVj7wvOQyo,976
9
9
  pyezvizapi/light_bulb.py,sha256=9wgycG3dTvBbrsxQjQnXal-GA8VXPsIN1m-CTtRh8i0,7797
@@ -12,10 +12,10 @@ pyezvizapi/mqtt.py,sha256=aOL-gexZgYvCCaNQ03M4vZan91d5p2Fl_qsFykn9NW4,22365
12
12
  pyezvizapi/test_cam_rtsp.py,sha256=O9NHh-vcNFfnzNw8jbuhM9a_5TWfNZIMXaJP7Lmkaj4,5162
13
13
  pyezvizapi/test_mqtt.py,sha256=Orn-fwZPJIE4G5KROMX0MRAkLwU6nLb9LUtXyb2ZCQs,4147
14
14
  pyezvizapi/utils.py,sha256=G8gGjG0ecdN05Y0vxOHvcQMtQXgVB7nHzyvCzz66kLk,12148
15
- pyezvizapi-1.0.2.8.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
16
- pyezvizapi-1.0.2.8.dist-info/licenses/LICENSE.md,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
17
- pyezvizapi-1.0.2.8.dist-info/METADATA,sha256=8yaFfx3GUt93XZuBRmBOqB8jS6-skT_cz97iRWG5r_U,695
18
- pyezvizapi-1.0.2.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
- pyezvizapi-1.0.2.8.dist-info/entry_points.txt,sha256=_BSJ3eNb2H_AZkRdsv1s4mojqWn3N7m503ujvg1SudA,56
20
- pyezvizapi-1.0.2.8.dist-info/top_level.txt,sha256=gMZTelIi8z7pXyTCQLLaIkxVRrDQ_lS2NEv0WgfHrHs,11
21
- pyezvizapi-1.0.2.8.dist-info/RECORD,,
15
+ pyezvizapi-1.0.2.9.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
16
+ pyezvizapi-1.0.2.9.dist-info/licenses/LICENSE.md,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
17
+ pyezvizapi-1.0.2.9.dist-info/METADATA,sha256=Pu7OMl5ZW__CgfeoCeiPuhnSDktaHXINE9LdugtpN9U,695
18
+ pyezvizapi-1.0.2.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ pyezvizapi-1.0.2.9.dist-info/entry_points.txt,sha256=_BSJ3eNb2H_AZkRdsv1s4mojqWn3N7m503ujvg1SudA,56
20
+ pyezvizapi-1.0.2.9.dist-info/top_level.txt,sha256=gMZTelIi8z7pXyTCQLLaIkxVRrDQ_lS2NEv0WgfHrHs,11
21
+ pyezvizapi-1.0.2.9.dist-info/RECORD,,