pyimouapi 1.3.2__tar.gz → 1.3.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.3.2 → pyimouapi-1.3.4}/PKG-INFO +4 -3
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/README.md +3 -2
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi/__init__.py +1 -1
- pyimouapi-1.3.4/pyimouapi/collection_point.py +89 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi/const.py +63 -9
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi/device.py +48 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi/ha_device.py +173 -68
- pyimouapi-1.3.4/pyimouapi/select_option.py +123 -0
- pyimouapi-1.3.4/pyimouapi/siren.py +15 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi.egg-info/PKG-INFO +4 -3
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi.egg-info/SOURCES.txt +8 -1
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyproject.toml +1 -1
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/setup.py +1 -1
- pyimouapi-1.3.4/tests/test_collection_point.py +205 -0
- pyimouapi-1.3.4/tests/test_select_option.py +111 -0
- pyimouapi-1.3.4/tests/test_siren.py +272 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/tests/test_update_from_detail.py +9 -7
- pyimouapi-1.3.4/tests/test_write_optimistic_state.py +127 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/LICENSE +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi/exceptions.py +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi/openapi.py +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi/sensor.py +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi.egg-info/dependency_links.txt +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi.egg-info/requires.txt +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/pyimouapi.egg-info/top_level.txt +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/setup.cfg +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/tests/test_channel_id_and_api_guards.py +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/tests/test_collect_property_entities.py +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/tests/test_device_summaries.py +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/tests/test_event_identifier_map.py +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/tests/test_lookup_property.py +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/tests/test_message_callback.py +0 -0
- {pyimouapi-1.3.2 → pyimouapi-1.3.4}/tests/test_sensor_normalize.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyimouapi
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.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
|
|
@@ -30,8 +30,9 @@ Async Python client for the **Imou Open Platform** cloud APIs. Built on **aiohtt
|
|
|
30
30
|
| Module | Role |
|
|
31
31
|
|--------|------|
|
|
32
32
|
| `pyimouapi.openapi` | `ImouOpenApiClient` — auth, signing, token lifecycle, HTTP calls |
|
|
33
|
-
| `pyimouapi.device` | `ImouDeviceManager`, `ImouDevice`, `ImouChannel` — listing, PTZ, alarms, storage, and related endpoints |
|
|
34
|
-
| `pyimouapi.
|
|
33
|
+
| `pyimouapi.device` | `ImouDeviceManager`, `ImouDevice`, `ImouChannel` — listing, PTZ, alarms, storage, collection points (`getCollection` / `turnCollection`), and related endpoints |
|
|
34
|
+
| `pyimouapi.collection_point` | Parsing helpers for PaaS / IoT collection point (preset) name lists |
|
|
35
|
+
| `pyimouapi.ha_device` | `ImouHaDeviceManager`, `ImouHaDevice`, … — aggregated “device model” helpers for automation stacks (including `select.collection_point` when the device exposes `CollectionPoint` or IoT refs `21500`/`22000`) |
|
|
35
36
|
| `pyimouapi.exceptions` | `ImouException` and typed errors (connect, request, invalid credentials, …) |
|
|
36
37
|
|
|
37
38
|
The top-level `pyimouapi` package re-exports common symbols. Import submodules directly when needed, for example `from pyimouapi.ha_device import ImouHaDeviceManager`.
|
|
@@ -11,8 +11,9 @@ Async Python client for the **Imou Open Platform** cloud APIs. Built on **aiohtt
|
|
|
11
11
|
| Module | Role |
|
|
12
12
|
|--------|------|
|
|
13
13
|
| `pyimouapi.openapi` | `ImouOpenApiClient` — auth, signing, token lifecycle, HTTP calls |
|
|
14
|
-
| `pyimouapi.device` | `ImouDeviceManager`, `ImouDevice`, `ImouChannel` — listing, PTZ, alarms, storage, and related endpoints |
|
|
15
|
-
| `pyimouapi.
|
|
14
|
+
| `pyimouapi.device` | `ImouDeviceManager`, `ImouDevice`, `ImouChannel` — listing, PTZ, alarms, storage, collection points (`getCollection` / `turnCollection`), and related endpoints |
|
|
15
|
+
| `pyimouapi.collection_point` | Parsing helpers for PaaS / IoT collection point (preset) name lists |
|
|
16
|
+
| `pyimouapi.ha_device` | `ImouHaDeviceManager`, `ImouHaDevice`, … — aggregated “device model” helpers for automation stacks (including `select.collection_point` when the device exposes `CollectionPoint` or IoT refs `21500`/`22000`) |
|
|
16
17
|
| `pyimouapi.exceptions` | `ImouException` and typed errors (connect, request, invalid credentials, …) |
|
|
17
18
|
|
|
18
19
|
The top-level `pyimouapi` package re-exports common symbols. Import submodules directly when needed, for example `from pyimouapi.ha_device import ImouHaDeviceManager`.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Collection point (PTZ preset) parsing helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from .const import IOT_COLLECTION_NAME_REF, PARAM_COLLECTION_POINT_PROMPT
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def parse_paas_collection_names(data: dict[str, Any]) -> list[str]:
|
|
11
|
+
"""Extract preset names from getCollection PaaS response data."""
|
|
12
|
+
names: list[str] = []
|
|
13
|
+
for item in data.get("collections") or []:
|
|
14
|
+
if not isinstance(item, dict):
|
|
15
|
+
continue
|
|
16
|
+
name = item.get("name")
|
|
17
|
+
if name and str(name) != PARAM_COLLECTION_POINT_PROMPT:
|
|
18
|
+
names.append(str(name))
|
|
19
|
+
return unique_preserve_order(names)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _name_from_collection_item(item: dict[str, Any]) -> str | None:
|
|
23
|
+
for key in ("Name", "name", IOT_COLLECTION_NAME_REF):
|
|
24
|
+
value = item.get(key)
|
|
25
|
+
if value:
|
|
26
|
+
return str(value)
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def parse_iot_collection_names(output_data: Any) -> list[str]:
|
|
31
|
+
"""Extract preset names from GetCollection IoT outputData."""
|
|
32
|
+
names: list[str] = []
|
|
33
|
+
if output_data is None:
|
|
34
|
+
return names
|
|
35
|
+
|
|
36
|
+
if isinstance(output_data, dict):
|
|
37
|
+
for value in output_data.values():
|
|
38
|
+
if isinstance(value, list):
|
|
39
|
+
names.extend(_names_from_collection_items(value))
|
|
40
|
+
elif isinstance(value, str) and value != PARAM_COLLECTION_POINT_PROMPT:
|
|
41
|
+
names.append(value)
|
|
42
|
+
return unique_preserve_order(names)
|
|
43
|
+
|
|
44
|
+
if isinstance(output_data, list):
|
|
45
|
+
if output_data and all(isinstance(item, dict) for item in output_data):
|
|
46
|
+
if any(
|
|
47
|
+
item.get("identifier") == "collection"
|
|
48
|
+
or IOT_COLLECTION_NAME_REF in item
|
|
49
|
+
or "Name" in item
|
|
50
|
+
for item in output_data
|
|
51
|
+
):
|
|
52
|
+
names.extend(_names_from_collection_items(output_data))
|
|
53
|
+
else:
|
|
54
|
+
for item in output_data:
|
|
55
|
+
if not isinstance(item, dict):
|
|
56
|
+
continue
|
|
57
|
+
nested = item.get("value")
|
|
58
|
+
if isinstance(nested, list):
|
|
59
|
+
names.extend(_names_from_collection_items(nested))
|
|
60
|
+
return unique_preserve_order(names)
|
|
61
|
+
|
|
62
|
+
return names
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _names_from_collection_items(items: list[Any]) -> list[str]:
|
|
66
|
+
names: list[str] = []
|
|
67
|
+
for item in items:
|
|
68
|
+
if not isinstance(item, dict):
|
|
69
|
+
continue
|
|
70
|
+
name = _name_from_collection_item(item)
|
|
71
|
+
if name and name != PARAM_COLLECTION_POINT_PROMPT:
|
|
72
|
+
names.append(name)
|
|
73
|
+
return names
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def unique_preserve_order(names: list[str]) -> list[str]:
|
|
77
|
+
seen: set[str] = set()
|
|
78
|
+
ordered: list[str] = []
|
|
79
|
+
for name in names:
|
|
80
|
+
if name in seen:
|
|
81
|
+
continue
|
|
82
|
+
seen.add(name)
|
|
83
|
+
ordered.append(name)
|
|
84
|
+
return ordered
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def build_collection_point_options(names: list[str]) -> list[str]:
|
|
88
|
+
"""Build select options with placeholder first, preserving API order."""
|
|
89
|
+
return [PARAM_COLLECTION_POINT_PROMPT, *unique_preserve_order(names)]
|
|
@@ -23,6 +23,10 @@ API_ENDPOINT_GET_PRODUCT_MODEL = "/openapi/getProductModel"
|
|
|
23
23
|
API_ENDPOINT_GET_IOT_DEVICE_DETAIL_INFO = "/openapi/getIotDeviceDetailInfo"
|
|
24
24
|
API_ENDPOINT_WAKE_UP_DEVICE = "/openapi/wakeUpDevice"
|
|
25
25
|
API_ENDPOINT_SET_MESSAGE_CALLBACK = "/openapi/setMessageCallback"
|
|
26
|
+
API_ENDPOINT_GET_COLLECTION = "/openapi/getCollection"
|
|
27
|
+
API_ENDPOINT_TURN_COLLECTION = "/openapi/turnCollection"
|
|
28
|
+
API_ENDPOINT_SIREN_START = "/openapi/sirenStart"
|
|
29
|
+
API_ENDPOINT_SIREN_STOP = "/openapi/sirenStop"
|
|
26
30
|
|
|
27
31
|
# error_codes
|
|
28
32
|
ERROR_CODE_SUCCESS = "0"
|
|
@@ -109,6 +113,11 @@ PARAM_MOTION_DETECT = "motion_detect"
|
|
|
109
113
|
PARAM_STORAGE_USED = "storage_used"
|
|
110
114
|
PARAM_RESTART_DEVICE = "restart_device"
|
|
111
115
|
PARAM_NIGHT_VISION_MODE = "night_vision_mode"
|
|
116
|
+
PARAM_DEVICE_VOLUME = "device_volume"
|
|
117
|
+
PARAM_COLLECTION_POINT = "collection_point"
|
|
118
|
+
PARAM_COLLECTION_POINT_PROMPT = "select_collection_point"
|
|
119
|
+
PARAM_SIREN_START = "siren_start"
|
|
120
|
+
PARAM_SIREN_STOP = "siren_stop"
|
|
112
121
|
PARAM_PTZ = "ptz"
|
|
113
122
|
PARAM_TEMPERATURE_CURRENT = "temperature_current"
|
|
114
123
|
PARAM_HUMIDITY_CURRENT = "humidity_current"
|
|
@@ -128,6 +137,18 @@ PARAM_ABILITY_REFS = "abilityRefs"
|
|
|
128
137
|
PARAM_REF_TYPE = "ref_type"
|
|
129
138
|
PARAM_EXPRESSION = "expression"
|
|
130
139
|
PARAM_OUTPUT_DATA = "outputData"
|
|
140
|
+
PARAM_TURN_REF = "turn_ref"
|
|
141
|
+
PARAM_TURN_INPUT_REF = "turn_input_ref"
|
|
142
|
+
PARAM_INPUT_REF = "input_ref"
|
|
143
|
+
PARAM_COLLECTION_NAME = "name"
|
|
144
|
+
|
|
145
|
+
IOT_GET_COLLECTION_REF = "21500"
|
|
146
|
+
IOT_TURN_COLLECTION_REF = "22000"
|
|
147
|
+
IOT_TURN_COLLECTION_NAME_REF = "22001"
|
|
148
|
+
IOT_COLLECTION_NAME_REF = "21551"
|
|
149
|
+
IOT_SIREN_START_REF = "25500"
|
|
150
|
+
IOT_SIREN_START_INPUT_REF = "25501"
|
|
151
|
+
IOT_SIREN_STOP_REF = "22200"
|
|
131
152
|
PARAM_VALUE_TYPE = "value_type"
|
|
132
153
|
PARAM_ACCESS_TYPE = "accessType"
|
|
133
154
|
PARAM_ABILITY = "ability"
|
|
@@ -294,6 +315,8 @@ SWITCH_TYPE_REF = {
|
|
|
294
315
|
# Required capacity for various button types
|
|
295
316
|
BUTTON_TYPE_ABILITY = {
|
|
296
317
|
"restart_device": ["Reboot"],
|
|
318
|
+
"siren_start": ["Siren"],
|
|
319
|
+
"siren_stop": ["Siren"],
|
|
297
320
|
"ptz_up": ["PT", "PTZ"],
|
|
298
321
|
"ptz_down": ["PT", "PTZ"],
|
|
299
322
|
"ptz_left": ["PT", "PTZ"],
|
|
@@ -331,6 +354,15 @@ BUTTON_TYPE_REF = {
|
|
|
331
354
|
],
|
|
332
355
|
},
|
|
333
356
|
],
|
|
357
|
+
"siren_start": [
|
|
358
|
+
{
|
|
359
|
+
"ref": IOT_SIREN_START_REF,
|
|
360
|
+
"input_ref": IOT_SIREN_START_INPUT_REF,
|
|
361
|
+
},
|
|
362
|
+
],
|
|
363
|
+
"siren_stop": [
|
|
364
|
+
{"ref": IOT_SIREN_STOP_REF},
|
|
365
|
+
],
|
|
334
366
|
"ptz_up": [
|
|
335
367
|
{"ref": "22100"},
|
|
336
368
|
{"ref": "88700"},
|
|
@@ -371,39 +403,61 @@ BUTTON_TYPE_REF = {
|
|
|
371
403
|
# Required capacity for various select types
|
|
372
404
|
SELECT_TYPE_ABILITY = {
|
|
373
405
|
"night_vision_mode": ["NVM"],
|
|
406
|
+
"collection_point": ["CollectionPoint"],
|
|
374
407
|
}
|
|
375
408
|
SELECT_TYPE_REF = {
|
|
376
409
|
"night_vision_mode": [
|
|
377
410
|
{
|
|
378
411
|
"ref": "17400",
|
|
379
|
-
"default": "
|
|
380
|
-
"options": ["
|
|
412
|
+
"default": "intelligent",
|
|
413
|
+
"options": ["intelligent", "fullcolor", "infrared", "off"],
|
|
381
414
|
"value_type": "int",
|
|
382
415
|
},
|
|
383
416
|
{
|
|
384
417
|
"ref": "139700",
|
|
385
|
-
"default": "
|
|
386
|
-
"options": [
|
|
418
|
+
"default": "intelligent",
|
|
419
|
+
"options": [
|
|
420
|
+
"intelligent",
|
|
421
|
+
"fullcolor",
|
|
422
|
+
"infrared",
|
|
423
|
+
"off",
|
|
424
|
+
"custom",
|
|
425
|
+
],
|
|
426
|
+
"value_type": "int",
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
"ref": "112400",
|
|
430
|
+
"default": "infrared",
|
|
431
|
+
"options": ["infrared", "off"],
|
|
387
432
|
"value_type": "int",
|
|
388
433
|
},
|
|
389
|
-
{"ref": "112400", "default": "2", "options": ["2", "3"], "value_type": "int"},
|
|
390
434
|
],
|
|
391
435
|
"mode": [
|
|
392
436
|
{
|
|
393
437
|
"ref": "15200",
|
|
394
|
-
"default": "
|
|
395
|
-
"options": ["
|
|
438
|
+
"default": "home",
|
|
439
|
+
"options": ["home", "away", "disarm"],
|
|
396
440
|
"value_type": "int",
|
|
397
441
|
}
|
|
398
442
|
],
|
|
399
443
|
"device_volume": [
|
|
400
444
|
{
|
|
401
445
|
"ref": "15400",
|
|
402
|
-
"default": "
|
|
403
|
-
"options": ["
|
|
446
|
+
"default": "low",
|
|
447
|
+
"options": ["mute", "low", "medium", "high"],
|
|
404
448
|
"value_type": "int",
|
|
405
449
|
}
|
|
406
450
|
],
|
|
451
|
+
"collection_point": [
|
|
452
|
+
{
|
|
453
|
+
"ref": IOT_GET_COLLECTION_REF,
|
|
454
|
+
"turn_ref": IOT_TURN_COLLECTION_REF,
|
|
455
|
+
"turn_input_ref": IOT_TURN_COLLECTION_NAME_REF,
|
|
456
|
+
"ref_type": "services",
|
|
457
|
+
"default": PARAM_COLLECTION_POINT_PROMPT,
|
|
458
|
+
"options": [PARAM_COLLECTION_POINT_PROMPT],
|
|
459
|
+
}
|
|
460
|
+
],
|
|
407
461
|
}
|
|
408
462
|
# Required capacity for various sensor types
|
|
409
463
|
SENSOR_TYPE_ABILITY = {
|
|
@@ -10,6 +10,7 @@ from .const import (
|
|
|
10
10
|
API_ENDPOINT_CONTROL_DEVICE_PTZ,
|
|
11
11
|
API_ENDPOINT_DEVICE_SD_CARD_STATUS,
|
|
12
12
|
API_ENDPOINT_DEVICE_STORAGE,
|
|
13
|
+
API_ENDPOINT_GET_COLLECTION,
|
|
13
14
|
API_ENDPOINT_GET_DEVICE_ALARM_PARAM,
|
|
14
15
|
API_ENDPOINT_GET_DEVICE_LIVE_INFO,
|
|
15
16
|
API_ENDPOINT_GET_DEVICE_NIGHT_VISION_MODE,
|
|
@@ -27,6 +28,9 @@ from .const import (
|
|
|
27
28
|
API_ENDPOINT_SET_DEVICE_SNAP,
|
|
28
29
|
API_ENDPOINT_SET_DEVICE_STATUS,
|
|
29
30
|
API_ENDPOINT_SET_IOT_DEVICE_PROPERTIES,
|
|
31
|
+
API_ENDPOINT_SIREN_START,
|
|
32
|
+
API_ENDPOINT_SIREN_STOP,
|
|
33
|
+
API_ENDPOINT_TURN_COLLECTION,
|
|
30
34
|
API_ENDPOINT_WAKE_UP_DEVICE,
|
|
31
35
|
NIGHT_VISION_MODE_MAP,
|
|
32
36
|
PARAM_ABILITY_REFS,
|
|
@@ -39,6 +43,7 @@ from .const import (
|
|
|
39
43
|
PARAM_CHANNEL_NUM,
|
|
40
44
|
PARAM_CHANNEL_STATUS,
|
|
41
45
|
PARAM_CHANNELS,
|
|
46
|
+
PARAM_COLLECTION_NAME,
|
|
42
47
|
PARAM_CONTENT,
|
|
43
48
|
PARAM_COUNT,
|
|
44
49
|
PARAM_DEVICE_ABILITY,
|
|
@@ -206,6 +211,10 @@ class ImouDevice:
|
|
|
206
211
|
def parent_device_id(self) -> str | None:
|
|
207
212
|
return self._parent_device_id
|
|
208
213
|
|
|
214
|
+
@property
|
|
215
|
+
def channel_number(self) -> int:
|
|
216
|
+
return self._channel_number
|
|
217
|
+
|
|
209
218
|
@property
|
|
210
219
|
def is_ipc(self) -> bool:
|
|
211
220
|
return (
|
|
@@ -641,6 +650,45 @@ class ImouDeviceManager:
|
|
|
641
650
|
API_ENDPOINT_GET_IOT_DEVICE_DETAIL_INFO, params
|
|
642
651
|
)
|
|
643
652
|
|
|
653
|
+
async def async_get_device_collection(
|
|
654
|
+
self, device_id: str, channel_id: str
|
|
655
|
+
) -> dict[str, Any]:
|
|
656
|
+
params = {
|
|
657
|
+
PARAM_DEVICE_ID: device_id,
|
|
658
|
+
PARAM_CHANNEL_ID: channel_id,
|
|
659
|
+
}
|
|
660
|
+
return await self._imou_api_client.async_request_api(
|
|
661
|
+
API_ENDPOINT_GET_COLLECTION, params
|
|
662
|
+
)
|
|
663
|
+
|
|
664
|
+
async def async_turn_device_collection(
|
|
665
|
+
self, device_id: str, channel_id: str, name: str
|
|
666
|
+
) -> None:
|
|
667
|
+
params = {
|
|
668
|
+
PARAM_DEVICE_ID: device_id,
|
|
669
|
+
PARAM_CHANNEL_ID: channel_id,
|
|
670
|
+
PARAM_COLLECTION_NAME: name,
|
|
671
|
+
}
|
|
672
|
+
await self._imou_api_client.async_request_api(
|
|
673
|
+
API_ENDPOINT_TURN_COLLECTION, params
|
|
674
|
+
)
|
|
675
|
+
|
|
676
|
+
async def async_siren_start(
|
|
677
|
+
self, device_id: str, channels: list[int] | None = None
|
|
678
|
+
) -> None:
|
|
679
|
+
params: dict[str, Any] = {PARAM_DEVICE_ID: device_id}
|
|
680
|
+
if channels is not None:
|
|
681
|
+
params[PARAM_CHANNELS] = channels
|
|
682
|
+
await self._imou_api_client.async_request_api(API_ENDPOINT_SIREN_START, params)
|
|
683
|
+
|
|
684
|
+
async def async_siren_stop(
|
|
685
|
+
self, device_id: str, channels: list[int] | None = None
|
|
686
|
+
) -> None:
|
|
687
|
+
params: dict[str, Any] = {PARAM_DEVICE_ID: device_id}
|
|
688
|
+
if channels is not None:
|
|
689
|
+
params[PARAM_CHANNELS] = channels
|
|
690
|
+
await self._imou_api_client.async_request_api(API_ENDPOINT_SIREN_STOP, params)
|
|
691
|
+
|
|
644
692
|
async def _async_update_device_ability_refs(self, imou_device: ImouDevice) -> None:
|
|
645
693
|
device_id = imou_device.device_id
|
|
646
694
|
if imou_device.parent_product_id is not None:
|