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.
- {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/METADATA +1 -5
- conson_xp-1.3.0.dist-info/RECORD +164 -0
- xp/__init__.py +4 -3
- xp/cli/__init__.py +1 -1
- xp/cli/commands/__init__.py +1 -2
- xp/cli/commands/conbus/conbus.py +9 -37
- xp/cli/commands/conbus/conbus_actiontable_commands.py +26 -4
- xp/cli/commands/conbus/conbus_autoreport_commands.py +58 -30
- xp/cli/commands/conbus/conbus_blink_commands.py +61 -29
- xp/cli/commands/conbus/conbus_config_commands.py +10 -5
- xp/cli/commands/conbus/conbus_custom_commands.py +16 -5
- xp/cli/commands/conbus/conbus_datapoint_commands.py +32 -10
- xp/cli/commands/conbus/conbus_discover_commands.py +20 -7
- xp/cli/commands/conbus/conbus_lightlevel_commands.py +114 -39
- xp/cli/commands/conbus/conbus_linknumber_commands.py +50 -25
- xp/cli/commands/conbus/conbus_msactiontable_commands.py +36 -5
- xp/cli/commands/conbus/conbus_output_commands.py +52 -14
- xp/cli/commands/conbus/conbus_raw_commands.py +17 -6
- xp/cli/commands/conbus/conbus_receive_commands.py +20 -10
- xp/cli/commands/conbus/conbus_scan_commands.py +17 -4
- xp/cli/commands/file_commands.py +35 -18
- xp/cli/commands/homekit/homekit.py +14 -8
- xp/cli/commands/homekit/homekit_start_commands.py +8 -6
- xp/cli/commands/module_commands.py +38 -23
- xp/cli/commands/reverse_proxy_commands.py +27 -19
- 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 -3
- 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 +25 -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/conbus/conbus_writeconfig.py +60 -0
- 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_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 +42 -18
- xp/services/conbus/conbus_discover_service.py +43 -7
- 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/conbus/write_config_service.py +193 -0
- 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_datapoint_service.py +70 -0
- 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 +4 -47
- xp/utils/serialization.py +6 -0
- xp/utils/time_utils.py +6 -11
- conson_xp-1.1.0.dist-info/RECORD +0 -181
- xp/api/__init__.py +0 -1
- xp/api/main.py +0 -110
- xp/api/models/__init__.py +0 -1
- xp/api/models/api.py +0 -20
- xp/api/models/discover.py +0 -21
- xp/api/routers/__init__.py +0 -17
- xp/api/routers/conbus.py +0 -5
- xp/api/routers/conbus_blink.py +0 -105
- xp/api/routers/conbus_custom.py +0 -63
- xp/api/routers/conbus_datapoint.py +0 -67
- xp/api/routers/conbus_output.py +0 -147
- xp/api/routers/errors.py +0 -37
- xp/cli/commands/api.py +0 -16
- xp/cli/commands/api_start_commands.py +0 -126
- xp/services/conbus/conbus_autoreport_get_service.py +0 -85
- xp/services/conbus/conbus_autoreport_set_service.py +0 -128
- xp/services/conbus/conbus_lightlevel_get_service.py +0 -101
- xp/services/conbus/conbus_lightlevel_set_service.py +0 -205
- xp/services/conbus/conbus_linknumber_get_service.py +0 -86
- xp/services/conbus/conbus_linknumber_set_service.py +0 -155
- {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/WHEEL +0 -0
- {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/entry_points.txt +0 -0
- {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
|
-
|
|
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