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
@@ -12,17 +12,22 @@ from xp.utils.checksum import calculate_checksum
12
12
 
13
13
 
14
14
  class XPOutputError(Exception):
15
- """Raised when XP24 action operations fail"""
15
+ """Raised when XP24 action operations fail."""
16
16
 
17
17
  pass
18
18
 
19
19
 
20
20
  class TelegramOutputService:
21
- """
22
- Service for XP action operations.
21
+ """Service for XP action operations.
23
22
 
24
23
  Handles parsing and validation of XP24 action telegrams,
25
24
  status queries, and action command generation.
25
+
26
+ Attributes:
27
+ MAX_OUTPUTS: Maximum number of outputs supported.
28
+ XP_OUTPUT_PATTERN: Regex pattern for XP24 action telegrams.
29
+ XP_ACK_NAK_PATTERN: Regex pattern for ACK/NAK response telegrams.
30
+ telegram_service: TelegramService instance for parsing.
26
31
  """
27
32
 
28
33
  MAX_OUTPUTS = 99
@@ -32,18 +37,21 @@ class TelegramOutputService:
32
37
  XP_ACK_NAK_PATTERN = re.compile(r"^<R(\d{10})F(1[89])D([A-Z0-9]{2})>$")
33
38
 
34
39
  def __init__(self, telegram_service: TelegramService) -> None:
35
- """Initialize the XP output service"""
40
+ """Initialize the XP output service.
41
+
42
+ Args:
43
+ telegram_service: TelegramService instance for parsing operations.
44
+ """
36
45
  self.telegram_service = telegram_service
37
46
 
38
47
  def validate_output_number(self, output_number: int) -> None:
39
- """
40
- Validate XP24 output number according to architecture constraints.
48
+ """Validate XP24 output number according to architecture constraints.
41
49
 
42
50
  Args:
43
- output_number: Output number to validate (0-3)
51
+ output_number: Output number to validate (0-3).
44
52
 
45
53
  Raises:
46
- XPOutputError: If output number is invalid
54
+ XPOutputError: If output number is invalid.
47
55
  """
48
56
  if not isinstance(output_number, int):
49
57
  raise XPOutputError(
@@ -58,14 +66,13 @@ class TelegramOutputService:
58
66
 
59
67
  @staticmethod
60
68
  def validate_serial_number(serial_number: str) -> None:
61
- """
62
- Validate serial number format.
69
+ """Validate serial number format.
63
70
 
64
71
  Args:
65
- serial_number: Serial number to validate
72
+ serial_number: Serial number to validate.
66
73
 
67
74
  Raises:
68
- XP24ActionError: If serial number is invalid
75
+ XPOutputError: If serial number is invalid.
69
76
  """
70
77
  if not isinstance(serial_number, str):
71
78
  raise XPOutputError(
@@ -81,19 +88,18 @@ class TelegramOutputService:
81
88
  def generate_system_action_telegram(
82
89
  self, serial_number: str, output_number: int, action: ActionType
83
90
  ) -> str:
84
- """
85
- Generate XP24 action telegram string.
91
+ """Generate XP24 action telegram string.
86
92
 
87
93
  Args:
88
- serial_number: Target module serial number
89
- output_number: Output number (0-3)
90
- action: Action type (PRESS/RELEASE)
94
+ serial_number: Target module serial number.
95
+ output_number: Output number (0-3).
96
+ action: Action type (PRESS/RELEASE).
91
97
 
92
98
  Returns:
93
- Complete telegram string with checksum
99
+ Complete telegram string with checksum.
94
100
 
95
101
  Raises:
96
- XP24ActionError: If parameters are invalid
102
+ XPOutputError: If parameters are invalid.
97
103
  """
98
104
  # Validate outputs according to architecture constraints
99
105
  self.validate_serial_number(serial_number)
@@ -115,17 +121,13 @@ class TelegramOutputService:
115
121
  return f"<{data_part}{checksum}>"
116
122
 
117
123
  def generate_system_status_telegram(self, serial_number: str) -> str:
118
- """
119
- Generate XP output status query telegram.
124
+ """Generate XP output status query telegram.
120
125
 
121
126
  Args:
122
- serial_number: Target module serial number
127
+ serial_number: Target module serial number.
123
128
 
124
129
  Returns:
125
- Complete status query telegram string
126
-
127
- Raises:
128
- XPOutputError: If serial number is invalid
130
+ Complete status query telegram string.
129
131
  """
130
132
  # Validate outputs
131
133
  self.validate_serial_number(serial_number)
@@ -142,17 +144,16 @@ class TelegramOutputService:
142
144
  return f"<{data_part}{checksum}>"
143
145
 
144
146
  def parse_reply_telegram(self, raw_telegram: str) -> OutputTelegram:
145
- """
146
- Parse a raw XP output response telegram string.
147
+ """Parse a raw XP output response telegram string.
147
148
 
148
149
  Args:
149
- raw_telegram: The raw telegram string (e.g., "<R0012345003F18DFF>")
150
+ raw_telegram: The raw telegram string (e.g., "<R0012345003F18DFF>").
150
151
 
151
152
  Returns:
152
- XPOutputTelegram object with parsed data
153
+ XPOutputTelegram object with parsed data.
153
154
 
154
155
  Raises:
155
- XPOutputError: If telegram format is invalid
156
+ XPOutputError: If telegram format is invalid.
156
157
  """
157
158
  if not raw_telegram:
158
159
  raise XPOutputError("Empty telegram string")
@@ -193,17 +194,16 @@ class TelegramOutputService:
193
194
  raise XPOutputError(f"Invalid values in XP24 action telegram: {e}")
194
195
 
195
196
  def parse_system_telegram(self, raw_telegram: str) -> OutputTelegram:
196
- """
197
- Parse a raw XP output telegram string.
197
+ """Parse a raw XP output telegram string.
198
198
 
199
199
  Args:
200
- raw_telegram: The raw telegram string (e.g., "<S0012345008F27D00AAFN>")
200
+ raw_telegram: The raw telegram string (e.g., "<S0012345008F27D00AAFN>").
201
201
 
202
202
  Returns:
203
- XPOutputTelegram object with parsed data
203
+ XPOutputTelegram object with parsed data.
204
204
 
205
205
  Raises:
206
- XPOutputError: If telegram format is invalid
206
+ XPOutputError: If telegram format is invalid.
207
207
  """
208
208
  if not raw_telegram:
209
209
  raise XPOutputError("Empty telegram string")
@@ -247,17 +247,16 @@ class TelegramOutputService:
247
247
  raise XPOutputError(f"Invalid values in XP24 action telegram: {e}")
248
248
 
249
249
  def parse_status_response(self, raw_telegram: str) -> list[bool]:
250
- """
251
- Parse XP24 status response telegram to extract output states.
250
+ """Parse XP24 status response telegram to extract output states.
252
251
 
253
252
  Args:
254
- raw_telegram: Raw reply telegram (e.g., "<R0012345008F02D12xxxx1110FJ>")
253
+ raw_telegram: Raw reply telegram (e.g., "<R0012345008F02D12xxxx1110FJ>").
255
254
 
256
255
  Returns:
257
- Dictionary mapping output numbers (0-3) to their states (True=ON, False=OFF)
256
+ Dictionary mapping output numbers (0-3) to their states (True=ON, False=OFF).
258
257
 
259
258
  Raises:
260
- XP24ActionError: If telegram format is invalid
259
+ XPOutputError: If output telegram is invalid.
261
260
  """
262
261
  if not raw_telegram:
263
262
  raise XPOutputError("Empty status response telegram")
@@ -285,14 +284,13 @@ class TelegramOutputService:
285
284
 
286
285
  @staticmethod
287
286
  def format_status_summary(status: Dict[int, bool]) -> str:
288
- """
289
- Format status dictionary into human-readable summary.
287
+ """Format status dictionary into human-readable summary.
290
288
 
291
289
  Args:
292
- status: Dictionary mapping output numbers to states
290
+ status: Dictionary mapping output numbers to states.
293
291
 
294
292
  Returns:
295
- Formatted status summary string
293
+ Formatted status summary string.
296
294
  """
297
295
  lines = ["XP24 Output Status:"]
298
296
  for output_num in sorted(status.keys()):
@@ -303,14 +301,13 @@ class TelegramOutputService:
303
301
 
304
302
  @staticmethod
305
303
  def format_action_summary(telegram: OutputTelegram) -> str:
306
- """
307
- Format XP24 action telegram for human-readable output.
304
+ """Format XP24 action telegram for human-readable output.
308
305
 
309
306
  Args:
310
- telegram: The parsed action telegram
307
+ telegram: The parsed action telegram.
311
308
 
312
309
  Returns:
313
- Formatted string summary
310
+ Formatted string summary.
314
311
  """
315
312
  checksum_status = ""
316
313
  if telegram.checksum_validated is not None:
@@ -1,3 +1,8 @@
1
+ """Telegram Service for parsing XP telegrams.
2
+
3
+ This module provides telegram parsing functionality for event, system, and reply telegrams.
4
+ """
5
+
1
6
  import re
2
7
  from typing import Union
3
8
 
@@ -13,17 +18,21 @@ from xp.utils.checksum import calculate_checksum
13
18
 
14
19
 
15
20
  class TelegramParsingError(Exception):
16
- """Raised when telegram parsing fails"""
21
+ """Raised when telegram parsing fails."""
17
22
 
18
23
  pass
19
24
 
20
25
 
21
26
  class TelegramService:
22
- """
23
- Service for parsing event telegrams from the console bus.
27
+ """Service for parsing event telegrams from the console bus.
24
28
 
25
29
  Handles parsing of telegrams in the format:
26
30
  <[EO]{module_type}L{link_number}I{output_number}{event_type}{checksum}>
31
+
32
+ Attributes:
33
+ EVENT_TELEGRAM_PATTERN: Regex pattern for event telegrams.
34
+ SYSTEM_TELEGRAM_PATTERN: Regex pattern for system telegrams.
35
+ REPLY_TELEGRAM_PATTERN: Regex pattern for reply telegrams.
27
36
  """
28
37
 
29
38
  # <O06L00I07MAG>
@@ -38,21 +47,20 @@ class TelegramService:
38
47
  REPLY_TELEGRAM_PATTERN = re.compile(r"^<R(\d{10})F(\d{2})(.+?)([A-Z0-9]{2})>$")
39
48
 
40
49
  def __init__(self) -> None:
41
- """Initialize the telegram service"""
50
+ """Initialize the telegram service."""
42
51
  pass
43
52
 
44
53
  def parse_event_telegram(self, raw_telegram: str) -> EventTelegram:
45
- """
46
- Parse a raw telegram string into an EventTelegram object.
54
+ """Parse a raw telegram string into an EventTelegram object.
47
55
 
48
56
  Args:
49
- raw_telegram: The raw telegram string (e.g., "<E14L00I02MAK>")
57
+ raw_telegram: The raw telegram string (e.g., "<E14L00I02MAK>").
50
58
 
51
59
  Returns:
52
- EventTelegram object with parsed data
60
+ EventTelegram object with parsed data.
53
61
 
54
62
  Raises:
55
- TelegramParsingError: If the telegram format is invalid
63
+ TelegramParsingError: If the telegram format is invalid.
56
64
  """
57
65
  if not raw_telegram:
58
66
  raise TelegramParsingError("Empty telegram string")
@@ -114,14 +122,13 @@ class TelegramService:
114
122
  def validate_checksum(
115
123
  telegram: Union[EventTelegram, ReplyTelegram, SystemTelegram, OutputTelegram],
116
124
  ) -> bool:
117
- """
118
- Validate the checksum of a parsed telegram.
125
+ """Validate the checksum of a parsed telegram.
119
126
 
120
127
  Args:
121
- telegram: The parsed telegram
128
+ telegram: The parsed telegram.
122
129
 
123
130
  Returns:
124
- True if checksum is valid, False otherwise
131
+ True if checksum is valid, False otherwise.
125
132
  """
126
133
  if not telegram.checksum or len(telegram.checksum) != 2:
127
134
  return False
@@ -141,14 +148,13 @@ class TelegramService:
141
148
 
142
149
  @staticmethod
143
150
  def format_event_telegram_summary(telegram: EventTelegram) -> str:
144
- """
145
- Format a telegram for human-readable output.
151
+ """Format a telegram for human-readable output.
146
152
 
147
153
  Args:
148
- telegram: The parsed telegram
154
+ telegram: The parsed telegram.
149
155
 
150
156
  Returns:
151
- Formatted string summary
157
+ Formatted string summary.
152
158
  """
153
159
  checksum_status = ""
154
160
  if telegram.checksum_validated is not None:
@@ -163,17 +169,16 @@ class TelegramService:
163
169
  )
164
170
 
165
171
  def parse_system_telegram(self, raw_telegram: str) -> SystemTelegram:
166
- """
167
- Parse a raw system telegram string into a SystemTelegram object.
172
+ """Parse a raw system telegram string into a SystemTelegram object.
168
173
 
169
174
  Args:
170
- raw_telegram: The raw telegram string (e.g., "<S0020012521F02D18FN>")
175
+ raw_telegram: The raw telegram string (e.g., "<S0020012521F02D18FN>").
171
176
 
172
177
  Returns:
173
- SystemTelegram object with parsed data
178
+ SystemTelegram object with parsed data.
174
179
 
175
180
  Raises:
176
- TelegramParsingError: If the telegram format is invalid
181
+ TelegramParsingError: If the telegram format is invalid.
177
182
  """
178
183
  if not raw_telegram:
179
184
  raise TelegramParsingError("Empty telegram string")
@@ -222,17 +227,16 @@ class TelegramService:
222
227
  raise TelegramParsingError(f"Invalid values in system telegram: {e}")
223
228
 
224
229
  def parse_reply_telegram(self, raw_telegram: str) -> ReplyTelegram:
225
- """
226
- Parse a raw reply telegram string into a ReplyTelegram object.
230
+ """Parse a raw reply telegram string into a ReplyTelegram object.
227
231
 
228
232
  Args:
229
- raw_telegram: The raw telegram string (e.g., "<R0020012521F02D18+26,0§CIL>")
233
+ raw_telegram: The raw telegram string (e.g., "<R0020012521F02D18+26,0§CIL>").
230
234
 
231
235
  Returns:
232
- ReplyTelegram object with parsed data
236
+ ReplyTelegram object with parsed data.
233
237
 
234
238
  Raises:
235
- TelegramParsingError: If the telegram format is invalid
239
+ TelegramParsingError: If the telegram format is invalid.
236
240
  """
237
241
  if not raw_telegram:
238
242
  raise TelegramParsingError("Empty telegram string")
@@ -290,18 +294,16 @@ class TelegramService:
290
294
  def parse_telegram(
291
295
  self, raw_telegram: str
292
296
  ) -> Union[EventTelegram, SystemTelegram, ReplyTelegram]:
293
- """
294
- Auto-detect and parse any type of telegram.
297
+ """Auto-detect and parse any type of telegram.
295
298
 
296
299
  Args:
297
- raw_telegram: The raw telegram string
300
+ raw_telegram: The raw telegram string.
298
301
 
299
302
  Returns:
300
- Appropriate telegram object based on type
303
+ Appropriate telegram object based on type.
301
304
 
302
305
  Raises:
303
- TelegramParsingError: If the telegram format is invalid or unknown
304
- :rtype: Union[EventTelegram, SystemTelegram, ReplyTelegram]
306
+ TelegramParsingError: If the telegram format is invalid or unknown.
305
307
  """
306
308
  if not raw_telegram:
307
309
  raise TelegramParsingError("Empty telegram string")
@@ -324,14 +326,13 @@ class TelegramService:
324
326
 
325
327
  @staticmethod
326
328
  def format_system_telegram_summary(telegram: SystemTelegram) -> str:
327
- """
328
- Format a system telegram for human-readable output.
329
+ """Format a system telegram for human-readable output.
329
330
 
330
331
  Args:
331
- telegram: The parsed system telegram
332
+ telegram: The parsed system telegram.
332
333
 
333
334
  Returns:
334
- Formatted string summary
335
+ Formatted string summary.
335
336
  """
336
337
  checksum_status = ""
337
338
  if telegram.checksum_validated is not None:
@@ -347,14 +348,13 @@ class TelegramService:
347
348
 
348
349
  @staticmethod
349
350
  def format_reply_telegram_summary(telegram: ReplyTelegram) -> str:
350
- """
351
- Format a reply telegram for human-readable output.
351
+ """Format a reply telegram for human-readable output.
352
352
 
353
353
  Args:
354
- telegram: The parsed reply telegram
354
+ telegram: The parsed reply telegram.
355
355
 
356
356
  Returns:
357
- Formatted string summary
357
+ Formatted string summary.
358
358
  """
359
359
  parsed_data = telegram.parse_datapoint_value
360
360
  data_display = (
@@ -15,7 +15,7 @@ from xp.utils.checksum import calculate_checksum
15
15
 
16
16
 
17
17
  class VersionParsingError(Exception):
18
- """Raised when version parsing fails"""
18
+ """Raised when version parsing fails."""
19
19
 
20
20
  pass
21
21
 
@@ -204,7 +204,9 @@ class VersionService:
204
204
  return Response(
205
205
  success=False,
206
206
  data=None,
207
- error=f"Not a version reply telegram. Data point: {telegram.datapoint_type.name if telegram.datapoint_type else 'Unknown'}",
207
+ error=f"Not a version reply telegram. "
208
+ f"Data point: "
209
+ f"{telegram.datapoint_type.name if telegram.datapoint_type else 'Unknown'}",
208
210
  )
209
211
 
210
212
  # Parse the version using the telegram's built-in parser
xp/utils/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- """Utility functions for XP CLI tool"""
1
+ """Utility functions for XP CLI tool."""
2
2
 
3
3
  from xp.utils.checksum import calculate_checksum
4
4
  from xp.utils.event_helper import get_first_response
xp/utils/dependencies.py CHANGED
@@ -101,7 +101,6 @@ class ServiceContainer:
101
101
 
102
102
  def _register_services(self) -> None:
103
103
  """Register all services in the container based on dependency graph."""
104
-
105
104
  # ConbusClientConfig
106
105
  self.container.register(
107
106
  ConbusClientConfig,
xp/utils/serialization.py CHANGED
@@ -153,6 +153,9 @@ def de_nibble(nibble_str: str) -> int:
153
153
 
154
154
  Returns:
155
155
  Byte value (0-255)
156
+
157
+ Raises:
158
+ ValueError: If nibble string is not exactly 2 characters
156
159
  """
157
160
  if len(nibble_str) != 2:
158
161
  raise ValueError("Nibble string must be exactly 2 characters")
@@ -177,6 +180,9 @@ def de_nibbles(str_val: str) -> bytearray:
177
180
 
178
181
  Returns:
179
182
  List of integers representing the decoded bytes
183
+
184
+ Raises:
185
+ ValueError: If string length is not even for nibble conversion
180
186
  """
181
187
  if len(str_val) % 2 != 0:
182
188
  raise ValueError("String length must be even for nibble conversion")
xp/utils/time_utils.py CHANGED
@@ -6,7 +6,7 @@ from typing import Optional
6
6
 
7
7
 
8
8
  class TimeParsingError(Exception):
9
- """Raised when time parsing fails"""
9
+ """Raised when time parsing fails."""
10
10
 
11
11
  pass
12
12
 
@@ -14,8 +14,7 @@ class TimeParsingError(Exception):
14
14
  def parse_log_timestamp(
15
15
  timestamp_str: str, base_date: Optional[datetime] = None
16
16
  ) -> datetime:
17
- """
18
- Parse timestamp from console bus log format: HH:MM:SS,mmm
17
+ """Parse timestamp from console bus log format: HH:MM:SS,mmm.
19
18
 
20
19
  Args:
21
20
  timestamp_str: Timestamp string (e.g., "22:44:20,352")
@@ -66,8 +65,7 @@ def parse_log_timestamp(
66
65
 
67
66
 
68
67
  def format_log_timestamp(dt: datetime) -> str:
69
- """
70
- Format datetime to console bus log timestamp format: HH:MM:SS,mmm
68
+ """Format datetime to console bus log timestamp format: HH:MM:SS,mmm.
71
69
 
72
70
  Args:
73
71
  dt: datetime object to format
@@ -81,8 +79,7 @@ def format_log_timestamp(dt: datetime) -> str:
81
79
  def parse_time_range(
82
80
  time_range_str: str, base_date: Optional[datetime] = None
83
81
  ) -> tuple[datetime, datetime]:
84
- """
85
- Parse time range string like "22:44:20,352-22:44:25,500"
82
+ """Parse time range string like "22:44:20,352-22:44:25,500".
86
83
 
87
84
  Args:
88
85
  time_range_str: Time range string
@@ -108,8 +105,7 @@ def parse_time_range(
108
105
 
109
106
 
110
107
  def calculate_duration_ms(start_time: datetime, end_time: datetime) -> int:
111
- """
112
- Calculate duration between two timestamps in milliseconds
108
+ """Calculate duration between two timestamps in milliseconds.
113
109
 
114
110
  Args:
115
111
  start_time: Start timestamp
@@ -123,8 +119,7 @@ def calculate_duration_ms(start_time: datetime, end_time: datetime) -> int:
123
119
 
124
120
 
125
121
  def is_valid_log_timestamp(timestamp_str: str) -> bool:
126
- """
127
- Check if timestamp string is valid console bus log format
122
+ """Check if timestamp string is valid console bus log format.
128
123
 
129
124
  Args:
130
125
  timestamp_str: Timestamp string to validate