axis 62__tar.gz → 64__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.
Files changed (108) hide show
  1. axis-64/PKG-INFO +41 -0
  2. {axis-62 → axis-64}/axis/__main__.py +2 -2
  3. {axis-62 → axis-64}/axis/interfaces/mqtt.py +1 -1
  4. {axis-62 → axis-64}/axis/models/event.py +8 -3
  5. {axis-62 → axis-64}/axis/models/ptz_cgi.py +1 -2
  6. {axis-62 → axis-64}/axis/rtsp.py +15 -2
  7. axis-64/axis.egg-info/PKG-INFO +41 -0
  8. axis-64/axis.egg-info/requires.txt +23 -0
  9. {axis-62 → axis-64}/pyproject.toml +15 -16
  10. {axis-62 → axis-64}/tests/test_event.py +24 -0
  11. {axis-62 → axis-64}/tests/test_rtsp.py +27 -3
  12. axis-62/PKG-INFO +0 -24
  13. axis-62/axis.egg-info/PKG-INFO +0 -24
  14. axis-62/axis.egg-info/requires.txt +0 -24
  15. {axis-62 → axis-64}/LICENSE +0 -0
  16. {axis-62 → axis-64}/README.md +0 -0
  17. {axis-62 → axis-64}/axis/__init__.py +0 -0
  18. {axis-62 → axis-64}/axis/device.py +0 -0
  19. {axis-62 → axis-64}/axis/errors.py +0 -0
  20. {axis-62 → axis-64}/axis/interfaces/__init__.py +0 -0
  21. {axis-62 → axis-64}/axis/interfaces/api_discovery.py +0 -0
  22. {axis-62 → axis-64}/axis/interfaces/api_handler.py +0 -0
  23. {axis-62 → axis-64}/axis/interfaces/applications/__init__.py +0 -0
  24. {axis-62 → axis-64}/axis/interfaces/applications/application_handler.py +0 -0
  25. {axis-62 → axis-64}/axis/interfaces/applications/applications.py +0 -0
  26. {axis-62 → axis-64}/axis/interfaces/applications/fence_guard.py +0 -0
  27. {axis-62 → axis-64}/axis/interfaces/applications/loitering_guard.py +0 -0
  28. {axis-62 → axis-64}/axis/interfaces/applications/motion_guard.py +0 -0
  29. {axis-62 → axis-64}/axis/interfaces/applications/object_analytics.py +0 -0
  30. {axis-62 → axis-64}/axis/interfaces/applications/vmd4.py +0 -0
  31. {axis-62 → axis-64}/axis/interfaces/basic_device_info.py +0 -0
  32. {axis-62 → axis-64}/axis/interfaces/event_instances.py +0 -0
  33. {axis-62 → axis-64}/axis/interfaces/event_manager.py +0 -0
  34. {axis-62 → axis-64}/axis/interfaces/light_control.py +0 -0
  35. {axis-62 → axis-64}/axis/interfaces/parameters/__init__.py +0 -0
  36. {axis-62 → axis-64}/axis/interfaces/parameters/brand.py +0 -0
  37. {axis-62 → axis-64}/axis/interfaces/parameters/image.py +0 -0
  38. {axis-62 → axis-64}/axis/interfaces/parameters/io_port.py +0 -0
  39. {axis-62 → axis-64}/axis/interfaces/parameters/param_cgi.py +0 -0
  40. {axis-62 → axis-64}/axis/interfaces/parameters/param_handler.py +0 -0
  41. {axis-62 → axis-64}/axis/interfaces/parameters/properties.py +0 -0
  42. {axis-62 → axis-64}/axis/interfaces/parameters/ptz.py +0 -0
  43. {axis-62 → axis-64}/axis/interfaces/parameters/stream_profile.py +0 -0
  44. {axis-62 → axis-64}/axis/interfaces/pir_sensor_configuration.py +0 -0
  45. {axis-62 → axis-64}/axis/interfaces/port_cgi.py +0 -0
  46. {axis-62 → axis-64}/axis/interfaces/port_management.py +0 -0
  47. {axis-62 → axis-64}/axis/interfaces/ptz.py +0 -0
  48. {axis-62 → axis-64}/axis/interfaces/pwdgrp_cgi.py +0 -0
  49. {axis-62 → axis-64}/axis/interfaces/stream_profiles.py +0 -0
  50. {axis-62 → axis-64}/axis/interfaces/user_groups.py +0 -0
  51. {axis-62 → axis-64}/axis/interfaces/vapix.py +0 -0
  52. {axis-62 → axis-64}/axis/interfaces/view_areas.py +0 -0
  53. {axis-62 → axis-64}/axis/models/__init__.py +0 -0
  54. {axis-62 → axis-64}/axis/models/api.py +0 -0
  55. {axis-62 → axis-64}/axis/models/api_discovery.py +0 -0
  56. {axis-62 → axis-64}/axis/models/applications/__init__.py +0 -0
  57. {axis-62 → axis-64}/axis/models/applications/application.py +0 -0
  58. {axis-62 → axis-64}/axis/models/applications/fence_guard.py +0 -0
  59. {axis-62 → axis-64}/axis/models/applications/loitering_guard.py +0 -0
  60. {axis-62 → axis-64}/axis/models/applications/motion_guard.py +0 -0
  61. {axis-62 → axis-64}/axis/models/applications/object_analytics.py +0 -0
  62. {axis-62 → axis-64}/axis/models/applications/vmd4.py +0 -0
  63. {axis-62 → axis-64}/axis/models/basic_device_info.py +0 -0
  64. {axis-62 → axis-64}/axis/models/configuration.py +0 -0
  65. {axis-62 → axis-64}/axis/models/event_instance.py +0 -0
  66. {axis-62 → axis-64}/axis/models/light_control.py +0 -0
  67. {axis-62 → axis-64}/axis/models/mqtt.py +0 -0
  68. {axis-62 → axis-64}/axis/models/parameters/__init__.py +0 -0
  69. {axis-62 → axis-64}/axis/models/parameters/brand.py +0 -0
  70. {axis-62 → axis-64}/axis/models/parameters/image.py +0 -0
  71. {axis-62 → axis-64}/axis/models/parameters/io_port.py +0 -0
  72. {axis-62 → axis-64}/axis/models/parameters/param_cgi.py +0 -0
  73. {axis-62 → axis-64}/axis/models/parameters/properties.py +0 -0
  74. {axis-62 → axis-64}/axis/models/parameters/ptz.py +0 -0
  75. {axis-62 → axis-64}/axis/models/parameters/stream_profile.py +0 -0
  76. {axis-62 → axis-64}/axis/models/pir_sensor_configuration.py +0 -0
  77. {axis-62 → axis-64}/axis/models/port_cgi.py +0 -0
  78. {axis-62 → axis-64}/axis/models/port_management.py +0 -0
  79. {axis-62 → axis-64}/axis/models/pwdgrp_cgi.py +0 -0
  80. {axis-62 → axis-64}/axis/models/stream_profile.py +0 -0
  81. {axis-62 → axis-64}/axis/models/user_group.py +0 -0
  82. {axis-62 → axis-64}/axis/models/view_area.py +0 -0
  83. {axis-62 → axis-64}/axis/py.typed +0 -0
  84. {axis-62 → axis-64}/axis/stream_manager.py +0 -0
  85. {axis-62 → axis-64}/axis.egg-info/SOURCES.txt +0 -0
  86. {axis-62 → axis-64}/axis.egg-info/dependency_links.txt +0 -0
  87. {axis-62 → axis-64}/axis.egg-info/entry_points.txt +0 -0
  88. {axis-62 → axis-64}/axis.egg-info/top_level.txt +0 -0
  89. {axis-62 → axis-64}/setup.cfg +0 -0
  90. {axis-62 → axis-64}/tests/test_api_discovery.py +0 -0
  91. {axis-62 → axis-64}/tests/test_api_handler.py +0 -0
  92. {axis-62 → axis-64}/tests/test_basic_device_info.py +0 -0
  93. {axis-62 → axis-64}/tests/test_configuration.py +0 -0
  94. {axis-62 → axis-64}/tests/test_device.py +0 -0
  95. {axis-62 → axis-64}/tests/test_event_instances.py +0 -0
  96. {axis-62 → axis-64}/tests/test_event_stream.py +0 -0
  97. {axis-62 → axis-64}/tests/test_light_control.py +0 -0
  98. {axis-62 → axis-64}/tests/test_mqtt.py +0 -0
  99. {axis-62 → axis-64}/tests/test_pir_sensor_configuration.py +0 -0
  100. {axis-62 → axis-64}/tests/test_port_cgi.py +0 -0
  101. {axis-62 → axis-64}/tests/test_port_management.py +0 -0
  102. {axis-62 → axis-64}/tests/test_ptz.py +0 -0
  103. {axis-62 → axis-64}/tests/test_pwdgrp_cgi.py +0 -0
  104. {axis-62 → axis-64}/tests/test_stream_manager.py +0 -0
  105. {axis-62 → axis-64}/tests/test_stream_profiles.py +0 -0
  106. {axis-62 → axis-64}/tests/test_user_groups.py +0 -0
  107. {axis-62 → axis-64}/tests/test_vapix.py +0 -0
  108. {axis-62 → axis-64}/tests/test_view_areas.py +0 -0
axis-64/PKG-INFO ADDED
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.1
2
+ Name: axis
3
+ Version: 64
4
+ Summary: A Python library for communicating with devices from Axis Communications
5
+ Author-email: Robert Svensson <Kane610@users.noreply.github.com>
6
+ License: MIT
7
+ Project-URL: Source Code, https://github.com/Kane610/axis
8
+ Project-URL: Bug Reports, https://github.com/Kane610/axis/issues
9
+ Project-URL: Forum, https://community.home-assistant.io/t/axis-camera-component/
10
+ Keywords: axis,vapix,homeassistant
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Home Automation
17
+ Requires-Python: >=3.12.0
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: httpx>=0.26
21
+ Requires-Dist: orjson>3.9
22
+ Requires-Dist: packaging>23
23
+ Requires-Dist: xmltodict>=0.13.0
24
+ Provides-Extra: requirements
25
+ Requires-Dist: httpx==0.27.2; extra == "requirements"
26
+ Requires-Dist: orjson==3.10.12; extra == "requirements"
27
+ Requires-Dist: packaging==24.2; extra == "requirements"
28
+ Requires-Dist: xmltodict==0.14.2; extra == "requirements"
29
+ Provides-Extra: requirements-test
30
+ Requires-Dist: mypy==1.13.0; extra == "requirements-test"
31
+ Requires-Dist: pytest==8.3.4; extra == "requirements-test"
32
+ Requires-Dist: pytest-aiohttp==1.0.5; extra == "requirements-test"
33
+ Requires-Dist: pytest-asyncio==0.25.0; extra == "requirements-test"
34
+ Requires-Dist: pytest-cov==6.0.0; extra == "requirements-test"
35
+ Requires-Dist: respx==0.21.1; extra == "requirements-test"
36
+ Requires-Dist: ruff==0.8.3; extra == "requirements-test"
37
+ Requires-Dist: types-xmltodict==v0.14.0.20241009; extra == "requirements-test"
38
+ Provides-Extra: requirements-dev
39
+ Requires-Dist: pre-commit==4.0.1; extra == "requirements-dev"
40
+
41
+ Python project to set up a connection towards Axis Communications devices and to subscribe to specific events on the metadatastream.
@@ -71,8 +71,8 @@ async def main(
71
71
 
72
72
  try:
73
73
  if events:
74
- while True:
75
- await asyncio.sleep(1)
74
+ done = asyncio.Event()
75
+ await done.wait()
76
76
 
77
77
  except asyncio.CancelledError:
78
78
  device.stream.stop()
@@ -25,7 +25,7 @@ from .api_handler import ApiHandler
25
25
  DEFAULT_TOPICS = ["//."]
26
26
 
27
27
 
28
- def mqtt_json_to_event(msg: bytes | str) -> dict[str, Any]:
28
+ def mqtt_json_to_event(msg: bytes | bytearray | memoryview | str) -> dict[str, Any]:
29
29
  """Convert JSON message from MQTT to event format."""
30
30
  message = orjson.loads(msg)
31
31
  topic = message["topic"].replace("onvif", "tns1").replace("axis", "tnsaxis")
@@ -122,12 +122,17 @@ def traverse(
122
122
 
123
123
 
124
124
  def extract_name_value(
125
- data: dict[str, list[dict[str, str]] | dict[str, str]],
125
+ data: dict[str, list[dict[str, str]] | dict[str, str]], prefer: str | None = None
126
126
  ) -> tuple[str, str]:
127
127
  """Extract name and value from a simple item, take first dictionary if it is a list."""
128
128
  item = data.get("SimpleItem", {})
129
129
  if isinstance(item, list):
130
- item = item[0]
130
+ if prefer is None:
131
+ item = item[0]
132
+ else:
133
+ item = next(
134
+ (item for item in item if item.get("@Name", "") == prefer), item[0]
135
+ )
131
136
  return item.get("@Name", ""), item.get("@Value", "")
132
137
  # return item.get("Name", ""), item.get("Value", "")
133
138
 
@@ -206,7 +211,7 @@ class Event:
206
211
 
207
212
  data_type = data_value = ""
208
213
  if match := traverse(raw, DATA):
209
- data_type, data_value = extract_name_value(match)
214
+ data_type, data_value = extract_name_value(match, "active")
210
215
 
211
216
  return cls._decode_from_dict(
212
217
  {
@@ -269,8 +269,7 @@ class PtzControlRequest(ApiRequest):
269
269
  data["center"] = f"{x},{y}"
270
270
  if self.area_zoom:
271
271
  x, y, z = self.area_zoom
272
- if z < 1:
273
- z = 1
272
+ z = max(z, 1)
274
273
  data["areazoom"] = f"{x},{y},{z}"
275
274
  if self.center or self.area_zoom:
276
275
  if self.image_width:
@@ -35,6 +35,7 @@ class State(enum.StrEnum):
35
35
 
36
36
 
37
37
  TIME_OUT_LIMIT = 5
38
+ RTP_HEADER_SIZE = 12
38
39
 
39
40
 
40
41
  class RTSPClient(asyncio.Protocol):
@@ -191,6 +192,7 @@ class RTPClient:
191
192
  self.callback = callback
192
193
  self.data: deque[bytes] = deque()
193
194
  self.transport: asyncio.BaseTransport | None = None
195
+ self.fragment: bool = False
194
196
 
195
197
  def connection_made(self, transport: asyncio.BaseTransport) -> None:
196
198
  """Execute when port is up and listening.
@@ -207,8 +209,19 @@ class RTPClient:
207
209
  def datagram_received(self, data: bytes, addr: Any) -> None:
208
210
  """Signals when new data is available."""
209
211
  if self.callback:
210
- self.data.append(data[12:])
211
- self.callback(Signal.DATA)
212
+ payload = data[RTP_HEADER_SIZE:]
213
+
214
+ # if the previous packet was a fragment, then merge it
215
+ if self.fragment:
216
+ previous = self.data.pop()
217
+ self.data.append(previous + payload)
218
+ else:
219
+ self.data.append(payload)
220
+
221
+ # check whether the RTP marker bit is set, if not it is a fragment
222
+ self.fragment = (data[1] & 0b1 << 7) == 0
223
+ if not self.fragment:
224
+ self.callback(Signal.DATA)
212
225
 
213
226
 
214
227
  class RTSPSession:
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.1
2
+ Name: axis
3
+ Version: 64
4
+ Summary: A Python library for communicating with devices from Axis Communications
5
+ Author-email: Robert Svensson <Kane610@users.noreply.github.com>
6
+ License: MIT
7
+ Project-URL: Source Code, https://github.com/Kane610/axis
8
+ Project-URL: Bug Reports, https://github.com/Kane610/axis/issues
9
+ Project-URL: Forum, https://community.home-assistant.io/t/axis-camera-component/
10
+ Keywords: axis,vapix,homeassistant
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Home Automation
17
+ Requires-Python: >=3.12.0
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: httpx>=0.26
21
+ Requires-Dist: orjson>3.9
22
+ Requires-Dist: packaging>23
23
+ Requires-Dist: xmltodict>=0.13.0
24
+ Provides-Extra: requirements
25
+ Requires-Dist: httpx==0.27.2; extra == "requirements"
26
+ Requires-Dist: orjson==3.10.12; extra == "requirements"
27
+ Requires-Dist: packaging==24.2; extra == "requirements"
28
+ Requires-Dist: xmltodict==0.14.2; extra == "requirements"
29
+ Provides-Extra: requirements-test
30
+ Requires-Dist: mypy==1.13.0; extra == "requirements-test"
31
+ Requires-Dist: pytest==8.3.4; extra == "requirements-test"
32
+ Requires-Dist: pytest-aiohttp==1.0.5; extra == "requirements-test"
33
+ Requires-Dist: pytest-asyncio==0.25.0; extra == "requirements-test"
34
+ Requires-Dist: pytest-cov==6.0.0; extra == "requirements-test"
35
+ Requires-Dist: respx==0.21.1; extra == "requirements-test"
36
+ Requires-Dist: ruff==0.8.3; extra == "requirements-test"
37
+ Requires-Dist: types-xmltodict==v0.14.0.20241009; extra == "requirements-test"
38
+ Provides-Extra: requirements-dev
39
+ Requires-Dist: pre-commit==4.0.1; extra == "requirements-dev"
40
+
41
+ Python project to set up a connection towards Axis Communications devices and to subscribe to specific events on the metadatastream.
@@ -0,0 +1,23 @@
1
+ httpx>=0.26
2
+ orjson>3.9
3
+ packaging>23
4
+ xmltodict>=0.13.0
5
+
6
+ [requirements]
7
+ httpx==0.27.2
8
+ orjson==3.10.12
9
+ packaging==24.2
10
+ xmltodict==0.14.2
11
+
12
+ [requirements-dev]
13
+ pre-commit==4.0.1
14
+
15
+ [requirements-test]
16
+ mypy==1.13.0
17
+ pytest==8.3.4
18
+ pytest-aiohttp==1.0.5
19
+ pytest-asyncio==0.25.0
20
+ pytest-cov==6.0.0
21
+ respx==0.21.1
22
+ ruff==0.8.3
23
+ types-xmltodict==v0.14.0.20241009
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["setuptools==68.0.0", "wheel==0.40.0"]
2
+ requires = ["setuptools==75.6.0", "wheel==0.45.1"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "axis"
7
- version = "62"
7
+ version = "64"
8
8
  license = {text = "MIT"}
9
9
  description = "A Python library for communicating with devices from Axis Communications"
10
10
  readme = "README.md"
@@ -28,24 +28,23 @@ dependencies = [
28
28
 
29
29
  [project.optional-dependencies]
30
30
  requirements = [
31
- "httpx==0.27.0",
32
- "orjson==3.10.6",
33
- "packaging==24.1",
34
- "xmltodict==0.13.0",
31
+ "httpx==0.27.2",
32
+ "orjson==3.10.12",
33
+ "packaging==24.2",
34
+ "xmltodict==0.14.2",
35
35
  ]
36
- requirements_test = [
37
- "mypy==1.10.1",
38
- "pytest==8.2.2",
36
+ requirements-test = [
37
+ "mypy==1.13.0",
38
+ "pytest==8.3.4",
39
39
  "pytest-aiohttp==1.0.5",
40
- "pytest-asyncio==0.23.7",
41
- "pytest-cov==5.0.0",
40
+ "pytest-asyncio==0.25.0",
41
+ "pytest-cov==6.0.0",
42
42
  "respx==0.21.1",
43
- "ruff==0.5.0",
44
- "types-orjson==3.6.2",
45
- "types-xmltodict==v0.13.0.3",
43
+ "ruff==0.8.3",
44
+ "types-xmltodict==v0.14.0.20241009",
46
45
  ]
47
- requirements_dev = [
48
- "pre-commit==3.7.1"
46
+ requirements-dev = [
47
+ "pre-commit==4.0.1"
49
48
  ]
50
49
 
51
50
  [project.urls]
@@ -18,6 +18,7 @@ from .event_fixtures import (
18
18
  LIGHT_STATUS_INIT,
19
19
  LOITERING_GUARD_INIT,
20
20
  MOTION_GUARD_INIT,
21
+ OBJECT_ANALYTICS_ANY_CHANGE,
21
22
  OBJECT_ANALYTICS_INIT,
22
23
  PIR_CHANGE,
23
24
  PIR_INIT,
@@ -133,6 +134,18 @@ from .event_fixtures import (
133
134
  "tripped": False,
134
135
  },
135
136
  ),
137
+ (
138
+ OBJECT_ANALYTICS_ANY_CHANGE,
139
+ {
140
+ "topic": "tnsaxis:CameraApplicationPlatform/ObjectAnalytics/Device1Scenario1",
141
+ "source": "",
142
+ "source_idx": "Device1Scenario1",
143
+ "group": EventGroup.MOTION,
144
+ "type": "Object Analytics",
145
+ "state": "1",
146
+ "tripped": True,
147
+ },
148
+ ),
136
149
  (
137
150
  PIR_INIT,
138
151
  {
@@ -329,6 +342,17 @@ def test_create_event(input: bytes, expected: tuple) -> None:
329
342
  "value": "1",
330
343
  },
331
344
  ),
345
+ (
346
+ OBJECT_ANALYTICS_ANY_CHANGE,
347
+ {
348
+ "operation": "Changed",
349
+ "topic": "tnsaxis:CameraApplicationPlatform/ObjectAnalytics/Device1Scenario1",
350
+ "source": "",
351
+ "source_idx": "",
352
+ "type": "active",
353
+ "value": "1",
354
+ },
355
+ ),
332
356
  ],
333
357
  )
334
358
  def test_parse_event_xml(input: bytes, expected: dict):
@@ -9,9 +9,14 @@ from unittest.mock import Mock, patch
9
9
 
10
10
  import pytest
11
11
 
12
- from axis.rtsp import RTSPClient, Signal, State
12
+ from axis.rtsp import RTP_HEADER_SIZE, RTSPClient, Signal, State
13
13
 
14
14
  from .conftest import HOST, RTSP_PORT
15
+ from .packet_fixtures import (
16
+ RTP_PACKET1_FULL,
17
+ RTP_PACKET2_FRAGMENT1,
18
+ RTP_PACKET2_FRAGMENT2,
19
+ )
15
20
 
16
21
  LOGGER = logging.getLogger(__name__)
17
22
 
@@ -514,14 +519,33 @@ def test_rtp_client(rtsp_client, caplog):
514
519
  assert "Stream recepient offline" in caplog.text
515
520
 
516
521
  with patch.object(rtp_client.client, "callback") as mock_callback:
517
- rtp_client.client.datagram_received("0123456789ABCDEF", "addr")
522
+ rtp_client.client.datagram_received(
523
+ bytes.fromhex("008000000000000000000000AABBCCDD"), "addr"
524
+ )
518
525
  mock_callback.assert_called_with(Signal.DATA)
519
- assert rtp_client.data == "CDEF"
526
+ assert rtp_client.data == bytes.fromhex("AABBCCDD")
520
527
 
521
528
  rtsp_client.stop()
522
529
  mock_transport.close.assert_called()
523
530
 
524
531
 
532
+ @pytest.mark.parametrize(
533
+ ("packets"),
534
+ [([RTP_PACKET1_FULL]), ([RTP_PACKET2_FRAGMENT1, RTP_PACKET2_FRAGMENT2])],
535
+ )
536
+ def test_rtp_fragment(rtsp_client, packets: list[bytes]):
537
+ """Verify RTP fragment handling."""
538
+ rtp_client = rtsp_client.rtp
539
+
540
+ with patch.object(rtp_client.client, "callback") as mock_callback:
541
+ payload = b""
542
+ for packet in packets:
543
+ rtp_client.client.datagram_received(packet, "addr")
544
+ payload += packet[RTP_HEADER_SIZE:]
545
+ mock_callback.assert_called_with(Signal.DATA)
546
+ assert rtp_client.data == payload
547
+
548
+
525
549
  def test_methods(rtsp_client):
526
550
  """Verify method attributes."""
527
551
  method = rtsp_client.method
axis-62/PKG-INFO DELETED
@@ -1,24 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: axis
3
- Version: 62
4
- Summary: A Python library for communicating with devices from Axis Communications
5
- Author-email: Robert Svensson <Kane610@users.noreply.github.com>
6
- License: MIT
7
- Project-URL: Source Code, https://github.com/Kane610/axis
8
- Project-URL: Bug Reports, https://github.com/Kane610/axis/issues
9
- Project-URL: Forum, https://community.home-assistant.io/t/axis-camera-component/
10
- Keywords: axis,vapix,homeassistant
11
- Classifier: Development Status :: 5 - Production/Stable
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python :: 3.12
16
- Classifier: Topic :: Home Automation
17
- Requires-Python: >=3.12.0
18
- Description-Content-Type: text/markdown
19
- Provides-Extra: requirements
20
- Provides-Extra: requirements_test
21
- Provides-Extra: requirements_dev
22
- License-File: LICENSE
23
-
24
- Python project to set up a connection towards Axis Communications devices and to subscribe to specific events on the metadatastream.
@@ -1,24 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: axis
3
- Version: 62
4
- Summary: A Python library for communicating with devices from Axis Communications
5
- Author-email: Robert Svensson <Kane610@users.noreply.github.com>
6
- License: MIT
7
- Project-URL: Source Code, https://github.com/Kane610/axis
8
- Project-URL: Bug Reports, https://github.com/Kane610/axis/issues
9
- Project-URL: Forum, https://community.home-assistant.io/t/axis-camera-component/
10
- Keywords: axis,vapix,homeassistant
11
- Classifier: Development Status :: 5 - Production/Stable
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python :: 3.12
16
- Classifier: Topic :: Home Automation
17
- Requires-Python: >=3.12.0
18
- Description-Content-Type: text/markdown
19
- Provides-Extra: requirements
20
- Provides-Extra: requirements_test
21
- Provides-Extra: requirements_dev
22
- License-File: LICENSE
23
-
24
- Python project to set up a connection towards Axis Communications devices and to subscribe to specific events on the metadatastream.
@@ -1,24 +0,0 @@
1
- httpx>=0.26
2
- orjson>3.9
3
- packaging>23
4
- xmltodict>=0.13.0
5
-
6
- [requirements]
7
- httpx==0.27.0
8
- orjson==3.10.6
9
- packaging==24.1
10
- xmltodict==0.13.0
11
-
12
- [requirements_dev]
13
- pre-commit==3.7.1
14
-
15
- [requirements_test]
16
- mypy==1.10.1
17
- pytest==8.2.2
18
- pytest-aiohttp==1.0.5
19
- pytest-asyncio==0.23.7
20
- pytest-cov==5.0.0
21
- respx==0.21.1
22
- ruff==0.5.0
23
- types-orjson==3.6.2
24
- types-xmltodict==v0.13.0.3
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes