pyezvizapi 1.0.1.7__py3-none-any.whl → 1.0.1.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.
- pyezvizapi/__init__.py +11 -1
- pyezvizapi/__main__.py +406 -283
- pyezvizapi/camera.py +494 -118
- pyezvizapi/cas.py +36 -43
- pyezvizapi/client.py +785 -1345
- pyezvizapi/constants.py +6 -1
- pyezvizapi/exceptions.py +9 -9
- pyezvizapi/light_bulb.py +80 -31
- pyezvizapi/models.py +103 -0
- pyezvizapi/mqtt.py +42 -14
- pyezvizapi/test_cam_rtsp.py +95 -109
- pyezvizapi/test_mqtt.py +101 -30
- pyezvizapi/utils.py +0 -1
- {pyezvizapi-1.0.1.7.dist-info → pyezvizapi-1.0.1.9.dist-info}/METADATA +2 -2
- pyezvizapi-1.0.1.9.dist-info/RECORD +21 -0
- pyezvizapi-1.0.1.7.dist-info/RECORD +0 -20
- {pyezvizapi-1.0.1.7.dist-info → pyezvizapi-1.0.1.9.dist-info}/WHEEL +0 -0
- {pyezvizapi-1.0.1.7.dist-info → pyezvizapi-1.0.1.9.dist-info}/entry_points.txt +0 -0
- {pyezvizapi-1.0.1.7.dist-info → pyezvizapi-1.0.1.9.dist-info}/licenses/LICENSE +0 -0
- {pyezvizapi-1.0.1.7.dist-info → pyezvizapi-1.0.1.9.dist-info}/licenses/LICENSE.md +0 -0
- {pyezvizapi-1.0.1.7.dist-info → pyezvizapi-1.0.1.9.dist-info}/top_level.txt +0 -0
pyezvizapi/test_cam_rtsp.py
CHANGED
|
@@ -1,149 +1,135 @@
|
|
|
1
1
|
"""Test camera RTSP authentication."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
2
5
|
import base64
|
|
3
6
|
import hashlib
|
|
4
7
|
import socket
|
|
8
|
+
from typing import TypedDict
|
|
5
9
|
|
|
6
10
|
from .exceptions import AuthTestResultFailed, InvalidHost
|
|
7
11
|
|
|
8
12
|
|
|
9
|
-
def genmsg_describe(url, seq, user_agent, auth_seq):
|
|
10
|
-
"""Generate RTSP
|
|
11
|
-
msg_ret = "DESCRIBE
|
|
12
|
-
msg_ret += "CSeq:
|
|
13
|
-
msg_ret += "Authorization:
|
|
14
|
-
msg_ret += "User-Agent:
|
|
15
|
-
msg_ret += "Accept: application/sdp\r\n"
|
|
16
|
-
msg_ret += "\r\n"
|
|
13
|
+
def genmsg_describe(url: str, seq: int, user_agent: str, auth_seq: str) -> str:
|
|
14
|
+
"""Generate RTSP DESCRIBE request message."""
|
|
15
|
+
msg_ret = f"DESCRIBE {url} RTSP/1.0\r\n"
|
|
16
|
+
msg_ret += f"CSeq: {seq}\r\n"
|
|
17
|
+
msg_ret += f"Authorization: {auth_seq}\r\n"
|
|
18
|
+
msg_ret += f"User-Agent: {user_agent}\r\n"
|
|
19
|
+
msg_ret += "Accept: application/sdp\r\n\r\n"
|
|
17
20
|
return msg_ret
|
|
18
21
|
|
|
19
22
|
|
|
23
|
+
class RTSPDetails(TypedDict):
|
|
24
|
+
"""Typed structure for RTSP test parameters."""
|
|
25
|
+
bufLen: int
|
|
26
|
+
defaultServerIp: str
|
|
27
|
+
defaultServerPort: int
|
|
28
|
+
defaultTestUri: str
|
|
29
|
+
defaultUserAgent: str
|
|
30
|
+
defaultUsername: str | None
|
|
31
|
+
defaultPassword: str | None
|
|
32
|
+
|
|
33
|
+
|
|
20
34
|
class TestRTSPAuth:
|
|
21
|
-
"""Test RTSP credentials."""
|
|
35
|
+
"""Test RTSP credentials against an RTSP server."""
|
|
36
|
+
|
|
37
|
+
_rtsp_details: RTSPDetails
|
|
22
38
|
|
|
23
39
|
def __init__(
|
|
24
|
-
self,
|
|
25
|
-
ip_addr,
|
|
26
|
-
username=None,
|
|
27
|
-
password=None,
|
|
28
|
-
test_uri="",
|
|
40
|
+
self, ip_addr: str, username: str | None = None, password: str | None = None, test_uri: str = ""
|
|
29
41
|
) -> None:
|
|
30
42
|
"""Initialize RTSP credential test."""
|
|
31
|
-
self._rtsp_details =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def generate_auth_string(self, realm, method, uri, nonce):
|
|
42
|
-
"""Generate
|
|
43
|
-
map_return_info = {}
|
|
43
|
+
self._rtsp_details = RTSPDetails(
|
|
44
|
+
bufLen=1024,
|
|
45
|
+
defaultServerIp=ip_addr,
|
|
46
|
+
defaultServerPort=554,
|
|
47
|
+
defaultTestUri=test_uri,
|
|
48
|
+
defaultUserAgent="RTSP Client",
|
|
49
|
+
defaultUsername=username,
|
|
50
|
+
defaultPassword=password,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def generate_auth_string(self, realm: bytes, method: str, uri: str, nonce: bytes) -> str:
|
|
54
|
+
"""Generate the HTTP Digest Authorization header value."""
|
|
44
55
|
m_1 = hashlib.md5(
|
|
45
|
-
f"{self._rtsp_details['defaultUsername']}:"
|
|
46
|
-
f"{realm.decode()}:"
|
|
47
|
-
f"{self._rtsp_details['defaultPassword']}".encode()
|
|
56
|
+
f"{self._rtsp_details['defaultUsername']}:{realm.decode()}:{self._rtsp_details['defaultPassword']}".encode()
|
|
48
57
|
).hexdigest()
|
|
49
58
|
m_2 = hashlib.md5(f"{method}:{uri}".encode()).hexdigest()
|
|
50
|
-
response = hashlib.md5(f"{m_1}:{nonce}:{m_2}".encode()).hexdigest()
|
|
59
|
+
response = hashlib.md5(f"{m_1}:{nonce.decode()}:{m_2}".encode()).hexdigest()
|
|
51
60
|
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
return (
|
|
62
|
+
"Digest "
|
|
54
63
|
f"username=\"{self._rtsp_details['defaultUsername']}\", "
|
|
55
|
-
f
|
|
56
|
-
|
|
57
|
-
f
|
|
58
|
-
f
|
|
59
|
-
f
|
|
64
|
+
f"realm=\"{realm.decode()}\", "
|
|
65
|
+
'algorithm="MD5", '
|
|
66
|
+
f"nonce=\"{nonce.decode()}\", "
|
|
67
|
+
f"uri=\"{uri}\", "
|
|
68
|
+
f"response=\"{response}\""
|
|
60
69
|
)
|
|
61
|
-
return map_return_info
|
|
62
70
|
|
|
63
|
-
def main(self):
|
|
64
|
-
"""
|
|
65
|
-
session = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
71
|
+
def main(self) -> None:
|
|
72
|
+
"""Open RTSP socket, try Basic and then Digest auth for DESCRIBE."""
|
|
73
|
+
session: socket.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
66
74
|
|
|
67
75
|
try:
|
|
68
76
|
session.connect(
|
|
69
|
-
(
|
|
70
|
-
self._rtsp_details["defaultServerIp"],
|
|
71
|
-
self._rtsp_details["defaultServerPort"],
|
|
72
|
-
)
|
|
77
|
+
(self._rtsp_details["defaultServerIp"], self._rtsp_details["defaultServerPort"])
|
|
73
78
|
)
|
|
74
|
-
|
|
75
79
|
except TimeoutError as err:
|
|
76
80
|
raise AuthTestResultFailed("Invalid ip or camera hibernating") from err
|
|
77
|
-
|
|
78
81
|
except (socket.gaierror, ConnectionRefusedError) as err:
|
|
79
82
|
raise InvalidHost("Invalid IP or Hostname") from err
|
|
80
83
|
|
|
81
|
-
seq = 1
|
|
84
|
+
seq: int = 1
|
|
82
85
|
|
|
83
|
-
url =
|
|
84
|
-
"rtsp://"
|
|
85
|
-
+ self._rtsp_details["defaultServerIp"]
|
|
86
|
-
+ self._rtsp_details["defaultTestUri"]
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
auth_seq = base64.b64encode(
|
|
90
|
-
f"{self._rtsp_details['defaultUsername']}:"
|
|
91
|
-
f"{self._rtsp_details['defaultPassword']}".encode("ascii")
|
|
92
|
-
)
|
|
93
|
-
auth_seq = "Basic " + auth_seq.decode()
|
|
86
|
+
url: str = "rtsp://" + self._rtsp_details["defaultServerIp"] + self._rtsp_details["defaultTestUri"]
|
|
94
87
|
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
# Basic Authorization header
|
|
89
|
+
auth_b64: bytes = base64.b64encode(
|
|
90
|
+
f"{self._rtsp_details['defaultUsername']}:{self._rtsp_details['defaultPassword']}".encode("ascii")
|
|
97
91
|
)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
)
|
|
103
|
-
msg1 = session.recv(self._rtsp_details["bufLen"])
|
|
104
|
-
seq
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
print(
|
|
130
|
-
genmsg_describe(
|
|
131
|
-
url, seq, self._rtsp_details["defaultUserAgent"], auth_seq
|
|
132
|
-
)
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
session.send(
|
|
136
|
-
genmsg_describe(
|
|
137
|
-
url, seq, self._rtsp_details["defaultUserAgent"], auth_seq
|
|
138
|
-
).encode()
|
|
139
|
-
)
|
|
92
|
+
auth_seq: str = "Basic " + auth_b64.decode()
|
|
93
|
+
|
|
94
|
+
describe = genmsg_describe(url, seq, self._rtsp_details["defaultUserAgent"], auth_seq)
|
|
95
|
+
print(describe)
|
|
96
|
+
session.send(describe.encode())
|
|
97
|
+
msg1: bytes = session.recv(self._rtsp_details["bufLen"])
|
|
98
|
+
seq += 1
|
|
99
|
+
|
|
100
|
+
decoded = msg1.decode()
|
|
101
|
+
if "200 OK" in decoded:
|
|
102
|
+
print(f"Basic auth result: {decoded}")
|
|
103
|
+
print("Basic Auth test passed. Credentials Valid!")
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
if "Unauthorized" in decoded:
|
|
107
|
+
# Basic failed, do new DESCRIBE with digest authentication.
|
|
108
|
+
start = decoded.find("realm")
|
|
109
|
+
begin = decoded.find('"', start)
|
|
110
|
+
end = decoded.find('"', begin + 1)
|
|
111
|
+
realm: bytes = msg1[begin + 1 : end]
|
|
112
|
+
|
|
113
|
+
start = decoded.find("nonce")
|
|
114
|
+
begin = decoded.find('"', start)
|
|
115
|
+
end = decoded.find('"', begin + 1)
|
|
116
|
+
nonce: bytes = msg1[begin + 1 : end]
|
|
117
|
+
|
|
118
|
+
auth_seq = self.generate_auth_string(realm, "DESCRIBE", self._rtsp_details["defaultTestUri"], nonce)
|
|
119
|
+
|
|
120
|
+
describe = genmsg_describe(url, seq, self._rtsp_details["defaultUserAgent"], auth_seq)
|
|
121
|
+
print(describe)
|
|
122
|
+
session.send(describe.encode())
|
|
140
123
|
msg1 = session.recv(self._rtsp_details["bufLen"])
|
|
141
|
-
|
|
124
|
+
decoded = msg1.decode()
|
|
125
|
+
print(f"Digest auth result: {decoded}")
|
|
142
126
|
|
|
143
|
-
if
|
|
144
|
-
|
|
127
|
+
if "200 OK" in decoded:
|
|
128
|
+
print("Digest Auth test Passed. Credentials Valid!")
|
|
129
|
+
return
|
|
145
130
|
|
|
146
|
-
if
|
|
131
|
+
if "401 Unauthorized" in decoded:
|
|
147
132
|
raise AuthTestResultFailed("Credentials not valid!!")
|
|
148
133
|
|
|
149
|
-
|
|
134
|
+
print("Basic Auth test passed. Credentials Valid!")
|
|
135
|
+
# ruff: noqa: T201
|
pyezvizapi/test_mqtt.py
CHANGED
|
@@ -1,64 +1,135 @@
|
|
|
1
|
-
"""MQTT test module.
|
|
1
|
+
"""MQTT test module.
|
|
2
2
|
|
|
3
|
+
Run a simple MQTT listener using either a saved token file
|
|
4
|
+
(`--token-file ezviz_token.json`) or by prompting for username/password
|
|
5
|
+
with MFA similar to the main CLI.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
3
11
|
from getpass import getpass
|
|
4
12
|
import json
|
|
5
13
|
import logging
|
|
6
14
|
from pathlib import Path
|
|
15
|
+
import sys
|
|
7
16
|
import time
|
|
8
|
-
from typing import Any
|
|
17
|
+
from typing import Any, cast
|
|
9
18
|
|
|
10
|
-
from .client import EzvizClient
|
|
11
|
-
from .
|
|
19
|
+
from .client import EzvizClient
|
|
20
|
+
from .exceptions import EzvizAuthVerificationCode, PyEzvizError
|
|
12
21
|
|
|
13
|
-
logging.basicConfig(level=logging.INFO)
|
|
22
|
+
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
|
|
14
23
|
|
|
15
24
|
LOG_FILE = Path("mqtt_messages.jsonl") # JSON Lines format
|
|
16
25
|
|
|
17
26
|
|
|
18
27
|
def message_handler(msg: dict[str, Any]) -> None:
|
|
19
|
-
"""Handle new MQTT messages by printing and saving them to a file.
|
|
20
|
-
|
|
21
|
-
Args:
|
|
22
|
-
msg (Dict[str, Any]): The decoded MQTT message.
|
|
23
|
-
"""
|
|
28
|
+
"""Handle new MQTT messages by printing and saving them to a file."""
|
|
24
29
|
print("📩 New MQTT message:", msg)
|
|
25
|
-
|
|
26
|
-
# Append to JSONL file
|
|
27
30
|
with LOG_FILE.open("a", encoding="utf-8") as f:
|
|
28
31
|
f.write(json.dumps(msg, ensure_ascii=False) + "\n")
|
|
29
32
|
|
|
30
33
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
def _load_token_file(path: str | None) -> dict[str, Any] | None:
|
|
35
|
+
if not path:
|
|
36
|
+
return None
|
|
37
|
+
p = Path(path)
|
|
38
|
+
if not p.exists():
|
|
39
|
+
return None
|
|
40
|
+
try:
|
|
41
|
+
return cast(dict[str, Any], json.loads(p.read_text(encoding="utf-8")))
|
|
42
|
+
except (OSError, json.JSONDecodeError):
|
|
43
|
+
logging.getLogger(__name__).warning("Failed to read token file: %s", p)
|
|
44
|
+
return None
|
|
40
45
|
|
|
41
|
-
# Step 1: Log into Ezviz to get a token
|
|
42
|
-
client = EzvizClient(account=username, password=password)
|
|
43
|
-
client.login()
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
def _save_token_file(path: str | None, token: dict[str, Any]) -> None:
|
|
48
|
+
if not path:
|
|
49
|
+
return
|
|
50
|
+
p = Path(path)
|
|
51
|
+
try:
|
|
52
|
+
p.write_text(json.dumps(token, indent=2), encoding="utf-8")
|
|
53
|
+
logging.getLogger(__name__).info("Saved token to %s", p)
|
|
54
|
+
except OSError:
|
|
55
|
+
logging.getLogger(__name__).warning("Failed to save token file: %s", p)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def main(argv: list[str] | None = None) -> int:
|
|
59
|
+
"""Entry point for testing MQTT messages."""
|
|
60
|
+
parser = argparse.ArgumentParser(prog="test_mqtt")
|
|
61
|
+
parser.add_argument("-u", "--username", required=False, help="Ezviz username")
|
|
62
|
+
parser.add_argument("-p", "--password", required=False, help="Ezviz password")
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"-r",
|
|
65
|
+
"--region",
|
|
66
|
+
required=False,
|
|
67
|
+
default="apiieu.ezvizlife.com",
|
|
68
|
+
help="Ezviz API region",
|
|
69
|
+
)
|
|
70
|
+
parser.add_argument(
|
|
71
|
+
"--token-file",
|
|
72
|
+
type=str,
|
|
73
|
+
default="ezviz_token.json",
|
|
74
|
+
help="Path to JSON token file (default: ezviz_token.json)",
|
|
75
|
+
)
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
"--save-token",
|
|
78
|
+
action="store_true",
|
|
79
|
+
help="Save token to --token-file after successful login",
|
|
48
80
|
)
|
|
81
|
+
args = parser.parse_args(argv)
|
|
82
|
+
|
|
83
|
+
token = _load_token_file(args.token_file)
|
|
84
|
+
|
|
85
|
+
username = args.username
|
|
86
|
+
password = args.password
|
|
87
|
+
|
|
88
|
+
# If no token and missing username/password, prompt interactively
|
|
89
|
+
if not token and (not username or not password):
|
|
90
|
+
print("No token found. Please enter Ezviz credentials.")
|
|
91
|
+
if not username:
|
|
92
|
+
username = input("Username: ")
|
|
93
|
+
if not password:
|
|
94
|
+
password = getpass("Password: ")
|
|
95
|
+
|
|
96
|
+
client = EzvizClient(username, password, args.region, token=token)
|
|
97
|
+
|
|
98
|
+
# Login if we have credentials (to refresh session and populate service URLs)
|
|
99
|
+
if username and password:
|
|
100
|
+
try:
|
|
101
|
+
client.login()
|
|
102
|
+
except EzvizAuthVerificationCode:
|
|
103
|
+
mfa_code = input("MFA code required, please input MFA code.\n")
|
|
104
|
+
try:
|
|
105
|
+
code_int = int(mfa_code.strip())
|
|
106
|
+
except ValueError:
|
|
107
|
+
code_int = None
|
|
108
|
+
client.login(sms_code=code_int)
|
|
109
|
+
except PyEzvizError as exp:
|
|
110
|
+
print(f"Login failed: {exp}")
|
|
111
|
+
return 1
|
|
112
|
+
|
|
113
|
+
# Start MQTT client
|
|
114
|
+
mqtt_client = client.get_mqtt_client(on_message_callback=message_handler)
|
|
49
115
|
mqtt_client.connect()
|
|
50
116
|
|
|
51
117
|
try:
|
|
52
118
|
print("Listening for MQTT messages... (Ctrl+C to quit)")
|
|
53
119
|
while True:
|
|
54
|
-
time.sleep(1)
|
|
120
|
+
time.sleep(1)
|
|
55
121
|
except KeyboardInterrupt:
|
|
56
122
|
print("\nStopping...")
|
|
57
123
|
finally:
|
|
58
124
|
mqtt_client.stop()
|
|
59
125
|
print("Stopped.")
|
|
60
126
|
|
|
127
|
+
if args.save_token and args.token_file:
|
|
128
|
+
_save_token_file(args.token_file, cast(dict[str, Any], client._token)) # noqa: SLF001
|
|
129
|
+
|
|
130
|
+
return 0
|
|
61
131
|
|
|
62
|
-
if __name__ == "__main__":
|
|
63
|
-
main()
|
|
64
132
|
|
|
133
|
+
if __name__ == "__main__":
|
|
134
|
+
sys.exit(main())
|
|
135
|
+
# ruff: noqa: T201
|
pyezvizapi/utils.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyezvizapi
|
|
3
|
-
Version: 1.0.1.
|
|
3
|
+
Version: 1.0.1.9
|
|
4
4
|
Summary: Pilot your Ezviz cameras
|
|
5
5
|
Home-page: https://github.com/RenierM26/pyEzvizApi/
|
|
6
6
|
Author: Renier Moorcroft
|
|
7
7
|
Author-email: RenierM26@users.github.com
|
|
8
8
|
License: Apache Software License 2.0
|
|
9
|
-
Requires-Python: >=3.
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
License-File: LICENSE.md
|
|
12
12
|
Requires-Dist: requests
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
pyezvizapi/__init__.py,sha256=IDnIN_nfIISVwuy0cVBh4wspgAav6MuOJCQGajjyU3g,1881
|
|
2
|
+
pyezvizapi/__main__.py,sha256=SeV954H-AV-U1thNxRd7rWTGtSlfWyNzdrjF8gikYus,20777
|
|
3
|
+
pyezvizapi/api_endpoints.py,sha256=rk6VinLVCn-B6DxnhfV79liplNpgUsipNbTEa_MRVwU,2755
|
|
4
|
+
pyezvizapi/camera.py,sha256=Vpuh7RkUBfSmNCFAXaALzfvvL0RD3SzJJyWqwZzWuHk,25191
|
|
5
|
+
pyezvizapi/cas.py,sha256=ISmb-eTPuacI10L87lULbQ-oDMBuygO7Tf-s9f-tvYE,5995
|
|
6
|
+
pyezvizapi/client.py,sha256=dcHAsdtfSTkVCrkaEZKpFggDXX4t5debpuxc76sOy-k,71267
|
|
7
|
+
pyezvizapi/constants.py,sha256=R0zGg8Rv59An36dSXQLl3WU7VbpTbpo2comk9VJc68k,12535
|
|
8
|
+
pyezvizapi/exceptions.py,sha256=8rmxEUQdrziqMe-M1SeeRd0HtP2IDQ2xpJVj7wvOQyo,976
|
|
9
|
+
pyezvizapi/light_bulb.py,sha256=9wgycG3dTvBbrsxQjQnXal-GA8VXPsIN1m-CTtRh8i0,7797
|
|
10
|
+
pyezvizapi/models.py,sha256=NQzwTP0yEe2IWU-Vc6nAn87xulpTuo0MX2Rcf0WxifA,4176
|
|
11
|
+
pyezvizapi/mqtt.py,sha256=aOL-gexZgYvCCaNQ03M4vZan91d5p2Fl_qsFykn9NW4,22365
|
|
12
|
+
pyezvizapi/test_cam_rtsp.py,sha256=WGSM5EiOTl_r1mWHoMb7bXHm_BCn1P9X_669YQ38r6k,4903
|
|
13
|
+
pyezvizapi/test_mqtt.py,sha256=Orn-fwZPJIE4G5KROMX0MRAkLwU6nLb9LUtXyb2ZCQs,4147
|
|
14
|
+
pyezvizapi/utils.py,sha256=o342o3LI9eP8qla1vXM2rqlVbdTiLK0dAqrkyUSXpg8,5939
|
|
15
|
+
pyezvizapi-1.0.1.9.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
16
|
+
pyezvizapi-1.0.1.9.dist-info/licenses/LICENSE.md,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
17
|
+
pyezvizapi-1.0.1.9.dist-info/METADATA,sha256=kZWGIVtf7BcQ1WJRCFCDQZmh1NibUNQs_S6TONkU-CQ,695
|
|
18
|
+
pyezvizapi-1.0.1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
+
pyezvizapi-1.0.1.9.dist-info/entry_points.txt,sha256=_BSJ3eNb2H_AZkRdsv1s4mojqWn3N7m503ujvg1SudA,56
|
|
20
|
+
pyezvizapi-1.0.1.9.dist-info/top_level.txt,sha256=gMZTelIi8z7pXyTCQLLaIkxVRrDQ_lS2NEv0WgfHrHs,11
|
|
21
|
+
pyezvizapi-1.0.1.9.dist-info/RECORD,,
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
pyezvizapi/__init__.py,sha256=ByMIDi_hdJa7Sc7GoJmviTOBe4DILx2E4UzhEpEzQis,1422
|
|
2
|
-
pyezvizapi/__main__.py,sha256=OsawbYa-eoLUTOMr4xWeryq4sDzs09WL9GELKQTbda8,16396
|
|
3
|
-
pyezvizapi/api_endpoints.py,sha256=rk6VinLVCn-B6DxnhfV79liplNpgUsipNbTEa_MRVwU,2755
|
|
4
|
-
pyezvizapi/camera.py,sha256=BpmLySbnWWEKimSwgjx_cB60Q-6dbgdY-NA--NzUvps,11486
|
|
5
|
-
pyezvizapi/cas.py,sha256=d31ZflYSD9P40MnsNRNZbT0HVLvlnHokKpLbdAjWQ74,5631
|
|
6
|
-
pyezvizapi/client.py,sha256=uhtQ4bdM0zmnAPEt3cvxGtrqLFf0C15A5zIBE719pDE,86179
|
|
7
|
-
pyezvizapi/constants.py,sha256=ntH7gNNRHQ66Dek2Uhk9PD4wXT0h7QTDn929LFGSP9I,12333
|
|
8
|
-
pyezvizapi/exceptions.py,sha256=28lLyM0ILTRHgWqr9D-DqqKFXx7POuF0WAZctdC8Kbc,735
|
|
9
|
-
pyezvizapi/light_bulb.py,sha256=ADLrPZ6NL4vANzmohU63QuD9qVGkKHkX9C0o7Evbv-A,5730
|
|
10
|
-
pyezvizapi/mqtt.py,sha256=9i2dkVuNgf9KB2b-58HqHuKIzl-Ouuodg0dJ0DYpUOo,21649
|
|
11
|
-
pyezvizapi/test_cam_rtsp.py,sha256=w7GPcYIeK78TxL8zFDihdGSDQNWcYrurwZOr6uFzzgo,4902
|
|
12
|
-
pyezvizapi/test_mqtt.py,sha256=6thgcsfvl-wSR2Xrp8miG7PHfg9Q-a4AZ8VvOhEsBBQ,1651
|
|
13
|
-
pyezvizapi/utils.py,sha256=zjbvQiJ_Q-qwbB_FImXVjuaRct9cogBRKDxzFHbx4ek,5940
|
|
14
|
-
pyezvizapi-1.0.1.7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
15
|
-
pyezvizapi-1.0.1.7.dist-info/licenses/LICENSE.md,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
16
|
-
pyezvizapi-1.0.1.7.dist-info/METADATA,sha256=e4GDIcD5BMofWTvFXl6EIUpF-2vrRGp1n9VTMZCOKPs,694
|
|
17
|
-
pyezvizapi-1.0.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
18
|
-
pyezvizapi-1.0.1.7.dist-info/entry_points.txt,sha256=_BSJ3eNb2H_AZkRdsv1s4mojqWn3N7m503ujvg1SudA,56
|
|
19
|
-
pyezvizapi-1.0.1.7.dist-info/top_level.txt,sha256=gMZTelIi8z7pXyTCQLLaIkxVRrDQ_lS2NEv0WgfHrHs,11
|
|
20
|
-
pyezvizapi-1.0.1.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|