conson-xp 1.46.0__py3-none-any.whl → 1.48.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.46.0.dist-info → conson_xp-1.48.0.dist-info}/METADATA +1 -1
- conson_xp-1.48.0.dist-info/RECORD +210 -0
- xp/__init__.py +3 -2
- xp/cli/commands/conbus/conbus.py +1 -1
- xp/cli/commands/conbus/conbus_actiontable_commands.py +33 -19
- xp/cli/commands/conbus/conbus_autoreport_commands.py +8 -4
- xp/cli/commands/conbus/conbus_blink_commands.py +20 -10
- xp/cli/commands/conbus/conbus_config_commands.py +2 -1
- xp/cli/commands/conbus/conbus_custom_commands.py +4 -2
- xp/cli/commands/conbus/conbus_datapoint_commands.py +10 -5
- xp/cli/commands/conbus/conbus_discover_commands.py +8 -4
- xp/cli/commands/conbus/conbus_event_commands.py +8 -4
- xp/cli/commands/conbus/conbus_export_commands.py +8 -4
- xp/cli/commands/conbus/conbus_lightlevel_commands.py +16 -8
- xp/cli/commands/conbus/conbus_linknumber_commands.py +8 -4
- xp/cli/commands/conbus/conbus_modulenumber_commands.py +8 -4
- xp/cli/commands/conbus/conbus_msactiontable_commands.py +78 -40
- xp/cli/commands/conbus/conbus_output_commands.py +16 -8
- xp/cli/commands/conbus/conbus_raw_commands.py +6 -3
- xp/cli/commands/conbus/conbus_receive_commands.py +6 -3
- xp/cli/commands/conbus/conbus_scan_commands.py +6 -3
- xp/cli/commands/file_commands.py +6 -3
- xp/cli/commands/homekit/homekit.py +4 -2
- xp/cli/commands/homekit/homekit_start_commands.py +2 -1
- xp/cli/commands/module_commands.py +8 -4
- xp/cli/commands/reverse_proxy_commands.py +8 -4
- xp/cli/commands/server/server_commands.py +6 -3
- xp/cli/commands/telegram/telegram_blink_commands.py +4 -2
- xp/cli/commands/telegram/telegram_checksum_commands.py +4 -2
- xp/cli/commands/telegram/telegram_discover_commands.py +2 -1
- xp/cli/commands/telegram/telegram_linknumber_commands.py +4 -2
- xp/cli/commands/telegram/telegram_parse_commands.py +4 -2
- xp/cli/commands/telegram/telegram_version_commands.py +2 -1
- xp/cli/commands/term/term_commands.py +4 -2
- xp/cli/main.py +2 -1
- xp/cli/utils/click_tree.py +6 -3
- xp/cli/utils/datapoint_type_choice.py +4 -2
- xp/cli/utils/decorators.py +42 -21
- xp/cli/utils/error_handlers.py +16 -8
- xp/cli/utils/formatters.py +22 -11
- xp/cli/utils/module_type_choice.py +4 -2
- xp/cli/utils/serial_number_type.py +4 -2
- xp/cli/utils/system_function_choice.py +4 -2
- xp/cli/utils/xp_module_type.py +4 -2
- xp/models/actiontable/actiontable.py +8 -8
- xp/models/actiontable/actiontable_type.py +20 -0
- xp/models/actiontable/msactiontable_xp20.py +8 -4
- xp/models/actiontable/msactiontable_xp24.py +12 -6
- xp/models/actiontable/msactiontable_xp33.py +20 -10
- xp/models/conbus/conbus.py +8 -4
- xp/models/conbus/conbus_autoreport.py +4 -2
- xp/models/conbus/conbus_blink.py +4 -2
- xp/models/conbus/conbus_client_config.py +6 -3
- xp/models/conbus/conbus_connection_status.py +4 -2
- xp/models/conbus/conbus_custom.py +4 -2
- xp/models/conbus/conbus_datapoint.py +4 -2
- xp/models/conbus/conbus_discover.py +6 -3
- xp/models/conbus/conbus_event_list.py +4 -2
- xp/models/conbus/conbus_event_raw.py +4 -2
- xp/models/conbus/conbus_export.py +2 -1
- xp/models/conbus/conbus_lightlevel.py +4 -2
- xp/models/conbus/conbus_linknumber.py +4 -2
- xp/models/conbus/conbus_logger_config.py +8 -4
- xp/models/conbus/conbus_output.py +4 -2
- xp/models/conbus/conbus_raw.py +4 -2
- xp/models/conbus/conbus_receive.py +4 -2
- xp/models/conbus/conbus_writeconfig.py +4 -2
- xp/models/config/conson_module_config.py +8 -4
- xp/models/homekit/homekit_accessory.py +4 -2
- xp/models/homekit/homekit_config.py +12 -6
- xp/models/log_entry.py +16 -8
- xp/models/protocol/conbus_protocol.py +36 -18
- xp/models/response.py +12 -8
- xp/models/telegram/action_type.py +4 -2
- xp/models/telegram/datapoint_type.py +4 -2
- xp/models/telegram/event_telegram.py +14 -7
- xp/models/telegram/event_type.py +2 -1
- xp/models/telegram/input_action_type.py +2 -1
- xp/models/telegram/input_type.py +2 -1
- xp/models/telegram/module_type.py +24 -12
- xp/models/telegram/module_type_code.py +2 -1
- xp/models/telegram/output_telegram.py +16 -10
- xp/models/telegram/reply_telegram.py +24 -13
- xp/models/telegram/system_function.py +6 -3
- xp/models/telegram/system_telegram.py +10 -6
- xp/models/telegram/telegram.py +2 -1
- xp/models/telegram/telegram_type.py +2 -1
- xp/models/telegram/timeparam_type.py +2 -1
- xp/models/term/connection_state.py +4 -2
- xp/models/term/module_state.py +2 -1
- xp/models/term/protocol_keys_config.py +6 -3
- xp/models/term/status_message.py +2 -1
- xp/models/term/telegram_display.py +2 -1
- xp/models/write_config_type.py +4 -2
- xp/services/actiontable/actiontable_serializer.py +34 -41
- xp/services/{conbus/actiontable/actiontable_download_state_machine.py → actiontable/download_state_machine.py} +13 -8
- xp/services/actiontable/msactiontable_xp20_serializer.py +73 -50
- xp/services/actiontable/msactiontable_xp24_serializer.py +73 -54
- xp/services/actiontable/msactiontable_xp33_serializer.py +44 -20
- xp/services/actiontable/serializer_protocol.py +76 -0
- xp/services/conbus/actiontable/actiontable_download_service.py +68 -31
- xp/services/conbus/actiontable/actiontable_list_service.py +17 -4
- xp/services/conbus/actiontable/actiontable_show_service.py +10 -6
- xp/services/conbus/actiontable/actiontable_upload_service.py +17 -9
- xp/services/conbus/conbus_blink_all_service.py +16 -8
- xp/services/conbus/conbus_blink_service.py +14 -7
- xp/services/conbus/conbus_custom_service.py +16 -8
- xp/services/conbus/conbus_datapoint_queryall_service.py +18 -9
- xp/services/conbus/conbus_datapoint_service.py +18 -9
- xp/services/conbus/conbus_discover_service.py +24 -13
- xp/services/conbus/conbus_event_list_service.py +11 -7
- xp/services/conbus/conbus_event_raw_service.py +18 -10
- xp/services/conbus/conbus_export_service.py +28 -14
- xp/services/conbus/conbus_output_service.py +18 -10
- xp/services/conbus/conbus_raw_service.py +16 -8
- xp/services/conbus/conbus_receive_service.py +18 -10
- xp/services/conbus/conbus_scan_service.py +18 -10
- xp/services/conbus/msactiontable/msactiontable_upload_service.py +18 -10
- xp/services/conbus/write_config_service.py +18 -9
- xp/services/homekit/homekit_cache_service.py +12 -6
- xp/services/homekit/homekit_conbus_service.py +12 -6
- xp/services/homekit/homekit_config_validator.py +34 -17
- xp/services/homekit/homekit_conson_validator.py +18 -9
- xp/services/homekit/homekit_dimminglight.py +14 -7
- xp/services/homekit/homekit_dimminglight_service.py +14 -7
- xp/services/homekit/homekit_hap_service.py +18 -9
- xp/services/homekit/homekit_lightbulb.py +10 -5
- xp/services/homekit/homekit_lightbulb_service.py +10 -5
- xp/services/homekit/homekit_module_service.py +8 -4
- xp/services/homekit/homekit_outlet.py +14 -7
- xp/services/homekit/homekit_outlet_service.py +12 -6
- xp/services/homekit/homekit_service.py +24 -12
- xp/services/log_file_service.py +16 -8
- xp/services/module_type_service.py +10 -5
- xp/services/protocol/conbus_event_protocol.py +51 -26
- xp/services/protocol/conbus_protocol.py +36 -19
- xp/services/protocol/protocol_factory.py +12 -6
- xp/services/protocol/telegram_protocol.py +12 -6
- xp/services/reverse_proxy_service.py +26 -14
- xp/services/server/base_server_service.py +42 -23
- xp/services/server/client_buffer_manager.py +12 -7
- xp/services/server/cp20_server_service.py +10 -7
- xp/services/server/device_service_factory.py +12 -8
- xp/services/server/server_service.py +18 -11
- xp/services/server/xp130_server_service.py +11 -8
- xp/services/server/xp20_server_service.py +16 -10
- xp/services/server/xp230_server_service.py +10 -7
- xp/services/server/xp24_server_service.py +22 -13
- xp/services/server/xp33_server_service.py +44 -25
- xp/services/telegram/telegram_blink_service.py +14 -8
- xp/services/telegram/telegram_checksum_service.py +12 -7
- xp/services/telegram/telegram_datapoint_service.py +14 -9
- xp/services/telegram/telegram_discover_service.py +28 -15
- xp/services/telegram/telegram_link_number_service.py +18 -10
- xp/services/telegram/telegram_output_service.py +24 -12
- xp/services/telegram/telegram_service.py +22 -11
- xp/services/telegram/telegram_version_service.py +14 -8
- xp/services/term/protocol_monitor_service.py +30 -16
- xp/services/term/state_monitor_service.py +39 -21
- xp/term/protocol.py +12 -6
- xp/term/state.py +12 -7
- xp/term/widgets/help_menu.py +6 -3
- xp/term/widgets/modules_list.py +20 -10
- xp/term/widgets/protocol_log.py +12 -6
- xp/term/widgets/status_footer.py +10 -5
- xp/utils/checksum.py +6 -3
- xp/utils/dependencies.py +25 -30
- xp/utils/event_helper.py +6 -4
- xp/utils/logging.py +6 -3
- xp/utils/serialization.py +30 -16
- xp/utils/state_machine.py +16 -9
- xp/utils/time_utils.py +6 -3
- conson_xp-1.46.0.dist-info/RECORD +0 -211
- xp/services/conbus/msactiontable/msactiontable_download_service.py +0 -275
- xp/services/conbus/msactiontable/msactiontable_list_service.py +0 -100
- xp/services/conbus/msactiontable/msactiontable_show_service.py +0 -89
- {conson_xp-1.46.0.dist-info → conson_xp-1.48.0.dist-info}/WHEEL +0 -0
- {conson_xp-1.46.0.dist-info → conson_xp-1.48.0.dist-info}/entry_points.txt +0 -0
- {conson_xp-1.46.0.dist-info → conson_xp-1.48.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Protocol Factory for Twisted protocol creation.
|
|
2
3
|
|
|
3
4
|
This module provides factory classes for protocol instantiation.
|
|
4
5
|
"""
|
|
@@ -18,7 +19,8 @@ from xp.services.protocol import TelegramProtocol
|
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class TelegramFactory(protocol.ClientFactory):
|
|
21
|
-
"""
|
|
22
|
+
"""
|
|
23
|
+
Factory for creating Telegram protocol instances.
|
|
22
24
|
|
|
23
25
|
Attributes:
|
|
24
26
|
event_bus: Event bus for dispatching protocol events.
|
|
@@ -33,7 +35,8 @@ class TelegramFactory(protocol.ClientFactory):
|
|
|
33
35
|
telegram_protocol: TelegramProtocol,
|
|
34
36
|
connector: IConnector,
|
|
35
37
|
) -> None:
|
|
36
|
-
"""
|
|
38
|
+
"""
|
|
39
|
+
Initialize TelegramFactory.
|
|
37
40
|
|
|
38
41
|
Args:
|
|
39
42
|
event_bus: Event bus for protocol events.
|
|
@@ -46,7 +49,8 @@ class TelegramFactory(protocol.ClientFactory):
|
|
|
46
49
|
self.logger = logging.getLogger(__name__)
|
|
47
50
|
|
|
48
51
|
def buildProtocol(self, addr: IAddress) -> TelegramProtocol:
|
|
49
|
-
"""
|
|
52
|
+
"""
|
|
53
|
+
Build protocol instance for connection.
|
|
50
54
|
|
|
51
55
|
Args:
|
|
52
56
|
addr: Address of the connection.
|
|
@@ -58,7 +62,8 @@ class TelegramFactory(protocol.ClientFactory):
|
|
|
58
62
|
return self.telegram_protocol
|
|
59
63
|
|
|
60
64
|
def clientConnectionFailed(self, connector: IConnector, reason: Failure) -> None:
|
|
61
|
-
"""
|
|
65
|
+
"""
|
|
66
|
+
Handle connection failure event.
|
|
62
67
|
|
|
63
68
|
Args:
|
|
64
69
|
connector: Connection connector instance.
|
|
@@ -68,7 +73,8 @@ class TelegramFactory(protocol.ClientFactory):
|
|
|
68
73
|
self.connector.stop()
|
|
69
74
|
|
|
70
75
|
def clientConnectionLost(self, connector: IConnector, reason: Failure) -> None:
|
|
71
|
-
"""
|
|
76
|
+
"""
|
|
77
|
+
Handle connection lost event.
|
|
72
78
|
|
|
73
79
|
Args:
|
|
74
80
|
connector: Connection connector instance.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Telegram Protocol for XP telegram communication.
|
|
2
3
|
|
|
3
4
|
This module provides the protocol implementation for telegram-based communication.
|
|
4
5
|
"""
|
|
@@ -20,7 +21,8 @@ from xp.utils import calculate_checksum
|
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class TelegramProtocol(protocol.Protocol):
|
|
23
|
-
"""
|
|
24
|
+
"""
|
|
25
|
+
Twisted protocol for XP telegram communication with built-in debouncing.
|
|
24
26
|
|
|
25
27
|
Automatically deduplicates identical telegram frames sent within a
|
|
26
28
|
configurable time window (default 50ms).
|
|
@@ -38,7 +40,8 @@ class TelegramProtocol(protocol.Protocol):
|
|
|
38
40
|
event_bus: EventBus
|
|
39
41
|
|
|
40
42
|
def __init__(self, event_bus: EventBus, debounce_ms: int = 50) -> None:
|
|
41
|
-
"""
|
|
43
|
+
"""
|
|
44
|
+
Initialize TelegramProtocol.
|
|
42
45
|
|
|
43
46
|
Args:
|
|
44
47
|
event_bus: Event bus for dispatching protocol events.
|
|
@@ -64,7 +67,8 @@ class TelegramProtocol(protocol.Protocol):
|
|
|
64
67
|
self.logger.error(f"Error scheduling async handler: {e}", exc_info=True)
|
|
65
68
|
|
|
66
69
|
def _on_task_done(self, task: asyncio.Task) -> None:
|
|
67
|
-
"""
|
|
70
|
+
"""
|
|
71
|
+
Handle async task completion.
|
|
68
72
|
|
|
69
73
|
Args:
|
|
70
74
|
task: Completed async task.
|
|
@@ -92,7 +96,8 @@ class TelegramProtocol(protocol.Protocol):
|
|
|
92
96
|
)
|
|
93
97
|
|
|
94
98
|
def dataReceived(self, data: bytes) -> None:
|
|
95
|
-
"""
|
|
99
|
+
"""
|
|
100
|
+
Handle received data from Twisted.
|
|
96
101
|
|
|
97
102
|
Args:
|
|
98
103
|
data: Raw bytes received from connection.
|
|
@@ -164,7 +169,8 @@ class TelegramProtocol(protocol.Protocol):
|
|
|
164
169
|
)
|
|
165
170
|
|
|
166
171
|
def sendFrame(self, data: bytes) -> None:
|
|
167
|
-
"""
|
|
172
|
+
"""
|
|
173
|
+
Send telegram frame.
|
|
168
174
|
|
|
169
175
|
Args:
|
|
170
176
|
data: Raw telegram payload (without checksum/framing).
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Conbus Reverse Proxy Service for TCP relay with telegram monitoring.
|
|
2
3
|
|
|
3
|
-
This service implements a TCP reverse proxy that listens on port 10001 and forwards
|
|
4
|
-
|
|
4
|
+
This service implements a TCP reverse proxy that listens on port 10001 and forwards all
|
|
5
|
+
telegrams to the configured Conbus server while printing bidirectional traffic.
|
|
5
6
|
"""
|
|
6
7
|
|
|
7
8
|
import logging
|
|
@@ -46,7 +47,8 @@ class ReverseProxyService:
|
|
|
46
47
|
cli_config: ConbusClientConfig,
|
|
47
48
|
listen_port: int,
|
|
48
49
|
):
|
|
49
|
-
"""
|
|
50
|
+
"""
|
|
51
|
+
Initialize the Conbus reverse proxy service.
|
|
50
52
|
|
|
51
53
|
Args:
|
|
52
54
|
cli_config: Conbus client configuration.
|
|
@@ -66,7 +68,8 @@ class ReverseProxyService:
|
|
|
66
68
|
|
|
67
69
|
@property
|
|
68
70
|
def target_ip(self) -> str:
|
|
69
|
-
"""
|
|
71
|
+
"""
|
|
72
|
+
Get target server IP.
|
|
70
73
|
|
|
71
74
|
Returns:
|
|
72
75
|
Target server IP address.
|
|
@@ -75,7 +78,8 @@ class ReverseProxyService:
|
|
|
75
78
|
|
|
76
79
|
@property
|
|
77
80
|
def target_port(self) -> int:
|
|
78
|
-
"""
|
|
81
|
+
"""
|
|
82
|
+
Get target server port.
|
|
79
83
|
|
|
80
84
|
Returns:
|
|
81
85
|
Target server port number.
|
|
@@ -83,7 +87,8 @@ class ReverseProxyService:
|
|
|
83
87
|
return self.cli_config.conbus.port
|
|
84
88
|
|
|
85
89
|
def start_proxy(self) -> Response:
|
|
86
|
-
"""
|
|
90
|
+
"""
|
|
91
|
+
Start the reverse proxy server.
|
|
87
92
|
|
|
88
93
|
Returns:
|
|
89
94
|
Response object with success status and proxy details.
|
|
@@ -139,7 +144,8 @@ class ReverseProxyService:
|
|
|
139
144
|
)
|
|
140
145
|
|
|
141
146
|
def stop_proxy(self) -> Response:
|
|
142
|
-
"""
|
|
147
|
+
"""
|
|
148
|
+
Stop the reverse proxy server.
|
|
143
149
|
|
|
144
150
|
Returns:
|
|
145
151
|
Response object with success status.
|
|
@@ -171,7 +177,8 @@ class ReverseProxyService:
|
|
|
171
177
|
)
|
|
172
178
|
|
|
173
179
|
def get_status(self) -> Response:
|
|
174
|
-
"""
|
|
180
|
+
"""
|
|
181
|
+
Get current proxy status and active connections.
|
|
175
182
|
|
|
176
183
|
Returns:
|
|
177
184
|
Response object with proxy status and connection details.
|
|
@@ -230,7 +237,8 @@ class ReverseProxyService:
|
|
|
230
237
|
def _handle_client(
|
|
231
238
|
self, client_socket: socket.socket, client_address: tuple, conn_id: str
|
|
232
239
|
) -> None:
|
|
233
|
-
"""
|
|
240
|
+
"""
|
|
241
|
+
Handle individual client connection with server relay.
|
|
234
242
|
|
|
235
243
|
Args:
|
|
236
244
|
client_socket: Client socket connection.
|
|
@@ -314,7 +322,8 @@ class ReverseProxyService:
|
|
|
314
322
|
dest_label: str,
|
|
315
323
|
conn_id: str,
|
|
316
324
|
) -> None:
|
|
317
|
-
"""
|
|
325
|
+
"""
|
|
326
|
+
Relay data between sockets with telegram monitoring.
|
|
318
327
|
|
|
319
328
|
Args:
|
|
320
329
|
source_socket: Source socket to receive from.
|
|
@@ -366,7 +375,8 @@ class ReverseProxyService:
|
|
|
366
375
|
self.logger.error(f"Error in data relay: {e} [{conn_id}]")
|
|
367
376
|
|
|
368
377
|
def _close_connection_pair(self, conn_id: str) -> None:
|
|
369
|
-
"""
|
|
378
|
+
"""
|
|
379
|
+
Close both client and server sockets for a connection.
|
|
370
380
|
|
|
371
381
|
Args:
|
|
372
382
|
conn_id: Connection identifier.
|
|
@@ -409,7 +419,8 @@ class ReverseProxyService:
|
|
|
409
419
|
|
|
410
420
|
@staticmethod
|
|
411
421
|
def timestamp() -> str:
|
|
412
|
-
"""
|
|
422
|
+
"""
|
|
423
|
+
Generate timestamp string for logging.
|
|
413
424
|
|
|
414
425
|
Returns:
|
|
415
426
|
Timestamp string in HH:MM:SS,mmm format.
|
|
@@ -417,7 +428,8 @@ class ReverseProxyService:
|
|
|
417
428
|
return datetime.now().strftime("%H:%M:%S,%f")[:-3]
|
|
418
429
|
|
|
419
430
|
def run_blocking(self) -> None:
|
|
420
|
-
"""
|
|
431
|
+
"""
|
|
432
|
+
Run the proxy in blocking mode (for CLI usage).
|
|
421
433
|
|
|
422
434
|
Raises:
|
|
423
435
|
ReverseProxyError: If proxy fails to start.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Base Server Service with shared functionality.
|
|
2
3
|
|
|
3
|
-
This module provides a base class for all XP device server services,
|
|
4
|
-
|
|
4
|
+
This module provides a base class for all XP device server services, containing common
|
|
5
|
+
functionality like module type response generation.
|
|
5
6
|
"""
|
|
6
7
|
|
|
7
8
|
import logging
|
|
@@ -20,12 +21,13 @@ class BaseServerService(ABC):
|
|
|
20
21
|
"""
|
|
21
22
|
Base class for all XP device server services.
|
|
22
23
|
|
|
23
|
-
Provides common functionality that is shared across all device types,
|
|
24
|
-
|
|
24
|
+
Provides common functionality that is shared across all device types, such as module
|
|
25
|
+
type response generation.
|
|
25
26
|
"""
|
|
26
27
|
|
|
27
28
|
def __init__(self, serial_number: str):
|
|
28
|
-
"""
|
|
29
|
+
"""
|
|
30
|
+
Initialize base server service.
|
|
29
31
|
|
|
30
32
|
Args:
|
|
31
33
|
serial_number: The device serial number.
|
|
@@ -52,7 +54,8 @@ class BaseServerService(ABC):
|
|
|
52
54
|
def generate_datapoint_type_response(
|
|
53
55
|
self, datapoint_type: DataPointType
|
|
54
56
|
) -> Optional[str]:
|
|
55
|
-
"""
|
|
57
|
+
"""
|
|
58
|
+
Generate datapoint_type response telegram.
|
|
56
59
|
|
|
57
60
|
Args:
|
|
58
61
|
datapoint_type: The type of datapoint to query.
|
|
@@ -81,7 +84,8 @@ class BaseServerService(ABC):
|
|
|
81
84
|
return telegram
|
|
82
85
|
|
|
83
86
|
def _check_request_for_device(self, request: SystemTelegram) -> bool:
|
|
84
|
-
"""
|
|
87
|
+
"""
|
|
88
|
+
Check if request is for this device (including broadcast).
|
|
85
89
|
|
|
86
90
|
Args:
|
|
87
91
|
request: The system telegram request to check.
|
|
@@ -93,7 +97,8 @@ class BaseServerService(ABC):
|
|
|
93
97
|
|
|
94
98
|
@staticmethod
|
|
95
99
|
def _build_response_telegram(data_part: str) -> str:
|
|
96
|
-
"""
|
|
100
|
+
"""
|
|
101
|
+
Build a complete response telegram with checksum.
|
|
97
102
|
|
|
98
103
|
Args:
|
|
99
104
|
data_part: The data part of the telegram without checksum.
|
|
@@ -105,7 +110,8 @@ class BaseServerService(ABC):
|
|
|
105
110
|
return f"<{data_part}{checksum}>"
|
|
106
111
|
|
|
107
112
|
def _log_response(self, response_type: str, telegram: str) -> None:
|
|
108
|
-
"""
|
|
113
|
+
"""
|
|
114
|
+
Log response generation.
|
|
109
115
|
|
|
110
116
|
Args:
|
|
111
117
|
response_type: The type of response being generated.
|
|
@@ -116,7 +122,8 @@ class BaseServerService(ABC):
|
|
|
116
122
|
)
|
|
117
123
|
|
|
118
124
|
def generate_discover_response(self) -> str:
|
|
119
|
-
"""
|
|
125
|
+
"""
|
|
126
|
+
Generate discover response telegram.
|
|
120
127
|
|
|
121
128
|
Returns:
|
|
122
129
|
The discover response telegram string.
|
|
@@ -129,7 +136,8 @@ class BaseServerService(ABC):
|
|
|
129
136
|
def set_link_number(
|
|
130
137
|
self, request: SystemTelegram, new_link_number: int
|
|
131
138
|
) -> Optional[str]:
|
|
132
|
-
"""
|
|
139
|
+
"""
|
|
140
|
+
Set link number and generate ACK response.
|
|
133
141
|
|
|
134
142
|
Args:
|
|
135
143
|
request: The system telegram request.
|
|
@@ -155,7 +163,8 @@ class BaseServerService(ABC):
|
|
|
155
163
|
return None
|
|
156
164
|
|
|
157
165
|
def _get_msactiontable_serializer(self) -> Optional[Any]:
|
|
158
|
-
"""
|
|
166
|
+
"""
|
|
167
|
+
Get the MsActionTable serializer for this device.
|
|
159
168
|
|
|
160
169
|
Subclasses should override this to return their specific serializer.
|
|
161
170
|
|
|
@@ -165,7 +174,8 @@ class BaseServerService(ABC):
|
|
|
165
174
|
return None
|
|
166
175
|
|
|
167
176
|
def _get_msactiontable(self) -> Optional[Any]:
|
|
168
|
-
"""
|
|
177
|
+
"""
|
|
178
|
+
Get the MsActionTable for this device.
|
|
169
179
|
|
|
170
180
|
Subclasses should override this to return their msactiontable instance.
|
|
171
181
|
|
|
@@ -208,7 +218,8 @@ class BaseServerService(ABC):
|
|
|
208
218
|
def _handle_download_msactiontable_ack_request(
|
|
209
219
|
self, _request: SystemTelegram
|
|
210
220
|
) -> Optional[str]:
|
|
211
|
-
"""
|
|
221
|
+
"""
|
|
222
|
+
Handle MsActionTable download ACK protocol.
|
|
212
223
|
|
|
213
224
|
Args:
|
|
214
225
|
_request: The system telegram request (unused, kept for signature consistency).
|
|
@@ -225,7 +236,8 @@ class BaseServerService(ABC):
|
|
|
225
236
|
return self._build_response_telegram(f"R{self.serial_number}F19D") # NAK
|
|
226
237
|
|
|
227
238
|
def process_system_telegram(self, request: SystemTelegram) -> Optional[str]:
|
|
228
|
-
"""
|
|
239
|
+
"""
|
|
240
|
+
Template method for processing system telegrams.
|
|
229
241
|
|
|
230
242
|
Args:
|
|
231
243
|
request: The system telegram request to process.
|
|
@@ -287,7 +299,8 @@ class BaseServerService(ABC):
|
|
|
287
299
|
def _handle_device_specific_data_request(
|
|
288
300
|
self, request: SystemTelegram
|
|
289
301
|
) -> Optional[str]:
|
|
290
|
-
"""
|
|
302
|
+
"""
|
|
303
|
+
Override in subclasses for device-specific data requests.
|
|
291
304
|
|
|
292
305
|
Args:
|
|
293
306
|
request: The system telegram request.
|
|
@@ -298,7 +311,8 @@ class BaseServerService(ABC):
|
|
|
298
311
|
return None
|
|
299
312
|
|
|
300
313
|
def _handle_write_config_request(self, request: SystemTelegram) -> Optional[str]:
|
|
301
|
-
"""
|
|
314
|
+
"""
|
|
315
|
+
Handle WRITE_CONFIG requests.
|
|
302
316
|
|
|
303
317
|
Args:
|
|
304
318
|
request: The system telegram request.
|
|
@@ -312,7 +326,8 @@ class BaseServerService(ABC):
|
|
|
312
326
|
return self._handle_device_specific_config_request()
|
|
313
327
|
|
|
314
328
|
def _handle_action_request(self, request: SystemTelegram) -> Optional[str]:
|
|
315
|
-
"""
|
|
329
|
+
"""
|
|
330
|
+
Handle ACTION requests.
|
|
316
331
|
|
|
317
332
|
Args:
|
|
318
333
|
request: The system telegram request.
|
|
@@ -325,7 +340,8 @@ class BaseServerService(ABC):
|
|
|
325
340
|
def _handle_device_specific_action_request(
|
|
326
341
|
self, request: SystemTelegram
|
|
327
342
|
) -> Optional[str]:
|
|
328
|
-
"""
|
|
343
|
+
"""
|
|
344
|
+
Override in subclasses for device-specific data requests.
|
|
329
345
|
|
|
330
346
|
Args:
|
|
331
347
|
request: The system telegram request.
|
|
@@ -337,7 +353,8 @@ class BaseServerService(ABC):
|
|
|
337
353
|
|
|
338
354
|
@staticmethod
|
|
339
355
|
def _handle_device_specific_config_request() -> Optional[str]:
|
|
340
|
-
"""
|
|
356
|
+
"""
|
|
357
|
+
Override in subclasses for device-specific config requests.
|
|
341
358
|
|
|
342
359
|
Returns:
|
|
343
360
|
The response telegram string, or None if request cannot be handled.
|
|
@@ -345,7 +362,8 @@ class BaseServerService(ABC):
|
|
|
345
362
|
return None
|
|
346
363
|
|
|
347
364
|
def add_telegram_buffer(self, telegram: str) -> None:
|
|
348
|
-
"""
|
|
365
|
+
"""
|
|
366
|
+
Add telegram to the buffer.
|
|
349
367
|
|
|
350
368
|
Args:
|
|
351
369
|
telegram: The telegram string to add to the buffer.
|
|
@@ -355,7 +373,8 @@ class BaseServerService(ABC):
|
|
|
355
373
|
self.telegram_buffer.append(telegram)
|
|
356
374
|
|
|
357
375
|
def collect_telegram_buffer(self) -> list[str]:
|
|
358
|
-
"""
|
|
376
|
+
"""
|
|
377
|
+
Collecting telegrams from the buffer.
|
|
359
378
|
|
|
360
379
|
Returns:
|
|
361
380
|
List of telegram strings from the buffer. The buffer is cleared after collection.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Client buffer manager for broadcasting telegrams to connected clients.
|
|
2
3
|
|
|
3
|
-
This module provides thread-safe management of per-client telegram queues,
|
|
4
|
-
|
|
4
|
+
This module provides thread-safe management of per-client telegram queues, enabling
|
|
5
|
+
broadcast of telegrams from device services to all connected clients.
|
|
5
6
|
"""
|
|
6
7
|
|
|
7
8
|
import queue
|
|
@@ -24,7 +25,8 @@ class ClientBufferManager:
|
|
|
24
25
|
self._lock = threading.Lock()
|
|
25
26
|
|
|
26
27
|
def register_client(self, client_socket: socket.socket) -> queue.Queue[str]:
|
|
27
|
-
"""
|
|
28
|
+
"""
|
|
29
|
+
Register a new client and create its telegram queue.
|
|
28
30
|
|
|
29
31
|
Args:
|
|
30
32
|
client_socket: The socket of the connecting client.
|
|
@@ -38,7 +40,8 @@ class ClientBufferManager:
|
|
|
38
40
|
return client_queue
|
|
39
41
|
|
|
40
42
|
def unregister_client(self, client_socket: socket.socket) -> None:
|
|
41
|
-
"""
|
|
43
|
+
"""
|
|
44
|
+
Unregister a client and remove its telegram queue.
|
|
42
45
|
|
|
43
46
|
Args:
|
|
44
47
|
client_socket: The socket of the disconnecting client.
|
|
@@ -47,7 +50,8 @@ class ClientBufferManager:
|
|
|
47
50
|
self._buffers.pop(client_socket, None)
|
|
48
51
|
|
|
49
52
|
def broadcast(self, telegram: str) -> None:
|
|
50
|
-
"""
|
|
53
|
+
"""
|
|
54
|
+
Broadcast a telegram to all connected clients.
|
|
51
55
|
|
|
52
56
|
Args:
|
|
53
57
|
telegram: The telegram string to broadcast.
|
|
@@ -57,7 +61,8 @@ class ClientBufferManager:
|
|
|
57
61
|
client_queue.put(telegram)
|
|
58
62
|
|
|
59
63
|
def get_queue(self, client_socket: socket.socket) -> Optional[queue.Queue[str]]:
|
|
60
|
-
"""
|
|
64
|
+
"""
|
|
65
|
+
Retrieve the queue for a specific client.
|
|
61
66
|
|
|
62
67
|
Args:
|
|
63
68
|
client_socket: The socket of the client.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
CP20 Server Service for device emulation.
|
|
2
3
|
|
|
3
|
-
This service provides CP20-specific device emulation functionality,
|
|
4
|
-
|
|
4
|
+
This service provides CP20-specific device emulation functionality, including response
|
|
5
|
+
generation and device configuration handling.
|
|
5
6
|
"""
|
|
6
7
|
|
|
7
8
|
from typing import Dict, Optional
|
|
@@ -22,8 +23,8 @@ class CP20ServerService(BaseServerService):
|
|
|
22
23
|
"""
|
|
23
24
|
CP20 device emulation service.
|
|
24
25
|
|
|
25
|
-
Generates CP20-specific responses, handles CP20 device configuration,
|
|
26
|
-
|
|
26
|
+
Generates CP20-specific responses, handles CP20 device configuration, and implements
|
|
27
|
+
CP20 telegram format.
|
|
27
28
|
"""
|
|
28
29
|
|
|
29
30
|
def __init__(
|
|
@@ -32,7 +33,8 @@ class CP20ServerService(BaseServerService):
|
|
|
32
33
|
_variant: str = "",
|
|
33
34
|
_msactiontable_serializer: Optional[MsActionTableSerializer] = None,
|
|
34
35
|
):
|
|
35
|
-
"""
|
|
36
|
+
"""
|
|
37
|
+
Initialize CP20 server service.
|
|
36
38
|
|
|
37
39
|
Args:
|
|
38
40
|
serial_number: The device serial number.
|
|
@@ -51,7 +53,8 @@ class CP20ServerService(BaseServerService):
|
|
|
51
53
|
return None
|
|
52
54
|
|
|
53
55
|
def get_device_info(self) -> Dict:
|
|
54
|
-
"""
|
|
56
|
+
"""
|
|
57
|
+
Get CP20 device information.
|
|
55
58
|
|
|
56
59
|
Returns:
|
|
57
60
|
Dictionary containing device information.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Device Service Factory for creating device instances.
|
|
2
3
|
|
|
3
|
-
This module provides a factory for creating device service instances
|
|
4
|
-
|
|
4
|
+
This module provides a factory for creating device service instances with proper
|
|
5
|
+
dependency injection of serializers.
|
|
5
6
|
"""
|
|
6
7
|
|
|
7
8
|
from xp.services.actiontable.msactiontable_serializer import MsActionTableSerializer
|
|
@@ -24,10 +25,11 @@ from xp.services.server.xp230_server_service import XP230ServerService
|
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
class DeviceServiceFactory:
|
|
27
|
-
"""
|
|
28
|
+
"""
|
|
29
|
+
Factory for creating device service instances.
|
|
28
30
|
|
|
29
|
-
Encapsulates device creation logic and handles serializer injection
|
|
30
|
-
|
|
31
|
+
Encapsulates device creation logic and handles serializer injection for different
|
|
32
|
+
device types.
|
|
31
33
|
"""
|
|
32
34
|
|
|
33
35
|
def __init__(
|
|
@@ -37,7 +39,8 @@ class DeviceServiceFactory:
|
|
|
37
39
|
xp33ms_serializer: Xp33MsActionTableSerializer,
|
|
38
40
|
ms_serializer: MsActionTableSerializer,
|
|
39
41
|
):
|
|
40
|
-
"""
|
|
42
|
+
"""
|
|
43
|
+
Initialize device service factory.
|
|
41
44
|
|
|
42
45
|
Args:
|
|
43
46
|
xp20ms_serializer: XP20 MsActionTable serializer (injected via DI).
|
|
@@ -51,7 +54,8 @@ class DeviceServiceFactory:
|
|
|
51
54
|
self.ms_serializer = ms_serializer
|
|
52
55
|
|
|
53
56
|
def create_device(self, module_type: str, serial_number: str) -> BaseServerService:
|
|
54
|
-
"""
|
|
57
|
+
"""
|
|
58
|
+
Create device instance for given module type.
|
|
55
59
|
|
|
56
60
|
Args:
|
|
57
61
|
module_type: Module type code (e.g., "XP20", "XP33LR").
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Conbus Server Service for emulating device discover responses.
|
|
2
3
|
|
|
3
|
-
This service implements a TCP server that listens on port 10001 and responds to
|
|
4
|
-
|
|
4
|
+
This service implements a TCP server that listens on port 10001 and responds to Discover
|
|
5
|
+
Request telegrams with configurable device information.
|
|
5
6
|
"""
|
|
6
7
|
|
|
7
8
|
import logging
|
|
@@ -32,8 +33,8 @@ class ServerService:
|
|
|
32
33
|
"""
|
|
33
34
|
Main TCP server implementation for Conbus device emulation.
|
|
34
35
|
|
|
35
|
-
Manages TCP socket lifecycle, handles client connections,
|
|
36
|
-
|
|
36
|
+
Manages TCP socket lifecycle, handles client connections, parses Discover Request
|
|
37
|
+
telegrams, and coordinates device responses.
|
|
37
38
|
"""
|
|
38
39
|
|
|
39
40
|
def __init__(
|
|
@@ -44,7 +45,8 @@ class ServerService:
|
|
|
44
45
|
config_path: str = "server.yml",
|
|
45
46
|
port: int = 10001,
|
|
46
47
|
):
|
|
47
|
-
"""
|
|
48
|
+
"""
|
|
49
|
+
Initialize the Conbus server service.
|
|
48
50
|
|
|
49
51
|
Args:
|
|
50
52
|
telegram_service: Service for parsing system telegrams.
|
|
@@ -121,7 +123,8 @@ class ServerService:
|
|
|
121
123
|
)
|
|
122
124
|
|
|
123
125
|
def start_server(self) -> None:
|
|
124
|
-
"""
|
|
126
|
+
"""
|
|
127
|
+
Start the TCP server on port 10001.
|
|
125
128
|
|
|
126
129
|
Raises:
|
|
127
130
|
ServerError: If server is already running or fails to start.
|
|
@@ -255,7 +258,8 @@ class ServerService:
|
|
|
255
258
|
self.logger.error(f"Error closing client socket: {e}")
|
|
256
259
|
|
|
257
260
|
def _process_request(self, message: str) -> List[str]:
|
|
258
|
-
"""
|
|
261
|
+
"""
|
|
262
|
+
Process incoming request and generate responses.
|
|
259
263
|
|
|
260
264
|
Args:
|
|
261
265
|
message: Message potentially containing multiple telegrams in format <TELEGRAM><TELEGRAM2>...
|
|
@@ -284,7 +288,8 @@ class ServerService:
|
|
|
284
288
|
return responses
|
|
285
289
|
|
|
286
290
|
def _split_telegrams(self, message: str) -> List[str]:
|
|
287
|
-
"""
|
|
291
|
+
"""
|
|
292
|
+
Split message into individual telegrams.
|
|
288
293
|
|
|
289
294
|
Args:
|
|
290
295
|
message: Raw message containing one or more telegrams in format <TELEGRAM><TELEGRAM2>...
|
|
@@ -319,7 +324,8 @@ class ServerService:
|
|
|
319
324
|
return telegrams
|
|
320
325
|
|
|
321
326
|
def _process_single_telegram(self, telegram: str) -> List[str]:
|
|
322
|
-
"""
|
|
327
|
+
"""
|
|
328
|
+
Process a single telegram and generate responses.
|
|
323
329
|
|
|
324
330
|
Args:
|
|
325
331
|
telegram: A single telegram string.
|
|
@@ -376,7 +382,8 @@ class ServerService:
|
|
|
376
382
|
return responses
|
|
377
383
|
|
|
378
384
|
def get_server_status(self) -> dict:
|
|
379
|
-
"""
|
|
385
|
+
"""
|
|
386
|
+
Get current server status.
|
|
380
387
|
|
|
381
388
|
Returns:
|
|
382
389
|
Dictionary containing server status information.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
XP130 Server Service for device emulation.
|
|
2
3
|
|
|
3
|
-
This service provides XP130-specific device emulation functionality,
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
This service provides XP130-specific device emulation functionality, including response
|
|
5
|
+
generation and device configuration handling. XP130 is an Ethernet/TCPIP interface
|
|
6
|
+
module.
|
|
6
7
|
"""
|
|
7
8
|
|
|
8
9
|
from typing import Dict, Optional
|
|
@@ -22,8 +23,8 @@ class XP130ServerService(BaseServerService):
|
|
|
22
23
|
"""
|
|
23
24
|
XP130 device emulation service.
|
|
24
25
|
|
|
25
|
-
Generates XP130-specific responses, handles XP130 device configuration,
|
|
26
|
-
|
|
26
|
+
Generates XP130-specific responses, handles XP130 device configuration, and
|
|
27
|
+
implements XP130 telegram format for Ethernet/TCPIP interface module.
|
|
27
28
|
"""
|
|
28
29
|
|
|
29
30
|
def __init__(
|
|
@@ -32,7 +33,8 @@ class XP130ServerService(BaseServerService):
|
|
|
32
33
|
_variant: str = "",
|
|
33
34
|
_msactiontable_serializer: Optional[MsActionTableSerializer] = None,
|
|
34
35
|
):
|
|
35
|
-
"""
|
|
36
|
+
"""
|
|
37
|
+
Initialize XP130 server service.
|
|
36
38
|
|
|
37
39
|
Args:
|
|
38
40
|
serial_number: The device serial number.
|
|
@@ -50,7 +52,8 @@ class XP130ServerService(BaseServerService):
|
|
|
50
52
|
self.gateway = "192.168.1.1"
|
|
51
53
|
|
|
52
54
|
def get_device_info(self) -> Dict:
|
|
53
|
-
"""
|
|
55
|
+
"""
|
|
56
|
+
Get XP130 device information.
|
|
54
57
|
|
|
55
58
|
Returns:
|
|
56
59
|
Dictionary containing device information.
|