onvif-python 0.1.2__tar.gz → 0.1.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.
- {onvif_python-0.1.2/onvif_python.egg-info → onvif_python-0.1.4}/PKG-INFO +28 -10
- {onvif_python-0.1.2 → onvif_python-0.1.4}/README.md +27 -9
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/cli/interactive.py +231 -20
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/cli/main.py +94 -21
- onvif_python-0.1.4/onvif/cli/utils.py +1247 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/operator.py +6 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4/onvif_python.egg-info}/PKG-INFO +28 -10
- {onvif_python-0.1.2 → onvif_python-0.1.4}/pyproject.toml +1 -1
- onvif_python-0.1.2/onvif/cli/utils.py +0 -475
- {onvif_python-0.1.2 → onvif_python-0.1.4}/LICENSE.md +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/MANIFEST.in +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/__init__.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/cli/__init__.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/cli/__main__.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/client.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/__init__.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/accesscontrol.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/accessrules.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/actionengine.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/analytics/analytics.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/analytics/ruleengine.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/analyticsdevice.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/appmgmt.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/authenticationbehavior.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/credential.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/deviceio.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/devicemgmt.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/display.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/doorcontrol.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/events/events.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/events/notification.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/events/pullpoint.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/events/subscription.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/imaging.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/media.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/media2.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/provisioning.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/ptz.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/receiver.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/recording.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/replay.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/schedule.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/search.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/security/advancedsecurity.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/security/authorizationserver.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/security/dot1x.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/security/jwt.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/security/keystore.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/security/mediasigning.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/security/tlsserver.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/thermal.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/services/uplink.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/utils/__init__.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/utils/error_handlers.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/utils/exceptions.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/utils/wsdl.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/utils/xml_capture.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/utils/zeep.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/accesscontrol/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/accessrules/wsdl/accessrules.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/accessrules/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/actionengine.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/advancedsecurity/wsdl/advancedsecurity.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/advancedsecurity/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/analyticsdevice.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/appmgmt/wsdl/appmgmt.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/appmgmt/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/authenticationbehavior/wsdl/authenticationbehavior.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/authenticationbehavior/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/credential/wsdl/credential.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/credential/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/device/wsdl/devicemgmt.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/deviceio.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/display/display.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/display/wsdl/index.htm +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/display.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/doorcontrol/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/events/wsdl/bw-2-vs-mod.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/events/wsdl/event-vs.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/events/wsdl/event.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/events/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/federatedsearch.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/media/wsdl/media.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/pacs/accesscontrol.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/pacs/doorcontrol.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/pacs/types.xsd +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/provisioning/wsdl/provisioning.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/receiver.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/recording.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/replay.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/schedule/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/schedule/wsdl/schedule.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/schema/common.xsd +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/schema/metadatastream.xsd +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/schema/onvif.xsd +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/search.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/thermal/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/thermal/wsdl/thermal.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/topics/topicns.xml +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/uplink/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver10/uplink/wsdl/uplink.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/analytics/humanbody.xsd +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/analytics/humanface.xsd +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/analytics/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/analytics/radiometry.xsd +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/analytics/rules.xsd +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/analytics/wsdl/analytics.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/analytics/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/imaging/wsdl/imaging.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/media/wsdl/index.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/media/wsdl/media.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/ptz/wsdl/ptz.wsdl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/util/federated_search_documentation.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/util/fedsearch-docu-viewer.xsl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/util/onvif-wsdl-viewer.xsl +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif/wsdl/ver20/util/operationIndex.html +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif_python.egg-info/SOURCES.txt +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif_python.egg-info/dependency_links.txt +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif_python.egg-info/entry_points.txt +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif_python.egg-info/requires.txt +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/onvif_python.egg-info/top_level.txt +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/setup.cfg +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/setup.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/tests/test_client.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/tests/test_core.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/tests/test_error_handlers.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/tests/test_exceptions.py +0 -0
- {onvif_python-0.1.2 → onvif_python-0.1.4}/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.1.
|
|
3
|
+
Version: 0.1.4
|
|
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
|
|
@@ -39,9 +39,9 @@ Dynamic: license-file
|
|
|
39
39
|
# ONVIF Python
|
|
40
40
|
|
|
41
41
|
[](https://github.com/nirsimetri/onvif-python?tab=MIT-1-ov-file)
|
|
42
|
-
[](https://deepwiki.com/nirsimetri/onvif-python)
|
|
43
|
+
[](https://pypi.org/project/onvif-python/)
|
|
44
|
+
[](https://clickpy.clickhouse.com/dashboard/onvif-python)
|
|
45
45
|
<br>
|
|
46
46
|
[](https://github.com/nirsimetri/onvif-python/actions/workflows/python-app.yml)
|
|
47
47
|
[](https://github.com/nirsimetri/onvif-python/actions/workflows/python-publish.yml)
|
|
@@ -186,12 +186,12 @@ This library includes a powerful command-line interface (CLI) for interacting wi
|
|
|
186
186
|
<tr>
|
|
187
187
|
<td width="34.2%">
|
|
188
188
|
<a href="https://github.com/nirsimetri/onvif-python">
|
|
189
|
-
<img src="
|
|
189
|
+
<img src="https://raw.githubusercontent.com/nirsimetri/onvif-python/refs/heads/main/assets/onvif_cli.png" />
|
|
190
190
|
</a>
|
|
191
191
|
</td>
|
|
192
192
|
<td width="65.8%">
|
|
193
193
|
<a href="https://github.com/nirsimetri/onvif-python">
|
|
194
|
-
<img src="
|
|
194
|
+
<img src="https://raw.githubusercontent.com/nirsimetri/onvif-python/refs/heads/main/assets/onvif_operations.png" />
|
|
195
195
|
</a>
|
|
196
196
|
</td>
|
|
197
197
|
</tr>
|
|
@@ -212,10 +212,10 @@ This library includes a powerful command-line interface (CLI) for interacting wi
|
|
|
212
212
|
|
|
213
213
|
```bash
|
|
214
214
|
usage: onvif [-h] [--host HOST] [--port PORT] [--username USERNAME] [--password PASSWORD] [--discover] [--timeout TIMEOUT] [--https] [--no-verify]
|
|
215
|
-
[--no-patch] [--interactive] [--debug] [--wsdl WSDL] [--cache {all,db,mem,none}]
|
|
215
|
+
[--no-patch] [--interactive] [--debug] [--wsdl WSDL] [--cache {all,db,mem,none}] [--version]
|
|
216
216
|
[service] [method] [params ...]
|
|
217
217
|
|
|
218
|
-
ONVIF Terminal Client —
|
|
218
|
+
ONVIF Terminal Client — v0.1.4
|
|
219
219
|
https://github.com/nirsimetri/onvif-python
|
|
220
220
|
|
|
221
221
|
positional arguments:
|
|
@@ -241,6 +241,7 @@ options:
|
|
|
241
241
|
--wsdl WSDL Custom WSDL directory path
|
|
242
242
|
--cache {all,db,mem,none}
|
|
243
243
|
Caching mode for ONVIFClient (default: all). 'all': memory+disk, 'db': disk-only, 'mem': memory-only, 'none': disabled.
|
|
244
|
+
--version, -v Show ONVIF CLI version and exit
|
|
244
245
|
|
|
245
246
|
Examples:
|
|
246
247
|
# Discover ONVIF devices on network
|
|
@@ -269,7 +270,7 @@ Examples:
|
|
|
269
270
|
<summary><b>2. Interactive Shell</b></summary>
|
|
270
271
|
|
|
271
272
|
```bash
|
|
272
|
-
ONVIF Interactive Shell Commands -
|
|
273
|
+
ONVIF Interactive Shell Commands - v0.1.4
|
|
273
274
|
https://github.com/nirsimetri/onvif-python
|
|
274
275
|
|
|
275
276
|
Basic Commands:
|
|
@@ -286,7 +287,11 @@ Navigation Commands:
|
|
|
286
287
|
up - Exit current service mode (go up one level)
|
|
287
288
|
pwd - Show current service context
|
|
288
289
|
clear - Clear terminal screen
|
|
289
|
-
|
|
290
|
+
help <command> - Show help for a specific command
|
|
291
|
+
|
|
292
|
+
Service Mode Commands:
|
|
293
|
+
desc <method> - Show method documentation
|
|
294
|
+
type <method> - Show input/output types from WSDL
|
|
290
295
|
|
|
291
296
|
Method Execution:
|
|
292
297
|
<method> - Execute method without parameters
|
|
@@ -374,6 +379,9 @@ onvif --discover --username admin --password admin123 --interactive
|
|
|
374
379
|
|
|
375
380
|
# Short form
|
|
376
381
|
onvif -d -u admin -p admin123 -i
|
|
382
|
+
|
|
383
|
+
# Discover and interactive (will prompt for credentials)
|
|
384
|
+
onvif -d -i
|
|
377
385
|
```
|
|
378
386
|
|
|
379
387
|
**Discover and Execute Command:**
|
|
@@ -745,6 +753,9 @@ If your device is not listed right now, feel free to contribute your test result
|
|
|
745
753
|
|
|
746
754
|
This library fully supports all major ONVIF Profiles listed below. Each profile represents a standardized set of features and use cases, ensuring interoperability between ONVIF-compliant devices and clients. You can use this library to integrate with devices and systems that implement any of these profiles.
|
|
747
755
|
|
|
756
|
+
<details>
|
|
757
|
+
<summary><b>ONVIF profiles list</b></summary>
|
|
758
|
+
|
|
748
759
|
| Name | Specifications | Main Features | Typical Use Case | Support |
|
|
749
760
|
|-----------|----------------|---------------|------------------|---------|
|
|
750
761
|
| Profile_S | [Document](https://www.onvif.org/wp-content/uploads/2019/12/ONVIF_Profile_-S_Specification_v1-3.pdf) | Video streaming, PTZ, audio, multicasting | Network video transmitters (cameras) and receivers (recorders, VMS) | ✅ Yes |
|
|
@@ -755,6 +766,8 @@ This library fully supports all major ONVIF Profiles listed below. Each profile
|
|
|
755
766
|
| Profile_D | [Document](https://www.onvif.org/wp-content/uploads/2021/06/onvif-profile-d-specification-v1-0.pdf) | Access control peripherals (locks, sensors, relays) | Peripheral devices for access control | ✅ Yes |
|
|
756
767
|
| Profile_M | [Document](https://www.onvif.org/wp-content/uploads/2024/04/onvif-profile-m-specification-v1-1.pdf) | Metadata, analytics events, object detection | Analytics devices, metadata clients | ✅ Yes |
|
|
757
768
|
|
|
769
|
+
</details>
|
|
770
|
+
|
|
758
771
|
For a full description of each profile and its features, visit [ONVIF Profiles](https://www.onvif.org/profiles/).
|
|
759
772
|
|
|
760
773
|
## Implemented ONVIF Services
|
|
@@ -764,6 +777,9 @@ For a full description of each profile and its features, visit [ONVIF Profiles](
|
|
|
764
777
|
|
|
765
778
|
Below is a list of ONVIF services implemented and supported by this library, along with links to the official specifications, service definitions, and schema files as referenced from the [ONVIF Developer Specs](https://developer.onvif.org/pub/specs/branches/development/doc/index.html). This table provides a quick overview of the available ONVIF features and their technical documentation for integration and development purposes.
|
|
766
779
|
|
|
780
|
+
<details>
|
|
781
|
+
<summary><b>ONVIF services list</b></summary>
|
|
782
|
+
|
|
767
783
|
| Service | Specifications | Service Definitions | Schema Files | Status |
|
|
768
784
|
|------------------------|-------------------------------|-----------------------------|-------------------------------------|------------|
|
|
769
785
|
| Device Management | [Document](https://developer.onvif.org/pub/specs/branches/development/doc/Core.xml) | [device.wsdl](https://developer.onvif.org/pub/specs/branches/development/wsdl/ver10/device/wsdl/devicemgmt.wsdl) | [onvif.xsd](https://developer.onvif.org/pub/specs/branches/development/wsdl/ver10/schema/onvif.xsd) <br> [common.xsd](https://developer.onvif.org/pub/specs/branches/development/wsdl/ver10/schema/common.xsd) | ✅ Complete |
|
|
@@ -795,6 +811,8 @@ Below is a list of ONVIF services implemented and supported by this library, alo
|
|
|
795
811
|
| Uplink | [Document](https://developer.onvif.org/pub/specs/branches/development/doc/Uplink.xml) | [uplink.wsdl](https://developer.onvif.org/pub/specs/branches/development/wsdl/ver10/uplink/wsdl/uplink.wsdl) | - | ✅ Complete |
|
|
796
812
|
| WebRTC | [Document](https://developer.onvif.org/pub/specs/branches/development/doc/WebRTC.xml) | - | - | ❌ Any idea? |
|
|
797
813
|
|
|
814
|
+
</details>
|
|
815
|
+
|
|
798
816
|
## Service Bindings in ONVIF
|
|
799
817
|
|
|
800
818
|
ONVIF services are defined by WSDL bindings. In this library, there are two main patterns:
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# ONVIF Python
|
|
2
2
|
|
|
3
3
|
[](https://github.com/nirsimetri/onvif-python?tab=MIT-1-ov-file)
|
|
4
|
-
[](https://deepwiki.com/nirsimetri/onvif-python)
|
|
5
|
+
[](https://pypi.org/project/onvif-python/)
|
|
6
|
+
[](https://clickpy.clickhouse.com/dashboard/onvif-python)
|
|
7
7
|
<br>
|
|
8
8
|
[](https://github.com/nirsimetri/onvif-python/actions/workflows/python-app.yml)
|
|
9
9
|
[](https://github.com/nirsimetri/onvif-python/actions/workflows/python-publish.yml)
|
|
@@ -148,12 +148,12 @@ This library includes a powerful command-line interface (CLI) for interacting wi
|
|
|
148
148
|
<tr>
|
|
149
149
|
<td width="34.2%">
|
|
150
150
|
<a href="https://github.com/nirsimetri/onvif-python">
|
|
151
|
-
<img src="
|
|
151
|
+
<img src="https://raw.githubusercontent.com/nirsimetri/onvif-python/refs/heads/main/assets/onvif_cli.png" />
|
|
152
152
|
</a>
|
|
153
153
|
</td>
|
|
154
154
|
<td width="65.8%">
|
|
155
155
|
<a href="https://github.com/nirsimetri/onvif-python">
|
|
156
|
-
<img src="
|
|
156
|
+
<img src="https://raw.githubusercontent.com/nirsimetri/onvif-python/refs/heads/main/assets/onvif_operations.png" />
|
|
157
157
|
</a>
|
|
158
158
|
</td>
|
|
159
159
|
</tr>
|
|
@@ -174,10 +174,10 @@ This library includes a powerful command-line interface (CLI) for interacting wi
|
|
|
174
174
|
|
|
175
175
|
```bash
|
|
176
176
|
usage: onvif [-h] [--host HOST] [--port PORT] [--username USERNAME] [--password PASSWORD] [--discover] [--timeout TIMEOUT] [--https] [--no-verify]
|
|
177
|
-
[--no-patch] [--interactive] [--debug] [--wsdl WSDL] [--cache {all,db,mem,none}]
|
|
177
|
+
[--no-patch] [--interactive] [--debug] [--wsdl WSDL] [--cache {all,db,mem,none}] [--version]
|
|
178
178
|
[service] [method] [params ...]
|
|
179
179
|
|
|
180
|
-
ONVIF Terminal Client —
|
|
180
|
+
ONVIF Terminal Client — v0.1.4
|
|
181
181
|
https://github.com/nirsimetri/onvif-python
|
|
182
182
|
|
|
183
183
|
positional arguments:
|
|
@@ -203,6 +203,7 @@ options:
|
|
|
203
203
|
--wsdl WSDL Custom WSDL directory path
|
|
204
204
|
--cache {all,db,mem,none}
|
|
205
205
|
Caching mode for ONVIFClient (default: all). 'all': memory+disk, 'db': disk-only, 'mem': memory-only, 'none': disabled.
|
|
206
|
+
--version, -v Show ONVIF CLI version and exit
|
|
206
207
|
|
|
207
208
|
Examples:
|
|
208
209
|
# Discover ONVIF devices on network
|
|
@@ -231,7 +232,7 @@ Examples:
|
|
|
231
232
|
<summary><b>2. Interactive Shell</b></summary>
|
|
232
233
|
|
|
233
234
|
```bash
|
|
234
|
-
ONVIF Interactive Shell Commands -
|
|
235
|
+
ONVIF Interactive Shell Commands - v0.1.4
|
|
235
236
|
https://github.com/nirsimetri/onvif-python
|
|
236
237
|
|
|
237
238
|
Basic Commands:
|
|
@@ -248,7 +249,11 @@ Navigation Commands:
|
|
|
248
249
|
up - Exit current service mode (go up one level)
|
|
249
250
|
pwd - Show current service context
|
|
250
251
|
clear - Clear terminal screen
|
|
251
|
-
|
|
252
|
+
help <command> - Show help for a specific command
|
|
253
|
+
|
|
254
|
+
Service Mode Commands:
|
|
255
|
+
desc <method> - Show method documentation
|
|
256
|
+
type <method> - Show input/output types from WSDL
|
|
252
257
|
|
|
253
258
|
Method Execution:
|
|
254
259
|
<method> - Execute method without parameters
|
|
@@ -336,6 +341,9 @@ onvif --discover --username admin --password admin123 --interactive
|
|
|
336
341
|
|
|
337
342
|
# Short form
|
|
338
343
|
onvif -d -u admin -p admin123 -i
|
|
344
|
+
|
|
345
|
+
# Discover and interactive (will prompt for credentials)
|
|
346
|
+
onvif -d -i
|
|
339
347
|
```
|
|
340
348
|
|
|
341
349
|
**Discover and Execute Command:**
|
|
@@ -707,6 +715,9 @@ If your device is not listed right now, feel free to contribute your test result
|
|
|
707
715
|
|
|
708
716
|
This library fully supports all major ONVIF Profiles listed below. Each profile represents a standardized set of features and use cases, ensuring interoperability between ONVIF-compliant devices and clients. You can use this library to integrate with devices and systems that implement any of these profiles.
|
|
709
717
|
|
|
718
|
+
<details>
|
|
719
|
+
<summary><b>ONVIF profiles list</b></summary>
|
|
720
|
+
|
|
710
721
|
| Name | Specifications | Main Features | Typical Use Case | Support |
|
|
711
722
|
|-----------|----------------|---------------|------------------|---------|
|
|
712
723
|
| Profile_S | [Document](https://www.onvif.org/wp-content/uploads/2019/12/ONVIF_Profile_-S_Specification_v1-3.pdf) | Video streaming, PTZ, audio, multicasting | Network video transmitters (cameras) and receivers (recorders, VMS) | ✅ Yes |
|
|
@@ -717,6 +728,8 @@ This library fully supports all major ONVIF Profiles listed below. Each profile
|
|
|
717
728
|
| Profile_D | [Document](https://www.onvif.org/wp-content/uploads/2021/06/onvif-profile-d-specification-v1-0.pdf) | Access control peripherals (locks, sensors, relays) | Peripheral devices for access control | ✅ Yes |
|
|
718
729
|
| Profile_M | [Document](https://www.onvif.org/wp-content/uploads/2024/04/onvif-profile-m-specification-v1-1.pdf) | Metadata, analytics events, object detection | Analytics devices, metadata clients | ✅ Yes |
|
|
719
730
|
|
|
731
|
+
</details>
|
|
732
|
+
|
|
720
733
|
For a full description of each profile and its features, visit [ONVIF Profiles](https://www.onvif.org/profiles/).
|
|
721
734
|
|
|
722
735
|
## Implemented ONVIF Services
|
|
@@ -726,6 +739,9 @@ For a full description of each profile and its features, visit [ONVIF Profiles](
|
|
|
726
739
|
|
|
727
740
|
Below is a list of ONVIF services implemented and supported by this library, along with links to the official specifications, service definitions, and schema files as referenced from the [ONVIF Developer Specs](https://developer.onvif.org/pub/specs/branches/development/doc/index.html). This table provides a quick overview of the available ONVIF features and their technical documentation for integration and development purposes.
|
|
728
741
|
|
|
742
|
+
<details>
|
|
743
|
+
<summary><b>ONVIF services list</b></summary>
|
|
744
|
+
|
|
729
745
|
| Service | Specifications | Service Definitions | Schema Files | Status |
|
|
730
746
|
|------------------------|-------------------------------|-----------------------------|-------------------------------------|------------|
|
|
731
747
|
| Device Management | [Document](https://developer.onvif.org/pub/specs/branches/development/doc/Core.xml) | [device.wsdl](https://developer.onvif.org/pub/specs/branches/development/wsdl/ver10/device/wsdl/devicemgmt.wsdl) | [onvif.xsd](https://developer.onvif.org/pub/specs/branches/development/wsdl/ver10/schema/onvif.xsd) <br> [common.xsd](https://developer.onvif.org/pub/specs/branches/development/wsdl/ver10/schema/common.xsd) | ✅ Complete |
|
|
@@ -757,6 +773,8 @@ Below is a list of ONVIF services implemented and supported by this library, alo
|
|
|
757
773
|
| Uplink | [Document](https://developer.onvif.org/pub/specs/branches/development/doc/Uplink.xml) | [uplink.wsdl](https://developer.onvif.org/pub/specs/branches/development/wsdl/ver10/uplink/wsdl/uplink.wsdl) | - | ✅ Complete |
|
|
758
774
|
| WebRTC | [Document](https://developer.onvif.org/pub/specs/branches/development/doc/WebRTC.xml) | - | - | ❌ Any idea? |
|
|
759
775
|
|
|
776
|
+
</details>
|
|
777
|
+
|
|
760
778
|
## Service Bindings in ONVIF
|
|
761
779
|
|
|
762
780
|
ONVIF services are defined by WSDL bindings. In this library, there are two main patterns:
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import cmd
|
|
4
4
|
import sys
|
|
5
5
|
import socket
|
|
6
|
+
import ssl
|
|
7
|
+
import os
|
|
6
8
|
import threading
|
|
7
9
|
import textwrap
|
|
8
10
|
from datetime import datetime
|
|
@@ -21,6 +23,7 @@ from .utils import (
|
|
|
21
23
|
format_capabilities_as_services,
|
|
22
24
|
format_services_list,
|
|
23
25
|
get_method_documentation,
|
|
26
|
+
get_operation_type_info,
|
|
24
27
|
)
|
|
25
28
|
|
|
26
29
|
|
|
@@ -61,6 +64,7 @@ class InteractiveShell(cmd.Cmd):
|
|
|
61
64
|
"pwd",
|
|
62
65
|
"shortcuts",
|
|
63
66
|
"desc",
|
|
67
|
+
"type",
|
|
64
68
|
]
|
|
65
69
|
|
|
66
70
|
# For background health check
|
|
@@ -179,7 +183,7 @@ class InteractiveShell(cmd.Cmd):
|
|
|
179
183
|
" / __ \\/ | / / | / / _/ ____/",
|
|
180
184
|
" / / / / |/ /| | / // // /_ ",
|
|
181
185
|
"/ /_/ / /| / | |/ // // __/ ",
|
|
182
|
-
"\\____/_/ |_/ |___/___/_/ v0.1.
|
|
186
|
+
"\\____/_/ |_/ |___/___/_/ v0.1.4",
|
|
183
187
|
" ",
|
|
184
188
|
]
|
|
185
189
|
|
|
@@ -218,22 +222,39 @@ class InteractiveShell(cmd.Cmd):
|
|
|
218
222
|
self._health_check_thread.start()
|
|
219
223
|
|
|
220
224
|
def _periodic_health_check(self):
|
|
221
|
-
"""Periodically checks device connection using
|
|
222
|
-
# Wait
|
|
225
|
+
"""Periodically checks device connection using TCP or TLS depending on mode."""
|
|
226
|
+
# Wait before first check to allow intro to finish
|
|
223
227
|
self._stop_health_check.wait(10.0)
|
|
228
|
+
|
|
224
229
|
while not self._stop_health_check.is_set():
|
|
225
230
|
sock = None
|
|
226
231
|
try:
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
232
|
+
sock = socket.create_connection(
|
|
233
|
+
(self.args.host, self.args.port), timeout=5.0
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# If HTTPS, perform a short TLS handshake check
|
|
237
|
+
if getattr(self.args, "https", False):
|
|
238
|
+
context = ssl.create_default_context()
|
|
239
|
+
context.check_hostname = False
|
|
240
|
+
context.verify_mode = ssl.CERT_NONE
|
|
241
|
+
|
|
242
|
+
with context.wrap_socket(
|
|
243
|
+
sock, server_hostname=self.args.host
|
|
244
|
+
) as ssock:
|
|
245
|
+
ssock.settimeout(5)
|
|
246
|
+
# Try a minimal handshake
|
|
247
|
+
ssock.do_handshake()
|
|
248
|
+
|
|
249
|
+
# If we reach here, the connection (and TLS if applicable) succeeded
|
|
250
|
+
pass
|
|
230
251
|
|
|
231
|
-
# Try to connect to the host and port
|
|
232
|
-
sock.connect((self.args.host, self.args.port))
|
|
233
252
|
except (
|
|
234
253
|
socket.timeout,
|
|
235
254
|
ConnectionRefusedError,
|
|
236
255
|
socket.gaierror,
|
|
256
|
+
ssl.SSLError,
|
|
257
|
+
ssl.SSLEOFError,
|
|
237
258
|
OSError,
|
|
238
259
|
) as e:
|
|
239
260
|
# Connection failed, trigger exit
|
|
@@ -242,7 +263,7 @@ class InteractiveShell(cmd.Cmd):
|
|
|
242
263
|
file=sys.stderr,
|
|
243
264
|
)
|
|
244
265
|
print(
|
|
245
|
-
f"{colorize('Error:', 'red')}
|
|
266
|
+
f"{colorize('Error:', 'red')} Health check failed: {e}",
|
|
246
267
|
file=sys.stderr,
|
|
247
268
|
)
|
|
248
269
|
print(
|
|
@@ -251,15 +272,13 @@ class InteractiveShell(cmd.Cmd):
|
|
|
251
272
|
)
|
|
252
273
|
# Forcibly exit the entire process. This is necessary to interrupt
|
|
253
274
|
# the blocking input() call in the main thread.
|
|
254
|
-
import os
|
|
255
|
-
|
|
256
275
|
os._exit(1)
|
|
257
276
|
finally:
|
|
258
277
|
# Ensure the socket is always closed
|
|
259
278
|
if sock:
|
|
260
279
|
sock.close()
|
|
261
280
|
|
|
262
|
-
# Wait
|
|
281
|
+
# Wait before next check or stop signal
|
|
263
282
|
self._stop_health_check.wait(5.0) # Check every 5 seconds
|
|
264
283
|
|
|
265
284
|
def _handle_connection_error(self, e):
|
|
@@ -766,8 +785,9 @@ class InteractiveShell(cmd.Cmd):
|
|
|
766
785
|
|
|
767
786
|
if not self.current_service:
|
|
768
787
|
print(
|
|
769
|
-
f"{colorize('Error:', 'red')}
|
|
788
|
+
f"{colorize('Error:', 'red')} You must be in a service mode to use 'desc'."
|
|
770
789
|
)
|
|
790
|
+
print(f"Enter a service first (e.g., {colorize('devicemgmt', 'yellow')})")
|
|
771
791
|
return
|
|
772
792
|
|
|
773
793
|
if not method_name:
|
|
@@ -808,8 +828,175 @@ class InteractiveShell(cmd.Cmd):
|
|
|
808
828
|
f"No documentation or parameter info found for method '{method_name}'."
|
|
809
829
|
)
|
|
810
830
|
|
|
811
|
-
def
|
|
812
|
-
|
|
831
|
+
def complete_desc(self, text, line, begidx, endidx):
|
|
832
|
+
"""Autocomplete method names for desc command"""
|
|
833
|
+
if not self.current_service:
|
|
834
|
+
return []
|
|
835
|
+
methods = get_service_methods(self.current_service)
|
|
836
|
+
return [m for m in methods if m.lower().startswith(text.lower())]
|
|
837
|
+
|
|
838
|
+
def do_type(self, line):
|
|
839
|
+
"""Show input and output types for an operation. Usage: type <operation_name>"""
|
|
840
|
+
operation_name = line.strip()
|
|
841
|
+
|
|
842
|
+
if not self.current_service:
|
|
843
|
+
print(
|
|
844
|
+
f"{colorize('Error:', 'red')} You must be in a service mode to use 'type'."
|
|
845
|
+
)
|
|
846
|
+
print(f"Enter a service first (e.g., {colorize('d', 'yellow')})")
|
|
847
|
+
return
|
|
848
|
+
|
|
849
|
+
if not operation_name:
|
|
850
|
+
print(f"Usage: {colorize('type <operation_name>', 'yellow')}")
|
|
851
|
+
return
|
|
852
|
+
|
|
853
|
+
if not hasattr(self.current_service, operation_name):
|
|
854
|
+
print(
|
|
855
|
+
f"{colorize('Error:', 'red')} Operation '{operation_name}' not found in service '{self.current_service_name}'."
|
|
856
|
+
)
|
|
857
|
+
print(f"Use {colorize('ls', 'yellow')} to see available operations.")
|
|
858
|
+
return
|
|
859
|
+
|
|
860
|
+
type_info = get_operation_type_info(self.current_service, operation_name)
|
|
861
|
+
|
|
862
|
+
if type_info:
|
|
863
|
+
# Helper function to display parameters recursively with tree-style indentation
|
|
864
|
+
def display_params(params, prefix_lines=None, is_root_level=False):
|
|
865
|
+
"""
|
|
866
|
+
Display parameters with tree-style formatting.
|
|
867
|
+
|
|
868
|
+
Args:
|
|
869
|
+
params: List of parameter dictionaries
|
|
870
|
+
prefix_lines: List of strings representing the tree prefix for each line
|
|
871
|
+
is_root_level: If True, don't show tree characters at this level
|
|
872
|
+
"""
|
|
873
|
+
if prefix_lines is None:
|
|
874
|
+
prefix_lines = []
|
|
875
|
+
|
|
876
|
+
for idx, param in enumerate(params):
|
|
877
|
+
is_last = idx == len(params) - 1
|
|
878
|
+
|
|
879
|
+
# Determine tree characters (only if not root level)
|
|
880
|
+
if is_root_level:
|
|
881
|
+
tree_branch = ""
|
|
882
|
+
tree_continue = ""
|
|
883
|
+
else:
|
|
884
|
+
if is_last:
|
|
885
|
+
tree_branch = "└── "
|
|
886
|
+
tree_continue = " "
|
|
887
|
+
else:
|
|
888
|
+
tree_branch = "├── "
|
|
889
|
+
tree_continue = "│ "
|
|
890
|
+
|
|
891
|
+
# Determine prefix symbol: + for attributes, - for elements
|
|
892
|
+
prefix_symbol = "+" if param.get("is_attribute", False) else "-"
|
|
893
|
+
|
|
894
|
+
# Format occurrences based on type
|
|
895
|
+
occurs = ""
|
|
896
|
+
if param.get("is_attribute", False):
|
|
897
|
+
# For attributes: only show "required" if use="required"
|
|
898
|
+
# Default for attributes is optional (no label needed)
|
|
899
|
+
if param["minOccurs"] == "1": # This means use="required"
|
|
900
|
+
occurs = f" - {colorize('required', 'yellow')}"
|
|
901
|
+
# If minOccurs == "0", it's optional (default), so no label
|
|
902
|
+
else:
|
|
903
|
+
# For elements: show unbounded, optional, or required
|
|
904
|
+
if param["maxOccurs"] == "unbounded":
|
|
905
|
+
occurs = f" - {colorize('unbounded', 'magenta')}"
|
|
906
|
+
elif param["minOccurs"] == "0":
|
|
907
|
+
occurs = f" - {colorize('optional', 'green')}"
|
|
908
|
+
else:
|
|
909
|
+
occurs = f" - {colorize('required', 'yellow')}"
|
|
910
|
+
|
|
911
|
+
# Format type
|
|
912
|
+
type_str = f"[{param['type']}]" if param["type"] else ""
|
|
913
|
+
|
|
914
|
+
# Build the current line prefix from all previous levels
|
|
915
|
+
current_prefix = "".join(prefix_lines)
|
|
916
|
+
|
|
917
|
+
# Add spacing for root level items
|
|
918
|
+
if is_root_level:
|
|
919
|
+
current_prefix = " "
|
|
920
|
+
|
|
921
|
+
# Display parameter name with tree structure, prefix, occurrence, and type
|
|
922
|
+
# Only add semicolon separator if there's an occurrence label
|
|
923
|
+
separator = ";" if occurs else ""
|
|
924
|
+
param_line = f"{current_prefix}{tree_branch}{prefix_symbol}{colorize(param['name'], 'white')}{occurs}{separator} {colorize(type_str, 'cyan')}"
|
|
925
|
+
print(param_line)
|
|
926
|
+
|
|
927
|
+
# Display documentation if available
|
|
928
|
+
if param.get("documentation"):
|
|
929
|
+
doc_lines = param["documentation"].split("\n")
|
|
930
|
+
for doc_line in doc_lines:
|
|
931
|
+
if doc_line.strip():
|
|
932
|
+
# Add tree continuation for documentation
|
|
933
|
+
if is_root_level:
|
|
934
|
+
doc_prefix = " "
|
|
935
|
+
else:
|
|
936
|
+
doc_prefix = current_prefix + tree_continue
|
|
937
|
+
wrapped_doc = textwrap.fill(
|
|
938
|
+
doc_line.strip(),
|
|
939
|
+
width=96, # Slightly less to account for tree chars
|
|
940
|
+
initial_indent=doc_prefix + " ",
|
|
941
|
+
subsequent_indent=doc_prefix + " ",
|
|
942
|
+
)
|
|
943
|
+
print(colorize(wrapped_doc, "reset"))
|
|
944
|
+
|
|
945
|
+
# Display children recursively with updated prefix
|
|
946
|
+
if param.get("children"):
|
|
947
|
+
if is_root_level:
|
|
948
|
+
# Start tree structure from children
|
|
949
|
+
new_prefix_lines = [" "]
|
|
950
|
+
else:
|
|
951
|
+
new_prefix_lines = prefix_lines + [tree_continue]
|
|
952
|
+
display_params(
|
|
953
|
+
param["children"], new_prefix_lines, is_root_level=False
|
|
954
|
+
)
|
|
955
|
+
|
|
956
|
+
# Display Input
|
|
957
|
+
if type_info["input"]:
|
|
958
|
+
input_msg = type_info["input"]
|
|
959
|
+
print(f"\n{colorize('Input:', 'cyan')}")
|
|
960
|
+
msg_name = f"[{input_msg['name']}]"
|
|
961
|
+
print(f"{colorize(msg_name, 'yellow')}")
|
|
962
|
+
|
|
963
|
+
if input_msg["parameters"]:
|
|
964
|
+
display_params(input_msg["parameters"], is_root_level=True)
|
|
965
|
+
else:
|
|
966
|
+
print(f" {colorize('(no parameters)', 'reset')}")
|
|
967
|
+
else:
|
|
968
|
+
print(
|
|
969
|
+
f"\n{colorize('Input:', 'cyan')} {colorize('(not defined)', 'reset')}"
|
|
970
|
+
)
|
|
971
|
+
|
|
972
|
+
# Display Output
|
|
973
|
+
if type_info["output"]:
|
|
974
|
+
output_msg = type_info["output"]
|
|
975
|
+
print(f"\n{colorize('Output:', 'cyan')}")
|
|
976
|
+
msg_name = f"[{output_msg['name']}]"
|
|
977
|
+
print(f"{colorize(msg_name, 'yellow')}")
|
|
978
|
+
|
|
979
|
+
if output_msg["parameters"]:
|
|
980
|
+
display_params(output_msg["parameters"], is_root_level=True)
|
|
981
|
+
else:
|
|
982
|
+
print(f" {colorize('(no parameters)', 'reset')}")
|
|
983
|
+
else:
|
|
984
|
+
print(
|
|
985
|
+
f"\n{colorize('Output:', 'cyan')} {colorize('(not defined)', 'reset')}"
|
|
986
|
+
)
|
|
987
|
+
|
|
988
|
+
print() # Add newline for spacing
|
|
989
|
+
else:
|
|
990
|
+
print(
|
|
991
|
+
f"{colorize('Error:', 'red')} Could not retrieve type information for '{operation_name}'."
|
|
992
|
+
)
|
|
993
|
+
|
|
994
|
+
def complete_type(self, text, line, begidx, endidx):
|
|
995
|
+
"""Autocomplete method names for type command"""
|
|
996
|
+
if not self.current_service:
|
|
997
|
+
return []
|
|
998
|
+
methods = get_service_methods(self.current_service)
|
|
999
|
+
return [m for m in methods if m.lower().startswith(text.lower())]
|
|
813
1000
|
|
|
814
1001
|
def do_cd(self, line):
|
|
815
1002
|
"""Change to service directory (alias for entering service)"""
|
|
@@ -821,6 +1008,11 @@ class InteractiveShell(cmd.Cmd):
|
|
|
821
1008
|
return
|
|
822
1009
|
return self.do_enter_service(line)
|
|
823
1010
|
|
|
1011
|
+
def complete_cd(self, text, line, begidx, endidx):
|
|
1012
|
+
"""Autocomplete service names for cd command"""
|
|
1013
|
+
services = get_device_available_services(self.client)
|
|
1014
|
+
return [s for s in services if s.lower().startswith(text.lower())]
|
|
1015
|
+
|
|
824
1016
|
def do_pwd(self, line):
|
|
825
1017
|
"""Show current service context"""
|
|
826
1018
|
if self.current_service_name:
|
|
@@ -844,7 +1036,11 @@ class InteractiveShell(cmd.Cmd):
|
|
|
844
1036
|
up - Go up one level
|
|
845
1037
|
pwd - Show current context
|
|
846
1038
|
clear - Clear terminal screen
|
|
847
|
-
|
|
1039
|
+
help <command> - Show help for a command
|
|
1040
|
+
|
|
1041
|
+
{colorize('Service Mode Commands:', 'yellow')}
|
|
1042
|
+
desc <method> - Show method documentation
|
|
1043
|
+
type <method> - Show input/output types from WSDL
|
|
848
1044
|
|
|
849
1045
|
{colorize('Quick Access:', 'yellow')}
|
|
850
1046
|
caps - Show capabilities (same as 'capabilities')
|
|
@@ -925,6 +1121,10 @@ class InteractiveShell(cmd.Cmd):
|
|
|
925
1121
|
else:
|
|
926
1122
|
print(f"{colorize('Error:', 'red')} No stored data named '{line}'")
|
|
927
1123
|
|
|
1124
|
+
def complete_rm(self, text, line, begidx, endidx):
|
|
1125
|
+
"""Autocomplete stored variable names for rm command"""
|
|
1126
|
+
return [name for name in self.stored_data.keys() if name.startswith(text)]
|
|
1127
|
+
|
|
928
1128
|
def do_show(self, line):
|
|
929
1129
|
"""Show stored data: show <name> or show <name>.<attribute> or show <name>[index]"""
|
|
930
1130
|
if not line:
|
|
@@ -947,10 +1147,17 @@ class InteractiveShell(cmd.Cmd):
|
|
|
947
1147
|
else:
|
|
948
1148
|
print(f"{colorize('Error:', 'red')} Cannot resolve '{line}'")
|
|
949
1149
|
|
|
1150
|
+
def complete_show(self, text, line, begidx, endidx):
|
|
1151
|
+
"""Autocomplete stored variable names for show command"""
|
|
1152
|
+
# Get the part being completed
|
|
1153
|
+
parts = line.split()
|
|
1154
|
+
if len(parts) <= 1 or (len(parts) == 2 and not line.endswith(" ")):
|
|
1155
|
+
# Completing the variable name
|
|
1156
|
+
return [name for name in self.stored_data.keys() if name.startswith(text)]
|
|
1157
|
+
return []
|
|
1158
|
+
|
|
950
1159
|
def do_clear(self, line):
|
|
951
1160
|
"""Clear terminal screen"""
|
|
952
|
-
import os
|
|
953
|
-
|
|
954
1161
|
# Clear screen for both Windows and Unix-like systems
|
|
955
1162
|
os.system("cls" if os.name == "nt" else "clear")
|
|
956
1163
|
|
|
@@ -1093,7 +1300,7 @@ class InteractiveShell(cmd.Cmd):
|
|
|
1093
1300
|
super().do_help(line)
|
|
1094
1301
|
else:
|
|
1095
1302
|
help_text = f"""
|
|
1096
|
-
{colorize('ONVIF Interactive Shell Commands -', 'cyan')}\n{colorize('https://github.com/nirsimetri/onvif-python', 'white')}
|
|
1303
|
+
{colorize('ONVIF Interactive Shell Commands - v0.1.4', 'cyan')}\n{colorize('https://github.com/nirsimetri/onvif-python', 'white')}
|
|
1097
1304
|
|
|
1098
1305
|
{colorize('Basic Commands:', 'yellow')}
|
|
1099
1306
|
capabilities, caps - Show device capabilities
|
|
@@ -1109,7 +1316,11 @@ class InteractiveShell(cmd.Cmd):
|
|
|
1109
1316
|
up - Exit current service mode (go up one level)
|
|
1110
1317
|
pwd - Show current service context
|
|
1111
1318
|
clear - Clear terminal screen
|
|
1112
|
-
|
|
1319
|
+
help <command> - Show help for a specific command
|
|
1320
|
+
|
|
1321
|
+
{colorize('Service Mode Commands:', 'yellow')}
|
|
1322
|
+
desc <method> - Show method documentation
|
|
1323
|
+
type <method> - Show input/output types from WSDL
|
|
1113
1324
|
|
|
1114
1325
|
{colorize('Method Execution:', 'yellow')}
|
|
1115
1326
|
<method> - Execute method without parameters
|