onvif-python 0.0.6__tar.gz → 0.0.7__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 (123) hide show
  1. {onvif_python-0.0.6/onvif_python.egg-info → onvif_python-0.0.7}/PKG-INFO +188 -3
  2. {onvif_python-0.0.6 → onvif_python-0.0.7}/README.md +187 -2
  3. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/__init__.py +3 -5
  4. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/client.py +3 -8
  5. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/operator.py +3 -4
  6. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/imaging.py +3 -1
  7. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/provisioning.py +1 -1
  8. onvif_python-0.0.7/onvif/utils/__init__.py +14 -0
  9. onvif_python-0.0.7/onvif/utils/error_handlers.py +76 -0
  10. onvif_python-0.0.7/onvif/utils/exceptions.py +69 -0
  11. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/utils/xml_capture.py +38 -38
  12. onvif_python-0.0.7/onvif/utils/zeep.py +385 -0
  13. {onvif_python-0.0.6 → onvif_python-0.0.7/onvif_python.egg-info}/PKG-INFO +188 -3
  14. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif_python.egg-info/SOURCES.txt +1 -0
  15. {onvif_python-0.0.6 → onvif_python-0.0.7}/pyproject.toml +1 -1
  16. onvif_python-0.0.6/onvif/utils/__init__.py +0 -5
  17. onvif_python-0.0.6/onvif/utils/exceptions.py +0 -33
  18. onvif_python-0.0.6/onvif/utils/zeep.py +0 -286
  19. {onvif_python-0.0.6 → onvif_python-0.0.7}/LICENSE.md +0 -0
  20. {onvif_python-0.0.6 → onvif_python-0.0.7}/MANIFEST.in +0 -0
  21. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/__init__.py +0 -0
  22. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/accesscontrol.py +0 -0
  23. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/accessrules.py +0 -0
  24. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/actionengine.py +0 -0
  25. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/analytics/analytics.py +0 -0
  26. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/analytics/ruleengine.py +0 -0
  27. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/analyticsdevice.py +0 -0
  28. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/appmgmt.py +0 -0
  29. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/authenticationbehavior.py +0 -0
  30. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/credential.py +0 -0
  31. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/deviceio.py +0 -0
  32. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/devicemgmt.py +0 -0
  33. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/display.py +0 -0
  34. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/doorcontrol.py +0 -0
  35. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/events/events.py +0 -0
  36. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/events/notification.py +0 -0
  37. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/events/pullpoint.py +0 -0
  38. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/events/subscription.py +0 -0
  39. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/media.py +0 -0
  40. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/media2.py +0 -0
  41. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/ptz.py +0 -0
  42. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/receiver.py +0 -0
  43. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/recording.py +0 -0
  44. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/replay.py +0 -0
  45. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/schedule.py +0 -0
  46. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/search.py +0 -0
  47. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/security/advancedsecurity.py +0 -0
  48. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/security/authorizationserver.py +0 -0
  49. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/security/dot1x.py +0 -0
  50. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/security/jwt.py +0 -0
  51. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/security/keystore.py +0 -0
  52. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/security/mediasigning.py +0 -0
  53. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/security/tlsserver.py +0 -0
  54. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/thermal.py +0 -0
  55. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/services/uplink.py +0 -0
  56. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/utils/wsdl.py +0 -0
  57. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/accesscontrol/wsdl/index.html +0 -0
  58. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/accessrules/wsdl/accessrules.wsdl +0 -0
  59. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/accessrules/wsdl/index.html +0 -0
  60. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/actionengine.wsdl +0 -0
  61. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/advancedsecurity/wsdl/advancedsecurity.wsdl +0 -0
  62. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/advancedsecurity/wsdl/index.html +0 -0
  63. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/analyticsdevice.wsdl +0 -0
  64. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/appmgmt/wsdl/appmgmt.wsdl +0 -0
  65. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/appmgmt/wsdl/index.html +0 -0
  66. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/authenticationbehavior/wsdl/authenticationbehavior.wsdl +0 -0
  67. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/authenticationbehavior/wsdl/index.html +0 -0
  68. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/credential/wsdl/credential.wsdl +0 -0
  69. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/credential/wsdl/index.html +0 -0
  70. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/device/wsdl/devicemgmt.wsdl +0 -0
  71. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/deviceio.wsdl +0 -0
  72. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/display/display.wsdl +0 -0
  73. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/display/wsdl/index.htm +0 -0
  74. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/display.wsdl +0 -0
  75. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/doorcontrol/wsdl/index.html +0 -0
  76. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/events/wsdl/bw-2-vs-mod.wsdl +0 -0
  77. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/events/wsdl/event-vs.wsdl +0 -0
  78. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/events/wsdl/event.wsdl +0 -0
  79. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/events/wsdl/index.html +0 -0
  80. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/federatedsearch.wsdl +0 -0
  81. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/media/wsdl/media.wsdl +0 -0
  82. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/pacs/accesscontrol.wsdl +0 -0
  83. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/pacs/doorcontrol.wsdl +0 -0
  84. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/pacs/types.xsd +0 -0
  85. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/provisioning/wsdl/provisioning.wsdl +0 -0
  86. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/receiver.wsdl +0 -0
  87. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/recording.wsdl +0 -0
  88. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/replay.wsdl +0 -0
  89. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/schedule/wsdl/index.html +0 -0
  90. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/schedule/wsdl/schedule.wsdl +0 -0
  91. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/schema/common.xsd +0 -0
  92. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/schema/metadatastream.xsd +0 -0
  93. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/schema/onvif.xsd +0 -0
  94. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/search.wsdl +0 -0
  95. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/thermal/wsdl/index.html +0 -0
  96. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/thermal/wsdl/thermal.wsdl +0 -0
  97. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/topics/topicns.xml +0 -0
  98. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/uplink/wsdl/index.html +0 -0
  99. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver10/uplink/wsdl/uplink.wsdl +0 -0
  100. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/analytics/humanbody.xsd +0 -0
  101. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/analytics/humanface.xsd +0 -0
  102. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/analytics/index.html +0 -0
  103. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/analytics/radiometry.xsd +0 -0
  104. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/analytics/rules.xsd +0 -0
  105. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/analytics/wsdl/analytics.wsdl +0 -0
  106. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/analytics/wsdl/index.html +0 -0
  107. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/imaging/wsdl/imaging.wsdl +0 -0
  108. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/media/wsdl/index.html +0 -0
  109. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/media/wsdl/media.wsdl +0 -0
  110. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/ptz/wsdl/ptz.wsdl +0 -0
  111. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/util/federated_search_documentation.html +0 -0
  112. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/util/fedsearch-docu-viewer.xsl +0 -0
  113. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/util/onvif-wsdl-viewer.xsl +0 -0
  114. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif/wsdl/ver20/util/operationIndex.html +0 -0
  115. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif_python.egg-info/dependency_links.txt +0 -0
  116. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif_python.egg-info/requires.txt +0 -0
  117. {onvif_python-0.0.6 → onvif_python-0.0.7}/onvif_python.egg-info/top_level.txt +0 -0
  118. {onvif_python-0.0.6 → onvif_python-0.0.7}/setup.cfg +0 -0
  119. {onvif_python-0.0.6 → onvif_python-0.0.7}/setup.py +0 -0
  120. {onvif_python-0.0.6 → onvif_python-0.0.7}/tests/test_client.py +0 -0
  121. {onvif_python-0.0.6 → onvif_python-0.0.7}/tests/test_core.py +0 -0
  122. {onvif_python-0.0.6 → onvif_python-0.0.7}/tests/test_exceptions.py +0 -0
  123. {onvif_python-0.0.6 → onvif_python-0.0.7}/tests/test_wsdl_map.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: onvif-python
3
- Version: 0.0.6
3
+ Version: 0.0.7
4
4
  Summary: A comprehensive and developer-friendly Python library for working with ONVIF-compliant devices
5
5
  Author-email: Nirsimetri Technologies® <open@nirsimetri.com>
6
6
  Maintainer: Kaburagi
@@ -43,9 +43,9 @@ Dynamic: license-file
43
43
 
44
44
  [![License](https://img.shields.io/badge/License-MIT-blue)](https://github.com/nirsimetri/onvif-python?tab=MIT-1-ov-file)
45
45
  [![DeepWiki](https://img.shields.io/badge/DeepWiki-AI%20Wiki-orange)](https://deepwiki.com/nirsimetri/onvif-python)
46
- [![Release](https://img.shields.io/badge/Release-v0.0.6-red?logo=archive)](https://github.com/nirsimetri/onvif-python/releases)
46
+ [![Release](https://img.shields.io/badge/Release-v0.0.7-red?logo=archive)](https://github.com/nirsimetri/onvif-python/releases)
47
47
  <br>
48
- [![PyPI](https://img.shields.io/badge/PyPI-0.0.6-yellow?logo=archive)](https://pypi.org/project/onvif-python/)
48
+ [![PyPI](https://img.shields.io/badge/PyPI-0.0.7-yellow?logo=archive)](https://pypi.org/project/onvif-python/)
49
49
  [![Downloads](https://img.shields.io/pypi/dm/onvif-python?label=PyPI%20Downloads)](https://clickpy.clickhouse.com/dashboard/onvif-python)
50
50
 
51
51
  Are you having trouble finding a Python ONVIF library that supports your device?
@@ -150,6 +150,191 @@ Explore more advanced usage and service-specific operations in the [`examples/`]
150
150
  > [!IMPORTANT]
151
151
  > If you're new to ONVIF and want to learn more, we highly recommend taking the official free online course provided by ONVIF at [Introduction to ONVIF Course](https://www.onvif.org/about/introduction-to-onvif-course). Please note that we are not endorsed or sponsored by ONVIF, see [Legal Notice](#legal-notice) for details.
152
152
 
153
+ ## ONVIFClient Parameters
154
+
155
+ The `ONVIFClient` class provides various configuration options to customize the connection behavior, caching strategy, security settings, and debugging capabilities. Below is a detailed description of all available parameters:
156
+
157
+ ### Basic Parameters
158
+
159
+ | Parameter | Type | Required | Default | Description |
160
+ |-----------|------|----------|---------|-------------|
161
+ | `host` | `str` | ✅ Yes | - | IP address or hostname of the ONVIF device (e.g., `"192.168.1.17"`) |
162
+ | `port` | `int` | ✅ Yes | - | Port number for ONVIF service (common ports: `80`, `8000`, `8080`) |
163
+ | `username` | `str` | ✅ Yes | - | Username for device authentication (use digest authentication) |
164
+ | `password` | `str` | ✅ Yes | - | Password for device authentication |
165
+
166
+ ### Connection Parameters
167
+
168
+ | Parameter | Type | Required | Default | Description |
169
+ |-----------|------|----------|---------|-------------|
170
+ | `timeout` | `int` | ❌ No | `10` | Connection timeout in seconds for SOAP requests |
171
+ | `use_https` | `bool` | ❌ No | `False` | Use HTTPS instead of HTTP for secure communication |
172
+ | `verify_ssl` | `bool` | ❌ No | `True` | Verify SSL certificates when using HTTPS (set to `False` for self-signed certificates) |
173
+
174
+ ### Caching Parameters
175
+
176
+ | Parameter | Type | Required | Default | Description |
177
+ |-----------|------|----------|---------|-------------|
178
+ | `cache` | `CacheMode` | ❌ No | `CacheMode.ALL` | WSDL caching strategy (see [Cache Modes](#cache-modes) below) |
179
+
180
+ ### Feature Parameters
181
+
182
+ | Parameter | Type | Required | Default | Description |
183
+ |-----------|------|----------|---------|-------------|
184
+ | `apply_patch` | `bool` | ❌ No | `True` | Enable zeep patching for better xsd:any field parsing and automatic flattening |
185
+ | `capture_xml` | `bool` | ❌ No | `False` | Enable XML capture plugin for debugging SOAP requests/responses |
186
+
187
+ ### Cache Modes
188
+
189
+ The library provides four caching strategies via the `CacheMode` enum:
190
+
191
+ | Mode | Description | Best For | Startup Speed | Disk Usage | Memory Usage |
192
+ |------|-------------|----------|---------------|------------|--------------|
193
+ | `CacheMode.ALL` | In-memory + disk cache (SQLite) | Production servers, multi-device apps | ⚡⚡⚡ Fast | 💾 High | 🧠 High |
194
+ | `CacheMode.DB` | Disk cache only (SQLite) | Batch jobs, CLI tools | ⚡⚡ Medium | 💾 Medium | 🧠 Low |
195
+ | `CacheMode.MEM` | In-memory cache only | Short-lived scripts, demos | ⚡⚡ Medium | 💾 None | 🧠 Medium |
196
+ | `CacheMode.NONE` | No caching | Testing, debugging | ⚡ Slow | 💾 None | 🧠 Low |
197
+
198
+ **Recommendation:** Use `CacheMode.ALL` (default) for production applications to maximize performance.
199
+
200
+ ### Usage Examples
201
+
202
+ **Basic Connection:**
203
+ ```python
204
+ from onvif import ONVIFClient
205
+
206
+ # Minimal configuration
207
+ client = ONVIFClient("192.168.1.17", 80, "admin", "password")
208
+ ```
209
+
210
+ **Secure Connection (HTTPS):**
211
+ ```python
212
+ from onvif import ONVIFClient
213
+
214
+ # Connect via HTTPS with custom timeout
215
+ client = ONVIFClient(
216
+ "your-cctv-node.viewplexus.com",
217
+ 443, # HTTPS port
218
+ "admin",
219
+ "password",
220
+ timeout=30,
221
+ use_https=True,
222
+ verify_ssl=False # For self-signed certificates
223
+ )
224
+ ```
225
+
226
+ **Performance Optimized (Memory Cache):**
227
+ ```python
228
+ from onvif import ONVIFClient, CacheMode
229
+
230
+ # Use memory-only cache for quick scripts
231
+ client = ONVIFClient(
232
+ "192.168.1.17",
233
+ 80,
234
+ "admin",
235
+ "password",
236
+ cache=CacheMode.MEM
237
+ )
238
+ ```
239
+
240
+ **No Caching (Testing):**
241
+ ```python
242
+ from onvif import ONVIFClient, CacheMode
243
+
244
+ # Disable all caching for testing
245
+ client = ONVIFClient(
246
+ "192.168.1.17",
247
+ 80,
248
+ "admin",
249
+ "password",
250
+ cache=CacheMode.NONE,
251
+ apply_patch=False # Use original zeep behavior
252
+ )
253
+ ```
254
+
255
+ **Debugging Mode (XML Capture):**
256
+ ```python
257
+ from onvif import ONVIFClient
258
+
259
+ # Enable XML capture for debugging
260
+ client = ONVIFClient(
261
+ "192.168.1.17",
262
+ 80,
263
+ "admin",
264
+ "password",
265
+ capture_xml=True # Captures all SOAP requests/responses
266
+ )
267
+
268
+ # Make some ONVIF calls
269
+ device = client.devicemgmt()
270
+ info = device.GetDeviceInformation()
271
+ services = device.GetCapabilities()
272
+
273
+ # Access the XML capture plugin
274
+ if client.xml_plugin:
275
+ # Get last captured request/response
276
+ print("Last Request XML:")
277
+ print(client.xml_plugin.last_sent_xml)
278
+
279
+ print("\nLast Response XML:")
280
+ print(client.xml_plugin.last_received_xml)
281
+
282
+ print(f"\nLast Operation: {client.xml_plugin.last_operation}")
283
+
284
+ # Get complete history of all requests/responses
285
+ print(f"\nTotal captured operations: {len(client.xml_plugin.history)}")
286
+ for item in client.xml_plugin.history:
287
+ print(f" - {item['operation']} ({item['type']})")
288
+
289
+ # Save captured XML to files
290
+ client.xml_plugin.save_to_file(
291
+ request_file="last_request.xml",
292
+ response_file="last_response.xml"
293
+ )
294
+
295
+ # Clear history when done
296
+ client.xml_plugin.clear_history()
297
+ ```
298
+
299
+ > [!NOTE]
300
+ > **XML Capture Plugin Methods:**
301
+ > - `last_sent_xml` - Get the last SOAP request XML
302
+ > - `last_received_xml` - Get the last SOAP response XML
303
+ > - `last_operation` - Get the name of the last operation
304
+ > - `history` - List of all captured requests/responses with metadata
305
+ > - `get_last_request()` - Method to get last request
306
+ > - `get_last_response()` - Method to get last response
307
+ > - `get_history()` - Method to get all history
308
+ > - `save_to_file(request_file, response_file)` - Save XML to files
309
+ > - `clear_history()` - Clear captured history
310
+
311
+
312
+ **Production Configuration:**
313
+ ```python
314
+ from onvif import ONVIFClient, CacheMode
315
+
316
+ # Recommended production settings
317
+ client = ONVIFClient(
318
+ host="your-cctv-node.viewplexus.com",
319
+ port=443,
320
+ username="admin",
321
+ password="secure_password",
322
+ timeout=15,
323
+ cache=CacheMode.ALL, # Maximum performance
324
+ use_https=True, # Secure communication
325
+ verify_ssl=True, # Verify certificates (default)
326
+ apply_patch=True, # Enhanced parsing (default)
327
+ capture_xml=False # Disable debug mode (default)
328
+ )
329
+ ```
330
+
331
+ ### Notes
332
+
333
+ - **Authentication:** This library uses **WS-UsernameToken with Digest** authentication by default, which is the standard for ONVIF devices.
334
+ - **Patching:** The `apply_patch=True` (default) enables custom zeep patching that improves `xsd:any` field parsing. This is recommended for better compatibility with ONVIF responses.
335
+ - **XML Capture:** Only use `capture_xml=True` during development/debugging as it increases memory usage and may expose sensitive data in logs.
336
+ - **Cache Location:** Disk cache (when using `CacheMode.DB` or `CacheMode.ALL`) is stored in `~/.onvif-python/onvif_zeep_cache.sqlite`.
337
+
153
338
  ## Service Discovery: Understanding Device Capabilities
154
339
 
155
340
  > [!WARNING]
@@ -2,9 +2,9 @@
2
2
 
3
3
  [![License](https://img.shields.io/badge/License-MIT-blue)](https://github.com/nirsimetri/onvif-python?tab=MIT-1-ov-file)
4
4
  [![DeepWiki](https://img.shields.io/badge/DeepWiki-AI%20Wiki-orange)](https://deepwiki.com/nirsimetri/onvif-python)
5
- [![Release](https://img.shields.io/badge/Release-v0.0.6-red?logo=archive)](https://github.com/nirsimetri/onvif-python/releases)
5
+ [![Release](https://img.shields.io/badge/Release-v0.0.7-red?logo=archive)](https://github.com/nirsimetri/onvif-python/releases)
6
6
  <br>
7
- [![PyPI](https://img.shields.io/badge/PyPI-0.0.6-yellow?logo=archive)](https://pypi.org/project/onvif-python/)
7
+ [![PyPI](https://img.shields.io/badge/PyPI-0.0.7-yellow?logo=archive)](https://pypi.org/project/onvif-python/)
8
8
  [![Downloads](https://img.shields.io/pypi/dm/onvif-python?label=PyPI%20Downloads)](https://clickpy.clickhouse.com/dashboard/onvif-python)
9
9
 
10
10
  Are you having trouble finding a Python ONVIF library that supports your device?
@@ -109,6 +109,191 @@ Explore more advanced usage and service-specific operations in the [`examples/`]
109
109
  > [!IMPORTANT]
110
110
  > If you're new to ONVIF and want to learn more, we highly recommend taking the official free online course provided by ONVIF at [Introduction to ONVIF Course](https://www.onvif.org/about/introduction-to-onvif-course). Please note that we are not endorsed or sponsored by ONVIF, see [Legal Notice](#legal-notice) for details.
111
111
 
112
+ ## ONVIFClient Parameters
113
+
114
+ The `ONVIFClient` class provides various configuration options to customize the connection behavior, caching strategy, security settings, and debugging capabilities. Below is a detailed description of all available parameters:
115
+
116
+ ### Basic Parameters
117
+
118
+ | Parameter | Type | Required | Default | Description |
119
+ |-----------|------|----------|---------|-------------|
120
+ | `host` | `str` | ✅ Yes | - | IP address or hostname of the ONVIF device (e.g., `"192.168.1.17"`) |
121
+ | `port` | `int` | ✅ Yes | - | Port number for ONVIF service (common ports: `80`, `8000`, `8080`) |
122
+ | `username` | `str` | ✅ Yes | - | Username for device authentication (use digest authentication) |
123
+ | `password` | `str` | ✅ Yes | - | Password for device authentication |
124
+
125
+ ### Connection Parameters
126
+
127
+ | Parameter | Type | Required | Default | Description |
128
+ |-----------|------|----------|---------|-------------|
129
+ | `timeout` | `int` | ❌ No | `10` | Connection timeout in seconds for SOAP requests |
130
+ | `use_https` | `bool` | ❌ No | `False` | Use HTTPS instead of HTTP for secure communication |
131
+ | `verify_ssl` | `bool` | ❌ No | `True` | Verify SSL certificates when using HTTPS (set to `False` for self-signed certificates) |
132
+
133
+ ### Caching Parameters
134
+
135
+ | Parameter | Type | Required | Default | Description |
136
+ |-----------|------|----------|---------|-------------|
137
+ | `cache` | `CacheMode` | ❌ No | `CacheMode.ALL` | WSDL caching strategy (see [Cache Modes](#cache-modes) below) |
138
+
139
+ ### Feature Parameters
140
+
141
+ | Parameter | Type | Required | Default | Description |
142
+ |-----------|------|----------|---------|-------------|
143
+ | `apply_patch` | `bool` | ❌ No | `True` | Enable zeep patching for better xsd:any field parsing and automatic flattening |
144
+ | `capture_xml` | `bool` | ❌ No | `False` | Enable XML capture plugin for debugging SOAP requests/responses |
145
+
146
+ ### Cache Modes
147
+
148
+ The library provides four caching strategies via the `CacheMode` enum:
149
+
150
+ | Mode | Description | Best For | Startup Speed | Disk Usage | Memory Usage |
151
+ |------|-------------|----------|---------------|------------|--------------|
152
+ | `CacheMode.ALL` | In-memory + disk cache (SQLite) | Production servers, multi-device apps | ⚡⚡⚡ Fast | 💾 High | 🧠 High |
153
+ | `CacheMode.DB` | Disk cache only (SQLite) | Batch jobs, CLI tools | ⚡⚡ Medium | 💾 Medium | 🧠 Low |
154
+ | `CacheMode.MEM` | In-memory cache only | Short-lived scripts, demos | ⚡⚡ Medium | 💾 None | 🧠 Medium |
155
+ | `CacheMode.NONE` | No caching | Testing, debugging | ⚡ Slow | 💾 None | 🧠 Low |
156
+
157
+ **Recommendation:** Use `CacheMode.ALL` (default) for production applications to maximize performance.
158
+
159
+ ### Usage Examples
160
+
161
+ **Basic Connection:**
162
+ ```python
163
+ from onvif import ONVIFClient
164
+
165
+ # Minimal configuration
166
+ client = ONVIFClient("192.168.1.17", 80, "admin", "password")
167
+ ```
168
+
169
+ **Secure Connection (HTTPS):**
170
+ ```python
171
+ from onvif import ONVIFClient
172
+
173
+ # Connect via HTTPS with custom timeout
174
+ client = ONVIFClient(
175
+ "your-cctv-node.viewplexus.com",
176
+ 443, # HTTPS port
177
+ "admin",
178
+ "password",
179
+ timeout=30,
180
+ use_https=True,
181
+ verify_ssl=False # For self-signed certificates
182
+ )
183
+ ```
184
+
185
+ **Performance Optimized (Memory Cache):**
186
+ ```python
187
+ from onvif import ONVIFClient, CacheMode
188
+
189
+ # Use memory-only cache for quick scripts
190
+ client = ONVIFClient(
191
+ "192.168.1.17",
192
+ 80,
193
+ "admin",
194
+ "password",
195
+ cache=CacheMode.MEM
196
+ )
197
+ ```
198
+
199
+ **No Caching (Testing):**
200
+ ```python
201
+ from onvif import ONVIFClient, CacheMode
202
+
203
+ # Disable all caching for testing
204
+ client = ONVIFClient(
205
+ "192.168.1.17",
206
+ 80,
207
+ "admin",
208
+ "password",
209
+ cache=CacheMode.NONE,
210
+ apply_patch=False # Use original zeep behavior
211
+ )
212
+ ```
213
+
214
+ **Debugging Mode (XML Capture):**
215
+ ```python
216
+ from onvif import ONVIFClient
217
+
218
+ # Enable XML capture for debugging
219
+ client = ONVIFClient(
220
+ "192.168.1.17",
221
+ 80,
222
+ "admin",
223
+ "password",
224
+ capture_xml=True # Captures all SOAP requests/responses
225
+ )
226
+
227
+ # Make some ONVIF calls
228
+ device = client.devicemgmt()
229
+ info = device.GetDeviceInformation()
230
+ services = device.GetCapabilities()
231
+
232
+ # Access the XML capture plugin
233
+ if client.xml_plugin:
234
+ # Get last captured request/response
235
+ print("Last Request XML:")
236
+ print(client.xml_plugin.last_sent_xml)
237
+
238
+ print("\nLast Response XML:")
239
+ print(client.xml_plugin.last_received_xml)
240
+
241
+ print(f"\nLast Operation: {client.xml_plugin.last_operation}")
242
+
243
+ # Get complete history of all requests/responses
244
+ print(f"\nTotal captured operations: {len(client.xml_plugin.history)}")
245
+ for item in client.xml_plugin.history:
246
+ print(f" - {item['operation']} ({item['type']})")
247
+
248
+ # Save captured XML to files
249
+ client.xml_plugin.save_to_file(
250
+ request_file="last_request.xml",
251
+ response_file="last_response.xml"
252
+ )
253
+
254
+ # Clear history when done
255
+ client.xml_plugin.clear_history()
256
+ ```
257
+
258
+ > [!NOTE]
259
+ > **XML Capture Plugin Methods:**
260
+ > - `last_sent_xml` - Get the last SOAP request XML
261
+ > - `last_received_xml` - Get the last SOAP response XML
262
+ > - `last_operation` - Get the name of the last operation
263
+ > - `history` - List of all captured requests/responses with metadata
264
+ > - `get_last_request()` - Method to get last request
265
+ > - `get_last_response()` - Method to get last response
266
+ > - `get_history()` - Method to get all history
267
+ > - `save_to_file(request_file, response_file)` - Save XML to files
268
+ > - `clear_history()` - Clear captured history
269
+
270
+
271
+ **Production Configuration:**
272
+ ```python
273
+ from onvif import ONVIFClient, CacheMode
274
+
275
+ # Recommended production settings
276
+ client = ONVIFClient(
277
+ host="your-cctv-node.viewplexus.com",
278
+ port=443,
279
+ username="admin",
280
+ password="secure_password",
281
+ timeout=15,
282
+ cache=CacheMode.ALL, # Maximum performance
283
+ use_https=True, # Secure communication
284
+ verify_ssl=True, # Verify certificates (default)
285
+ apply_patch=True, # Enhanced parsing (default)
286
+ capture_xml=False # Disable debug mode (default)
287
+ )
288
+ ```
289
+
290
+ ### Notes
291
+
292
+ - **Authentication:** This library uses **WS-UsernameToken with Digest** authentication by default, which is the standard for ONVIF devices.
293
+ - **Patching:** The `apply_patch=True` (default) enables custom zeep patching that improves `xsd:any` field parsing. This is recommended for better compatibility with ONVIF responses.
294
+ - **XML Capture:** Only use `capture_xml=True` during development/debugging as it increases memory usage and may expose sensitive data in logs.
295
+ - **Cache Location:** Disk cache (when using `CacheMode.DB` or `CacheMode.ALL`) is stored in `~/.onvif-python/onvif_zeep_cache.sqlite`.
296
+
112
297
  ## Service Discovery: Understanding Device Capabilities
113
298
 
114
299
  > [!WARNING]
@@ -2,8 +2,7 @@
2
2
 
3
3
  from .client import ONVIFClient
4
4
  from .operator import ONVIFOperator, CacheMode
5
- from .utils import ONVIFWSDL, ONVIFOperationException
6
- from .utils.zeep import apply_patch, remove_patch, is_patched
5
+ from .utils import ONVIFWSDL, ONVIFOperationException, ONVIFErrorHandler, ZeepPatcher
7
6
 
8
7
  __all__ = [
9
8
  "ONVIFClient",
@@ -11,7 +10,6 @@ __all__ = [
11
10
  "CacheMode",
12
11
  "ONVIFWSDL",
13
12
  "ONVIFOperationException",
14
- "apply_patch",
15
- "remove_patch",
16
- "is_patched",
13
+ "ONVIFErrorHandler",
14
+ "ZeepPatcher",
17
15
  ]
@@ -41,12 +41,7 @@ from .services import (
41
41
  MediaSigning,
42
42
  )
43
43
  from .operator import CacheMode
44
- from .utils.zeep import (
45
- apply_patch as _apply_zeep_patch,
46
- remove_patch as _remove_zeep_patch,
47
- )
48
- from .utils.wsdl import ONVIFWSDL
49
- from .utils.xml_capture import XMLCapturePlugin
44
+ from .utils import ONVIFWSDL, ZeepPatcher, XMLCapturePlugin
50
45
 
51
46
 
52
47
  class ONVIFClient:
@@ -67,9 +62,9 @@ class ONVIFClient:
67
62
 
68
63
  # Apply or remove zeep patch based on user preference
69
64
  if apply_patch:
70
- _apply_zeep_patch()
65
+ ZeepPatcher.apply_patch()
71
66
  else:
72
- _remove_zeep_patch()
67
+ ZeepPatcher.remove_patch()
73
68
 
74
69
  # Initialize XML capture plugin if requested
75
70
  self.xml_plugin = None
@@ -10,8 +10,7 @@ from zeep.cache import SqliteCache
10
10
  from zeep.exceptions import Fault
11
11
  from zeep.wsse.username import UsernameToken
12
12
 
13
- from .utils import ONVIFOperationException
14
- from .utils.zeep import flatten_xsd_any_fields
13
+ from .utils import ONVIFOperationException, ZeepPatcher
15
14
 
16
15
 
17
16
  class CacheMode(Enum):
@@ -117,7 +116,7 @@ class ONVIFOperator:
117
116
  raise ValueError("Bindings must be set according to the WSDL service")
118
117
 
119
118
  self.service = self.client.create_service(binding, self.address)
120
- logging.debug(f"ONVIFCore initialized {binding} at {self.address}")
119
+ # logging.debug(f"ONVIFOperator initialized {binding} at {self.address}")
121
120
 
122
121
  def call(self, method: str, *args, **kwargs):
123
122
  try:
@@ -129,7 +128,7 @@ class ONVIFOperator:
129
128
  result = func(*args, **kwargs)
130
129
  # Post-process to flatten xsd:any fields if enabled (> v0.0.4 patch)
131
130
  if self.apply_flatten:
132
- return flatten_xsd_any_fields(result)
131
+ return ZeepPatcher.flatten_xsd_any_fields(result)
133
132
  return result
134
133
  except Fault as e:
135
134
  # logging.error(f"SOAP Fault in {method}: {e}")
@@ -28,7 +28,9 @@ class Imaging:
28
28
  "GetImagingSettings", VideoSourceToken=VideoSourceToken
29
29
  )
30
30
 
31
- def SetImagingSettings(self, VideoSourceToken, ImagingSettings, ForcePersistence=None):
31
+ def SetImagingSettings(
32
+ self, VideoSourceToken, ImagingSettings, ForcePersistence=None
33
+ ):
32
34
  return self.operator.call(
33
35
  "SetImagingSettings",
34
36
  VideoSourceToken=VideoSourceToken,
@@ -10,7 +10,7 @@ class Provisioning:
10
10
  # - ONVIF Release 16.12 (December 2016) Release Notes
11
11
  # - ProvisioningBinding (ver10/provisioning/wsdl/provisioning.wsdl)
12
12
  # - Operations: https://developer.onvif.org/pub/specs/branches/development/wsdl/ver10/provisioning/wsdl/provisioning.wsdl
13
-
13
+
14
14
  definition = ONVIFWSDL.get_definition("provisioning")
15
15
  self.operator = ONVIFOperator(
16
16
  definition["path"],
@@ -0,0 +1,14 @@
1
+ from .wsdl import ONVIFWSDL
2
+ from .exceptions import ONVIFOperationException
3
+ from .zeep import ZeepPatcher
4
+ from .xml_capture import XMLCapturePlugin
5
+ from .error_handlers import ONVIFErrorHandler
6
+
7
+
8
+ __all__ = [
9
+ "ONVIFWSDL",
10
+ "ONVIFOperationException",
11
+ "ZeepPatcher",
12
+ "XMLCapturePlugin",
13
+ "ONVIFErrorHandler",
14
+ ]
@@ -0,0 +1,76 @@
1
+ # onvif/utils/error_handlers.py
2
+
3
+ import logging
4
+ from zeep.exceptions import Fault
5
+ from .exceptions import ONVIFOperationException
6
+
7
+
8
+ class ONVIFErrorHandler:
9
+ """
10
+ Error handling utilities for ONVIF operations.
11
+
12
+ Provides static methods to handle ONVIF errors gracefully,
13
+ especially ActionNotSupported SOAP faults.
14
+ """
15
+
16
+ @staticmethod
17
+ def is_action_not_supported(exception):
18
+ """Check if an ONVIFOperationException is caused by ActionNotSupported SOAP fault."""
19
+ try:
20
+ # Handle ONVIFOperationException
21
+ if isinstance(exception, ONVIFOperationException):
22
+ original = exception.original_exception
23
+ else:
24
+ original = exception
25
+
26
+ # Check if it's a Fault with subcodes
27
+ if isinstance(original, Fault):
28
+ subcodes = getattr(original, "subcodes", None)
29
+ if subcodes:
30
+ for subcode in subcodes:
31
+ if hasattr(subcode, "localname"):
32
+ if subcode.localname == "ActionNotSupported":
33
+ return True
34
+ elif "ActionNotSupported" in str(subcode):
35
+ return True
36
+ except:
37
+ pass
38
+
39
+ return False
40
+
41
+ @staticmethod
42
+ def safe_call(func, default=None, ignore_unsupported=True, log_error=True):
43
+ """Safely call an ONVIF operation with graceful error handling."""
44
+ try:
45
+ return func()
46
+ except ONVIFOperationException as e:
47
+ # Check if it's ActionNotSupported error
48
+ if ignore_unsupported and ONVIFErrorHandler.is_action_not_supported(e):
49
+ # if log_error:
50
+ # logging.warning(f"Operation not supported: {e.operation}")
51
+ return default
52
+ # Re-raise other errors
53
+ raise
54
+ except Exception as e:
55
+ # Wrap unexpected exceptions
56
+ # if log_error:
57
+ # logging.error(f"Unexpected error in safe_call: {e}")
58
+ raise
59
+
60
+ @staticmethod
61
+ def ignore_unsupported(func):
62
+ """
63
+ Decorator to ignore ActionNotSupported SOAP faults.
64
+ Returns None for unsupported operations, raises other exceptions.
65
+ """
66
+
67
+ def wrapper(*args, **kwargs):
68
+ try:
69
+ return func(*args, **kwargs)
70
+ except ONVIFOperationException as e:
71
+ if ONVIFErrorHandler.is_action_not_supported(e):
72
+ # logging.warning(f"Operation not supported: {e.operation}")
73
+ return None
74
+ raise
75
+
76
+ return wrapper
@@ -0,0 +1,69 @@
1
+ # onvif/utils/exceptions.py
2
+
3
+ """
4
+ (1) SOAP Errors
5
+ (2) Transport/Protocol Errors
6
+ (3) Application Errors
7
+ """
8
+
9
+ from zeep.exceptions import Fault
10
+ import requests
11
+
12
+
13
+ class ONVIFOperationException(Exception):
14
+ def __init__(self, operation, original_exception):
15
+ self.operation = operation
16
+ self.original_exception = original_exception
17
+
18
+ if isinstance(original_exception, Fault):
19
+ # SOAP-level error
20
+ category = "SOAP Error"
21
+
22
+ # Extract fault information (supports both SOAP 1.1 and 1.2)
23
+ code = getattr(original_exception, "code", None) or getattr(
24
+ original_exception, "faultcode", None
25
+ )
26
+ subcodes = getattr(original_exception, "subcodes", None)
27
+ message = getattr(original_exception, "message", None) or str(
28
+ original_exception
29
+ )
30
+ detail = getattr(original_exception, "detail", None)
31
+
32
+ # Convert subcodes from QName objects to readable strings
33
+ if subcodes:
34
+ try:
35
+ # subcodes is a list of lxml.etree.QName objects
36
+ # QName objects have .localname (e.g., "ActionNotSupported")
37
+ # and .namespace (e.g., "http://www.onvif.org/ver10/error")
38
+ subcode_strings = []
39
+ for qname in subcodes:
40
+ if hasattr(qname, "localname"):
41
+ # Use only the local name without namespace
42
+ subcode_strings.append(qname.localname)
43
+ else:
44
+ # Fallback to string representation
45
+ subcode_strings.append(str(qname))
46
+ subcodes = ", ".join(subcode_strings)
47
+ except:
48
+ subcodes = str(subcodes)
49
+
50
+ # Build comprehensive error message
51
+ parts = [f"code={code}"]
52
+ if subcodes:
53
+ parts.append(f"subcode={subcodes}")
54
+ if message:
55
+ parts.append(f"msg={message}")
56
+ if detail:
57
+ parts.append(f"detail={detail}")
58
+
59
+ msg = f"{category}: {', '.join(parts)}"
60
+ elif isinstance(original_exception, requests.exceptions.RequestException):
61
+ # Transport/Protocol error
62
+ category = "Protocol Error"
63
+ msg = f"{category}: {str(original_exception)}"
64
+ else:
65
+ # Application or generic error
66
+ category = "Application Error"
67
+ msg = f"{category}: {str(original_exception)}"
68
+
69
+ super().__init__(f"ONVIF operation '{operation}' failed: {msg}")