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.
Files changed (179) hide show
  1. {conson_xp-1.46.0.dist-info → conson_xp-1.48.0.dist-info}/METADATA +1 -1
  2. conson_xp-1.48.0.dist-info/RECORD +210 -0
  3. xp/__init__.py +3 -2
  4. xp/cli/commands/conbus/conbus.py +1 -1
  5. xp/cli/commands/conbus/conbus_actiontable_commands.py +33 -19
  6. xp/cli/commands/conbus/conbus_autoreport_commands.py +8 -4
  7. xp/cli/commands/conbus/conbus_blink_commands.py +20 -10
  8. xp/cli/commands/conbus/conbus_config_commands.py +2 -1
  9. xp/cli/commands/conbus/conbus_custom_commands.py +4 -2
  10. xp/cli/commands/conbus/conbus_datapoint_commands.py +10 -5
  11. xp/cli/commands/conbus/conbus_discover_commands.py +8 -4
  12. xp/cli/commands/conbus/conbus_event_commands.py +8 -4
  13. xp/cli/commands/conbus/conbus_export_commands.py +8 -4
  14. xp/cli/commands/conbus/conbus_lightlevel_commands.py +16 -8
  15. xp/cli/commands/conbus/conbus_linknumber_commands.py +8 -4
  16. xp/cli/commands/conbus/conbus_modulenumber_commands.py +8 -4
  17. xp/cli/commands/conbus/conbus_msactiontable_commands.py +78 -40
  18. xp/cli/commands/conbus/conbus_output_commands.py +16 -8
  19. xp/cli/commands/conbus/conbus_raw_commands.py +6 -3
  20. xp/cli/commands/conbus/conbus_receive_commands.py +6 -3
  21. xp/cli/commands/conbus/conbus_scan_commands.py +6 -3
  22. xp/cli/commands/file_commands.py +6 -3
  23. xp/cli/commands/homekit/homekit.py +4 -2
  24. xp/cli/commands/homekit/homekit_start_commands.py +2 -1
  25. xp/cli/commands/module_commands.py +8 -4
  26. xp/cli/commands/reverse_proxy_commands.py +8 -4
  27. xp/cli/commands/server/server_commands.py +6 -3
  28. xp/cli/commands/telegram/telegram_blink_commands.py +4 -2
  29. xp/cli/commands/telegram/telegram_checksum_commands.py +4 -2
  30. xp/cli/commands/telegram/telegram_discover_commands.py +2 -1
  31. xp/cli/commands/telegram/telegram_linknumber_commands.py +4 -2
  32. xp/cli/commands/telegram/telegram_parse_commands.py +4 -2
  33. xp/cli/commands/telegram/telegram_version_commands.py +2 -1
  34. xp/cli/commands/term/term_commands.py +4 -2
  35. xp/cli/main.py +2 -1
  36. xp/cli/utils/click_tree.py +6 -3
  37. xp/cli/utils/datapoint_type_choice.py +4 -2
  38. xp/cli/utils/decorators.py +42 -21
  39. xp/cli/utils/error_handlers.py +16 -8
  40. xp/cli/utils/formatters.py +22 -11
  41. xp/cli/utils/module_type_choice.py +4 -2
  42. xp/cli/utils/serial_number_type.py +4 -2
  43. xp/cli/utils/system_function_choice.py +4 -2
  44. xp/cli/utils/xp_module_type.py +4 -2
  45. xp/models/actiontable/actiontable.py +8 -8
  46. xp/models/actiontable/actiontable_type.py +20 -0
  47. xp/models/actiontable/msactiontable_xp20.py +8 -4
  48. xp/models/actiontable/msactiontable_xp24.py +12 -6
  49. xp/models/actiontable/msactiontable_xp33.py +20 -10
  50. xp/models/conbus/conbus.py +8 -4
  51. xp/models/conbus/conbus_autoreport.py +4 -2
  52. xp/models/conbus/conbus_blink.py +4 -2
  53. xp/models/conbus/conbus_client_config.py +6 -3
  54. xp/models/conbus/conbus_connection_status.py +4 -2
  55. xp/models/conbus/conbus_custom.py +4 -2
  56. xp/models/conbus/conbus_datapoint.py +4 -2
  57. xp/models/conbus/conbus_discover.py +6 -3
  58. xp/models/conbus/conbus_event_list.py +4 -2
  59. xp/models/conbus/conbus_event_raw.py +4 -2
  60. xp/models/conbus/conbus_export.py +2 -1
  61. xp/models/conbus/conbus_lightlevel.py +4 -2
  62. xp/models/conbus/conbus_linknumber.py +4 -2
  63. xp/models/conbus/conbus_logger_config.py +8 -4
  64. xp/models/conbus/conbus_output.py +4 -2
  65. xp/models/conbus/conbus_raw.py +4 -2
  66. xp/models/conbus/conbus_receive.py +4 -2
  67. xp/models/conbus/conbus_writeconfig.py +4 -2
  68. xp/models/config/conson_module_config.py +8 -4
  69. xp/models/homekit/homekit_accessory.py +4 -2
  70. xp/models/homekit/homekit_config.py +12 -6
  71. xp/models/log_entry.py +16 -8
  72. xp/models/protocol/conbus_protocol.py +36 -18
  73. xp/models/response.py +12 -8
  74. xp/models/telegram/action_type.py +4 -2
  75. xp/models/telegram/datapoint_type.py +4 -2
  76. xp/models/telegram/event_telegram.py +14 -7
  77. xp/models/telegram/event_type.py +2 -1
  78. xp/models/telegram/input_action_type.py +2 -1
  79. xp/models/telegram/input_type.py +2 -1
  80. xp/models/telegram/module_type.py +24 -12
  81. xp/models/telegram/module_type_code.py +2 -1
  82. xp/models/telegram/output_telegram.py +16 -10
  83. xp/models/telegram/reply_telegram.py +24 -13
  84. xp/models/telegram/system_function.py +6 -3
  85. xp/models/telegram/system_telegram.py +10 -6
  86. xp/models/telegram/telegram.py +2 -1
  87. xp/models/telegram/telegram_type.py +2 -1
  88. xp/models/telegram/timeparam_type.py +2 -1
  89. xp/models/term/connection_state.py +4 -2
  90. xp/models/term/module_state.py +2 -1
  91. xp/models/term/protocol_keys_config.py +6 -3
  92. xp/models/term/status_message.py +2 -1
  93. xp/models/term/telegram_display.py +2 -1
  94. xp/models/write_config_type.py +4 -2
  95. xp/services/actiontable/actiontable_serializer.py +34 -41
  96. xp/services/{conbus/actiontable/actiontable_download_state_machine.py → actiontable/download_state_machine.py} +13 -8
  97. xp/services/actiontable/msactiontable_xp20_serializer.py +73 -50
  98. xp/services/actiontable/msactiontable_xp24_serializer.py +73 -54
  99. xp/services/actiontable/msactiontable_xp33_serializer.py +44 -20
  100. xp/services/actiontable/serializer_protocol.py +76 -0
  101. xp/services/conbus/actiontable/actiontable_download_service.py +68 -31
  102. xp/services/conbus/actiontable/actiontable_list_service.py +17 -4
  103. xp/services/conbus/actiontable/actiontable_show_service.py +10 -6
  104. xp/services/conbus/actiontable/actiontable_upload_service.py +17 -9
  105. xp/services/conbus/conbus_blink_all_service.py +16 -8
  106. xp/services/conbus/conbus_blink_service.py +14 -7
  107. xp/services/conbus/conbus_custom_service.py +16 -8
  108. xp/services/conbus/conbus_datapoint_queryall_service.py +18 -9
  109. xp/services/conbus/conbus_datapoint_service.py +18 -9
  110. xp/services/conbus/conbus_discover_service.py +24 -13
  111. xp/services/conbus/conbus_event_list_service.py +11 -7
  112. xp/services/conbus/conbus_event_raw_service.py +18 -10
  113. xp/services/conbus/conbus_export_service.py +28 -14
  114. xp/services/conbus/conbus_output_service.py +18 -10
  115. xp/services/conbus/conbus_raw_service.py +16 -8
  116. xp/services/conbus/conbus_receive_service.py +18 -10
  117. xp/services/conbus/conbus_scan_service.py +18 -10
  118. xp/services/conbus/msactiontable/msactiontable_upload_service.py +18 -10
  119. xp/services/conbus/write_config_service.py +18 -9
  120. xp/services/homekit/homekit_cache_service.py +12 -6
  121. xp/services/homekit/homekit_conbus_service.py +12 -6
  122. xp/services/homekit/homekit_config_validator.py +34 -17
  123. xp/services/homekit/homekit_conson_validator.py +18 -9
  124. xp/services/homekit/homekit_dimminglight.py +14 -7
  125. xp/services/homekit/homekit_dimminglight_service.py +14 -7
  126. xp/services/homekit/homekit_hap_service.py +18 -9
  127. xp/services/homekit/homekit_lightbulb.py +10 -5
  128. xp/services/homekit/homekit_lightbulb_service.py +10 -5
  129. xp/services/homekit/homekit_module_service.py +8 -4
  130. xp/services/homekit/homekit_outlet.py +14 -7
  131. xp/services/homekit/homekit_outlet_service.py +12 -6
  132. xp/services/homekit/homekit_service.py +24 -12
  133. xp/services/log_file_service.py +16 -8
  134. xp/services/module_type_service.py +10 -5
  135. xp/services/protocol/conbus_event_protocol.py +51 -26
  136. xp/services/protocol/conbus_protocol.py +36 -19
  137. xp/services/protocol/protocol_factory.py +12 -6
  138. xp/services/protocol/telegram_protocol.py +12 -6
  139. xp/services/reverse_proxy_service.py +26 -14
  140. xp/services/server/base_server_service.py +42 -23
  141. xp/services/server/client_buffer_manager.py +12 -7
  142. xp/services/server/cp20_server_service.py +10 -7
  143. xp/services/server/device_service_factory.py +12 -8
  144. xp/services/server/server_service.py +18 -11
  145. xp/services/server/xp130_server_service.py +11 -8
  146. xp/services/server/xp20_server_service.py +16 -10
  147. xp/services/server/xp230_server_service.py +10 -7
  148. xp/services/server/xp24_server_service.py +22 -13
  149. xp/services/server/xp33_server_service.py +44 -25
  150. xp/services/telegram/telegram_blink_service.py +14 -8
  151. xp/services/telegram/telegram_checksum_service.py +12 -7
  152. xp/services/telegram/telegram_datapoint_service.py +14 -9
  153. xp/services/telegram/telegram_discover_service.py +28 -15
  154. xp/services/telegram/telegram_link_number_service.py +18 -10
  155. xp/services/telegram/telegram_output_service.py +24 -12
  156. xp/services/telegram/telegram_service.py +22 -11
  157. xp/services/telegram/telegram_version_service.py +14 -8
  158. xp/services/term/protocol_monitor_service.py +30 -16
  159. xp/services/term/state_monitor_service.py +39 -21
  160. xp/term/protocol.py +12 -6
  161. xp/term/state.py +12 -7
  162. xp/term/widgets/help_menu.py +6 -3
  163. xp/term/widgets/modules_list.py +20 -10
  164. xp/term/widgets/protocol_log.py +12 -6
  165. xp/term/widgets/status_footer.py +10 -5
  166. xp/utils/checksum.py +6 -3
  167. xp/utils/dependencies.py +25 -30
  168. xp/utils/event_helper.py +6 -4
  169. xp/utils/logging.py +6 -3
  170. xp/utils/serialization.py +30 -16
  171. xp/utils/state_machine.py +16 -9
  172. xp/utils/time_utils.py +6 -3
  173. conson_xp-1.46.0.dist-info/RECORD +0 -211
  174. xp/services/conbus/msactiontable/msactiontable_download_service.py +0 -275
  175. xp/services/conbus/msactiontable/msactiontable_list_service.py +0 -100
  176. xp/services/conbus/msactiontable/msactiontable_show_service.py +0 -89
  177. {conson_xp-1.46.0.dist-info → conson_xp-1.48.0.dist-info}/WHEEL +0 -0
  178. {conson_xp-1.46.0.dist-info → conson_xp-1.48.0.dist-info}/entry_points.txt +0 -0
  179. {conson_xp-1.46.0.dist-info → conson_xp-1.48.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,5 @@
1
- """Protocol Factory for Twisted protocol creation.
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
- """Factory for creating Telegram protocol instances.
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
- """Initialize TelegramFactory.
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
- """Build protocol instance for connection.
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
- """Handle connection failure event.
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
- """Handle connection lost event.
76
+ """
77
+ Handle connection lost event.
72
78
 
73
79
  Args:
74
80
  connector: Connection connector instance.
@@ -1,4 +1,5 @@
1
- """Telegram Protocol for XP telegram communication.
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
- """Twisted protocol for XP telegram communication with built-in debouncing.
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
- """Initialize TelegramProtocol.
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
- """Handle async task completion.
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
- """Handle received data from Twisted.
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
- """Send telegram frame.
172
+ """
173
+ Send telegram frame.
168
174
 
169
175
  Args:
170
176
  data: Raw telegram payload (without checksum/framing).
@@ -1,7 +1,8 @@
1
- """Conbus Reverse Proxy Service for TCP relay with telegram monitoring.
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
- all telegrams to the configured Conbus server while printing bidirectional traffic.
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
- """Initialize the Conbus reverse proxy service.
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
- """Get target server IP.
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
- """Get target server port.
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
- """Start the reverse proxy server.
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
- """Stop the reverse proxy server.
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
- """Get current proxy status and active connections.
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
- """Handle individual client connection with server relay.
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
- """Relay data between sockets with telegram monitoring.
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
- """Close both client and server sockets for a connection.
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
- """Generate timestamp string for logging.
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
- """Run the proxy in blocking mode (for CLI usage).
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
- """Base Server Service with shared functionality.
1
+ """
2
+ Base Server Service with shared functionality.
2
3
 
3
- This module provides a base class for all XP device server services,
4
- containing common functionality like module type response generation.
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
- such as module type response generation.
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
- """Initialize base server service.
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
- """Generate datapoint_type response telegram.
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
- """Check if request is for this device (including broadcast).
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
- """Build a complete response telegram with checksum.
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
- """Log response generation.
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
- """Generate discover response telegram.
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
- """Set link number and generate ACK response.
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
- """Get the MsActionTable serializer for this device.
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
- """Get the MsActionTable for this device.
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
- """Handle MsActionTable download ACK protocol.
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
- """Template method for processing system telegrams.
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
- """Override in subclasses for device-specific data requests.
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
- """Handle WRITE_CONFIG requests.
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
- """Handle ACTION requests.
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
- """Override in subclasses for device-specific data requests.
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
- """Override in subclasses for device-specific config requests.
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
- """Add telegram to the buffer.
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
- """Collecting telegrams from the buffer.
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
- """Client buffer manager for broadcasting telegrams to connected clients.
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
- enabling broadcast of telegrams from device services to all connected clients.
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
- """Register a new client and create its telegram queue.
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
- """Unregister a client and remove its telegram queue.
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
- """Broadcast a telegram to all connected clients.
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
- """Retrieve the queue for a specific client.
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
- """CP20 Server Service for device emulation.
1
+ """
2
+ CP20 Server Service for device emulation.
2
3
 
3
- This service provides CP20-specific device emulation functionality,
4
- including response generation and device configuration handling.
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
- and implements CP20 telegram format.
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
- """Initialize CP20 server service.
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
- """Get CP20 device information.
56
+ """
57
+ Get CP20 device information.
55
58
 
56
59
  Returns:
57
60
  Dictionary containing device information.
@@ -1,7 +1,8 @@
1
- """Device Service Factory for creating device instances.
1
+ """
2
+ Device Service Factory for creating device instances.
2
3
 
3
- This module provides a factory for creating device service instances
4
- with proper dependency injection of serializers.
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
- """Factory for creating device service instances.
28
+ """
29
+ Factory for creating device service instances.
28
30
 
29
- Encapsulates device creation logic and handles serializer injection
30
- for different device types.
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
- """Initialize device service factory.
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
- """Create device instance for given module type.
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
- """Conbus Server Service for emulating device discover responses.
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
- Discover Request telegrams with configurable device information.
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
- parses Discover Request telegrams, and coordinates device responses.
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
- """Initialize the Conbus server service.
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
- """Start the TCP server on port 10001.
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
- """Process incoming request and generate responses.
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
- """Split message into individual telegrams.
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
- """Process a single telegram and generate responses.
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
- """Get current server status.
385
+ """
386
+ Get current server status.
380
387
 
381
388
  Returns:
382
389
  Dictionary containing server status information.
@@ -1,8 +1,9 @@
1
- """XP130 Server Service for device emulation.
1
+ """
2
+ XP130 Server Service for device emulation.
2
3
 
3
- This service provides XP130-specific device emulation functionality,
4
- including response generation and device configuration handling.
5
- XP130 is an Ethernet/TCPIP interface module.
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
- and implements XP130 telegram format for Ethernet/TCPIP interface module.
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
- """Initialize XP130 server service.
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
- """Get XP130 device information.
55
+ """
56
+ Get XP130 device information.
54
57
 
55
58
  Returns:
56
59
  Dictionary containing device information.