onvif-python 0.1.3__tar.gz → 0.1.5__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 (127) hide show
  1. {onvif_python-0.1.3/onvif_python.egg-info → onvif_python-0.1.5}/PKG-INFO +44 -8
  2. {onvif_python-0.1.3 → onvif_python-0.1.5}/README.md +43 -7
  3. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/cli/interactive.py +133 -23
  4. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/cli/main.py +28 -11
  5. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/cli/utils.py +207 -84
  6. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/client.py +4 -4
  7. {onvif_python-0.1.3 → onvif_python-0.1.5/onvif_python.egg-info}/PKG-INFO +44 -8
  8. {onvif_python-0.1.3 → onvif_python-0.1.5}/pyproject.toml +1 -1
  9. {onvif_python-0.1.3 → onvif_python-0.1.5}/LICENSE.md +0 -0
  10. {onvif_python-0.1.3 → onvif_python-0.1.5}/MANIFEST.in +0 -0
  11. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/__init__.py +0 -0
  12. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/cli/__init__.py +0 -0
  13. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/cli/__main__.py +0 -0
  14. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/operator.py +0 -0
  15. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/__init__.py +0 -0
  16. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/accesscontrol.py +0 -0
  17. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/accessrules.py +0 -0
  18. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/actionengine.py +0 -0
  19. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/analytics/analytics.py +0 -0
  20. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/analytics/ruleengine.py +0 -0
  21. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/analyticsdevice.py +0 -0
  22. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/appmgmt.py +0 -0
  23. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/authenticationbehavior.py +0 -0
  24. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/credential.py +0 -0
  25. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/deviceio.py +0 -0
  26. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/devicemgmt.py +0 -0
  27. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/display.py +0 -0
  28. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/doorcontrol.py +0 -0
  29. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/events/events.py +0 -0
  30. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/events/notification.py +0 -0
  31. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/events/pullpoint.py +0 -0
  32. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/events/subscription.py +0 -0
  33. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/imaging.py +0 -0
  34. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/media.py +0 -0
  35. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/media2.py +0 -0
  36. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/provisioning.py +0 -0
  37. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/ptz.py +0 -0
  38. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/receiver.py +0 -0
  39. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/recording.py +0 -0
  40. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/replay.py +0 -0
  41. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/schedule.py +0 -0
  42. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/search.py +0 -0
  43. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/security/advancedsecurity.py +0 -0
  44. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/security/authorizationserver.py +0 -0
  45. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/security/dot1x.py +0 -0
  46. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/security/jwt.py +0 -0
  47. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/security/keystore.py +0 -0
  48. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/security/mediasigning.py +0 -0
  49. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/security/tlsserver.py +0 -0
  50. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/thermal.py +0 -0
  51. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/services/uplink.py +0 -0
  52. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/utils/__init__.py +0 -0
  53. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/utils/error_handlers.py +0 -0
  54. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/utils/exceptions.py +0 -0
  55. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/utils/wsdl.py +0 -0
  56. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/utils/xml_capture.py +0 -0
  57. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/utils/zeep.py +0 -0
  58. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/accesscontrol/wsdl/index.html +0 -0
  59. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/accessrules/wsdl/accessrules.wsdl +0 -0
  60. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/accessrules/wsdl/index.html +0 -0
  61. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/actionengine.wsdl +0 -0
  62. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/advancedsecurity/wsdl/advancedsecurity.wsdl +0 -0
  63. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/advancedsecurity/wsdl/index.html +0 -0
  64. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/analyticsdevice.wsdl +0 -0
  65. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/appmgmt/wsdl/appmgmt.wsdl +0 -0
  66. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/appmgmt/wsdl/index.html +0 -0
  67. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/authenticationbehavior/wsdl/authenticationbehavior.wsdl +0 -0
  68. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/authenticationbehavior/wsdl/index.html +0 -0
  69. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/credential/wsdl/credential.wsdl +0 -0
  70. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/credential/wsdl/index.html +0 -0
  71. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/device/wsdl/devicemgmt.wsdl +0 -0
  72. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/deviceio.wsdl +0 -0
  73. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/display/display.wsdl +0 -0
  74. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/display/wsdl/index.htm +0 -0
  75. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/display.wsdl +0 -0
  76. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/doorcontrol/wsdl/index.html +0 -0
  77. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/events/wsdl/bw-2-vs-mod.wsdl +0 -0
  78. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/events/wsdl/event-vs.wsdl +0 -0
  79. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/events/wsdl/event.wsdl +0 -0
  80. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/events/wsdl/index.html +0 -0
  81. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/federatedsearch.wsdl +0 -0
  82. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/media/wsdl/media.wsdl +0 -0
  83. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/pacs/accesscontrol.wsdl +0 -0
  84. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/pacs/doorcontrol.wsdl +0 -0
  85. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/pacs/types.xsd +0 -0
  86. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/provisioning/wsdl/provisioning.wsdl +0 -0
  87. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/receiver.wsdl +0 -0
  88. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/recording.wsdl +0 -0
  89. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/replay.wsdl +0 -0
  90. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/schedule/wsdl/index.html +0 -0
  91. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/schedule/wsdl/schedule.wsdl +0 -0
  92. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/schema/common.xsd +0 -0
  93. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/schema/metadatastream.xsd +0 -0
  94. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/schema/onvif.xsd +0 -0
  95. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/search.wsdl +0 -0
  96. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/thermal/wsdl/index.html +0 -0
  97. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/thermal/wsdl/thermal.wsdl +0 -0
  98. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/topics/topicns.xml +0 -0
  99. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/uplink/wsdl/index.html +0 -0
  100. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver10/uplink/wsdl/uplink.wsdl +0 -0
  101. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/analytics/humanbody.xsd +0 -0
  102. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/analytics/humanface.xsd +0 -0
  103. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/analytics/index.html +0 -0
  104. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/analytics/radiometry.xsd +0 -0
  105. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/analytics/rules.xsd +0 -0
  106. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/analytics/wsdl/analytics.wsdl +0 -0
  107. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/analytics/wsdl/index.html +0 -0
  108. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/imaging/wsdl/imaging.wsdl +0 -0
  109. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/media/wsdl/index.html +0 -0
  110. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/media/wsdl/media.wsdl +0 -0
  111. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/ptz/wsdl/ptz.wsdl +0 -0
  112. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/util/federated_search_documentation.html +0 -0
  113. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/util/fedsearch-docu-viewer.xsl +0 -0
  114. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/util/onvif-wsdl-viewer.xsl +0 -0
  115. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif/wsdl/ver20/util/operationIndex.html +0 -0
  116. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif_python.egg-info/SOURCES.txt +0 -0
  117. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif_python.egg-info/dependency_links.txt +0 -0
  118. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif_python.egg-info/entry_points.txt +0 -0
  119. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif_python.egg-info/requires.txt +0 -0
  120. {onvif_python-0.1.3 → onvif_python-0.1.5}/onvif_python.egg-info/top_level.txt +0 -0
  121. {onvif_python-0.1.3 → onvif_python-0.1.5}/setup.cfg +0 -0
  122. {onvif_python-0.1.3 → onvif_python-0.1.5}/setup.py +0 -0
  123. {onvif_python-0.1.3 → onvif_python-0.1.5}/tests/test_client.py +0 -0
  124. {onvif_python-0.1.3 → onvif_python-0.1.5}/tests/test_core.py +0 -0
  125. {onvif_python-0.1.3 → onvif_python-0.1.5}/tests/test_error_handlers.py +0 -0
  126. {onvif_python-0.1.3 → onvif_python-0.1.5}/tests/test_exceptions.py +0 -0
  127. {onvif_python-0.1.3 → onvif_python-0.1.5}/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
3
+ Version: 0.1.5
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
@@ -38,9 +38,9 @@ Dynamic: license-file
38
38
 
39
39
  # ONVIF Python
40
40
 
41
- [![License](https://img.shields.io/badge/License-MIT-blue)](https://github.com/nirsimetri/onvif-python?tab=MIT-1-ov-file)
41
+ [![Codacy grade](https://img.shields.io/codacy/grade/bff08a94e4d447b690cea49c6594826d?label=Project%20Quality&logo=codacy)](https://app.codacy.com/gh/nirsimetri/onvif-python/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
42
42
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/nirsimetri/onvif-python)
43
- [![PyPI](https://img.shields.io/badge/PyPI-0.1.3-orange?logo=archive)](https://pypi.org/project/onvif-python/)
43
+ [![PyPI](https://img.shields.io/badge/PyPI-0.1.5-orange?logo=archive)](https://pypi.org/project/onvif-python/)
44
44
  [![Downloads](https://img.shields.io/pypi/dm/onvif-python?label=Downloads&color=red)](https://clickpy.clickhouse.com/dashboard/onvif-python)
45
45
  <br>
46
46
  [![Build](https://github.com/nirsimetri/onvif-python/actions/workflows/python-app.yml/badge.svg?branch=main)](https://github.com/nirsimetri/onvif-python/actions/workflows/python-app.yml)
@@ -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}] [--health-check-interval HEALTH_CHECK_INTERVAL] [--version]
216
216
  [service] [method] [params ...]
217
217
 
218
- ONVIF Terminal Client —
218
+ ONVIF Terminal Client — v0.1.5
219
219
  https://github.com/nirsimetri/onvif-python
220
220
 
221
221
  positional arguments:
@@ -241,6 +241,9 @@ 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
+ --health-check-interval HEALTH_CHECK_INTERVAL, -hci HEALTH_CHECK_INTERVAL
245
+ Health check interval in seconds for interactive mode (default: 10)
246
+ --version, -v Show ONVIF CLI version and exit
244
247
 
245
248
  Examples:
246
249
  # Discover ONVIF devices on network
@@ -269,7 +272,7 @@ Examples:
269
272
  <summary><b>2. Interactive Shell</b></summary>
270
273
 
271
274
  ```bash
272
- ONVIF Interactive Shell Commands -
275
+ ONVIF Interactive Shell Commands - v0.1.5
273
276
  https://github.com/nirsimetri/onvif-python
274
277
 
275
278
  Basic Commands:
@@ -278,15 +281,16 @@ Basic Commands:
278
281
  info - Show connection and device information
279
282
  exit, quit - Exit the shell
280
283
  shortcuts - Show available shortcuts
281
- help <command> - Show help for a specific command
282
284
 
283
285
  Navigation Commands:
284
286
  <service> - Enter service mode (e.g., devicemgmt, media)
287
+ <service> <argument> - Enter service mode with argument (e.g. pullpoint SubscriptionRef=<value>)
285
288
  cd <service> - Enter service mode (alias)
286
289
  ls - List commands/services/methods in grid format
287
290
  up - Exit current service mode (go up one level)
288
291
  pwd - Show current service context
289
292
  clear - Clear terminal screen
293
+ help <command> - Show help for a specific command
290
294
 
291
295
  Service Mode Commands:
292
296
  desc <method> - Show method documentation
@@ -300,6 +304,7 @@ Method Execution:
300
304
  Data Management:
301
305
  store <name> - Store last result with a name
302
306
  show <name> - Show stored data
307
+ show <name>[0] - Show element at index (for lists)
303
308
  show <name>.attribute - Show specific attribute
304
309
  show - List all stored data
305
310
  rm <name> - Remove stored data by name
@@ -367,6 +372,27 @@ If you omit the username or password, you will be prompted to enter them securel
367
372
  > [!IMPORTANT]
368
373
  > You can see all the other commands available in the interactive shell by trying it out directly. The interactive shell runs periodic background health checks to detect connection loss. It uses silent TCP pings to avoid interrupting your work and will automatically exit if the device is unreachable, similar to an SSH session.
369
374
 
375
+ **Command Chaining with `&&`:**
376
+
377
+ The CLI supports chaining multiple commands in a single line using the `&&` operator, allowing you to execute sequential operations efficiently:
378
+
379
+ ```bash
380
+ # Enter service and execute method in one line
381
+ 192.168.1.17:8000 > media && GetProfiles && store profiles
382
+
383
+ # Chain multiple method calls
384
+ 192.168.1.17:8000 > devicemgmt && GetDeviceInformation && store device_info
385
+
386
+ # Complex workflow
387
+ 192.168.1.17:8000 > media && GetProfiles && store profiles && up && imaging && GetImagingSettings VideoSourceToken=$profiles[0].VideoSourceConfiguration.SourceToken
388
+ ```
389
+
390
+ This feature is particularly useful for:
391
+ - Quick operations without entering service mode
392
+ - Scripting repetitive tasks
393
+ - Testing workflows
394
+ - Automating multi-step procedures
395
+
370
396
  **2. Device Discovery (WS-Discovery)**
371
397
 
372
398
  The CLI includes automatic ONVIF device discovery using the WS-Discovery protocol. This feature allows you to find all ONVIF-compliant devices on your local network without knowing their IP addresses beforehand.
@@ -490,7 +516,7 @@ The `ONVIFClient` class provides various configuration options to customize the
490
516
 
491
517
  | Parameter | Type | Required | Default | Description |
492
518
  |-----------|------|----------|---------|-------------|
493
- | `cache` | `CacheMode` | ❌ No | `CacheMode.ALL` | WSDL caching strategy (see [Cache Modes](#cache-modes) below) |
519
+ | `cache` | `CacheMode` | ❌ No | `CacheMode.ALL` | WSDL caching strategy (see **Cache Modes** below) |
494
520
 
495
521
  </details>
496
522
 
@@ -752,6 +778,9 @@ If your device is not listed right now, feel free to contribute your test result
752
778
 
753
779
  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.
754
780
 
781
+ <details>
782
+ <summary><b>ONVIF profiles list</b></summary>
783
+
755
784
  | Name | Specifications | Main Features | Typical Use Case | Support |
756
785
  |-----------|----------------|---------------|------------------|---------|
757
786
  | 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 |
@@ -762,6 +791,8 @@ This library fully supports all major ONVIF Profiles listed below. Each profile
762
791
  | 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 |
763
792
  | 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 |
764
793
 
794
+ </details>
795
+
765
796
  For a full description of each profile and its features, visit [ONVIF Profiles](https://www.onvif.org/profiles/).
766
797
 
767
798
  ## Implemented ONVIF Services
@@ -771,6 +802,9 @@ For a full description of each profile and its features, visit [ONVIF Profiles](
771
802
 
772
803
  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.
773
804
 
805
+ <details>
806
+ <summary><b>ONVIF services list</b></summary>
807
+
774
808
  | Service | Specifications | Service Definitions | Schema Files | Status |
775
809
  |------------------------|-------------------------------|-----------------------------|-------------------------------------|------------|
776
810
  | 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 |
@@ -802,6 +836,8 @@ Below is a list of ONVIF services implemented and supported by this library, alo
802
836
  | 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 |
803
837
  | WebRTC | [Document](https://developer.onvif.org/pub/specs/branches/development/doc/WebRTC.xml) | - | - | ❌ Any idea? |
804
838
 
839
+ </details>
840
+
805
841
  ## Service Bindings in ONVIF
806
842
 
807
843
  ONVIF services are defined by WSDL bindings. In this library, there are two main patterns:
@@ -1,8 +1,8 @@
1
1
  # ONVIF Python
2
2
 
3
- [![License](https://img.shields.io/badge/License-MIT-blue)](https://github.com/nirsimetri/onvif-python?tab=MIT-1-ov-file)
3
+ [![Codacy grade](https://img.shields.io/codacy/grade/bff08a94e4d447b690cea49c6594826d?label=Project%20Quality&logo=codacy)](https://app.codacy.com/gh/nirsimetri/onvif-python/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
4
4
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/nirsimetri/onvif-python)
5
- [![PyPI](https://img.shields.io/badge/PyPI-0.1.3-orange?logo=archive)](https://pypi.org/project/onvif-python/)
5
+ [![PyPI](https://img.shields.io/badge/PyPI-0.1.5-orange?logo=archive)](https://pypi.org/project/onvif-python/)
6
6
  [![Downloads](https://img.shields.io/pypi/dm/onvif-python?label=Downloads&color=red)](https://clickpy.clickhouse.com/dashboard/onvif-python)
7
7
  <br>
8
8
  [![Build](https://github.com/nirsimetri/onvif-python/actions/workflows/python-app.yml/badge.svg?branch=main)](https://github.com/nirsimetri/onvif-python/actions/workflows/python-app.yml)
@@ -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}] [--health-check-interval HEALTH_CHECK_INTERVAL] [--version]
178
178
  [service] [method] [params ...]
179
179
 
180
- ONVIF Terminal Client —
180
+ ONVIF Terminal Client — v0.1.5
181
181
  https://github.com/nirsimetri/onvif-python
182
182
 
183
183
  positional arguments:
@@ -203,6 +203,9 @@ 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
+ --health-check-interval HEALTH_CHECK_INTERVAL, -hci HEALTH_CHECK_INTERVAL
207
+ Health check interval in seconds for interactive mode (default: 10)
208
+ --version, -v Show ONVIF CLI version and exit
206
209
 
207
210
  Examples:
208
211
  # Discover ONVIF devices on network
@@ -231,7 +234,7 @@ Examples:
231
234
  <summary><b>2. Interactive Shell</b></summary>
232
235
 
233
236
  ```bash
234
- ONVIF Interactive Shell Commands -
237
+ ONVIF Interactive Shell Commands - v0.1.5
235
238
  https://github.com/nirsimetri/onvif-python
236
239
 
237
240
  Basic Commands:
@@ -240,15 +243,16 @@ Basic Commands:
240
243
  info - Show connection and device information
241
244
  exit, quit - Exit the shell
242
245
  shortcuts - Show available shortcuts
243
- help <command> - Show help for a specific command
244
246
 
245
247
  Navigation Commands:
246
248
  <service> - Enter service mode (e.g., devicemgmt, media)
249
+ <service> <argument> - Enter service mode with argument (e.g. pullpoint SubscriptionRef=<value>)
247
250
  cd <service> - Enter service mode (alias)
248
251
  ls - List commands/services/methods in grid format
249
252
  up - Exit current service mode (go up one level)
250
253
  pwd - Show current service context
251
254
  clear - Clear terminal screen
255
+ help <command> - Show help for a specific command
252
256
 
253
257
  Service Mode Commands:
254
258
  desc <method> - Show method documentation
@@ -262,6 +266,7 @@ Method Execution:
262
266
  Data Management:
263
267
  store <name> - Store last result with a name
264
268
  show <name> - Show stored data
269
+ show <name>[0] - Show element at index (for lists)
265
270
  show <name>.attribute - Show specific attribute
266
271
  show - List all stored data
267
272
  rm <name> - Remove stored data by name
@@ -329,6 +334,27 @@ If you omit the username or password, you will be prompted to enter them securel
329
334
  > [!IMPORTANT]
330
335
  > You can see all the other commands available in the interactive shell by trying it out directly. The interactive shell runs periodic background health checks to detect connection loss. It uses silent TCP pings to avoid interrupting your work and will automatically exit if the device is unreachable, similar to an SSH session.
331
336
 
337
+ **Command Chaining with `&&`:**
338
+
339
+ The CLI supports chaining multiple commands in a single line using the `&&` operator, allowing you to execute sequential operations efficiently:
340
+
341
+ ```bash
342
+ # Enter service and execute method in one line
343
+ 192.168.1.17:8000 > media && GetProfiles && store profiles
344
+
345
+ # Chain multiple method calls
346
+ 192.168.1.17:8000 > devicemgmt && GetDeviceInformation && store device_info
347
+
348
+ # Complex workflow
349
+ 192.168.1.17:8000 > media && GetProfiles && store profiles && up && imaging && GetImagingSettings VideoSourceToken=$profiles[0].VideoSourceConfiguration.SourceToken
350
+ ```
351
+
352
+ This feature is particularly useful for:
353
+ - Quick operations without entering service mode
354
+ - Scripting repetitive tasks
355
+ - Testing workflows
356
+ - Automating multi-step procedures
357
+
332
358
  **2. Device Discovery (WS-Discovery)**
333
359
 
334
360
  The CLI includes automatic ONVIF device discovery using the WS-Discovery protocol. This feature allows you to find all ONVIF-compliant devices on your local network without knowing their IP addresses beforehand.
@@ -452,7 +478,7 @@ The `ONVIFClient` class provides various configuration options to customize the
452
478
 
453
479
  | Parameter | Type | Required | Default | Description |
454
480
  |-----------|------|----------|---------|-------------|
455
- | `cache` | `CacheMode` | ❌ No | `CacheMode.ALL` | WSDL caching strategy (see [Cache Modes](#cache-modes) below) |
481
+ | `cache` | `CacheMode` | ❌ No | `CacheMode.ALL` | WSDL caching strategy (see **Cache Modes** below) |
456
482
 
457
483
  </details>
458
484
 
@@ -714,6 +740,9 @@ If your device is not listed right now, feel free to contribute your test result
714
740
 
715
741
  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.
716
742
 
743
+ <details>
744
+ <summary><b>ONVIF profiles list</b></summary>
745
+
717
746
  | Name | Specifications | Main Features | Typical Use Case | Support |
718
747
  |-----------|----------------|---------------|------------------|---------|
719
748
  | 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 |
@@ -724,6 +753,8 @@ This library fully supports all major ONVIF Profiles listed below. Each profile
724
753
  | 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 |
725
754
  | 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 |
726
755
 
756
+ </details>
757
+
727
758
  For a full description of each profile and its features, visit [ONVIF Profiles](https://www.onvif.org/profiles/).
728
759
 
729
760
  ## Implemented ONVIF Services
@@ -733,6 +764,9 @@ For a full description of each profile and its features, visit [ONVIF Profiles](
733
764
 
734
765
  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.
735
766
 
767
+ <details>
768
+ <summary><b>ONVIF services list</b></summary>
769
+
736
770
  | Service | Specifications | Service Definitions | Schema Files | Status |
737
771
  |------------------------|-------------------------------|-----------------------------|-------------------------------------|------------|
738
772
  | 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 |
@@ -764,6 +798,8 @@ Below is a list of ONVIF services implemented and supported by this library, alo
764
798
  | 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 |
765
799
  | WebRTC | [Document](https://developer.onvif.org/pub/specs/branches/development/doc/WebRTC.xml) | - | - | ❌ Any idea? |
766
800
 
801
+ </details>
802
+
767
803
  ## Service Bindings in ONVIF
768
804
 
769
805
  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
@@ -16,6 +18,7 @@ from ..utils.exceptions import ONVIFOperationException
16
18
  from .utils import (
17
19
  parse_json_params,
18
20
  get_service_methods,
21
+ get_service_required_args,
19
22
  get_device_available_services,
20
23
  colorize,
21
24
  format_capabilities_as_services,
@@ -170,6 +173,13 @@ class InteractiveShell(cmd.Cmd):
170
173
  if hasattr(args, "no_patch") and args.no_patch:
171
174
  options_info.append(f" ZeepPatcher : {colorize('Disabled', 'red')}")
172
175
 
176
+ if (
177
+ hasattr(args, "health_check_interval") and args.health_check_interval != 10
178
+ ): # 10 is default
179
+ options_info.append(
180
+ f" Health Check : every {colorize(f'{args.health_check_interval}s', 'yellow')}"
181
+ )
182
+
173
183
  # Format options info
174
184
  options_display = ""
175
185
  if options_info:
@@ -181,7 +191,7 @@ class InteractiveShell(cmd.Cmd):
181
191
  " / __ \\/ | / / | / / _/ ____/",
182
192
  " / / / / |/ /| | / // // /_ ",
183
193
  "/ /_/ / /| / | |/ // // __/ ",
184
- "\\____/_/ |_/ |___/___/_/ v0.1.3",
194
+ "\\____/_/ |_/ |___/___/_/ v0.1.5",
185
195
  " ",
186
196
  ]
187
197
 
@@ -220,22 +230,43 @@ class InteractiveShell(cmd.Cmd):
220
230
  self._health_check_thread.start()
221
231
 
222
232
  def _periodic_health_check(self):
223
- """Periodically checks device connection using a TCP socket ping."""
224
- # Wait a moment before the first check to allow the shell to display the intro
225
- self._stop_health_check.wait(10.0)
233
+ """Periodically checks device connection using TCP or TLS depending on mode."""
234
+ # Get health check interval from args, default to 10 seconds
235
+ health_check_interval = getattr(self.args, "health_check_interval", 10)
236
+
237
+ # Wait before first check to allow intro to finish
238
+ self._stop_health_check.wait(health_check_interval)
239
+
226
240
  while not self._stop_health_check.is_set():
227
241
  sock = None
228
242
  try:
229
- # Create a socket and set a short timeout
230
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
231
- sock.settimeout(3) # 3-second timeout for the connection attempt
243
+ sock = socket.create_connection(
244
+ (self.args.host, self.args.port), timeout=5.0
245
+ )
246
+
247
+ # If HTTPS, perform a short TLS handshake check
248
+ if getattr(self.args, "https", False):
249
+ context = ssl.create_default_context()
250
+ context.minimum_version = ssl.TLSVersion.TLSv1_2
251
+ context.check_hostname = False
252
+ context.verify_mode = ssl.CERT_NONE
253
+
254
+ with context.wrap_socket(
255
+ sock, server_hostname=self.args.host
256
+ ) as ssock:
257
+ ssock.settimeout(5)
258
+ # Try a minimal handshake
259
+ ssock.do_handshake()
260
+
261
+ # If we reach here, the connection (and TLS if applicable) succeeded
262
+ pass
232
263
 
233
- # Try to connect to the host and port
234
- sock.connect((self.args.host, self.args.port))
235
264
  except (
236
265
  socket.timeout,
237
266
  ConnectionRefusedError,
238
267
  socket.gaierror,
268
+ ssl.SSLError,
269
+ ssl.SSLEOFError,
239
270
  OSError,
240
271
  ) as e:
241
272
  # Connection failed, trigger exit
@@ -244,7 +275,7 @@ class InteractiveShell(cmd.Cmd):
244
275
  file=sys.stderr,
245
276
  )
246
277
  print(
247
- f"{colorize('Error:', 'red')} TCP check failed - {e}",
278
+ f"{colorize('Error:', 'red')} Health check failed: {e}",
248
279
  file=sys.stderr,
249
280
  )
250
281
  print(
@@ -253,16 +284,14 @@ class InteractiveShell(cmd.Cmd):
253
284
  )
254
285
  # Forcibly exit the entire process. This is necessary to interrupt
255
286
  # the blocking input() call in the main thread.
256
- import os
257
-
258
287
  os._exit(1)
259
288
  finally:
260
289
  # Ensure the socket is always closed
261
290
  if sock:
262
291
  sock.close()
263
292
 
264
- # Wait for the next interval or until stopped
265
- self._stop_health_check.wait(5.0) # Check every 5 seconds
293
+ # Wait before next check or stop signal
294
+ self._stop_health_check.wait(health_check_interval)
266
295
 
267
296
  def _handle_connection_error(self, e):
268
297
  """Handle connection errors by notifying the user and exiting."""
@@ -532,8 +561,17 @@ class InteractiveShell(cmd.Cmd):
532
561
 
533
562
  def default(self, line):
534
563
  """Handle unknown commands"""
535
- # Check if it's a service call using device-specific services
536
- if line in get_device_available_services(self.client):
564
+ available_services = get_device_available_services(self.client)
565
+
566
+ # Check if it's a service call (with or without arguments)
567
+ # Extract first word to check if it's a service name
568
+ first_word = line.split()[0] if line.split() else line
569
+
570
+ if first_word in available_services:
571
+ return self.do_enter_service(line)
572
+
573
+ # Check if the whole line (without arguments) is a service
574
+ if line in available_services:
537
575
  return self.do_enter_service(line)
538
576
 
539
577
  # Check if it's a method call in service context
@@ -704,8 +742,13 @@ class InteractiveShell(cmd.Cmd):
704
742
  else:
705
743
  print(f"{colorize('Error:', 'red')} {e}")
706
744
 
707
- def do_enter_service(self, service_name):
708
- """Enter service mode"""
745
+ def do_enter_service(self, line):
746
+ """Enter service mode with optional arguments for services that require them"""
747
+ # Parse service name and arguments
748
+ parts = line.split(None, 1)
749
+ service_name = parts[0] if parts else ""
750
+ args_str = parts[1] if len(parts) > 1 else ""
751
+
709
752
  available_services = get_device_available_services(self.client)
710
753
  if service_name not in available_services:
711
754
  print(f"{colorize('Error:', 'red')} Unknown service '{service_name}'")
@@ -714,7 +757,63 @@ class InteractiveShell(cmd.Cmd):
714
757
  return
715
758
 
716
759
  try:
717
- service = getattr(self.client, service_name)()
760
+ # Check if this service requires arguments
761
+ required_args = get_service_required_args(service_name)
762
+
763
+ if required_args:
764
+ # Service requires arguments
765
+ if not args_str:
766
+ # No arguments provided, show help
767
+ print(
768
+ f"{colorize('Error:', 'red')} Service '{service_name}' requires arguments"
769
+ )
770
+ print(
771
+ f"{colorize('Usage:', 'yellow')} {service_name} {' '.join([f'{arg}=<value>' for arg in required_args])}"
772
+ )
773
+ print(
774
+ f"{colorize('Example:', 'yellow')} {service_name} {required_args[0]}=$subscription"
775
+ )
776
+ return
777
+
778
+ # Parse arguments
779
+ try:
780
+ parsed_args = parse_json_params(args_str)
781
+ except Exception as e:
782
+ print(f"{colorize('Error parsing arguments:', 'red')} {e}")
783
+ return
784
+
785
+ # Check if all required arguments are provided
786
+ missing_args = [arg for arg in required_args if arg not in parsed_args]
787
+ if missing_args:
788
+ print(
789
+ f"{colorize('Error:', 'red')} Missing required arguments: {', '.join(missing_args)}"
790
+ )
791
+ print(
792
+ f"{colorize('Usage:', 'yellow')} {service_name} {' '.join([f'{arg}=<value>' for arg in required_args])}"
793
+ )
794
+ return
795
+
796
+ # Resolve stored references in arguments
797
+ for arg_name in required_args:
798
+ arg_value = parsed_args[arg_name]
799
+ if isinstance(arg_value, str) and arg_value.startswith("$"):
800
+ # Resolve stored reference
801
+ reference = arg_value[1:] # Remove $ prefix
802
+ resolved_value = self._resolve_stored_reference(reference)
803
+ if resolved_value is None:
804
+ print(
805
+ f"{colorize('Error:', 'red')} Could not resolve reference '{arg_value}'"
806
+ )
807
+ return
808
+ parsed_args[arg_name] = resolved_value
809
+
810
+ # Call service method with arguments
811
+ service_method = getattr(self.client, service_name)
812
+ service = service_method(**parsed_args)
813
+ else:
814
+ # Service doesn't require arguments
815
+ service = getattr(self.client, service_name)()
816
+
718
817
  self.current_service = service
719
818
  self.current_service_name = service_name
720
819
  self.update_prompt()
@@ -739,6 +838,10 @@ class InteractiveShell(cmd.Cmd):
739
838
 
740
839
  except Exception as e:
741
840
  print(f"{colorize('Error entering service:', 'red')} {e}")
841
+ if self.args.debug:
842
+ import traceback
843
+
844
+ traceback.print_exc()
742
845
 
743
846
  def do_ls(self, line):
744
847
  """List available commands/services like TAB completion"""
@@ -826,7 +929,7 @@ class InteractiveShell(cmd.Cmd):
826
929
  print(
827
930
  f"{colorize('Error:', 'red')} You must be in a service mode to use 'type'."
828
931
  )
829
- print(f"Enter a service first (e.g., {colorize('d', 'yellow')})")
932
+ print(f"Enter a service first (e.g., {colorize('devicemgmt', 'yellow')})")
830
933
  return
831
934
 
832
935
  if not operation_name:
@@ -1141,8 +1244,6 @@ class InteractiveShell(cmd.Cmd):
1141
1244
 
1142
1245
  def do_clear(self, line):
1143
1246
  """Clear terminal screen"""
1144
- import os
1145
-
1146
1247
  # Clear screen for both Windows and Unix-like systems
1147
1248
  os.system("cls" if os.name == "nt" else "clear")
1148
1249
 
@@ -1176,6 +1277,14 @@ class InteractiveShell(cmd.Cmd):
1176
1277
  if hasattr(self.args, "no_patch") and self.args.no_patch:
1177
1278
  options_info.append(f" ZeepPatcher : {colorize('Disabled', 'red')}")
1178
1279
 
1280
+ if (
1281
+ hasattr(self.args, "health_check_interval")
1282
+ and self.args.health_check_interval != 10
1283
+ ): # 10 is default
1284
+ options_info.append(
1285
+ f" Health Check : every {colorize(f'{self.args.health_check_interval}s', 'yellow')}"
1286
+ )
1287
+
1179
1288
  # Format options info
1180
1289
  options_display = ""
1181
1290
  if options_info:
@@ -1285,7 +1394,7 @@ class InteractiveShell(cmd.Cmd):
1285
1394
  super().do_help(line)
1286
1395
  else:
1287
1396
  help_text = f"""
1288
- {colorize('ONVIF Interactive Shell Commands -', 'cyan')}\n{colorize('https://github.com/nirsimetri/onvif-python', 'white')}
1397
+ {colorize('ONVIF Interactive Shell Commands - v0.1.5', 'cyan')}\n{colorize('https://github.com/nirsimetri/onvif-python', 'white')}
1289
1398
 
1290
1399
  {colorize('Basic Commands:', 'yellow')}
1291
1400
  capabilities, caps - Show device capabilities
@@ -1296,6 +1405,7 @@ class InteractiveShell(cmd.Cmd):
1296
1405
 
1297
1406
  {colorize('Navigation Commands:', 'yellow')}
1298
1407
  <service> - Enter service mode (e.g., devicemgmt, media)
1408
+ <service> <argument> - Enter service mode with argument (e.g. pullpoint SubscriptionRef=<value>)
1299
1409
  cd <service> - Enter service mode (alias)
1300
1410
  ls - List commands/services/methods in grid format
1301
1411
  up - Exit current service mode (go up one level)