conson-xp 1.45.0__py3-none-any.whl → 1.47.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.45.0.dist-info → conson_xp-1.47.0.dist-info}/METADATA +1 -1
- conson_xp-1.47.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 -15
- 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/actiontable/download_state_machine.py +281 -0
- xp/services/actiontable/msactiontable_xp20_serializer.py +77 -49
- xp/services/actiontable/msactiontable_xp24_serializer.py +78 -53
- xp/services/actiontable/msactiontable_xp33_serializer.py +39 -9
- xp/services/actiontable/serializer_protocol.py +76 -0
- xp/services/conbus/actiontable/actiontable_download_service.py +134 -280
- 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 +17 -9
- 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 +140 -21
- 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 +26 -31
- 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.45.0.dist-info/RECORD +0 -210
- 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.45.0.dist-info → conson_xp-1.47.0.dist-info}/WHEEL +0 -0
- {conson_xp-1.45.0.dist-info → conson_xp-1.47.0.dist-info}/entry_points.txt +0 -0
- {conson_xp-1.45.0.dist-info → conson_xp-1.47.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Conbus Event Protocol for XP telegram communication.
|
|
2
3
|
|
|
3
4
|
This module implements the Twisted protocol for Conbus communication.
|
|
4
5
|
"""
|
|
@@ -21,13 +22,21 @@ from xp.models import ConbusClientConfig, ModuleTypeCode
|
|
|
21
22
|
from xp.models.protocol.conbus_protocol import (
|
|
22
23
|
TelegramReceivedEvent,
|
|
23
24
|
)
|
|
25
|
+
from xp.models.telegram.datapoint_type import DataPointType
|
|
26
|
+
from xp.models.telegram.reply_telegram import ReplyTelegram
|
|
24
27
|
from xp.models.telegram.system_function import SystemFunction
|
|
25
28
|
from xp.models.telegram.telegram_type import TelegramType
|
|
29
|
+
from xp.services import TelegramService
|
|
26
30
|
from xp.utils import calculate_checksum
|
|
27
31
|
|
|
32
|
+
# Constants
|
|
33
|
+
NO_ERROR_CODE = "00"
|
|
34
|
+
CHUNK_HEADER_LENGTH = 2 # data_value format: 2-char counter + actiontable chunk
|
|
35
|
+
|
|
28
36
|
|
|
29
37
|
class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
30
|
-
"""
|
|
38
|
+
"""
|
|
39
|
+
Twisted protocol for XP telegram communication.
|
|
31
40
|
|
|
32
41
|
Attributes:
|
|
33
42
|
buffer: Buffer for incoming telegram data.
|
|
@@ -47,6 +56,10 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
47
56
|
on_telegram_sent: Signal emitted when a telegram is sent.
|
|
48
57
|
on_data_received: Signal emitted when data is received.
|
|
49
58
|
on_telegram_received: Signal emitted when a telegram is received.
|
|
59
|
+
on_invalid_telegram_received: Signal emitted when invalid telegram received.
|
|
60
|
+
on_read_datapoint_received: Signal emitted when read datapoint reply received.
|
|
61
|
+
on_actiontable_chunk_received: Signal emitted when actiontable chunk received.
|
|
62
|
+
on_eof_received: Signal emitted when EOF telegram received.
|
|
50
63
|
on_timeout: Signal emitted when timeout occurs.
|
|
51
64
|
on_failed: Signal emitted when operation fails.
|
|
52
65
|
on_start_reactor: Signal emitted when reactor starts.
|
|
@@ -68,6 +81,11 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
68
81
|
on_telegram_sent: Signal = Signal(bytes)
|
|
69
82
|
on_data_received: Signal = Signal(bytes)
|
|
70
83
|
on_telegram_received: Signal = Signal(TelegramReceivedEvent)
|
|
84
|
+
on_invalid_telegram_received: Signal = Signal(TelegramReceivedEvent)
|
|
85
|
+
on_read_datapoint_received: Signal = Signal(ReplyTelegram)
|
|
86
|
+
on_actiontable_chunk_received: Signal = Signal(ReplyTelegram, str)
|
|
87
|
+
on_eof_received: Signal = Signal(ReplyTelegram)
|
|
88
|
+
|
|
71
89
|
on_timeout: Signal = Signal()
|
|
72
90
|
on_failed: Signal = Signal(str)
|
|
73
91
|
on_start_reactor: Signal = Signal()
|
|
@@ -77,12 +95,15 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
77
95
|
self,
|
|
78
96
|
cli_config: ConbusClientConfig,
|
|
79
97
|
reactor: PosixReactorBase,
|
|
98
|
+
telegram_service: TelegramService,
|
|
80
99
|
) -> None:
|
|
81
|
-
"""
|
|
100
|
+
"""
|
|
101
|
+
Initialize ConbusProtocol.
|
|
82
102
|
|
|
83
103
|
Args:
|
|
84
104
|
cli_config: Configuration for Conbus client connection.
|
|
85
105
|
reactor: Twisted reactor for event handling.
|
|
106
|
+
telegram_service: Telegram service for parsing telegrams.
|
|
86
107
|
"""
|
|
87
108
|
self.buffer = b""
|
|
88
109
|
self.logger = logging.getLogger(__name__)
|
|
@@ -90,12 +111,14 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
90
111
|
self._reactor = reactor
|
|
91
112
|
self.timeout_seconds = self.cli_config.timeout
|
|
92
113
|
self.timeout_call: Optional[DelayedCall] = None
|
|
114
|
+
self.telegram_service = telegram_service
|
|
93
115
|
|
|
94
116
|
def connectionMade(self) -> None:
|
|
95
|
-
"""
|
|
117
|
+
"""
|
|
118
|
+
Handle connection established event.
|
|
96
119
|
|
|
97
|
-
Called when TCP connection is successfully established.
|
|
98
|
-
|
|
120
|
+
Called when TCP connection is successfully established. Starts inactivity
|
|
121
|
+
timeout monitoring.
|
|
99
122
|
"""
|
|
100
123
|
self.logger.debug("connectionMade")
|
|
101
124
|
self.on_connection_made.emit()
|
|
@@ -104,7 +127,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
104
127
|
self._reset_timeout()
|
|
105
128
|
|
|
106
129
|
def wait(self, wait_timeout: Optional[float] = None) -> None:
|
|
107
|
-
"""
|
|
130
|
+
"""
|
|
131
|
+
Wait for incoming telegrams with optional timeout override.
|
|
108
132
|
|
|
109
133
|
Args:
|
|
110
134
|
wait_timeout: Optional timeout in seconds to override default.
|
|
@@ -114,7 +138,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
114
138
|
self._reset_timeout()
|
|
115
139
|
|
|
116
140
|
def dataReceived(self, data: bytes) -> None:
|
|
117
|
-
"""
|
|
141
|
+
"""
|
|
142
|
+
Handle received data from TCP connection.
|
|
118
143
|
|
|
119
144
|
Parses incoming telegram frames and dispatches events.
|
|
120
145
|
|
|
@@ -171,10 +196,51 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
171
196
|
checksum=checksum,
|
|
172
197
|
checksum_valid=checksum_valid,
|
|
173
198
|
)
|
|
174
|
-
self.
|
|
199
|
+
self.emit_telegram_received(telegram_received)
|
|
200
|
+
|
|
201
|
+
def emit_telegram_received(self, telegram_received: TelegramReceivedEvent) -> None:
|
|
202
|
+
"""
|
|
203
|
+
Handle telegram received event.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
telegram_received: The telegram received event.
|
|
207
|
+
"""
|
|
208
|
+
self.logger.debug(f"Received {telegram_received}")
|
|
209
|
+
self.on_telegram_received.emit(telegram_received)
|
|
210
|
+
|
|
211
|
+
# Filter invalid telegrams
|
|
212
|
+
if not telegram_received.checksum_valid:
|
|
213
|
+
self.logger.debug("Filtered: invalid checksum")
|
|
214
|
+
self.on_invalid_telegram_received.emit(telegram_received)
|
|
215
|
+
return
|
|
216
|
+
|
|
217
|
+
if telegram_received.telegram_type != TelegramType.REPLY.value:
|
|
218
|
+
self.logger.debug(
|
|
219
|
+
f"Filtered: not a reply (got {telegram_received.telegram_type})"
|
|
220
|
+
)
|
|
221
|
+
self.on_invalid_telegram_received.emit(telegram_received)
|
|
222
|
+
return
|
|
223
|
+
|
|
224
|
+
reply_telegram = self.telegram_service.parse_reply_telegram(
|
|
225
|
+
telegram_received.frame
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
if reply_telegram.system_function == SystemFunction.READ_DATAPOINT:
|
|
229
|
+
self.on_read_datapoint_received.emit(reply_telegram)
|
|
230
|
+
return
|
|
231
|
+
|
|
232
|
+
if reply_telegram.system_function == SystemFunction.ACTIONTABLE:
|
|
233
|
+
actiontable_chunk = reply_telegram.data_value[CHUNK_HEADER_LENGTH:]
|
|
234
|
+
self.on_actiontable_chunk_received.emit(reply_telegram, actiontable_chunk)
|
|
235
|
+
return
|
|
236
|
+
|
|
237
|
+
if reply_telegram.system_function == SystemFunction.EOF:
|
|
238
|
+
self.on_eof_received.emit(reply_telegram)
|
|
239
|
+
return
|
|
175
240
|
|
|
176
241
|
def sendFrame(self, data: bytes) -> None:
|
|
177
|
-
"""
|
|
242
|
+
"""
|
|
243
|
+
Send telegram frame.
|
|
178
244
|
|
|
179
245
|
Args:
|
|
180
246
|
data: Raw telegram payload (without checksum/framing).
|
|
@@ -203,7 +269,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
203
269
|
system_function: SystemFunction,
|
|
204
270
|
data_value: str,
|
|
205
271
|
) -> None:
|
|
206
|
-
"""
|
|
272
|
+
"""
|
|
273
|
+
Send telegram with specified parameters.
|
|
207
274
|
|
|
208
275
|
Args:
|
|
209
276
|
telegram_type: Type of telegram to send.
|
|
@@ -222,7 +289,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
222
289
|
def send_event_telegram(
|
|
223
290
|
self, module_type_code: ModuleTypeCode, link_number: int, input_number: int
|
|
224
291
|
) -> None:
|
|
225
|
-
"""
|
|
292
|
+
"""
|
|
293
|
+
Send telegram with specified parameters.
|
|
226
294
|
|
|
227
295
|
Args:
|
|
228
296
|
module_type_code: Type code of module.
|
|
@@ -235,7 +303,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
235
303
|
self.send_raw_telegram(payload)
|
|
236
304
|
|
|
237
305
|
def send_raw_telegram(self, payload: str) -> None:
|
|
238
|
-
"""
|
|
306
|
+
"""
|
|
307
|
+
Send telegram with specified parameters.
|
|
239
308
|
|
|
240
309
|
Args:
|
|
241
310
|
payload: Telegram to send.
|
|
@@ -243,6 +312,48 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
243
312
|
self.telegram_queue.put_nowait(payload.encode())
|
|
244
313
|
self.call_later(0.0, self.start_queue_manager)
|
|
245
314
|
|
|
315
|
+
def send_error_status_query(self, serial_number: str) -> None:
|
|
316
|
+
"""
|
|
317
|
+
Send error status query telegram.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
serial_number: Device serial number.
|
|
321
|
+
"""
|
|
322
|
+
self.send_telegram(
|
|
323
|
+
telegram_type=TelegramType.SYSTEM,
|
|
324
|
+
serial_number=serial_number,
|
|
325
|
+
system_function=SystemFunction.READ_DATAPOINT,
|
|
326
|
+
data_value=DataPointType.MODULE_ERROR_CODE.value,
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
def send_download_request(self, serial_number: str) -> None:
|
|
330
|
+
"""
|
|
331
|
+
Send download request telegram.
|
|
332
|
+
|
|
333
|
+
Args:
|
|
334
|
+
serial_number: Device serial number.
|
|
335
|
+
"""
|
|
336
|
+
self.send_telegram(
|
|
337
|
+
telegram_type=TelegramType.SYSTEM,
|
|
338
|
+
serial_number=serial_number,
|
|
339
|
+
system_function=SystemFunction.DOWNLOAD_ACTIONTABLE,
|
|
340
|
+
data_value=NO_ERROR_CODE,
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
def send_ack(self, serial_number: str) -> None:
|
|
344
|
+
"""
|
|
345
|
+
Send ACK telegram.
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
serial_number: Device serial number.
|
|
349
|
+
"""
|
|
350
|
+
self.send_telegram(
|
|
351
|
+
telegram_type=TelegramType.SYSTEM,
|
|
352
|
+
serial_number=serial_number,
|
|
353
|
+
system_function=SystemFunction.ACK,
|
|
354
|
+
data_value=NO_ERROR_CODE,
|
|
355
|
+
)
|
|
356
|
+
|
|
246
357
|
def call_later(
|
|
247
358
|
self,
|
|
248
359
|
delay: float,
|
|
@@ -250,7 +361,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
250
361
|
*args: object,
|
|
251
362
|
**kw: object,
|
|
252
363
|
) -> DelayedCall:
|
|
253
|
-
"""
|
|
364
|
+
"""
|
|
365
|
+
Schedule a callable to be called later.
|
|
254
366
|
|
|
255
367
|
Args:
|
|
256
368
|
delay: Delay in seconds before calling.
|
|
@@ -264,7 +376,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
264
376
|
return self._reactor.callLater(delay, callable_action, *args, **kw)
|
|
265
377
|
|
|
266
378
|
def buildProtocol(self, addr: IAddress) -> protocol.Protocol:
|
|
267
|
-
"""
|
|
379
|
+
"""
|
|
380
|
+
Build protocol instance for connection.
|
|
268
381
|
|
|
269
382
|
Args:
|
|
270
383
|
addr: Address of the connection.
|
|
@@ -276,7 +389,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
276
389
|
return self
|
|
277
390
|
|
|
278
391
|
def clientConnectionFailed(self, connector: IConnector, reason: Failure) -> None:
|
|
279
|
-
"""
|
|
392
|
+
"""
|
|
393
|
+
Handle client connection failure.
|
|
280
394
|
|
|
281
395
|
Args:
|
|
282
396
|
connector: Connection connector instance.
|
|
@@ -288,7 +402,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
288
402
|
self._cancel_timeout()
|
|
289
403
|
|
|
290
404
|
def clientConnectionLost(self, connector: IConnector, reason: Failure) -> None:
|
|
291
|
-
"""
|
|
405
|
+
"""
|
|
406
|
+
Handle client connection lost event.
|
|
292
407
|
|
|
293
408
|
Args:
|
|
294
409
|
connector: Connection connector instance.
|
|
@@ -304,7 +419,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
304
419
|
self.on_timeout.emit()
|
|
305
420
|
|
|
306
421
|
def connection_failed(self, reason: Failure) -> None:
|
|
307
|
-
"""
|
|
422
|
+
"""
|
|
423
|
+
Handle connection failure.
|
|
308
424
|
|
|
309
425
|
Args:
|
|
310
426
|
reason: Failure reason details.
|
|
@@ -339,7 +455,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
339
455
|
self.logger.debug(f"Reactor stop failed (likely already stopped): {e}")
|
|
340
456
|
|
|
341
457
|
def connect(self) -> None:
|
|
342
|
-
"""
|
|
458
|
+
"""
|
|
459
|
+
Connect to TCP server.
|
|
343
460
|
|
|
344
461
|
Automatically detects and integrates with running asyncio event loop if present.
|
|
345
462
|
"""
|
|
@@ -397,7 +514,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
397
514
|
self.call_later(later, self.process_telegram_queue)
|
|
398
515
|
|
|
399
516
|
def set_event_loop(self, event_loop: asyncio.AbstractEventLoop) -> None:
|
|
400
|
-
"""
|
|
517
|
+
"""
|
|
518
|
+
Change the event loop.
|
|
401
519
|
|
|
402
520
|
Args:
|
|
403
521
|
event_loop: the event loop instance.
|
|
@@ -414,7 +532,8 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
414
532
|
self.logger.info("Set reactor to running state")
|
|
415
533
|
|
|
416
534
|
def __enter__(self) -> "ConbusEventProtocol":
|
|
417
|
-
"""
|
|
535
|
+
"""
|
|
536
|
+
Enter context manager.
|
|
418
537
|
|
|
419
538
|
Returns:
|
|
420
539
|
Self for context management.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Conbus Protocol for XP telegram communication.
|
|
2
3
|
|
|
3
4
|
This module implements the Twisted protocol for Conbus communication.
|
|
4
5
|
"""
|
|
@@ -22,7 +23,8 @@ from xp.utils import calculate_checksum
|
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
25
|
-
"""
|
|
26
|
+
"""
|
|
27
|
+
Twisted protocol for XP telegram communication.
|
|
26
28
|
|
|
27
29
|
Attributes:
|
|
28
30
|
buffer: Buffer for incoming telegram data.
|
|
@@ -40,7 +42,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
40
42
|
cli_config: ConbusClientConfig,
|
|
41
43
|
reactor: PosixReactorBase,
|
|
42
44
|
) -> None:
|
|
43
|
-
"""
|
|
45
|
+
"""
|
|
46
|
+
Initialize ConbusProtocol.
|
|
44
47
|
|
|
45
48
|
Args:
|
|
46
49
|
cli_config: Configuration for Conbus client connection.
|
|
@@ -54,10 +57,11 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
54
57
|
self.timeout_call: Optional[DelayedCall] = None
|
|
55
58
|
|
|
56
59
|
def connectionMade(self) -> None:
|
|
57
|
-
"""
|
|
60
|
+
"""
|
|
61
|
+
Handle connection established event.
|
|
58
62
|
|
|
59
|
-
Called when TCP connection is successfully established.
|
|
60
|
-
|
|
63
|
+
Called when TCP connection is successfully established. Starts inactivity
|
|
64
|
+
timeout monitoring.
|
|
61
65
|
"""
|
|
62
66
|
self.logger.debug("connectionMade")
|
|
63
67
|
self.connection_established()
|
|
@@ -65,7 +69,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
65
69
|
self._reset_timeout()
|
|
66
70
|
|
|
67
71
|
def dataReceived(self, data: bytes) -> None:
|
|
68
|
-
"""
|
|
72
|
+
"""
|
|
73
|
+
Handle received data from TCP connection.
|
|
69
74
|
|
|
70
75
|
Parses incoming telegram frames and dispatches events.
|
|
71
76
|
|
|
@@ -124,7 +129,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
124
129
|
self.telegram_received(telegram_received)
|
|
125
130
|
|
|
126
131
|
def sendFrame(self, data: bytes) -> None:
|
|
127
|
-
"""
|
|
132
|
+
"""
|
|
133
|
+
Send telegram frame.
|
|
128
134
|
|
|
129
135
|
Args:
|
|
130
136
|
data: Raw telegram payload (without checksum/framing).
|
|
@@ -153,7 +159,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
153
159
|
system_function: SystemFunction,
|
|
154
160
|
data_value: str,
|
|
155
161
|
) -> None:
|
|
156
|
-
"""
|
|
162
|
+
"""
|
|
163
|
+
Send telegram with specified parameters.
|
|
157
164
|
|
|
158
165
|
Args:
|
|
159
166
|
telegram_type: Type of telegram to send.
|
|
@@ -170,7 +177,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
170
177
|
self.sendFrame(payload.encode())
|
|
171
178
|
|
|
172
179
|
def buildProtocol(self, addr: IAddress) -> protocol.Protocol:
|
|
173
|
-
"""
|
|
180
|
+
"""
|
|
181
|
+
Build protocol instance for connection.
|
|
174
182
|
|
|
175
183
|
Args:
|
|
176
184
|
addr: Address of the connection.
|
|
@@ -182,7 +190,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
182
190
|
return self
|
|
183
191
|
|
|
184
192
|
def clientConnectionFailed(self, connector: IConnector, reason: Failure) -> None:
|
|
185
|
-
"""
|
|
193
|
+
"""
|
|
194
|
+
Handle client connection failure.
|
|
186
195
|
|
|
187
196
|
Args:
|
|
188
197
|
connector: Connection connector instance.
|
|
@@ -194,7 +203,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
194
203
|
self._stop_reactor()
|
|
195
204
|
|
|
196
205
|
def clientConnectionLost(self, connector: IConnector, reason: Failure) -> None:
|
|
197
|
-
"""
|
|
206
|
+
"""
|
|
207
|
+
Handle client connection lost event.
|
|
198
208
|
|
|
199
209
|
Args:
|
|
200
210
|
connector: Connection connector instance.
|
|
@@ -206,7 +216,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
206
216
|
self._stop_reactor()
|
|
207
217
|
|
|
208
218
|
def timeout(self) -> bool:
|
|
209
|
-
"""
|
|
219
|
+
"""
|
|
220
|
+
Handle timeout event.
|
|
210
221
|
|
|
211
222
|
Returns:
|
|
212
223
|
True to continue waiting for next timeout, False to stop.
|
|
@@ -216,7 +227,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
216
227
|
return False
|
|
217
228
|
|
|
218
229
|
def connection_failed(self, reason: Failure) -> None:
|
|
219
|
-
"""
|
|
230
|
+
"""
|
|
231
|
+
Handle connection failure.
|
|
220
232
|
|
|
221
233
|
Args:
|
|
222
234
|
reason: Failure reason details.
|
|
@@ -262,7 +274,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
262
274
|
self.reactor.run()
|
|
263
275
|
|
|
264
276
|
def __enter__(self) -> "ConbusProtocol":
|
|
265
|
-
"""
|
|
277
|
+
"""
|
|
278
|
+
Enter context manager.
|
|
266
279
|
|
|
267
280
|
Returns:
|
|
268
281
|
Self for context management.
|
|
@@ -282,7 +295,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
282
295
|
"""Override methods."""
|
|
283
296
|
|
|
284
297
|
def telegram_sent(self, telegram_sent: str) -> None:
|
|
285
|
-
"""
|
|
298
|
+
"""
|
|
299
|
+
Override callback when telegram has been sent.
|
|
286
300
|
|
|
287
301
|
Args:
|
|
288
302
|
telegram_sent: The telegram that was sent.
|
|
@@ -290,7 +304,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
290
304
|
pass
|
|
291
305
|
|
|
292
306
|
def telegram_received(self, telegram_received: TelegramReceivedEvent) -> None:
|
|
293
|
-
"""
|
|
307
|
+
"""
|
|
308
|
+
Override callback when telegram is received.
|
|
294
309
|
|
|
295
310
|
Args:
|
|
296
311
|
telegram_received: Event containing received telegram details.
|
|
@@ -302,7 +317,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
302
317
|
pass
|
|
303
318
|
|
|
304
319
|
def connection_lost(self, reason: Failure) -> None:
|
|
305
|
-
"""
|
|
320
|
+
"""
|
|
321
|
+
Override callback when connection is lost.
|
|
306
322
|
|
|
307
323
|
Args:
|
|
308
324
|
reason: Reason for connection loss.
|
|
@@ -310,7 +326,8 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
310
326
|
pass
|
|
311
327
|
|
|
312
328
|
def failed(self, message: str) -> None:
|
|
313
|
-
"""
|
|
329
|
+
"""
|
|
330
|
+
Override callback when connection failed.
|
|
314
331
|
|
|
315
332
|
Args:
|
|
316
333
|
message: Error message describing the failure.
|
|
@@ -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).
|