pyimouapi 1.0.2__tar.gz → 1.0.4__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.
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/PKG-INFO +5 -7
- pyimouapi-1.0.4/README.md +5 -0
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/pyimouapi/const.py +62 -0
- pyimouapi-1.0.4/pyimouapi/ha_device.py +313 -0
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/pyimouapi.egg-info/PKG-INFO +5 -7
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/pyimouapi.egg-info/SOURCES.txt +1 -1
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/setup.py +1 -5
- pyimouapi-1.0.2/README.md +0 -5
- pyimouapi-1.0.2/pyimouapi.egg-info/requires.txt +0 -2
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/LICENSE +0 -0
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/pyimouapi/__init__.py +0 -0
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/pyimouapi/device.py +0 -0
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/pyimouapi/exceptions.py +0 -0
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/pyimouapi/openapi.py +0 -0
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/pyimouapi.egg-info/dependency_links.txt +0 -0
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/pyimouapi.egg-info/top_level.txt +0 -0
- {pyimouapi-1.0.2 → pyimouapi-1.0.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyimouapi
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: A package for imou open api
|
|
5
5
|
Home-page: https://github.com/Imou-OpenPlatform/Py-Imou-Open-Api
|
|
6
6
|
Author: Imou-OpenPlatform
|
|
@@ -12,11 +12,9 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Topic :: Software Development :: Libraries
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: aiohttp==3.11.0
|
|
16
|
-
Requires-Dist: async-timeout==5.0.1
|
|
17
|
-
|
|
18
|
-
# Py-Imou-Open-Api
|
|
19
|
-
|
|
20
|
-
imou open platform api SDK for python
|
|
21
15
|
|
|
16
|
+
## 打包
|
|
17
|
+
python setup.py sdist bdist_wheel
|
|
22
18
|
|
|
19
|
+
## 上传
|
|
20
|
+
twine upload dist/*
|
|
@@ -67,3 +67,65 @@ PARAM_STREAM_ID = "streamId"
|
|
|
67
67
|
PARAM_OPERATION = "operation"
|
|
68
68
|
PARAM_DURATION = "duration"
|
|
69
69
|
PARAM_PROPERTIES = "properties"
|
|
70
|
+
PARAM_API_URL = "api_url"
|
|
71
|
+
PARAM_MOTION_DETECT = "motion_detect"
|
|
72
|
+
PARAM_MOBILE_DETECT = "mobile_detect"
|
|
73
|
+
PARAM_STATUS = "status"
|
|
74
|
+
PARAM_STORAGE_USED = "storage_used"
|
|
75
|
+
PARAM_NIGHT_VISION_MODE = "night_vision_mode"
|
|
76
|
+
PARAM_CURRENT_OPTION = "current_option"
|
|
77
|
+
PARAM_MODES = "modes"
|
|
78
|
+
PARAM_OPTIONS = "options"
|
|
79
|
+
PARAM_CHANNELS = "channels"
|
|
80
|
+
PARAM_USED_BYTES = "usedBytes"
|
|
81
|
+
PARAM_TOTAL_BYTES = "totalBytes"
|
|
82
|
+
PARAM_STREAMS = "streams"
|
|
83
|
+
PARAM_HLS = "hls"
|
|
84
|
+
PARAM_RESTART_DEVICE = "restart_device"
|
|
85
|
+
PARAM_URL = "url"
|
|
86
|
+
PARAM_CLOSE_CAMERA = "close_camera"
|
|
87
|
+
PARAM_WHITE_LIGHT = "white_light"
|
|
88
|
+
PARAM_AB_ALARM_SOUND = "ab_alarm_sound"
|
|
89
|
+
PARAM_AUDIO_ENCODE_CONTROL = "audio_encode_control"
|
|
90
|
+
|
|
91
|
+
# Configuration definitions
|
|
92
|
+
CONF_API_URL_SG = "openapi-sg.easy4ip.com"
|
|
93
|
+
CONF_API_URL_OR = "openapi-or.easy4ip.com"
|
|
94
|
+
CONF_API_URL_FK = "openapi-fk.easy4ip.com"
|
|
95
|
+
CONF_CLOSE_CAMERA = "CloseCamera"
|
|
96
|
+
CONF_WHITE_LIGHT = "WhiteLight"
|
|
97
|
+
CONF_AB_ALARM_SOUND = "AbAlarmSound"
|
|
98
|
+
CONF_AUDIO_ENCODE_CONTROL = "AudioEncodeControl"
|
|
99
|
+
CONF_NVM = "NVM"
|
|
100
|
+
CONF_PT = "PT"
|
|
101
|
+
|
|
102
|
+
PLATFORMS = [
|
|
103
|
+
"select",
|
|
104
|
+
"sensor",
|
|
105
|
+
"switch",
|
|
106
|
+
"camera",
|
|
107
|
+
"button"
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
SWITCH_TYPE_ABILITY = {
|
|
111
|
+
"close_camera": "CloseCamera",
|
|
112
|
+
"white_light": "WhiteLight",
|
|
113
|
+
"audio_encode_control": "AudioEncodeControl",
|
|
114
|
+
"ab_alarm_sound": "AbAlarmSound"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
SWITCH_TYPE_ENABLE = {
|
|
118
|
+
"motion_detect": ["motionDetect", "mobileDetect"],
|
|
119
|
+
"close_camera": ["closeCamera"],
|
|
120
|
+
"white_light": ["whiteLight"],
|
|
121
|
+
"audio_encode_control": ["audioEncodeControl"],
|
|
122
|
+
"ab_alarm_sound": ["abAlarmSound"]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
BUTTON_TYPE_PARAM_VALUE = {
|
|
126
|
+
"ptz_up": 0,
|
|
127
|
+
"ptz_down": 1,
|
|
128
|
+
"ptz_left": 2,
|
|
129
|
+
"ptz_right": 3
|
|
130
|
+
}
|
|
131
|
+
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
import re
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
import aiohttp
|
|
7
|
+
|
|
8
|
+
from .const import BUTTON_TYPE_PARAM_VALUE, SWITCH_TYPE_ENABLE, PARAM_MOTION_DETECT, PARAM_STATUS, PARAM_STORAGE_USED, \
|
|
9
|
+
PARAM_NIGHT_VISION_MODE, PARAM_MODE, PARAM_CURRENT_OPTION, PARAM_MODES, PARAM_OPTIONS, PARAM_CHANNELS, \
|
|
10
|
+
PARAM_CHANNEL_ID, PARAM_USED_BYTES, PARAM_TOTAL_BYTES, PARAM_STREAMS, PARAM_HLS, PARAM_RESTART_DEVICE, PARAM_URL, \
|
|
11
|
+
PARAM_CLOSE_CAMERA, PARAM_WHITE_LIGHT, PARAM_AB_ALARM_SOUND, PARAM_AUDIO_ENCODE_CONTROL, CONF_CLOSE_CAMERA, \
|
|
12
|
+
CONF_WHITE_LIGHT, CONF_AB_ALARM_SOUND, CONF_AUDIO_ENCODE_CONTROL, CONF_NVM, PARAM_STREAM_ID, CONF_PT
|
|
13
|
+
from .exceptions import RequestFailedException
|
|
14
|
+
from .device import ImouDeviceManager
|
|
15
|
+
|
|
16
|
+
_LOGGER: logging.Logger = logging.getLogger(__package__)
|
|
17
|
+
|
|
18
|
+
PATTERN = re.compile(r'^\d+$')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ImouHaDevice(object):
|
|
22
|
+
def __init__(self, device_id: str, channel_id: str, channel_name: str,
|
|
23
|
+
manufacturer: str, model: str, swversion: str, product_id: str):
|
|
24
|
+
self._device_id = device_id
|
|
25
|
+
self._channel_id = str(channel_id) if isinstance(channel_id, int) else channel_id
|
|
26
|
+
self._channel_name = channel_name
|
|
27
|
+
self._manufacturer = manufacturer
|
|
28
|
+
self._model = model
|
|
29
|
+
self._swversion = swversion
|
|
30
|
+
self._switches = {
|
|
31
|
+
PARAM_MOTION_DETECT: False
|
|
32
|
+
}
|
|
33
|
+
self._sensors = {
|
|
34
|
+
PARAM_STATUS: DeviceStatus.OFFLINE.status,
|
|
35
|
+
PARAM_STORAGE_USED: "Abnormal"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
self._selects = {
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
self._buttons = ["restart_device"]
|
|
42
|
+
self._product_id = product_id
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def device_id(self):
|
|
46
|
+
return self._device_id
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def channel_id(self):
|
|
50
|
+
return self._channel_id
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def channel_name(self):
|
|
54
|
+
return self._channel_name
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def manufacturer(self):
|
|
58
|
+
return self._manufacturer
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def model(self):
|
|
62
|
+
return self._model
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def swversion(self):
|
|
66
|
+
return self._swversion
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def switches(self):
|
|
70
|
+
return self._switches
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def sensors(self):
|
|
74
|
+
return self._sensors
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def selects(self):
|
|
78
|
+
return self._selects
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def buttons(self):
|
|
82
|
+
return self._buttons
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def product_id(self) -> str:
|
|
86
|
+
return self._product_id
|
|
87
|
+
|
|
88
|
+
def set_product_id(self, product_id: str) -> None:
|
|
89
|
+
self._product_id = product_id
|
|
90
|
+
|
|
91
|
+
def __str__(self):
|
|
92
|
+
return f"{self.device_id} {self.channel_id} {self.channel_name} {self.manufacturer} {self.model} {self.product_id} {self.swversion} {self.switches} {self.sensors} {self._selects}"
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def get_device_status(origin_value: str):
|
|
96
|
+
try:
|
|
97
|
+
for status in DeviceStatus:
|
|
98
|
+
if status.origin_value == origin_value:
|
|
99
|
+
return status.status
|
|
100
|
+
return DeviceStatus.OFFLINE.status
|
|
101
|
+
except Exception as e:
|
|
102
|
+
_LOGGER.info(f"An error occurred: {e}")
|
|
103
|
+
return DeviceStatus.OFFLINE.status
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class ImouHaDeviceManager(object):
|
|
107
|
+
def __init__(self, device_manager: ImouDeviceManager):
|
|
108
|
+
self._device_manager = device_manager
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def device_manager(self):
|
|
112
|
+
return self._device_manager
|
|
113
|
+
|
|
114
|
+
async def async_update_device_status(self, device: ImouHaDevice):
|
|
115
|
+
"""Update device status, with the updater calling every time the coordinator is updated"""
|
|
116
|
+
await asyncio.gather(
|
|
117
|
+
self.async_update_device_switch_status(device),
|
|
118
|
+
self.async_update_device_select_status(device),
|
|
119
|
+
self.async_update_device_sensor_status(device),
|
|
120
|
+
return_exceptions=True
|
|
121
|
+
)
|
|
122
|
+
_LOGGER.info(f"update_device_status finish: {device.__str__()}")
|
|
123
|
+
|
|
124
|
+
async def async_update_device_switch_status(self, device):
|
|
125
|
+
"""UPDATE SWITCH STATUS"""
|
|
126
|
+
for switch_type in device.switches.keys():
|
|
127
|
+
device.switches[switch_type] = any(await asyncio.gather(
|
|
128
|
+
*[self._async_update_device_switch_status_by_ability(device, ability_type) for ability_type in
|
|
129
|
+
SWITCH_TYPE_ENABLE[switch_type]], return_exceptions=True))
|
|
130
|
+
|
|
131
|
+
async def async_update_device_select_status(self, device):
|
|
132
|
+
"""UPDATE SELECT STATUS"""
|
|
133
|
+
for select_type in device.selects.keys():
|
|
134
|
+
await self.async_update_device_select_status_by_type(device, select_type)
|
|
135
|
+
|
|
136
|
+
async def async_update_device_sensor_status(self, device):
|
|
137
|
+
"""UPDATE SENSOR STATUS"""
|
|
138
|
+
for sensor_type in device.sensors.keys():
|
|
139
|
+
if sensor_type == PARAM_STATUS:
|
|
140
|
+
try:
|
|
141
|
+
data = await self.device_manager.async_get_device_online_status(device.device_id)
|
|
142
|
+
for channel in data[PARAM_CHANNELS]:
|
|
143
|
+
if channel[PARAM_CHANNEL_ID] == device.channel_id:
|
|
144
|
+
device.sensors[PARAM_STATUS] = get_device_status(channel["onLine"])
|
|
145
|
+
break
|
|
146
|
+
except RequestFailedException:
|
|
147
|
+
device.sensors[PARAM_STATUS] = DeviceStatus.OFFLINE.status
|
|
148
|
+
elif sensor_type == PARAM_STORAGE_USED:
|
|
149
|
+
await self._get_device_storage(device)
|
|
150
|
+
|
|
151
|
+
async def _get_device_storage(self, device):
|
|
152
|
+
try:
|
|
153
|
+
data = await self.device_manager.async_get_device_storage(device.device_id)
|
|
154
|
+
if data[PARAM_TOTAL_BYTES] != 0:
|
|
155
|
+
percentage_used = int(data[PARAM_USED_BYTES] * 100 / data[PARAM_TOTAL_BYTES])
|
|
156
|
+
device.sensors[PARAM_STORAGE_USED] = f"{percentage_used}%"
|
|
157
|
+
else:
|
|
158
|
+
device.sensors[PARAM_STORAGE_USED] = "No Storage Medium"
|
|
159
|
+
except RequestFailedException as exception:
|
|
160
|
+
if "DV1049" in exception.message:
|
|
161
|
+
device.sensors[PARAM_STORAGE_USED] = "No Storage Medium"
|
|
162
|
+
else:
|
|
163
|
+
device.sensors[PARAM_STORAGE_USED] = "Abnormal"
|
|
164
|
+
|
|
165
|
+
async def async_get_device_stream(self, device):
|
|
166
|
+
try:
|
|
167
|
+
return await self.async_get_device_exist_stream(device)
|
|
168
|
+
except RequestFailedException as exception:
|
|
169
|
+
if "LV1002" in exception.message:
|
|
170
|
+
try:
|
|
171
|
+
return await self.async_create_device_stream(device)
|
|
172
|
+
except RequestFailedException as ex:
|
|
173
|
+
if "LV1001" in ex.message:
|
|
174
|
+
return await self.async_get_device_exist_stream(device)
|
|
175
|
+
raise RequestFailedException("get_stream_url failed")
|
|
176
|
+
|
|
177
|
+
async def async_get_device_exist_stream(self, device):
|
|
178
|
+
data = await self.device_manager.async_get_stream_url(device.device_id, device.channel_id)
|
|
179
|
+
if PARAM_STREAMS in data and len(data[PARAM_STREAMS]) > 0:
|
|
180
|
+
# Prioritize obtaining high-definition live streaming addresses for HTTPS
|
|
181
|
+
for stream in data[PARAM_STREAMS]:
|
|
182
|
+
if "https" in stream[PARAM_HLS] and stream[PARAM_STREAM_ID] == 0:
|
|
183
|
+
_LOGGER.info(f"create_device_stream {stream[PARAM_HLS]}")
|
|
184
|
+
return stream[PARAM_HLS]
|
|
185
|
+
return data[PARAM_STREAMS][0][PARAM_HLS]
|
|
186
|
+
|
|
187
|
+
async def async_create_device_stream(self, device):
|
|
188
|
+
data = await self.device_manager.async_create_stream_url(device.device_id, device.channel_id)
|
|
189
|
+
if PARAM_STREAMS in data and len(data[PARAM_STREAMS]) > 0:
|
|
190
|
+
# Prioritize obtaining high-definition live streaming addresses for HTTPS
|
|
191
|
+
for stream in data[PARAM_STREAMS]:
|
|
192
|
+
if "https" in stream[PARAM_HLS] and stream[PARAM_STREAM_ID] == 0:
|
|
193
|
+
_LOGGER.info(f"create_device_stream {stream[PARAM_HLS]}")
|
|
194
|
+
return stream[PARAM_HLS]
|
|
195
|
+
return data[PARAM_STREAMS][0][PARAM_HLS]
|
|
196
|
+
|
|
197
|
+
async def async_get_device_image(self, device):
|
|
198
|
+
data = await self.device_manager.async_get_device_snap(device.device_id, device.channel_id)
|
|
199
|
+
if PARAM_URL in data:
|
|
200
|
+
await asyncio.sleep(3)
|
|
201
|
+
try:
|
|
202
|
+
async with aiohttp.ClientSession() as session:
|
|
203
|
+
response = await session.request("GET", data[PARAM_URL])
|
|
204
|
+
if response.status != 200:
|
|
205
|
+
raise RequestFailedException(f"request failed,status code {response.status}")
|
|
206
|
+
return await response.read()
|
|
207
|
+
except Exception as exception:
|
|
208
|
+
_LOGGER.info("error get_device_image %s", exception)
|
|
209
|
+
return None
|
|
210
|
+
|
|
211
|
+
async def async_get_devices(self) -> list[ImouHaDevice]:
|
|
212
|
+
"""
|
|
213
|
+
GET A LIST OF ALL DEVICES。
|
|
214
|
+
"""
|
|
215
|
+
devices = []
|
|
216
|
+
for device in await self.device_manager.async_get_devices():
|
|
217
|
+
if device.channel_number > 0 and len(device.channels) > 0:
|
|
218
|
+
for channel in device.channels:
|
|
219
|
+
imou_ha_device = ImouHaDevice(device.device_id, channel.channel_id,
|
|
220
|
+
channel.channel_name, device.brand, device.device_model,
|
|
221
|
+
device.device_version, device.product_id)
|
|
222
|
+
# Determine which switches are needed based on the ability
|
|
223
|
+
abilities = device.device_ability if len(device.channels) == 1 else channel.channel_ability
|
|
224
|
+
if CONF_CLOSE_CAMERA in abilities:
|
|
225
|
+
imou_ha_device.switches[PARAM_CLOSE_CAMERA] = False
|
|
226
|
+
if CONF_WHITE_LIGHT in abilities:
|
|
227
|
+
imou_ha_device.switches[PARAM_WHITE_LIGHT] = False
|
|
228
|
+
if CONF_AB_ALARM_SOUND in abilities:
|
|
229
|
+
imou_ha_device.switches[PARAM_AB_ALARM_SOUND] = False
|
|
230
|
+
if CONF_AUDIO_ENCODE_CONTROL in abilities:
|
|
231
|
+
imou_ha_device.switches[PARAM_AUDIO_ENCODE_CONTROL] = False
|
|
232
|
+
if CONF_NVM in abilities:
|
|
233
|
+
imou_ha_device.selects[PARAM_NIGHT_VISION_MODE] = {
|
|
234
|
+
PARAM_CURRENT_OPTION: "",
|
|
235
|
+
PARAM_OPTIONS: []
|
|
236
|
+
}
|
|
237
|
+
if CONF_PT in abilities:
|
|
238
|
+
imou_ha_device.buttons.extend(["ptz_up", "ptz_down", "ptz_left", "ptz_right"])
|
|
239
|
+
|
|
240
|
+
devices.append(imou_ha_device)
|
|
241
|
+
return devices
|
|
242
|
+
|
|
243
|
+
async def async_press_button(self, device_id: str, channel_id: str, button_type: str):
|
|
244
|
+
if "ptz" in button_type:
|
|
245
|
+
await self.device_manager.async_control_device_ptz(device_id, channel_id,
|
|
246
|
+
BUTTON_TYPE_PARAM_VALUE[button_type])
|
|
247
|
+
elif PARAM_RESTART_DEVICE == button_type:
|
|
248
|
+
await self.device_manager.async_restart_device(device_id)
|
|
249
|
+
|
|
250
|
+
async def async_switch_operation(self, device, switch_type: str, enable: bool):
|
|
251
|
+
if PARAM_MOTION_DETECT == switch_type:
|
|
252
|
+
await self.device_manager.async_modify_device_alarm_status(device.device_id, device.channel_id, enable)
|
|
253
|
+
else:
|
|
254
|
+
result = await asyncio.gather(
|
|
255
|
+
*[self._async_set_device_switch_status_by_ability(device, ability_type, enable)
|
|
256
|
+
for ability_type in SWITCH_TYPE_ENABLE[switch_type]],
|
|
257
|
+
return_exceptions=True)
|
|
258
|
+
# Request all failed, consider this operation a failure
|
|
259
|
+
if all(isinstance(result_item, Exception) for result_item in result):
|
|
260
|
+
raise result[0]
|
|
261
|
+
await asyncio.sleep(3)
|
|
262
|
+
device.switches[switch_type] = any(await asyncio.gather(
|
|
263
|
+
*[self._async_update_device_switch_status_by_ability(device, ability_type) for ability_type in
|
|
264
|
+
SWITCH_TYPE_ENABLE[switch_type]], return_exceptions=True))
|
|
265
|
+
|
|
266
|
+
async def async_select_option(self, device, select_type: str, option: str):
|
|
267
|
+
if PARAM_NIGHT_VISION_MODE == select_type:
|
|
268
|
+
await self.device_manager.async_set_device_night_vision_mode(device.device_id, device.channel_id, option)
|
|
269
|
+
|
|
270
|
+
async def _async_update_device_switch_status_by_ability(self, device, ability_type) -> bool:
|
|
271
|
+
# Updating the interface requires capturing exceptions for two main purposes:
|
|
272
|
+
# 1. To prevent the updater from failing to load due to exceptions;
|
|
273
|
+
# 2. To set default values
|
|
274
|
+
try:
|
|
275
|
+
data = await self.device_manager.async_get_device_status(device.device_id, device.channel_id,
|
|
276
|
+
ability_type)
|
|
277
|
+
return data[PARAM_STATUS] == "on"
|
|
278
|
+
except RequestFailedException:
|
|
279
|
+
return False
|
|
280
|
+
|
|
281
|
+
async def _async_set_device_switch_status_by_ability(self, device, ability_type, enable: bool) -> None:
|
|
282
|
+
await self.device_manager.async_set_device_status(device.device_id, device.channel_id, ability_type, enable)
|
|
283
|
+
|
|
284
|
+
async def async_update_device_select_status_by_type(self, device, select_type):
|
|
285
|
+
if select_type == PARAM_NIGHT_VISION_MODE:
|
|
286
|
+
try:
|
|
287
|
+
await self._async_update_device_night_vision_mode(device)
|
|
288
|
+
except RequestFailedException:
|
|
289
|
+
device.selects[PARAM_NIGHT_VISION_MODE] = {
|
|
290
|
+
PARAM_CURRENT_OPTION: "",
|
|
291
|
+
PARAM_OPTIONS: []
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async def _async_update_device_night_vision_mode(self, device):
|
|
295
|
+
data = await self.device_manager.async_get_device_night_vision_mode(device.device_id,
|
|
296
|
+
device.channel_id)
|
|
297
|
+
if PARAM_MODE not in data or PARAM_MODES not in data:
|
|
298
|
+
raise RequestFailedException("get_device_night_vision fail")
|
|
299
|
+
if data[PARAM_MODE] is not None:
|
|
300
|
+
device.selects[PARAM_NIGHT_VISION_MODE][PARAM_CURRENT_OPTION] = data[PARAM_MODE]
|
|
301
|
+
if data[PARAM_MODES] is not None:
|
|
302
|
+
device.selects[PARAM_NIGHT_VISION_MODE][PARAM_OPTIONS] = data[PARAM_MODES]
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class DeviceStatus(Enum):
|
|
306
|
+
ONLINE = ("1", "online")
|
|
307
|
+
OFFLINE = ("0", "offline")
|
|
308
|
+
SLEEP = ("4", "sleep")
|
|
309
|
+
UPGRADING = ("3", "upgrading")
|
|
310
|
+
|
|
311
|
+
def __init__(self, origin_value, status):
|
|
312
|
+
self.origin_value = origin_value
|
|
313
|
+
self.status = status
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyimouapi
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: A package for imou open api
|
|
5
5
|
Home-page: https://github.com/Imou-OpenPlatform/Py-Imou-Open-Api
|
|
6
6
|
Author: Imou-OpenPlatform
|
|
@@ -12,11 +12,9 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Topic :: Software Development :: Libraries
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: aiohttp==3.11.0
|
|
16
|
-
Requires-Dist: async-timeout==5.0.1
|
|
17
|
-
|
|
18
|
-
# Py-Imou-Open-Api
|
|
19
|
-
|
|
20
|
-
imou open platform api SDK for python
|
|
21
15
|
|
|
16
|
+
## 打包
|
|
17
|
+
python setup.py sdist bdist_wheel
|
|
22
18
|
|
|
19
|
+
## 上传
|
|
20
|
+
twine upload dist/*
|
|
@@ -5,9 +5,9 @@ pyimouapi/__init__.py
|
|
|
5
5
|
pyimouapi/const.py
|
|
6
6
|
pyimouapi/device.py
|
|
7
7
|
pyimouapi/exceptions.py
|
|
8
|
+
pyimouapi/ha_device.py
|
|
8
9
|
pyimouapi/openapi.py
|
|
9
10
|
pyimouapi.egg-info/PKG-INFO
|
|
10
11
|
pyimouapi.egg-info/SOURCES.txt
|
|
11
12
|
pyimouapi.egg-info/dependency_links.txt
|
|
12
|
-
pyimouapi.egg-info/requires.txt
|
|
13
13
|
pyimouapi.egg-info/top_level.txt
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name='pyimouapi',
|
|
5
|
-
version='1.0.
|
|
5
|
+
version='1.0.4',
|
|
6
6
|
packages=find_packages(),
|
|
7
7
|
description='A package for imou open api',
|
|
8
8
|
# long_description=open('README.md').read(),
|
|
@@ -13,10 +13,6 @@ setup(
|
|
|
13
13
|
author='Imou-OpenPlatform',
|
|
14
14
|
author_email='cloud_openteam_service@imou.com',
|
|
15
15
|
license='MIT',
|
|
16
|
-
install_requires=[
|
|
17
|
-
'aiohttp==3.11.0',
|
|
18
|
-
'async-timeout==5.0.1'
|
|
19
|
-
],
|
|
20
16
|
classifiers=[
|
|
21
17
|
'Intended Audience :: Developers',
|
|
22
18
|
'Operating System :: OS Independent',
|
pyimouapi-1.0.2/README.md
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|