axis 59__tar.gz → 61__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.
- {axis-59 → axis-61}/PKG-INFO +3 -3
- {axis-59 → axis-61}/axis/__main__.py +1 -1
- {axis-59 → axis-61}/axis/errors.py +7 -2
- {axis-59 → axis-61}/axis/interfaces/api_handler.py +1 -2
- {axis-59 → axis-61}/axis/interfaces/applications/motion_guard.py +1 -1
- {axis-59 → axis-61}/axis/interfaces/light_control.py +35 -45
- {axis-59 → axis-61}/axis/interfaces/mqtt.py +7 -14
- {axis-59 → axis-61}/axis/interfaces/port_management.py +1 -1
- {axis-59 → axis-61}/axis/interfaces/vapix.py +13 -8
- {axis-59 → axis-61}/axis/interfaces/view_areas.py +1 -1
- {axis-59 → axis-61}/axis/models/light_control.py +9 -7
- {axis-59 → axis-61}/axis/models/mqtt.py +178 -19
- {axis-59 → axis-61}/axis/models/parameters/properties.py +5 -4
- {axis-59 → axis-61}/axis/rtsp.py +19 -19
- {axis-59 → axis-61}/axis/stream_manager.py +2 -1
- {axis-59 → axis-61}/axis.egg-info/PKG-INFO +3 -3
- {axis-59 → axis-61}/axis.egg-info/requires.txt +3 -3
- {axis-59 → axis-61}/pyproject.toml +53 -35
- {axis-59 → axis-61}/tests/test_light_control.py +43 -25
- {axis-59 → axis-61}/tests/test_mqtt.py +4 -1
- {axis-59 → axis-61}/tests/test_user_groups.py +6 -3
- {axis-59 → axis-61}/tests/test_vapix.py +4 -2
- {axis-59 → axis-61}/LICENSE +0 -0
- {axis-59 → axis-61}/README.md +0 -0
- {axis-59 → axis-61}/axis/__init__.py +0 -0
- {axis-59 → axis-61}/axis/device.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/__init__.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/api_discovery.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/applications/__init__.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/applications/application_handler.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/applications/applications.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/applications/fence_guard.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/applications/loitering_guard.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/applications/object_analytics.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/applications/vmd4.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/basic_device_info.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/event_instances.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/event_manager.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/parameters/__init__.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/parameters/brand.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/parameters/image.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/parameters/io_port.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/parameters/param_cgi.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/parameters/param_handler.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/parameters/properties.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/parameters/ptz.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/parameters/stream_profile.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/pir_sensor_configuration.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/port_cgi.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/ptz.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/pwdgrp_cgi.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/stream_profiles.py +0 -0
- {axis-59 → axis-61}/axis/interfaces/user_groups.py +0 -0
- {axis-59 → axis-61}/axis/models/__init__.py +0 -0
- {axis-59 → axis-61}/axis/models/api.py +0 -0
- {axis-59 → axis-61}/axis/models/api_discovery.py +0 -0
- {axis-59 → axis-61}/axis/models/applications/__init__.py +0 -0
- {axis-59 → axis-61}/axis/models/applications/application.py +0 -0
- {axis-59 → axis-61}/axis/models/applications/fence_guard.py +0 -0
- {axis-59 → axis-61}/axis/models/applications/loitering_guard.py +0 -0
- {axis-59 → axis-61}/axis/models/applications/motion_guard.py +0 -0
- {axis-59 → axis-61}/axis/models/applications/object_analytics.py +0 -0
- {axis-59 → axis-61}/axis/models/applications/vmd4.py +0 -0
- {axis-59 → axis-61}/axis/models/basic_device_info.py +0 -0
- {axis-59 → axis-61}/axis/models/configuration.py +0 -0
- {axis-59 → axis-61}/axis/models/event.py +0 -0
- {axis-59 → axis-61}/axis/models/event_instance.py +0 -0
- {axis-59 → axis-61}/axis/models/parameters/__init__.py +0 -0
- {axis-59 → axis-61}/axis/models/parameters/brand.py +0 -0
- {axis-59 → axis-61}/axis/models/parameters/image.py +0 -0
- {axis-59 → axis-61}/axis/models/parameters/io_port.py +0 -0
- {axis-59 → axis-61}/axis/models/parameters/param_cgi.py +0 -0
- {axis-59 → axis-61}/axis/models/parameters/ptz.py +0 -0
- {axis-59 → axis-61}/axis/models/parameters/stream_profile.py +0 -0
- {axis-59 → axis-61}/axis/models/pir_sensor_configuration.py +0 -0
- {axis-59 → axis-61}/axis/models/port_cgi.py +0 -0
- {axis-59 → axis-61}/axis/models/port_management.py +0 -0
- {axis-59 → axis-61}/axis/models/ptz_cgi.py +0 -0
- {axis-59 → axis-61}/axis/models/pwdgrp_cgi.py +0 -0
- {axis-59 → axis-61}/axis/models/stream_profile.py +0 -0
- {axis-59 → axis-61}/axis/models/user_group.py +0 -0
- {axis-59 → axis-61}/axis/models/view_area.py +0 -0
- {axis-59 → axis-61}/axis/py.typed +0 -0
- {axis-59 → axis-61}/axis.egg-info/SOURCES.txt +0 -0
- {axis-59 → axis-61}/axis.egg-info/dependency_links.txt +0 -0
- {axis-59 → axis-61}/axis.egg-info/entry_points.txt +0 -0
- {axis-59 → axis-61}/axis.egg-info/top_level.txt +0 -0
- {axis-59 → axis-61}/setup.cfg +0 -0
- {axis-59 → axis-61}/tests/test_api_discovery.py +0 -0
- {axis-59 → axis-61}/tests/test_api_handler.py +0 -0
- {axis-59 → axis-61}/tests/test_basic_device_info.py +0 -0
- {axis-59 → axis-61}/tests/test_configuration.py +0 -0
- {axis-59 → axis-61}/tests/test_device.py +0 -0
- {axis-59 → axis-61}/tests/test_event.py +0 -0
- {axis-59 → axis-61}/tests/test_event_instances.py +0 -0
- {axis-59 → axis-61}/tests/test_event_stream.py +0 -0
- {axis-59 → axis-61}/tests/test_pir_sensor_configuration.py +0 -0
- {axis-59 → axis-61}/tests/test_port_cgi.py +0 -0
- {axis-59 → axis-61}/tests/test_port_management.py +0 -0
- {axis-59 → axis-61}/tests/test_ptz.py +0 -0
- {axis-59 → axis-61}/tests/test_pwdgrp_cgi.py +0 -0
- {axis-59 → axis-61}/tests/test_rtsp.py +0 -0
- {axis-59 → axis-61}/tests/test_stream_manager.py +0 -0
- {axis-59 → axis-61}/tests/test_stream_profiles.py +0 -0
- {axis-59 → axis-61}/tests/test_view_areas.py +0 -0
{axis-59 → axis-61}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: axis
|
|
3
|
-
Version:
|
|
3
|
+
Version: 61
|
|
4
4
|
Summary: A Python library for communicating with devices from Axis Communications
|
|
5
5
|
Author-email: Robert Svensson <Kane610@users.noreply.github.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,9 +12,9 @@ Classifier: Development Status :: 5 - Production/Stable
|
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
16
|
Classifier: Topic :: Home Automation
|
|
17
|
-
Requires-Python: >=3.
|
|
17
|
+
Requires-Python: >=3.12.0
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
Provides-Extra: requirements
|
|
20
20
|
Provides-Extra: requirements_test
|
|
@@ -20,7 +20,7 @@ async def axis_device(
|
|
|
20
20
|
host: str, port: int, username: str, password: str
|
|
21
21
|
) -> axis.device.AxisDevice:
|
|
22
22
|
"""Create a Axis device."""
|
|
23
|
-
session = AsyncClient(verify=False)
|
|
23
|
+
session = AsyncClient(verify=False) # noqa: S501
|
|
24
24
|
device = axis.device.AxisDevice(
|
|
25
25
|
axis.models.configuration.Configuration(
|
|
26
26
|
session, host, port=port, username=username, password=password
|
|
@@ -36,10 +36,15 @@ class PathNotFound(AxisException):
|
|
|
36
36
|
"""Path not found."""
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
ERRORS = {
|
|
39
|
+
ERRORS = {
|
|
40
|
+
401: Unauthorized,
|
|
41
|
+
403: Forbidden,
|
|
42
|
+
404: PathNotFound,
|
|
43
|
+
405: MethodNotAllowed,
|
|
44
|
+
}
|
|
40
45
|
|
|
41
46
|
|
|
42
47
|
def raise_error(error: int) -> None:
|
|
43
48
|
"""Raise error."""
|
|
44
49
|
cls = ERRORS.get(error, AxisException)
|
|
45
|
-
raise cls(
|
|
50
|
+
raise cls(error)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""API handler class and base class for an API endpoint."""
|
|
2
2
|
|
|
3
|
-
from abc import ABC
|
|
4
3
|
from collections.abc import (
|
|
5
4
|
Callable,
|
|
6
5
|
ItemsView,
|
|
@@ -26,7 +25,7 @@ UnsubscribeType = Callable[[], None]
|
|
|
26
25
|
ID_FILTER_ALL = "*"
|
|
27
26
|
|
|
28
27
|
|
|
29
|
-
class SubscriptionHandler
|
|
28
|
+
class SubscriptionHandler:
|
|
30
29
|
"""Manage subscription and notification to subscribers."""
|
|
31
30
|
|
|
32
31
|
def __init__(self) -> None:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
AXIS Motion Guard is a video motion detection application that detects
|
|
4
4
|
and triggers an alarm whenever an object, such as a person or vehicle,
|
|
5
|
-
moves within predefined areas in a camera
|
|
5
|
+
moves within predefined areas in a camera's field of view.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
from ...models.applications.application import ApplicationName
|
|
@@ -67,62 +67,60 @@ class LightHandler(ApiHandler[LightInformation]):
|
|
|
67
67
|
|
|
68
68
|
async def get_light_information(self) -> dict[str, LightInformation]:
|
|
69
69
|
"""List the light control information."""
|
|
70
|
-
assert isinstance(self.api_version, str)
|
|
71
70
|
bytes_data = await self.vapix.api_request(
|
|
72
|
-
GetLightInformationRequest(api_version=self.
|
|
71
|
+
GetLightInformationRequest(api_version=self.default_api_version)
|
|
73
72
|
)
|
|
74
73
|
return GetLightInformationResponse.decode(bytes_data).data
|
|
75
74
|
|
|
76
75
|
async def get_service_capabilities(self) -> ServiceCapabilities:
|
|
77
76
|
"""List the light control information."""
|
|
78
|
-
assert isinstance(self.api_version, str)
|
|
79
77
|
bytes_data = await self.vapix.api_request(
|
|
80
|
-
GetServiceCapabilitiesRequest(api_version=self.
|
|
78
|
+
GetServiceCapabilitiesRequest(api_version=self.default_api_version)
|
|
81
79
|
)
|
|
82
80
|
return GetServiceCapabilitiesResponse.decode(bytes_data).data
|
|
83
81
|
|
|
84
82
|
async def activate_light(self, light_id: str) -> None:
|
|
85
83
|
"""Activate the light."""
|
|
86
|
-
assert isinstance(self.api_version, str)
|
|
87
84
|
await self.vapix.api_request(
|
|
88
|
-
ActivateLightRequest(
|
|
85
|
+
ActivateLightRequest(
|
|
86
|
+
api_version=self.default_api_version, light_id=light_id
|
|
87
|
+
)
|
|
89
88
|
)
|
|
90
89
|
|
|
91
90
|
async def deactivate_light(self, light_id: str) -> None:
|
|
92
91
|
"""Deactivate the light."""
|
|
93
|
-
assert isinstance(self.api_version, str)
|
|
94
92
|
await self.vapix.api_request(
|
|
95
|
-
DeactivateLightRequest(
|
|
93
|
+
DeactivateLightRequest(
|
|
94
|
+
api_version=self.default_api_version, light_id=light_id
|
|
95
|
+
)
|
|
96
96
|
)
|
|
97
97
|
|
|
98
98
|
async def enable_light(self, light_id: str) -> None:
|
|
99
99
|
"""Activate the light."""
|
|
100
|
-
assert isinstance(self.api_version, str)
|
|
101
100
|
await self.vapix.api_request(
|
|
102
|
-
EnableLightRequest(api_version=self.
|
|
101
|
+
EnableLightRequest(api_version=self.default_api_version, light_id=light_id)
|
|
103
102
|
)
|
|
104
103
|
|
|
105
104
|
async def disable_light(self, light_id: str) -> None:
|
|
106
105
|
"""Deactivate the light."""
|
|
107
|
-
assert isinstance(self.api_version, str)
|
|
108
106
|
await self.vapix.api_request(
|
|
109
|
-
DisableLightRequest(api_version=self.
|
|
107
|
+
DisableLightRequest(api_version=self.default_api_version, light_id=light_id)
|
|
110
108
|
)
|
|
111
109
|
|
|
112
110
|
async def get_light_status(self, light_id: str) -> bool:
|
|
113
111
|
"""Get light status if its on or off."""
|
|
114
|
-
assert isinstance(self.api_version, str)
|
|
115
112
|
bytes_data = await self.vapix.api_request(
|
|
116
|
-
GetLightStatusRequest(
|
|
113
|
+
GetLightStatusRequest(
|
|
114
|
+
api_version=self.default_api_version, light_id=light_id
|
|
115
|
+
)
|
|
117
116
|
)
|
|
118
117
|
return GetLightStatusResponse.decode(bytes_data).data
|
|
119
118
|
|
|
120
119
|
async def set_automatic_intensity_mode(self, light_id: str, enabled: bool) -> None:
|
|
121
120
|
"""Enable the automatic light intensity control."""
|
|
122
|
-
assert isinstance(self.api_version, str)
|
|
123
121
|
await self.vapix.api_request(
|
|
124
122
|
SetAutomaticIntensityModeRequest(
|
|
125
|
-
api_version=self.
|
|
123
|
+
api_version=self.default_api_version,
|
|
126
124
|
light_id=light_id,
|
|
127
125
|
enabled=enabled,
|
|
128
126
|
)
|
|
@@ -130,18 +128,18 @@ class LightHandler(ApiHandler[LightInformation]):
|
|
|
130
128
|
|
|
131
129
|
async def get_valid_intensity(self, light_id: str) -> Range:
|
|
132
130
|
"""Get valid intensity range for light."""
|
|
133
|
-
assert isinstance(self.api_version, str)
|
|
134
131
|
bytes_data = await self.vapix.api_request(
|
|
135
|
-
GetValidIntensityRequest(
|
|
132
|
+
GetValidIntensityRequest(
|
|
133
|
+
api_version=self.default_api_version, light_id=light_id
|
|
134
|
+
)
|
|
136
135
|
)
|
|
137
136
|
return GetValidIntensityResponse.decode(bytes_data).data
|
|
138
137
|
|
|
139
138
|
async def set_manual_intensity(self, light_id: str, intensity: int) -> None:
|
|
140
139
|
"""Manually sets the intensity."""
|
|
141
|
-
assert isinstance(self.api_version, str)
|
|
142
140
|
await self.vapix.api_request(
|
|
143
141
|
SetManualIntensityRequest(
|
|
144
|
-
api_version=self.
|
|
142
|
+
api_version=self.default_api_version,
|
|
145
143
|
light_id=light_id,
|
|
146
144
|
intensity=intensity,
|
|
147
145
|
)
|
|
@@ -149,9 +147,10 @@ class LightHandler(ApiHandler[LightInformation]):
|
|
|
149
147
|
|
|
150
148
|
async def get_manual_intensity(self, light_id: str) -> int:
|
|
151
149
|
"""Enable the automatic light intensity control."""
|
|
152
|
-
assert isinstance(self.api_version, str)
|
|
153
150
|
bytes_data = await self.vapix.api_request(
|
|
154
|
-
GetManualIntensityRequest(
|
|
151
|
+
GetManualIntensityRequest(
|
|
152
|
+
api_version=self.default_api_version, light_id=light_id
|
|
153
|
+
)
|
|
155
154
|
)
|
|
156
155
|
return GetManualIntensityResponse.decode(bytes_data).data
|
|
157
156
|
|
|
@@ -159,10 +158,9 @@ class LightHandler(ApiHandler[LightInformation]):
|
|
|
159
158
|
self, light_id: str, led_id: int, intensity: int
|
|
160
159
|
) -> None:
|
|
161
160
|
"""Manually sets the intensity for an individual LED."""
|
|
162
|
-
assert isinstance(self.api_version, str)
|
|
163
161
|
await self.vapix.api_request(
|
|
164
162
|
SetIndividualIntensityRequest(
|
|
165
|
-
api_version=self.
|
|
163
|
+
api_version=self.default_api_version,
|
|
166
164
|
light_id=light_id,
|
|
167
165
|
led_id=led_id,
|
|
168
166
|
intensity=intensity,
|
|
@@ -171,10 +169,9 @@ class LightHandler(ApiHandler[LightInformation]):
|
|
|
171
169
|
|
|
172
170
|
async def get_individual_intensity(self, light_id: str, led_id: int) -> int:
|
|
173
171
|
"""Receives the intensity from the setIndividualIntensity request."""
|
|
174
|
-
assert isinstance(self.api_version, str)
|
|
175
172
|
bytes_data = await self.vapix.api_request(
|
|
176
173
|
GetIndividualIntensityRequest(
|
|
177
|
-
api_version=self.
|
|
174
|
+
api_version=self.default_api_version,
|
|
178
175
|
light_id=light_id,
|
|
179
176
|
led_id=led_id,
|
|
180
177
|
)
|
|
@@ -183,9 +180,10 @@ class LightHandler(ApiHandler[LightInformation]):
|
|
|
183
180
|
|
|
184
181
|
async def get_current_intensity(self, light_id: str) -> int:
|
|
185
182
|
"""Receives the intensity from the setIndividualIntensity request."""
|
|
186
|
-
assert isinstance(self.api_version, str)
|
|
187
183
|
bytes_data = await self.vapix.api_request(
|
|
188
|
-
GetCurrentIntensityRequest(
|
|
184
|
+
GetCurrentIntensityRequest(
|
|
185
|
+
api_version=self.default_api_version, light_id=light_id
|
|
186
|
+
)
|
|
189
187
|
)
|
|
190
188
|
return GetCurrentIntensityResponse.decode(bytes_data).data
|
|
191
189
|
|
|
@@ -195,21 +193,19 @@ class LightHandler(ApiHandler[LightInformation]):
|
|
|
195
193
|
"""Automatically control the angle of illumination.
|
|
196
194
|
|
|
197
195
|
Using this mode means that the angle of illumination
|
|
198
|
-
is the same as the camera
|
|
196
|
+
is the same as the camera's angle of view.
|
|
199
197
|
"""
|
|
200
|
-
assert isinstance(self.api_version, str)
|
|
201
198
|
await self.vapix.api_request(
|
|
202
199
|
SetAutomaticAngleOfIlluminationModeRequest(
|
|
203
|
-
api_version=self.
|
|
200
|
+
api_version=self.default_api_version, light_id=light_id, enabled=enabled
|
|
204
201
|
)
|
|
205
202
|
)
|
|
206
203
|
|
|
207
204
|
async def get_valid_angle_of_illumination(self, light_id: str) -> list[Range]:
|
|
208
205
|
"""List the valid angle of illumination values."""
|
|
209
|
-
assert isinstance(self.api_version, str)
|
|
210
206
|
bytes_data = await self.vapix.api_request(
|
|
211
207
|
GetValidAngleOfIlluminationRequest(
|
|
212
|
-
api_version=self.
|
|
208
|
+
api_version=self.default_api_version, light_id=light_id
|
|
213
209
|
)
|
|
214
210
|
)
|
|
215
211
|
return GetValidAngleOfIlluminationResponse.decode(bytes_data).data
|
|
@@ -220,12 +216,11 @@ class LightHandler(ApiHandler[LightInformation]):
|
|
|
220
216
|
"""Set the manual angle of illumination.
|
|
221
217
|
|
|
222
218
|
This is useful when the angle of illumination needs
|
|
223
|
-
to be different from the camera
|
|
219
|
+
to be different from the camera's view angle.
|
|
224
220
|
"""
|
|
225
|
-
assert isinstance(self.api_version, str)
|
|
226
221
|
await self.vapix.api_request(
|
|
227
222
|
SetManualAngleOfIlluminationModeRequest(
|
|
228
|
-
api_version=self.
|
|
223
|
+
api_version=self.default_api_version,
|
|
229
224
|
light_id=light_id,
|
|
230
225
|
angle_of_illumination=angle_of_illumination,
|
|
231
226
|
)
|
|
@@ -233,20 +228,18 @@ class LightHandler(ApiHandler[LightInformation]):
|
|
|
233
228
|
|
|
234
229
|
async def get_manual_angle_of_illumination(self, light_id: str) -> int:
|
|
235
230
|
"""Get the angle of illumination."""
|
|
236
|
-
assert isinstance(self.api_version, str)
|
|
237
231
|
bytes_data = await self.vapix.api_request(
|
|
238
232
|
GetManualAngleOfIlluminationRequest(
|
|
239
|
-
api_version=self.
|
|
233
|
+
api_version=self.default_api_version, light_id=light_id
|
|
240
234
|
)
|
|
241
235
|
)
|
|
242
236
|
return GetManualAngleOfIlluminationResponse.decode(bytes_data).data
|
|
243
237
|
|
|
244
238
|
async def get_current_angle_of_illumination(self, light_id: str) -> int:
|
|
245
239
|
"""Receive the current angle of illumination."""
|
|
246
|
-
assert isinstance(self.api_version, str)
|
|
247
240
|
bytes_data = await self.vapix.api_request(
|
|
248
241
|
GetCurrentAngleOfIlluminationRequest(
|
|
249
|
-
api_version=self.
|
|
242
|
+
api_version=self.default_api_version, light_id=light_id
|
|
250
243
|
)
|
|
251
244
|
)
|
|
252
245
|
return GetCurrentAngleOfIlluminationResponse.decode(bytes_data).data
|
|
@@ -255,25 +248,22 @@ class LightHandler(ApiHandler[LightInformation]):
|
|
|
255
248
|
self, light_id: str, enabled: bool
|
|
256
249
|
) -> None:
|
|
257
250
|
"""Enable automatic synchronization with the day/night mode."""
|
|
258
|
-
assert isinstance(self.api_version, str)
|
|
259
251
|
await self.vapix.api_request(
|
|
260
252
|
SetLightSynchronizeDayNightModeRequest(
|
|
261
|
-
api_version=self.
|
|
253
|
+
api_version=self.default_api_version, light_id=light_id, enabled=enabled
|
|
262
254
|
)
|
|
263
255
|
)
|
|
264
256
|
|
|
265
257
|
async def get_light_synchronization_day_night_mode(self, light_id: str) -> bool:
|
|
266
258
|
"""Check if the automatic synchronization is enabled with the day/night mode."""
|
|
267
|
-
assert isinstance(self.api_version, str)
|
|
268
259
|
bytes_data = await self.vapix.api_request(
|
|
269
260
|
GetLightSynchronizeDayNightModeRequest(
|
|
270
|
-
api_version=self.
|
|
261
|
+
api_version=self.default_api_version, light_id=light_id
|
|
271
262
|
)
|
|
272
263
|
)
|
|
273
264
|
return GetLightSynchronizeDayNightModeResponse.decode(bytes_data).data
|
|
274
265
|
|
|
275
266
|
async def get_supported_versions(self) -> list[str]:
|
|
276
267
|
"""List supported API versions."""
|
|
277
|
-
assert isinstance(self.api_version, str)
|
|
278
268
|
bytes_data = await self.vapix.api_request(GetSupportedVersionsRequest())
|
|
279
269
|
return GetSupportedVersionsResponse.decode(bytes_data).data
|
|
@@ -6,6 +6,7 @@ import orjson
|
|
|
6
6
|
|
|
7
7
|
from ..models.api_discovery import ApiId
|
|
8
8
|
from ..models.mqtt import (
|
|
9
|
+
API_VERSION,
|
|
9
10
|
ActivateClientRequest,
|
|
10
11
|
ClientConfig,
|
|
11
12
|
ClientConfigStatus,
|
|
@@ -21,8 +22,6 @@ from ..models.mqtt import (
|
|
|
21
22
|
)
|
|
22
23
|
from .api_handler import ApiHandler
|
|
23
24
|
|
|
24
|
-
API_VERSION = "1.0"
|
|
25
|
-
|
|
26
25
|
DEFAULT_TOPICS = ["//."]
|
|
27
26
|
|
|
28
27
|
|
|
@@ -56,41 +55,36 @@ class MqttClientHandler(ApiHandler[Any]):
|
|
|
56
55
|
|
|
57
56
|
async def configure_client(self, client_config: ClientConfig) -> None:
|
|
58
57
|
"""Configure MQTT Client."""
|
|
59
|
-
discovery_item = self.vapix.api_discovery[self.api_id]
|
|
60
58
|
await self.vapix.api_request(
|
|
61
59
|
ConfigureClientRequest(
|
|
62
|
-
api_version=
|
|
60
|
+
api_version=self.default_api_version, client_config=client_config
|
|
63
61
|
)
|
|
64
62
|
)
|
|
65
63
|
|
|
66
64
|
async def activate(self) -> None:
|
|
67
65
|
"""Activate MQTT Client."""
|
|
68
|
-
discovery_item = self.vapix.api_discovery[self.api_id]
|
|
69
66
|
await self.vapix.api_request(
|
|
70
|
-
ActivateClientRequest(api_version=
|
|
67
|
+
ActivateClientRequest(api_version=self.default_api_version)
|
|
71
68
|
)
|
|
72
69
|
|
|
73
70
|
async def deactivate(self) -> None:
|
|
74
71
|
"""Deactivate MQTT Client."""
|
|
75
|
-
discovery_item = self.vapix.api_discovery[self.api_id]
|
|
76
72
|
await self.vapix.api_request(
|
|
77
|
-
DeactivateClientRequest(api_version=
|
|
73
|
+
DeactivateClientRequest(api_version=self.default_api_version)
|
|
78
74
|
)
|
|
79
75
|
|
|
80
76
|
async def get_client_status(self) -> ClientConfigStatus:
|
|
81
77
|
"""Get MQTT Client status."""
|
|
82
|
-
discovery_item = self.vapix.api_discovery[self.api_id]
|
|
83
78
|
bytes_data = await self.vapix.api_request(
|
|
84
|
-
GetClientStatusRequest(api_version=
|
|
79
|
+
GetClientStatusRequest(api_version=self.default_api_version)
|
|
85
80
|
)
|
|
86
81
|
response = GetClientStatusResponse.decode(bytes_data)
|
|
87
82
|
return response.data
|
|
88
83
|
|
|
89
84
|
async def get_event_publication_config(self) -> EventPublicationConfig:
|
|
90
85
|
"""Get MQTT Client event publication config."""
|
|
91
|
-
discovery_item = self.vapix.api_discovery[self.api_id]
|
|
92
86
|
bytes_data = await self.vapix.api_request(
|
|
93
|
-
GetEventPublicationConfigRequest(api_version=
|
|
87
|
+
GetEventPublicationConfigRequest(api_version=self.default_api_version)
|
|
94
88
|
)
|
|
95
89
|
response = GetEventPublicationConfigResponse.decode(bytes_data)
|
|
96
90
|
return response.data
|
|
@@ -99,13 +93,12 @@ class MqttClientHandler(ApiHandler[Any]):
|
|
|
99
93
|
self, topics: list[str] = DEFAULT_TOPICS
|
|
100
94
|
) -> None:
|
|
101
95
|
"""Configure MQTT Client event publication."""
|
|
102
|
-
discovery_item = self.vapix.api_discovery[self.api_id]
|
|
103
96
|
event_filters = EventFilter.from_list(
|
|
104
97
|
[{"topicFilter": topic} for topic in topics]
|
|
105
98
|
)
|
|
106
99
|
config = EventPublicationConfig(event_filter_list=event_filters)
|
|
107
100
|
await self.vapix.api_request(
|
|
108
101
|
ConfigureEventPublicationRequest(
|
|
109
|
-
api_version=
|
|
102
|
+
api_version=self.default_api_version, config=config
|
|
110
103
|
)
|
|
111
104
|
)
|
|
@@ -45,7 +45,7 @@ class IoPortManagement(ApiHandler[Port]):
|
|
|
45
45
|
* Configuring the states and what constitutes a normal
|
|
46
46
|
and triggered state respectively.
|
|
47
47
|
This will make triggers activate in either open or closed circuits.
|
|
48
|
-
The reason the change is treated as a nice name is because it doesn
|
|
48
|
+
The reason the change is treated as a nice name is because it doesn't
|
|
49
49
|
affect the underlying behavior of the port.
|
|
50
50
|
Devices with configurable ports can change the direction
|
|
51
51
|
to either input or output.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Python library to enable Axis devices to integrate with Home Assistant."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import asyncio
|
|
4
6
|
import logging
|
|
5
7
|
from typing import TYPE_CHECKING, Any
|
|
@@ -7,11 +9,8 @@ from typing import TYPE_CHECKING, Any
|
|
|
7
9
|
import httpx
|
|
8
10
|
|
|
9
11
|
from ..errors import RequestError, raise_error
|
|
10
|
-
from ..models.api import ApiRequest
|
|
11
12
|
from ..models.pwdgrp_cgi import SecondaryGroup
|
|
12
|
-
from ..models.stream_profile import StreamProfile
|
|
13
13
|
from .api_discovery import ApiDiscoveryHandler
|
|
14
|
-
from .api_handler import ApiHandler
|
|
15
14
|
from .applications import (
|
|
16
15
|
ApplicationsHandler,
|
|
17
16
|
)
|
|
@@ -40,6 +39,9 @@ from .view_areas import ViewAreaHandler
|
|
|
40
39
|
|
|
41
40
|
if TYPE_CHECKING:
|
|
42
41
|
from ..device import AxisDevice
|
|
42
|
+
from ..models.api import ApiRequest
|
|
43
|
+
from ..models.stream_profile import StreamProfile
|
|
44
|
+
from .api_handler import ApiHandler
|
|
43
45
|
|
|
44
46
|
LOGGER = logging.getLogger(__name__)
|
|
45
47
|
|
|
@@ -49,7 +51,7 @@ TIME_OUT = 15
|
|
|
49
51
|
class Vapix:
|
|
50
52
|
"""Vapix parameter request."""
|
|
51
53
|
|
|
52
|
-
def __init__(self, device:
|
|
54
|
+
def __init__(self, device: AxisDevice) -> None:
|
|
53
55
|
"""Store local reference to device config."""
|
|
54
56
|
self.device = device
|
|
55
57
|
self.auth = httpx.DigestAuth(device.config.username, device.config.password)
|
|
@@ -274,16 +276,19 @@ class Vapix:
|
|
|
274
276
|
timeout=TIME_OUT,
|
|
275
277
|
)
|
|
276
278
|
|
|
277
|
-
except httpx.TimeoutException:
|
|
278
|
-
|
|
279
|
+
except httpx.TimeoutException as errt:
|
|
280
|
+
message = "Timeout"
|
|
281
|
+
raise RequestError(message) from errt
|
|
279
282
|
|
|
280
283
|
except httpx.TransportError as errc:
|
|
281
284
|
LOGGER.debug("%s", errc)
|
|
282
|
-
|
|
285
|
+
message = f"Connection error: {errc}"
|
|
286
|
+
raise RequestError(message) from errc
|
|
283
287
|
|
|
284
288
|
except httpx.RequestError as err:
|
|
285
289
|
LOGGER.debug("%s", err)
|
|
286
|
-
|
|
290
|
+
message = f"Unknown error: {err}"
|
|
291
|
+
raise RequestError(message) from err
|
|
287
292
|
|
|
288
293
|
try:
|
|
289
294
|
response.raise_for_status()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""View area API.
|
|
2
2
|
|
|
3
|
-
The View Area API makes it possible to define the subsections of a camera
|
|
3
|
+
The View Area API makes it possible to define the subsections of a camera's full view
|
|
4
4
|
as individual, virtual channels. This means that a wide angle and/or high resolution
|
|
5
5
|
camera can provide multiple video streams at a lower resolution where each stream
|
|
6
6
|
covers a specific region of interest. The API is also able to simplify the installation
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Light Control API data model."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
from dataclasses import dataclass
|
|
4
6
|
from typing import NotRequired, Self
|
|
5
7
|
|
|
@@ -225,14 +227,14 @@ class Range:
|
|
|
225
227
|
high: int
|
|
226
228
|
|
|
227
229
|
@classmethod
|
|
228
|
-
def from_dict(cls, data: RangeT) ->
|
|
230
|
+
def from_dict(cls, data: RangeT) -> Self:
|
|
229
231
|
"""Create range object from dict."""
|
|
230
|
-
return
|
|
232
|
+
return cls(low=data["low"], high=data["high"])
|
|
231
233
|
|
|
232
234
|
@classmethod
|
|
233
|
-
def from_list(cls, data: list[RangeT]) -> list[
|
|
235
|
+
def from_list(cls, data: list[RangeT]) -> list[Self]:
|
|
234
236
|
"""Create range object from dict."""
|
|
235
|
-
return [
|
|
237
|
+
return [cls.from_dict(range) for range in data]
|
|
236
238
|
|
|
237
239
|
|
|
238
240
|
@dataclass
|
|
@@ -277,7 +279,7 @@ class GetLightInformationResponse(ApiResponse[dict[str, LightInformation]]):
|
|
|
277
279
|
api_version=data["apiVersion"],
|
|
278
280
|
context=data["context"],
|
|
279
281
|
method=data["method"],
|
|
280
|
-
data=LightInformation.decode_to_dict(data
|
|
282
|
+
data=LightInformation.decode_to_dict(data.get("data", {}).get("items", [])),
|
|
281
283
|
)
|
|
282
284
|
|
|
283
285
|
|
|
@@ -294,9 +296,9 @@ class ServiceCapabilities:
|
|
|
294
296
|
day_night_synchronize_support: bool
|
|
295
297
|
|
|
296
298
|
@classmethod
|
|
297
|
-
def from_dict(cls, data: ServiceCapabilitiesT) ->
|
|
299
|
+
def from_dict(cls, data: ServiceCapabilitiesT) -> Self:
|
|
298
300
|
"""Create service capabilities object from dict."""
|
|
299
|
-
return
|
|
301
|
+
return cls(
|
|
300
302
|
automatic_intensity_support=data["automaticIntensitySupport"],
|
|
301
303
|
manual_intensity_support=data["manualIntensitySupport"],
|
|
302
304
|
get_current_intensity_support=data["getCurrentIntensitySupport"],
|