conson-xp 1.0.1__py3-none-any.whl → 1.2.0__py3-none-any.whl

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 (167) hide show
  1. {conson_xp-1.0.1.dist-info → conson_xp-1.2.0.dist-info}/METADATA +1 -1
  2. conson_xp-1.2.0.dist-info/RECORD +181 -0
  3. xp/__init__.py +4 -3
  4. xp/api/main.py +18 -3
  5. xp/api/models/api.py +13 -2
  6. xp/api/models/discover.py +12 -2
  7. xp/api/routers/conbus_blink.py +18 -6
  8. xp/api/routers/conbus_custom.py +11 -3
  9. xp/api/routers/conbus_datapoint.py +10 -3
  10. xp/api/routers/conbus_output.py +29 -9
  11. xp/api/routers/errors.py +6 -5
  12. xp/cli/__init__.py +1 -1
  13. xp/cli/commands/__init__.py +1 -0
  14. xp/cli/commands/api.py +1 -5
  15. xp/cli/commands/api_start_commands.py +14 -8
  16. xp/cli/commands/conbus/conbus.py +9 -37
  17. xp/cli/commands/conbus/conbus_actiontable_commands.py +21 -1
  18. xp/cli/commands/conbus/conbus_autoreport_commands.py +21 -11
  19. xp/cli/commands/conbus/conbus_blink_commands.py +53 -21
  20. xp/cli/commands/conbus/conbus_config_commands.py +7 -4
  21. xp/cli/commands/conbus/conbus_custom_commands.py +13 -4
  22. xp/cli/commands/conbus/conbus_datapoint_commands.py +28 -8
  23. xp/cli/commands/conbus/conbus_discover_commands.py +15 -4
  24. xp/cli/commands/conbus/conbus_lightlevel_commands.py +50 -11
  25. xp/cli/commands/conbus/conbus_linknumber_commands.py +21 -11
  26. xp/cli/commands/conbus/conbus_msactiontable_commands.py +25 -1
  27. xp/cli/commands/conbus/conbus_output_commands.py +46 -12
  28. xp/cli/commands/conbus/conbus_raw_commands.py +17 -6
  29. xp/cli/commands/conbus/conbus_receive_commands.py +15 -7
  30. xp/cli/commands/conbus/conbus_scan_commands.py +35 -102
  31. xp/cli/commands/file_commands.py +26 -15
  32. xp/cli/commands/homekit/homekit.py +14 -8
  33. xp/cli/commands/homekit/homekit_start_commands.py +5 -5
  34. xp/cli/commands/module_commands.py +26 -19
  35. xp/cli/commands/reverse_proxy_commands.py +24 -18
  36. xp/cli/commands/server/server_commands.py +18 -18
  37. xp/cli/commands/telegram/telegram.py +4 -12
  38. xp/cli/commands/telegram/telegram_blink_commands.py +10 -8
  39. xp/cli/commands/telegram/telegram_checksum_commands.py +19 -8
  40. xp/cli/commands/telegram/telegram_discover_commands.py +2 -4
  41. xp/cli/commands/telegram/telegram_linknumber_commands.py +11 -8
  42. xp/cli/commands/telegram/telegram_parse_commands.py +10 -9
  43. xp/cli/commands/telegram/telegram_version_commands.py +8 -4
  44. xp/cli/main.py +5 -1
  45. xp/cli/utils/click_tree.py +23 -3
  46. xp/cli/utils/datapoint_type_choice.py +20 -0
  47. xp/cli/utils/decorators.py +165 -14
  48. xp/cli/utils/error_handlers.py +49 -18
  49. xp/cli/utils/formatters.py +95 -10
  50. xp/cli/utils/serial_number_type.py +18 -0
  51. xp/cli/utils/system_function_choice.py +20 -0
  52. xp/cli/utils/xp_module_type.py +20 -0
  53. xp/connection/__init__.py +1 -1
  54. xp/connection/exceptions.py +5 -5
  55. xp/models/__init__.py +1 -1
  56. xp/models/actiontable/__init__.py +1 -0
  57. xp/models/actiontable/actiontable.py +17 -1
  58. xp/models/actiontable/msactiontable_xp20.py +10 -0
  59. xp/models/actiontable/msactiontable_xp24.py +20 -3
  60. xp/models/actiontable/msactiontable_xp33.py +27 -4
  61. xp/models/conbus/__init__.py +1 -0
  62. xp/models/conbus/conbus.py +34 -4
  63. xp/models/conbus/conbus_autoreport.py +20 -2
  64. xp/models/conbus/conbus_blink.py +22 -2
  65. xp/models/conbus/conbus_client_config.py +22 -1
  66. xp/models/conbus/conbus_connection_status.py +16 -2
  67. xp/models/conbus/conbus_custom.py +21 -2
  68. xp/models/conbus/conbus_datapoint.py +22 -2
  69. xp/models/conbus/conbus_discover.py +18 -2
  70. xp/models/conbus/conbus_lightlevel.py +20 -2
  71. xp/models/conbus/conbus_linknumber.py +20 -2
  72. xp/models/conbus/conbus_output.py +22 -2
  73. xp/models/conbus/conbus_raw.py +17 -2
  74. xp/models/conbus/conbus_receive.py +16 -2
  75. xp/models/homekit/__init__.py +1 -0
  76. xp/models/homekit/homekit_accessory.py +15 -1
  77. xp/models/homekit/homekit_config.py +52 -0
  78. xp/models/homekit/homekit_conson_config.py +32 -0
  79. xp/models/log_entry.py +49 -9
  80. xp/models/protocol/__init__.py +1 -0
  81. xp/models/protocol/conbus_protocol.py +130 -21
  82. xp/models/telegram/__init__.py +1 -0
  83. xp/models/telegram/action_type.py +16 -2
  84. xp/models/telegram/datapoint_type.py +36 -2
  85. xp/models/telegram/event_telegram.py +46 -10
  86. xp/models/telegram/event_type.py +8 -1
  87. xp/models/telegram/input_action_type.py +34 -2
  88. xp/models/telegram/input_type.py +9 -1
  89. xp/models/telegram/module_type.py +69 -19
  90. xp/models/telegram/module_type_code.py +43 -1
  91. xp/models/telegram/output_telegram.py +30 -6
  92. xp/models/telegram/reply_telegram.py +56 -11
  93. xp/models/telegram/system_function.py +35 -3
  94. xp/models/telegram/system_telegram.py +18 -4
  95. xp/models/telegram/telegram.py +12 -3
  96. xp/models/telegram/telegram_type.py +8 -1
  97. xp/models/telegram/timeparam_type.py +27 -0
  98. xp/models/write_config_type.py +17 -2
  99. xp/services/__init__.py +1 -1
  100. xp/services/conbus/__init__.py +1 -0
  101. xp/services/conbus/actiontable/__init__.py +1 -0
  102. xp/services/conbus/actiontable/actiontable_service.py +33 -2
  103. xp/services/conbus/actiontable/msactiontable_service.py +40 -3
  104. xp/services/conbus/actiontable/msactiontable_xp24_serializer.py +36 -4
  105. xp/services/conbus/actiontable/msactiontable_xp33_serializer.py +45 -5
  106. xp/services/conbus/conbus_autoreport_get_service.py +17 -8
  107. xp/services/conbus/conbus_autoreport_set_service.py +29 -16
  108. xp/services/conbus/conbus_blink_all_service.py +40 -21
  109. xp/services/conbus/conbus_blink_service.py +37 -13
  110. xp/services/conbus/conbus_custom_service.py +29 -13
  111. xp/services/conbus/conbus_datapoint_queryall_service.py +40 -16
  112. xp/services/conbus/conbus_datapoint_service.py +33 -12
  113. xp/services/conbus/conbus_discover_service.py +43 -7
  114. xp/services/conbus/conbus_lightlevel_get_service.py +22 -14
  115. xp/services/conbus/conbus_lightlevel_set_service.py +40 -20
  116. xp/services/conbus/conbus_linknumber_get_service.py +18 -10
  117. xp/services/conbus/conbus_linknumber_set_service.py +34 -8
  118. xp/services/conbus/conbus_output_service.py +33 -13
  119. xp/services/conbus/conbus_raw_service.py +36 -16
  120. xp/services/conbus/conbus_receive_service.py +38 -6
  121. xp/services/conbus/conbus_scan_service.py +45 -19
  122. xp/services/homekit/__init__.py +1 -0
  123. xp/services/homekit/homekit_cache_service.py +31 -6
  124. xp/services/homekit/homekit_conbus_service.py +33 -2
  125. xp/services/homekit/homekit_config_validator.py +97 -15
  126. xp/services/homekit/homekit_conson_validator.py +51 -7
  127. xp/services/homekit/homekit_dimminglight.py +47 -1
  128. xp/services/homekit/homekit_dimminglight_service.py +35 -1
  129. xp/services/homekit/homekit_hap_service.py +71 -18
  130. xp/services/homekit/homekit_lightbulb.py +35 -1
  131. xp/services/homekit/homekit_lightbulb_service.py +30 -2
  132. xp/services/homekit/homekit_module_service.py +23 -1
  133. xp/services/homekit/homekit_outlet.py +47 -1
  134. xp/services/homekit/homekit_outlet_service.py +44 -2
  135. xp/services/homekit/homekit_service.py +113 -19
  136. xp/services/log_file_service.py +37 -41
  137. xp/services/module_type_service.py +26 -5
  138. xp/services/protocol/__init__.py +1 -1
  139. xp/services/protocol/conbus_protocol.py +115 -20
  140. xp/services/protocol/protocol_factory.py +40 -0
  141. xp/services/protocol/telegram_protocol.py +38 -7
  142. xp/services/reverse_proxy_service.py +79 -14
  143. xp/services/server/__init__.py +1 -0
  144. xp/services/server/base_server_service.py +102 -14
  145. xp/services/server/cp20_server_service.py +12 -4
  146. xp/services/server/server_service.py +26 -11
  147. xp/services/server/xp130_server_service.py +11 -3
  148. xp/services/server/xp20_server_service.py +11 -3
  149. xp/services/server/xp230_server_service.py +11 -3
  150. xp/services/server/xp24_server_service.py +33 -6
  151. xp/services/server/xp33_server_service.py +41 -8
  152. xp/services/telegram/__init__.py +1 -0
  153. xp/services/telegram/telegram_blink_service.py +19 -31
  154. xp/services/telegram/telegram_checksum_service.py +10 -10
  155. xp/services/telegram/telegram_discover_service.py +58 -29
  156. xp/services/telegram/telegram_link_number_service.py +27 -40
  157. xp/services/telegram/telegram_output_service.py +46 -49
  158. xp/services/telegram/telegram_service.py +41 -41
  159. xp/services/telegram/telegram_version_service.py +4 -2
  160. xp/utils/__init__.py +1 -1
  161. xp/utils/dependencies.py +0 -1
  162. xp/utils/serialization.py +6 -0
  163. xp/utils/time_utils.py +6 -11
  164. conson_xp-1.0.1.dist-info/RECORD +0 -181
  165. {conson_xp-1.0.1.dist-info → conson_xp-1.2.0.dist-info}/WHEEL +0 -0
  166. {conson_xp-1.0.1.dist-info → conson_xp-1.2.0.dist-info}/entry_points.txt +0 -0
  167. {conson_xp-1.0.1.dist-info → conson_xp-1.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -17,9 +17,7 @@ from xp.services.module_type_service import ModuleTypeNotFoundError, ModuleTypeS
17
17
  cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
18
18
  )
19
19
  def module() -> None:
20
- """
21
- Module type operations
22
- """
20
+ """Perform module type operations."""
23
21
  pass
24
22
 
25
23
 
@@ -28,12 +26,14 @@ def module() -> None:
28
26
  @click.pass_context
29
27
  @list_command(ModuleTypeNotFoundError)
30
28
  def module_info(ctx: Context, identifier: str) -> None:
31
- """
32
- Get information about a module type by code or name.
29
+ r"""Get information about a module type by code or name.
33
30
 
34
- Examples:
31
+ Args:
32
+ ctx: Click context object.
33
+ identifier: Module code or name.
35
34
 
36
- \b
35
+ Examples:
36
+ \b
37
37
  xp module info 14
38
38
  xp module info XP2606
39
39
  """
@@ -63,12 +63,15 @@ def module_info(ctx: Context, identifier: str) -> None:
63
63
  @click.pass_context
64
64
  @list_command(Exception)
65
65
  def module_list(ctx: Context, category: str, group_by_category: bool) -> None:
66
- """
67
- List module types, optionally filtered by category.
66
+ r"""List module types, optionally filtered by category.
68
67
 
69
- Examples:
68
+ Args:
69
+ ctx: Click context object.
70
+ category: Filter by category.
71
+ group_by_category: Group modules by category.
70
72
 
71
- \b
73
+ Examples:
74
+ \b
72
75
  xp module list
73
76
  xp module list --category "Interface Panels"
74
77
  xp module list --group-by-category
@@ -115,12 +118,15 @@ def module_list(ctx: Context, category: str, group_by_category: bool) -> None:
115
118
  @click.pass_context
116
119
  @list_command(Exception)
117
120
  def module_search(ctx: Context, query: str, field: tuple) -> None:
118
- """
119
- Search for module types by name or description.
121
+ r"""Search for module types by name or description.
120
122
 
121
- Examples:
123
+ Args:
124
+ ctx: Click context object.
125
+ query: Search query.
126
+ field: Fields to search in.
122
127
 
123
- \b
128
+ Examples:
129
+ \b
124
130
  xp module search "push button"
125
131
  xp module search --field name "XP"
126
132
  """
@@ -147,12 +153,13 @@ def module_search(ctx: Context, query: str, field: tuple) -> None:
147
153
  @click.pass_context
148
154
  @list_command(Exception)
149
155
  def module_categories(ctx: Context) -> None:
150
- """
151
- List all available module categories.
156
+ r"""List all available module categories.
152
157
 
153
- Examples:
158
+ Args:
159
+ ctx: Click context object.
154
160
 
155
- \b
161
+ Examples:
162
+ \b
156
163
  xp module categories
157
164
  """
158
165
  service = ctx.obj.get("container").get_container().resolve(ModuleTypeService)
@@ -29,9 +29,7 @@ global_proxy_instance: Optional[ReverseProxyService] = None
29
29
  help_options_color="green",
30
30
  )
31
31
  def reverse_proxy() -> None:
32
- """
33
- Conbus reverse proxy operations
34
- """
32
+ """Perform Conbus reverse proxy operations."""
35
33
  pass
36
34
 
37
35
 
@@ -43,18 +41,24 @@ def reverse_proxy() -> None:
43
41
  @handle_service_errors(ReverseProxyError)
44
42
  @click.pass_context
45
43
  def start_proxy(ctx: Context, port: int, config: str) -> None:
46
- """
47
- Start the Conbus reverse proxy server.
44
+ r"""Start the Conbus reverse proxy server.
48
45
 
49
46
  The proxy listens on the specified port and forwards all telegrams
50
47
  to the target server configured in cli.yml. All traffic is monitored
51
48
  and printed with timestamps.
52
49
 
53
- Examples:
50
+ Args:
51
+ ctx: Click context object.
52
+ port: Port to listen on.
53
+ config: Configuration file path.
54
54
 
55
- \b
55
+ Examples:
56
+ \b
56
57
  xp rp start
57
58
  xp rp start --port 10002 --config my_cli.yml
59
+
60
+ Raises:
61
+ SystemExit: If proxy is already running.
58
62
  """
59
63
  global global_proxy_instance
60
64
 
@@ -74,6 +78,12 @@ def start_proxy(ctx: Context, port: int, config: str) -> None:
74
78
 
75
79
  # Handle graceful shutdown on SIGINT
76
80
  def signal_handler(signum: int, frame: Optional[FrameType]) -> None:
81
+ """Handle shutdown signals for graceful proxy termination.
82
+
83
+ Args:
84
+ signum: Signal number received.
85
+ frame: Current stack frame (may be None).
86
+ """
77
87
  if global_proxy_instance and global_proxy_instance.is_running:
78
88
  timestamp = global_proxy_instance.timestamp()
79
89
  print(f"\n{timestamp} [SHUTDOWN] Received interrupt signal ({signum})")
@@ -104,16 +114,15 @@ def start_proxy(ctx: Context, port: int, config: str) -> None:
104
114
  @reverse_proxy.command("stop")
105
115
  @handle_service_errors(ReverseProxyError)
106
116
  def stop_proxy() -> None:
107
- """
108
- Stop the running Conbus reverse proxy server.
117
+ r"""Stop the running Conbus reverse proxy server.
109
118
 
110
119
  Examples:
111
-
112
- \b
120
+ \b
113
121
  xp rp stop
114
- """
115
- global global_proxy_instance
116
122
 
123
+ Raises:
124
+ SystemExit: If proxy is not running.
125
+ """
117
126
  try:
118
127
  if global_proxy_instance is None or not global_proxy_instance.is_running:
119
128
  error_response = {
@@ -135,18 +144,15 @@ def stop_proxy() -> None:
135
144
  @reverse_proxy.command("status")
136
145
  @handle_service_errors(Exception)
137
146
  def proxy_status() -> None:
138
- """
139
- Get status of the Conbus reverse proxy server.
147
+ r"""Get status of the Conbus reverse proxy server.
140
148
 
141
149
  Shows current running state, listen port, target server,
142
150
  and active connection details.
143
151
 
144
152
  Examples:
145
-
146
- \b
153
+ \b
147
154
  xp rp status
148
155
  """
149
- global global_proxy_instance
150
156
  OutputFormatter(True)
151
157
 
152
158
  try:
@@ -20,9 +20,7 @@ _server_instance: Optional[ServerService] = None
20
20
  cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
21
21
  )
22
22
  def server() -> None:
23
- """
24
- Conbus emulator server operations
25
- """
23
+ """Perform Conbus emulator server operations."""
26
24
  pass
27
25
 
28
26
 
@@ -34,14 +32,20 @@ def server() -> None:
34
32
  @click.pass_context
35
33
  @handle_service_errors(ServerError)
36
34
  def start_server(ctx: Context, port: int, config: str) -> None:
37
- """
38
- Start the Conbus emulator server.
35
+ r"""Start the Conbus emulator server.
39
36
 
40
- Examples:
37
+ Args:
38
+ ctx: Click context object.
39
+ port: Port to listen on.
40
+ config: Configuration file path.
41
41
 
42
- \b
42
+ Examples:
43
+ \b
43
44
  xp server start
44
45
  xp server start --port 1001 --config my_config.yml
46
+
47
+ Raises:
48
+ SystemExit: If server is already running.
45
49
  """
46
50
  global _server_instance
47
51
 
@@ -76,16 +80,12 @@ def start_server(ctx: Context, port: int, config: str) -> None:
76
80
  @server.command("stop")
77
81
  @handle_service_errors(ServerError)
78
82
  def stop_server() -> None:
79
- """
80
- Stop the running Conbus emulator server.
83
+ r"""Stop the running Conbus emulator server.
81
84
 
82
85
  Examples:
83
-
84
- \b
86
+ \b
85
87
  xp server stop
86
88
  """
87
- global _server_instance
88
-
89
89
  try:
90
90
  if _server_instance is None or not _server_instance.is_running:
91
91
  ServerErrorHandler.handle_server_not_running_error()
@@ -104,15 +104,15 @@ def stop_server() -> None:
104
104
  @server.command("status")
105
105
  @handle_service_errors(Exception)
106
106
  def server_status() -> None:
107
- """
108
- Get status of the Conbus emulator server.
107
+ r"""Get status of the Conbus emulator server.
109
108
 
110
109
  Examples:
111
-
112
- \b
110
+ \b
113
111
  xp server status
112
+
113
+ Raises:
114
+ SystemExit: If status cannot be retrieved.
114
115
  """
115
- global _server_instance
116
116
  formatter = OutputFormatter(True)
117
117
 
118
118
  try:
@@ -8,9 +8,7 @@ from click_help_colors import HelpColorsGroup
8
8
  cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
9
9
  )
10
10
  def telegram() -> None:
11
- """
12
- Event telegram operations
13
- """
11
+ """Perform event telegram operations."""
14
12
  pass
15
13
 
16
14
 
@@ -18,9 +16,7 @@ def telegram() -> None:
18
16
  cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
19
17
  )
20
18
  def linknumber() -> None:
21
- """
22
- Link number operations for module configuration
23
- """
19
+ """Perform link number operations for module configuration."""
24
20
  pass
25
21
 
26
22
 
@@ -28,9 +24,7 @@ def linknumber() -> None:
28
24
  cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
29
25
  )
30
26
  def blink() -> None:
31
- """
32
- Blink operations for module LED control
33
- """
27
+ """Perform blink operations for module LED control."""
34
28
  pass
35
29
 
36
30
 
@@ -38,9 +32,7 @@ def blink() -> None:
38
32
  cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
39
33
  )
40
34
  def checksum() -> None:
41
- """
42
- Checksum calculation and validation operations
43
- """
35
+ """Perform checksum calculation and validation operations."""
44
36
  pass
45
37
 
46
38
 
@@ -16,12 +16,13 @@ from xp.services.telegram.telegram_blink_service import BlinkError, TelegramBlin
16
16
  @click.argument("serial_number", type=SERIAL)
17
17
  @handle_service_errors(BlinkError)
18
18
  def blink_on(serial_number: str) -> None:
19
- """
20
- Generate a telegram to start blinking module LED.
19
+ r"""Generate a telegram to start blinking module LED.
21
20
 
22
- Examples:
21
+ Args:
22
+ serial_number: 10-digit module serial number.
23
23
 
24
- \b
24
+ Examples:
25
+ \b
25
26
  xp blink on 0012345008
26
27
  xp blink on 0012345008
27
28
  """
@@ -49,12 +50,13 @@ def blink_on(serial_number: str) -> None:
49
50
  @click.argument("serial_number", type=SERIAL)
50
51
  @handle_service_errors(BlinkError)
51
52
  def blink_off(serial_number: str) -> None:
52
- """
53
- Generate a telegram to stop blinking module LED.
53
+ r"""Generate a telegram to stop blinking module LED.
54
54
 
55
- Examples:
55
+ Args:
56
+ serial_number: 10-digit module serial number.
56
57
 
57
- \b
58
+ Examples:
59
+ \b
58
60
  xp blink off 0012345011
59
61
  """
60
62
  service = TelegramBlinkService()
@@ -22,14 +22,19 @@ from xp.services.telegram.telegram_checksum_service import TelegramChecksumServi
22
22
  )
23
23
  @handle_service_errors(Exception)
24
24
  def calculate_checksum(data: str, algorithm: str) -> None:
25
- """
26
- Calculate checksum for given data string.
25
+ r"""Calculate checksum for given data string.
27
26
 
28
- Examples:
27
+ Args:
28
+ data: Data string to calculate checksum for.
29
+ algorithm: Checksum algorithm to use.
29
30
 
30
- \b
31
+ Examples:
32
+ \b
31
33
  xp checksum calculate "E14L00I02M"
32
34
  xp checksum calculate "E14L00I02M" --algorithm crc32
35
+
36
+ Raises:
37
+ SystemExit: If checksum calculation fails.
33
38
  """
34
39
  service = TelegramChecksumService()
35
40
  formatter = OutputFormatter(True)
@@ -65,14 +70,20 @@ def calculate_checksum(data: str, algorithm: str) -> None:
65
70
  )
66
71
  @handle_service_errors(Exception)
67
72
  def validate_checksum(data: str, expected_checksum: str, algorithm: str) -> None:
68
- """
69
- Validate data against expected checksum.
73
+ r"""Validate data against expected checksum.
70
74
 
71
- Examples:
75
+ Args:
76
+ data: Data string to validate.
77
+ expected_checksum: Expected checksum value.
78
+ algorithm: Checksum algorithm to use.
72
79
 
73
- \b
80
+ Examples:
81
+ \b
74
82
  xp checksum validate "E14L00I02M" "AK"
75
83
  xp checksum validate "E14L00I02M" "ABCDABCD" --algorithm crc32
84
+
85
+ Raises:
86
+ SystemExit: If checksum validation fails.
76
87
  """
77
88
  service = TelegramChecksumService()
78
89
  formatter = OutputFormatter(True)
@@ -17,12 +17,10 @@ from xp.services.telegram.telegram_discover_service import (
17
17
  @telegram.command("discover")
18
18
  @handle_service_errors(DiscoverError)
19
19
  def generate_discover() -> None:
20
- """
21
- Generate a discover telegram for device enumeration.
20
+ r"""Generate a discover telegram for device enumeration.
22
21
 
23
22
  Examples:
24
-
25
- \b
23
+ \b
26
24
  xp telegram discover
27
25
  """
28
26
  service = TelegramDiscoverService()
@@ -20,12 +20,14 @@ from xp.services.telegram.telegram_link_number_service import (
20
20
  @click.argument("link_number", type=int)
21
21
  @handle_service_errors(LinkNumberError)
22
22
  def generate_set_link_number(serial_number: str, link_number: int) -> None:
23
- """
24
- Generate a telegram to set module link number.
23
+ r"""Generate a telegram to set module link number.
25
24
 
26
- Examples:
25
+ Args:
26
+ serial_number: 10-digit module serial number.
27
+ link_number: Link number to set.
27
28
 
28
- \b
29
+ Examples:
30
+ \b
29
31
  xp telegram linknumber write 0012345005 25
30
32
  """
31
33
  service = LinkNumberService()
@@ -55,12 +57,13 @@ def generate_set_link_number(serial_number: str, link_number: int) -> None:
55
57
  @click.argument("serial_number", type=SERIAL)
56
58
  @handle_service_errors(LinkNumberError)
57
59
  def generate_read_link_number(serial_number: str) -> None:
58
- """
59
- Generate a telegram to read module link number.
60
+ r"""Generate a telegram to read module link number.
60
61
 
61
- Examples:
62
+ Args:
63
+ serial_number: 10-digit module serial number.
62
64
 
63
- \b
65
+ Examples:
66
+ \b
64
67
  xp telegram linknumber read 0012345005
65
68
  """
66
69
  service = LinkNumberService()
@@ -17,19 +17,19 @@ from xp.services.telegram.telegram_service import TelegramParsingError, Telegram
17
17
  @click.argument("telegram_string")
18
18
  @handle_service_errors(TelegramParsingError)
19
19
  def parse_any_telegram(telegram_string: str) -> None:
20
- """
21
- Auto-detect and parse any type of telegram (event, system, reply, or discover).
20
+ r"""Auto-detect and parse any type of telegram (event, system, reply, or discover).
22
21
 
23
- Examples:
22
+ Args:
23
+ telegram_string: Telegram string to parse.
24
24
 
25
- \b
25
+ Examples:
26
+ \b
26
27
  xp telegram parse "<E14L00I02MAK>"
27
28
  xp telegram parse "<S0020012521F02D18FN>"
28
29
  xp telegram parse "<R0020012521F02D18+26,0§CIL>"
29
30
  xp telegram parse "<S0000000000F01D00FA>"
30
31
  xp telegram parse "<R0012345011F01DFM>"
31
32
  xp telegram parse "<R0012345003F18DFF>"
32
-
33
33
  """
34
34
  service = TelegramService()
35
35
  TelegramFormatter(True)
@@ -47,12 +47,13 @@ def parse_any_telegram(telegram_string: str) -> None:
47
47
  @click.argument("telegram_string")
48
48
  @handle_service_errors(TelegramParsingError)
49
49
  def validate_telegram(telegram_string: str) -> None:
50
- """
51
- Validate the format of an event telegram.
50
+ r"""Validate the format of an event telegram.
52
51
 
53
- Examples:
52
+ Args:
53
+ telegram_string: Telegram string to validate.
54
54
 
55
- \b
55
+ Examples:
56
+ \b
56
57
  xp telegram validate "<E14L00I02MAK>"
57
58
  """
58
59
  service = TelegramService()
@@ -19,13 +19,17 @@ from xp.services.telegram.telegram_version_service import (
19
19
  @click.argument("serial_number", type=SERIAL)
20
20
  @handle_service_errors(VersionParsingError)
21
21
  def generate_version_request(serial_number: str) -> None:
22
- """
23
- Generate a telegram to request version information from a device.
22
+ r"""Generate a telegram to request version information from a device.
24
23
 
25
- Examples:
24
+ Args:
25
+ serial_number: 10-digit module serial number.
26
26
 
27
- \b
27
+ Examples:
28
+ \b
28
29
  xp telegram version 0012345011
30
+
31
+ Raises:
32
+ SystemExit: If request cannot be generated.
29
33
  """
30
34
  service = VersionService()
31
35
  formatter = OutputFormatter(True)
xp/cli/main.py CHANGED
@@ -27,7 +27,11 @@ from xp.utils.dependencies import ServiceContainer
27
27
  @click.version_option()
28
28
  @click.pass_context
29
29
  def cli(ctx: click.Context) -> None:
30
- """XP CLI tool for remote console bus operations"""
30
+ """XP CLI tool for remote console bus operations.
31
+
32
+ Args:
33
+ ctx: Click context object for passing state between commands.
34
+ """
31
35
  # Configure logging with thread information
32
36
  log_format = "%(asctime)s - [%(threadName)s-%(thread)d] - %(levelname)s - %(name)s - %(message)s"
33
37
  date_format = "%H:%M:%S"
@@ -1,13 +1,29 @@
1
- # save as click_tree.py
1
+ """Utilities for displaying Click command trees."""
2
+
2
3
  from typing import Any
3
4
 
4
5
  import click
5
6
 
6
7
 
7
8
  def add_tree_command(cli_group: click.Group, command_name: str = "help") -> Any:
8
- """Add a tree command to any Click group"""
9
+ """Add a tree command to any Click group.
10
+
11
+ Args:
12
+ cli_group: The Click group to add the tree command to.
13
+ command_name: Name of the tree command (default: "help").
14
+
15
+ Returns:
16
+ The tree command function.
17
+ """
9
18
 
10
19
  def print_command_tree(group: click.Group, ctx: click.Context, suffix: str) -> None:
20
+ """Print command tree recursively.
21
+
22
+ Args:
23
+ group: The Click group to print.
24
+ ctx: The Click context.
25
+ suffix: Prefix string for tree display.
26
+ """
11
27
  for name in sorted(group.list_commands(ctx)):
12
28
  cmd = group.get_command(ctx, name)
13
29
 
@@ -23,7 +39,11 @@ def add_tree_command(cli_group: click.Group, command_name: str = "help") -> Any:
23
39
  @cli_group.command(command_name)
24
40
  @click.pass_context
25
41
  def tree_command(ctx: click.Context) -> None:
26
- """Show complete command tree"""
42
+ """Show complete command tree.
43
+
44
+ Args:
45
+ ctx: The Click context.
46
+ """
27
47
  root = ctx.find_root().command
28
48
  root_ctx = ctx.find_root()
29
49
  root_name = root_ctx.info_name or "cli"
@@ -1,3 +1,5 @@
1
+ """Click parameter type for DataPointType enum validation."""
2
+
1
3
  from typing import Any, Optional
2
4
 
3
5
  import click
@@ -7,14 +9,32 @@ from xp.models.telegram.datapoint_type import DataPointType
7
9
 
8
10
  # noinspection DuplicatedCode
9
11
  class DatapointTypeChoice(click.ParamType):
12
+ """Click parameter type for validating DataPointType enum values.
13
+
14
+ Attributes:
15
+ name: The parameter type name.
16
+ choices: List of valid choice strings.
17
+ """
18
+
10
19
  name = "telegram_type"
11
20
 
12
21
  def __init__(self) -> None:
22
+ """Initialize the DatapointTypeChoice parameter type."""
13
23
  self.choices = [key.lower() for key in DataPointType.__members__.keys()]
14
24
 
15
25
  def convert(
16
26
  self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
17
27
  ) -> Any:
28
+ """Convert and validate input to DataPointType enum.
29
+
30
+ Args:
31
+ value: The input value to convert.
32
+ param: The Click parameter.
33
+ ctx: The Click context.
34
+
35
+ Returns:
36
+ DataPointType enum member if valid, None if input is None.
37
+ """
18
38
  if value is None:
19
39
  return value
20
40