conson-xp 1.1.0__py3-none-any.whl → 1.3.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 (174) hide show
  1. {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/METADATA +1 -5
  2. conson_xp-1.3.0.dist-info/RECORD +164 -0
  3. xp/__init__.py +4 -3
  4. xp/cli/__init__.py +1 -1
  5. xp/cli/commands/__init__.py +1 -2
  6. xp/cli/commands/conbus/conbus.py +9 -37
  7. xp/cli/commands/conbus/conbus_actiontable_commands.py +26 -4
  8. xp/cli/commands/conbus/conbus_autoreport_commands.py +58 -30
  9. xp/cli/commands/conbus/conbus_blink_commands.py +61 -29
  10. xp/cli/commands/conbus/conbus_config_commands.py +10 -5
  11. xp/cli/commands/conbus/conbus_custom_commands.py +16 -5
  12. xp/cli/commands/conbus/conbus_datapoint_commands.py +32 -10
  13. xp/cli/commands/conbus/conbus_discover_commands.py +20 -7
  14. xp/cli/commands/conbus/conbus_lightlevel_commands.py +114 -39
  15. xp/cli/commands/conbus/conbus_linknumber_commands.py +50 -25
  16. xp/cli/commands/conbus/conbus_msactiontable_commands.py +36 -5
  17. xp/cli/commands/conbus/conbus_output_commands.py +52 -14
  18. xp/cli/commands/conbus/conbus_raw_commands.py +17 -6
  19. xp/cli/commands/conbus/conbus_receive_commands.py +20 -10
  20. xp/cli/commands/conbus/conbus_scan_commands.py +17 -4
  21. xp/cli/commands/file_commands.py +35 -18
  22. xp/cli/commands/homekit/homekit.py +14 -8
  23. xp/cli/commands/homekit/homekit_start_commands.py +8 -6
  24. xp/cli/commands/module_commands.py +38 -23
  25. xp/cli/commands/reverse_proxy_commands.py +27 -19
  26. xp/cli/commands/server/server_commands.py +18 -18
  27. xp/cli/commands/telegram/telegram.py +4 -12
  28. xp/cli/commands/telegram/telegram_blink_commands.py +10 -8
  29. xp/cli/commands/telegram/telegram_checksum_commands.py +19 -8
  30. xp/cli/commands/telegram/telegram_discover_commands.py +2 -4
  31. xp/cli/commands/telegram/telegram_linknumber_commands.py +11 -8
  32. xp/cli/commands/telegram/telegram_parse_commands.py +10 -9
  33. xp/cli/commands/telegram/telegram_version_commands.py +8 -4
  34. xp/cli/main.py +5 -3
  35. xp/cli/utils/click_tree.py +23 -3
  36. xp/cli/utils/datapoint_type_choice.py +20 -0
  37. xp/cli/utils/decorators.py +165 -14
  38. xp/cli/utils/error_handlers.py +49 -18
  39. xp/cli/utils/formatters.py +95 -10
  40. xp/cli/utils/serial_number_type.py +18 -0
  41. xp/cli/utils/system_function_choice.py +20 -0
  42. xp/cli/utils/xp_module_type.py +20 -0
  43. xp/connection/__init__.py +1 -1
  44. xp/connection/exceptions.py +5 -5
  45. xp/models/__init__.py +1 -1
  46. xp/models/actiontable/__init__.py +1 -0
  47. xp/models/actiontable/actiontable.py +17 -1
  48. xp/models/actiontable/msactiontable_xp20.py +10 -0
  49. xp/models/actiontable/msactiontable_xp24.py +20 -3
  50. xp/models/actiontable/msactiontable_xp33.py +27 -4
  51. xp/models/conbus/__init__.py +1 -0
  52. xp/models/conbus/conbus.py +34 -4
  53. xp/models/conbus/conbus_autoreport.py +20 -2
  54. xp/models/conbus/conbus_blink.py +22 -2
  55. xp/models/conbus/conbus_client_config.py +22 -1
  56. xp/models/conbus/conbus_connection_status.py +16 -2
  57. xp/models/conbus/conbus_custom.py +21 -2
  58. xp/models/conbus/conbus_datapoint.py +25 -2
  59. xp/models/conbus/conbus_discover.py +18 -2
  60. xp/models/conbus/conbus_lightlevel.py +20 -2
  61. xp/models/conbus/conbus_linknumber.py +20 -2
  62. xp/models/conbus/conbus_output.py +22 -2
  63. xp/models/conbus/conbus_raw.py +17 -2
  64. xp/models/conbus/conbus_receive.py +16 -2
  65. xp/models/conbus/conbus_writeconfig.py +60 -0
  66. xp/models/homekit/__init__.py +1 -0
  67. xp/models/homekit/homekit_accessory.py +15 -1
  68. xp/models/homekit/homekit_config.py +52 -0
  69. xp/models/homekit/homekit_conson_config.py +32 -0
  70. xp/models/log_entry.py +49 -9
  71. xp/models/protocol/__init__.py +1 -0
  72. xp/models/protocol/conbus_protocol.py +130 -21
  73. xp/models/telegram/__init__.py +1 -0
  74. xp/models/telegram/action_type.py +16 -2
  75. xp/models/telegram/datapoint_type.py +36 -2
  76. xp/models/telegram/event_telegram.py +46 -10
  77. xp/models/telegram/event_type.py +8 -1
  78. xp/models/telegram/input_action_type.py +34 -2
  79. xp/models/telegram/input_type.py +9 -1
  80. xp/models/telegram/module_type.py +69 -19
  81. xp/models/telegram/module_type_code.py +43 -1
  82. xp/models/telegram/output_telegram.py +30 -6
  83. xp/models/telegram/reply_telegram.py +56 -11
  84. xp/models/telegram/system_function.py +35 -3
  85. xp/models/telegram/system_telegram.py +18 -4
  86. xp/models/telegram/telegram.py +12 -3
  87. xp/models/telegram/telegram_type.py +8 -1
  88. xp/models/telegram/timeparam_type.py +27 -0
  89. xp/models/write_config_type.py +17 -2
  90. xp/services/__init__.py +1 -1
  91. xp/services/conbus/__init__.py +1 -0
  92. xp/services/conbus/actiontable/__init__.py +1 -0
  93. xp/services/conbus/actiontable/actiontable_service.py +33 -2
  94. xp/services/conbus/actiontable/msactiontable_service.py +40 -3
  95. xp/services/conbus/actiontable/msactiontable_xp24_serializer.py +36 -4
  96. xp/services/conbus/actiontable/msactiontable_xp33_serializer.py +45 -5
  97. xp/services/conbus/conbus_blink_all_service.py +40 -21
  98. xp/services/conbus/conbus_blink_service.py +37 -13
  99. xp/services/conbus/conbus_custom_service.py +29 -13
  100. xp/services/conbus/conbus_datapoint_queryall_service.py +40 -16
  101. xp/services/conbus/conbus_datapoint_service.py +42 -18
  102. xp/services/conbus/conbus_discover_service.py +43 -7
  103. xp/services/conbus/conbus_output_service.py +33 -13
  104. xp/services/conbus/conbus_raw_service.py +36 -16
  105. xp/services/conbus/conbus_receive_service.py +38 -6
  106. xp/services/conbus/conbus_scan_service.py +44 -18
  107. xp/services/conbus/write_config_service.py +193 -0
  108. xp/services/homekit/__init__.py +1 -0
  109. xp/services/homekit/homekit_cache_service.py +31 -6
  110. xp/services/homekit/homekit_conbus_service.py +33 -2
  111. xp/services/homekit/homekit_config_validator.py +97 -15
  112. xp/services/homekit/homekit_conson_validator.py +51 -7
  113. xp/services/homekit/homekit_dimminglight.py +47 -1
  114. xp/services/homekit/homekit_dimminglight_service.py +35 -1
  115. xp/services/homekit/homekit_hap_service.py +71 -18
  116. xp/services/homekit/homekit_lightbulb.py +35 -1
  117. xp/services/homekit/homekit_lightbulb_service.py +30 -2
  118. xp/services/homekit/homekit_module_service.py +23 -1
  119. xp/services/homekit/homekit_outlet.py +47 -1
  120. xp/services/homekit/homekit_outlet_service.py +44 -2
  121. xp/services/homekit/homekit_service.py +113 -19
  122. xp/services/log_file_service.py +37 -41
  123. xp/services/module_type_service.py +26 -5
  124. xp/services/protocol/__init__.py +1 -1
  125. xp/services/protocol/conbus_protocol.py +110 -16
  126. xp/services/protocol/protocol_factory.py +40 -0
  127. xp/services/protocol/telegram_protocol.py +38 -7
  128. xp/services/reverse_proxy_service.py +79 -14
  129. xp/services/server/__init__.py +1 -0
  130. xp/services/server/base_server_service.py +102 -14
  131. xp/services/server/cp20_server_service.py +12 -4
  132. xp/services/server/server_service.py +26 -11
  133. xp/services/server/xp130_server_service.py +11 -3
  134. xp/services/server/xp20_server_service.py +11 -3
  135. xp/services/server/xp230_server_service.py +11 -3
  136. xp/services/server/xp24_server_service.py +33 -6
  137. xp/services/server/xp33_server_service.py +41 -8
  138. xp/services/telegram/__init__.py +1 -0
  139. xp/services/telegram/telegram_blink_service.py +19 -31
  140. xp/services/telegram/telegram_checksum_service.py +10 -10
  141. xp/services/telegram/telegram_datapoint_service.py +70 -0
  142. xp/services/telegram/telegram_discover_service.py +58 -29
  143. xp/services/telegram/telegram_link_number_service.py +27 -40
  144. xp/services/telegram/telegram_output_service.py +46 -49
  145. xp/services/telegram/telegram_service.py +41 -41
  146. xp/services/telegram/telegram_version_service.py +4 -2
  147. xp/utils/__init__.py +1 -1
  148. xp/utils/dependencies.py +4 -47
  149. xp/utils/serialization.py +6 -0
  150. xp/utils/time_utils.py +6 -11
  151. conson_xp-1.1.0.dist-info/RECORD +0 -181
  152. xp/api/__init__.py +0 -1
  153. xp/api/main.py +0 -110
  154. xp/api/models/__init__.py +0 -1
  155. xp/api/models/api.py +0 -20
  156. xp/api/models/discover.py +0 -21
  157. xp/api/routers/__init__.py +0 -17
  158. xp/api/routers/conbus.py +0 -5
  159. xp/api/routers/conbus_blink.py +0 -105
  160. xp/api/routers/conbus_custom.py +0 -63
  161. xp/api/routers/conbus_datapoint.py +0 -67
  162. xp/api/routers/conbus_output.py +0 -147
  163. xp/api/routers/errors.py +0 -37
  164. xp/cli/commands/api.py +0 -16
  165. xp/cli/commands/api_start_commands.py +0 -126
  166. xp/services/conbus/conbus_autoreport_get_service.py +0 -85
  167. xp/services/conbus/conbus_autoreport_set_service.py +0 -128
  168. xp/services/conbus/conbus_lightlevel_get_service.py +0 -101
  169. xp/services/conbus/conbus_lightlevel_set_service.py +0 -205
  170. xp/services/conbus/conbus_linknumber_get_service.py +0 -86
  171. xp/services/conbus/conbus_linknumber_set_service.py +0 -155
  172. {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/WHEEL +0 -0
  173. {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/entry_points.txt +0 -0
  174. {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -15,7 +15,7 @@ from xp.utils.checksum import calculate_checksum
15
15
 
16
16
 
17
17
  class LinkNumberError(Exception):
18
- """Raised when link number operations fail"""
18
+ """Raised when link number operations fail."""
19
19
 
20
20
  pass
21
21
 
@@ -29,23 +29,22 @@ class LinkNumberService:
29
29
  """
30
30
 
31
31
  def __init__(self) -> None:
32
- """Initialize the link number service"""
32
+ """Initialize the link number service."""
33
33
  pass
34
34
 
35
35
  @staticmethod
36
36
  def generate_set_link_number_telegram(serial_number: str, link_number: int) -> str:
37
- """
38
- Generate a telegram to set a module's link number.
37
+ """Generate a telegram to set a module's link number.
39
38
 
40
39
  Args:
41
- serial_number: The 10-digit module serial number
42
- link_number: The link number to set (0-99)
40
+ serial_number: The 10-digit module serial number.
41
+ link_number: The link number to set (0-99).
43
42
 
44
43
  Returns:
45
- Formatted telegram string (e.g., "<S0012345005F04D0425FO>")
44
+ Formatted telegram string (e.g., "<S0012345005F04D0425FO>").
46
45
 
47
46
  Raises:
48
- LinkNumberError: If parameters are invalid
47
+ LinkNumberError: If parameters are invalid.
49
48
  """
50
49
  # Validate serial number
51
50
  if not serial_number or len(serial_number) != 10:
@@ -80,17 +79,16 @@ class LinkNumberService:
80
79
 
81
80
  @staticmethod
82
81
  def generate_read_link_number_telegram(serial_number: str) -> str:
83
- """
84
- Generate a telegram to read a module's current link number.
82
+ """Generate a telegram to read a module's current link number.
85
83
 
86
84
  Args:
87
- serial_number: The 10-digit module serial number
85
+ serial_number: The 10-digit module serial number.
88
86
 
89
87
  Returns:
90
- Formatted telegram string for reading link number
88
+ Formatted telegram string for reading link number.
91
89
 
92
90
  Raises:
93
- LinkNumberError: If serial number is invalid
91
+ LinkNumberError: If serial number is invalid.
94
92
  """
95
93
  # Validate serial number
96
94
  if not serial_number or len(serial_number) != 10:
@@ -117,18 +115,14 @@ class LinkNumberService:
117
115
  def create_set_link_number_telegram_object(
118
116
  self, serial_number: str, link_number: int
119
117
  ) -> SystemTelegram:
120
- """
121
- Create a SystemTelegram object for setting link number.
118
+ """Create a SystemTelegram object for setting link number.
122
119
 
123
120
  Args:
124
- serial_number: The 10-digit module serial number
125
- link_number: The link number to set (0-99)
121
+ serial_number: The 10-digit module serial number.
122
+ link_number: The link number to set (0-99).
126
123
 
127
124
  Returns:
128
- SystemTelegram object representing the set link number command
129
-
130
- Raises:
131
- LinkNumberError: If parameters are invalid
125
+ SystemTelegram object representing the set link number command.
132
126
  """
133
127
  raw_telegram = self.generate_set_link_number_telegram(
134
128
  serial_number, link_number
@@ -150,17 +144,13 @@ class LinkNumberService:
150
144
  def create_read_link_number_telegram_object(
151
145
  self, serial_number: str
152
146
  ) -> SystemTelegram:
153
- """
154
- Create a SystemTelegram object for reading link number.
147
+ """Create a SystemTelegram object for reading link number.
155
148
 
156
149
  Args:
157
- serial_number: The 10-digit module serial number
150
+ serial_number: The 10-digit module serial number.
158
151
 
159
152
  Returns:
160
- SystemTelegram object representing the read link number command
161
-
162
- Raises:
163
- LinkNumberError: If serial number is invalid
153
+ SystemTelegram object representing the read link number command.
164
154
  """
165
155
  raw_telegram = self.generate_read_link_number_telegram(serial_number)
166
156
 
@@ -179,14 +169,13 @@ class LinkNumberService:
179
169
 
180
170
  @staticmethod
181
171
  def parse_link_number_from_reply(reply_telegram: ReplyTelegram) -> Optional[int]:
182
- """
183
- Parse the link number value from a reply telegram.
172
+ """Parse the link number value from a reply telegram.
184
173
 
185
174
  Args:
186
- reply_telegram: Reply telegram containing link number data
175
+ reply_telegram: Reply telegram containing link number data.
187
176
 
188
177
  Returns:
189
- Link number if successfully parsed, None otherwise
178
+ Link number if successfully parsed, None otherwise.
190
179
  """
191
180
  if (
192
181
  reply_telegram.datapoint_type != DataPointType.LINK_NUMBER
@@ -204,26 +193,24 @@ class LinkNumberService:
204
193
 
205
194
  @staticmethod
206
195
  def is_ack_response(reply_telegram: ReplyTelegram) -> bool:
207
- """
208
- Check if a reply telegram is an ACK response.
196
+ """Check if a reply telegram is an ACK response.
209
197
 
210
198
  Args:
211
- reply_telegram: Reply telegram to check
199
+ reply_telegram: Reply telegram to check.
212
200
 
213
201
  Returns:
214
- True if this is an ACK response (F18D), False otherwise
202
+ True if this is an ACK response (F18D), False otherwise.
215
203
  """
216
204
  return reply_telegram.system_function == SystemFunction.ACK
217
205
 
218
206
  @staticmethod
219
207
  def is_nak_response(reply_telegram: ReplyTelegram) -> bool:
220
- """
221
- Check if a reply telegram is a NAK response.
208
+ """Check if a reply telegram is a NAK response.
222
209
 
223
210
  Args:
224
- reply_telegram: Reply telegram to check
211
+ reply_telegram: Reply telegram to check.
225
212
 
226
213
  Returns:
227
- True if this is a NAK response (F19D), False otherwise
214
+ True if this is a NAK response (F19D), False otherwise.
228
215
  """
229
216
  return reply_telegram.system_function == SystemFunction.NAK
@@ -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