conson-xp 1.1.0__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.
- {conson_xp-1.1.0.dist-info → conson_xp-1.2.0.dist-info}/METADATA +1 -1
- conson_xp-1.2.0.dist-info/RECORD +181 -0
- xp/__init__.py +4 -3
- xp/api/main.py +18 -3
- xp/api/models/api.py +13 -2
- xp/api/models/discover.py +12 -2
- xp/api/routers/conbus_blink.py +18 -6
- xp/api/routers/conbus_custom.py +11 -3
- xp/api/routers/conbus_datapoint.py +10 -3
- xp/api/routers/conbus_output.py +29 -9
- xp/api/routers/errors.py +6 -5
- xp/cli/__init__.py +1 -1
- xp/cli/commands/__init__.py +1 -0
- xp/cli/commands/api.py +1 -5
- xp/cli/commands/api_start_commands.py +14 -8
- xp/cli/commands/conbus/conbus.py +9 -37
- xp/cli/commands/conbus/conbus_actiontable_commands.py +21 -1
- xp/cli/commands/conbus/conbus_autoreport_commands.py +21 -11
- xp/cli/commands/conbus/conbus_blink_commands.py +53 -21
- xp/cli/commands/conbus/conbus_config_commands.py +7 -4
- xp/cli/commands/conbus/conbus_custom_commands.py +13 -4
- xp/cli/commands/conbus/conbus_datapoint_commands.py +28 -8
- xp/cli/commands/conbus/conbus_discover_commands.py +15 -4
- xp/cli/commands/conbus/conbus_lightlevel_commands.py +50 -11
- xp/cli/commands/conbus/conbus_linknumber_commands.py +21 -11
- xp/cli/commands/conbus/conbus_msactiontable_commands.py +25 -1
- xp/cli/commands/conbus/conbus_output_commands.py +46 -12
- xp/cli/commands/conbus/conbus_raw_commands.py +17 -6
- xp/cli/commands/conbus/conbus_receive_commands.py +15 -7
- xp/cli/commands/conbus/conbus_scan_commands.py +17 -4
- xp/cli/commands/file_commands.py +26 -15
- xp/cli/commands/homekit/homekit.py +14 -8
- xp/cli/commands/homekit/homekit_start_commands.py +5 -5
- xp/cli/commands/module_commands.py +26 -19
- xp/cli/commands/reverse_proxy_commands.py +24 -18
- xp/cli/commands/server/server_commands.py +18 -18
- xp/cli/commands/telegram/telegram.py +4 -12
- xp/cli/commands/telegram/telegram_blink_commands.py +10 -8
- xp/cli/commands/telegram/telegram_checksum_commands.py +19 -8
- xp/cli/commands/telegram/telegram_discover_commands.py +2 -4
- xp/cli/commands/telegram/telegram_linknumber_commands.py +11 -8
- xp/cli/commands/telegram/telegram_parse_commands.py +10 -9
- xp/cli/commands/telegram/telegram_version_commands.py +8 -4
- xp/cli/main.py +5 -1
- xp/cli/utils/click_tree.py +23 -3
- xp/cli/utils/datapoint_type_choice.py +20 -0
- xp/cli/utils/decorators.py +165 -14
- xp/cli/utils/error_handlers.py +49 -18
- xp/cli/utils/formatters.py +95 -10
- xp/cli/utils/serial_number_type.py +18 -0
- xp/cli/utils/system_function_choice.py +20 -0
- xp/cli/utils/xp_module_type.py +20 -0
- xp/connection/__init__.py +1 -1
- xp/connection/exceptions.py +5 -5
- xp/models/__init__.py +1 -1
- xp/models/actiontable/__init__.py +1 -0
- xp/models/actiontable/actiontable.py +17 -1
- xp/models/actiontable/msactiontable_xp20.py +10 -0
- xp/models/actiontable/msactiontable_xp24.py +20 -3
- xp/models/actiontable/msactiontable_xp33.py +27 -4
- xp/models/conbus/__init__.py +1 -0
- xp/models/conbus/conbus.py +34 -4
- xp/models/conbus/conbus_autoreport.py +20 -2
- xp/models/conbus/conbus_blink.py +22 -2
- xp/models/conbus/conbus_client_config.py +22 -1
- xp/models/conbus/conbus_connection_status.py +16 -2
- xp/models/conbus/conbus_custom.py +21 -2
- xp/models/conbus/conbus_datapoint.py +22 -2
- xp/models/conbus/conbus_discover.py +18 -2
- xp/models/conbus/conbus_lightlevel.py +20 -2
- xp/models/conbus/conbus_linknumber.py +20 -2
- xp/models/conbus/conbus_output.py +22 -2
- xp/models/conbus/conbus_raw.py +17 -2
- xp/models/conbus/conbus_receive.py +16 -2
- xp/models/homekit/__init__.py +1 -0
- xp/models/homekit/homekit_accessory.py +15 -1
- xp/models/homekit/homekit_config.py +52 -0
- xp/models/homekit/homekit_conson_config.py +32 -0
- xp/models/log_entry.py +49 -9
- xp/models/protocol/__init__.py +1 -0
- xp/models/protocol/conbus_protocol.py +130 -21
- xp/models/telegram/__init__.py +1 -0
- xp/models/telegram/action_type.py +16 -2
- xp/models/telegram/datapoint_type.py +36 -2
- xp/models/telegram/event_telegram.py +46 -10
- xp/models/telegram/event_type.py +8 -1
- xp/models/telegram/input_action_type.py +34 -2
- xp/models/telegram/input_type.py +9 -1
- xp/models/telegram/module_type.py +69 -19
- xp/models/telegram/module_type_code.py +43 -1
- xp/models/telegram/output_telegram.py +30 -6
- xp/models/telegram/reply_telegram.py +56 -11
- xp/models/telegram/system_function.py +35 -3
- xp/models/telegram/system_telegram.py +18 -4
- xp/models/telegram/telegram.py +12 -3
- xp/models/telegram/telegram_type.py +8 -1
- xp/models/telegram/timeparam_type.py +27 -0
- xp/models/write_config_type.py +17 -2
- xp/services/__init__.py +1 -1
- xp/services/conbus/__init__.py +1 -0
- xp/services/conbus/actiontable/__init__.py +1 -0
- xp/services/conbus/actiontable/actiontable_service.py +33 -2
- xp/services/conbus/actiontable/msactiontable_service.py +40 -3
- xp/services/conbus/actiontable/msactiontable_xp24_serializer.py +36 -4
- xp/services/conbus/actiontable/msactiontable_xp33_serializer.py +45 -5
- xp/services/conbus/conbus_autoreport_get_service.py +17 -8
- xp/services/conbus/conbus_autoreport_set_service.py +29 -16
- xp/services/conbus/conbus_blink_all_service.py +40 -21
- xp/services/conbus/conbus_blink_service.py +37 -13
- xp/services/conbus/conbus_custom_service.py +29 -13
- xp/services/conbus/conbus_datapoint_queryall_service.py +40 -16
- xp/services/conbus/conbus_datapoint_service.py +33 -12
- xp/services/conbus/conbus_discover_service.py +43 -7
- xp/services/conbus/conbus_lightlevel_get_service.py +22 -14
- xp/services/conbus/conbus_lightlevel_set_service.py +40 -20
- xp/services/conbus/conbus_linknumber_get_service.py +18 -10
- xp/services/conbus/conbus_linknumber_set_service.py +34 -8
- xp/services/conbus/conbus_output_service.py +33 -13
- xp/services/conbus/conbus_raw_service.py +36 -16
- xp/services/conbus/conbus_receive_service.py +38 -6
- xp/services/conbus/conbus_scan_service.py +44 -18
- xp/services/homekit/__init__.py +1 -0
- xp/services/homekit/homekit_cache_service.py +31 -6
- xp/services/homekit/homekit_conbus_service.py +33 -2
- xp/services/homekit/homekit_config_validator.py +97 -15
- xp/services/homekit/homekit_conson_validator.py +51 -7
- xp/services/homekit/homekit_dimminglight.py +47 -1
- xp/services/homekit/homekit_dimminglight_service.py +35 -1
- xp/services/homekit/homekit_hap_service.py +71 -18
- xp/services/homekit/homekit_lightbulb.py +35 -1
- xp/services/homekit/homekit_lightbulb_service.py +30 -2
- xp/services/homekit/homekit_module_service.py +23 -1
- xp/services/homekit/homekit_outlet.py +47 -1
- xp/services/homekit/homekit_outlet_service.py +44 -2
- xp/services/homekit/homekit_service.py +113 -19
- xp/services/log_file_service.py +37 -41
- xp/services/module_type_service.py +26 -5
- xp/services/protocol/__init__.py +1 -1
- xp/services/protocol/conbus_protocol.py +110 -16
- xp/services/protocol/protocol_factory.py +40 -0
- xp/services/protocol/telegram_protocol.py +38 -7
- xp/services/reverse_proxy_service.py +79 -14
- xp/services/server/__init__.py +1 -0
- xp/services/server/base_server_service.py +102 -14
- xp/services/server/cp20_server_service.py +12 -4
- xp/services/server/server_service.py +26 -11
- xp/services/server/xp130_server_service.py +11 -3
- xp/services/server/xp20_server_service.py +11 -3
- xp/services/server/xp230_server_service.py +11 -3
- xp/services/server/xp24_server_service.py +33 -6
- xp/services/server/xp33_server_service.py +41 -8
- xp/services/telegram/__init__.py +1 -0
- xp/services/telegram/telegram_blink_service.py +19 -31
- xp/services/telegram/telegram_checksum_service.py +10 -10
- xp/services/telegram/telegram_discover_service.py +58 -29
- xp/services/telegram/telegram_link_number_service.py +27 -40
- xp/services/telegram/telegram_output_service.py +46 -49
- xp/services/telegram/telegram_service.py +41 -41
- xp/services/telegram/telegram_version_service.py +4 -2
- xp/utils/__init__.py +1 -1
- xp/utils/dependencies.py +0 -1
- xp/utils/serialization.py +6 -0
- xp/utils/time_utils.py +6 -11
- conson_xp-1.1.0.dist-info/RECORD +0 -181
- {conson_xp-1.1.0.dist-info → conson_xp-1.2.0.dist-info}/WHEEL +0 -0
- {conson_xp-1.1.0.dist-info → conson_xp-1.2.0.dist-info}/entry_points.txt +0 -0
- {conson_xp-1.1.0.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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
xp/utils/dependencies.py
CHANGED
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
|