conson-xp 1.34.0__py3-none-any.whl → 1.35.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.34.0.dist-info → conson_xp-1.35.0.dist-info}/METADATA +1 -1
- {conson_xp-1.34.0.dist-info → conson_xp-1.35.0.dist-info}/RECORD +29 -29
- xp/__init__.py +1 -1
- xp/cli/commands/conbus/conbus_actiontable_commands.py +34 -35
- xp/cli/commands/conbus/conbus_autoreport_commands.py +11 -10
- xp/cli/commands/conbus/conbus_custom_commands.py +6 -4
- xp/cli/commands/conbus/conbus_datapoint_commands.py +8 -6
- xp/cli/commands/conbus/conbus_lightlevel_commands.py +19 -16
- xp/cli/commands/conbus/conbus_linknumber_commands.py +7 -6
- xp/cli/commands/conbus/conbus_modulenumber_commands.py +7 -6
- xp/cli/commands/conbus/conbus_msactiontable_commands.py +7 -9
- xp/cli/commands/conbus/conbus_output_commands.py +9 -7
- xp/cli/commands/conbus/conbus_raw_commands.py +7 -2
- xp/cli/commands/conbus/conbus_scan_commands.py +4 -2
- xp/services/conbus/actiontable/actiontable_download_service.py +79 -37
- xp/services/conbus/actiontable/actiontable_list_service.py +17 -17
- xp/services/conbus/actiontable/actiontable_upload_service.py +78 -36
- xp/services/conbus/actiontable/msactiontable_service.py +88 -48
- xp/services/conbus/conbus_custom_service.py +81 -26
- xp/services/conbus/conbus_datapoint_queryall_service.py +90 -43
- xp/services/conbus/conbus_datapoint_service.py +76 -28
- xp/services/conbus/conbus_output_service.py +82 -22
- xp/services/conbus/conbus_raw_service.py +78 -37
- xp/services/conbus/conbus_scan_service.py +86 -42
- xp/services/conbus/write_config_service.py +76 -26
- xp/utils/dependencies.py +10 -20
- {conson_xp-1.34.0.dist-info → conson_xp-1.35.0.dist-info}/WHEEL +0 -0
- {conson_xp-1.34.0.dist-info → conson_xp-1.35.0.dist-info}/entry_points.txt +0 -0
- {conson_xp-1.34.0.dist-info → conson_xp-1.35.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -5,48 +5,57 @@ This service handles datapoint query operations for modules through Conbus teleg
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
from datetime import datetime
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import Any, Optional
|
|
9
9
|
|
|
10
|
-
from
|
|
10
|
+
from psygnal import Signal
|
|
11
11
|
|
|
12
|
-
from xp.models import
|
|
12
|
+
from xp.models import ConbusDatapointResponse
|
|
13
13
|
from xp.models.protocol.conbus_protocol import TelegramReceivedEvent
|
|
14
14
|
from xp.models.telegram.datapoint_type import DataPointType
|
|
15
15
|
from xp.models.telegram.reply_telegram import ReplyTelegram
|
|
16
16
|
from xp.models.telegram.system_function import SystemFunction
|
|
17
17
|
from xp.models.telegram.telegram_type import TelegramType
|
|
18
|
-
from xp.services.protocol import
|
|
18
|
+
from xp.services.protocol.conbus_event_protocol import ConbusEventProtocol
|
|
19
19
|
from xp.services.telegram.telegram_service import TelegramService
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class ConbusDatapointService
|
|
23
|
-
"""
|
|
24
|
-
Service for querying datapoints from Conbus modules.
|
|
22
|
+
class ConbusDatapointService:
|
|
23
|
+
"""Service for querying datapoints from Conbus modules.
|
|
25
24
|
|
|
26
|
-
Uses
|
|
25
|
+
Uses ConbusEventProtocol to provide datapoint query functionality
|
|
27
26
|
for reading sensor data and module information.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
conbus_protocol: Protocol instance for Conbus communication.
|
|
30
|
+
telegram_service: Service for parsing telegrams.
|
|
31
|
+
on_finish: Signal emitted when datapoint query completes (with response).
|
|
28
32
|
"""
|
|
29
33
|
|
|
34
|
+
on_finish: Signal = Signal(ConbusDatapointResponse)
|
|
35
|
+
|
|
30
36
|
def __init__(
|
|
31
37
|
self,
|
|
38
|
+
conbus_protocol: ConbusEventProtocol,
|
|
32
39
|
telegram_service: TelegramService,
|
|
33
|
-
cli_config: ConbusClientConfig,
|
|
34
|
-
reactor: PosixReactorBase,
|
|
35
40
|
) -> None:
|
|
36
41
|
"""Initialize the Conbus datapoint service.
|
|
37
42
|
|
|
38
43
|
Args:
|
|
44
|
+
conbus_protocol: Protocol instance for Conbus communication.
|
|
39
45
|
telegram_service: Service for parsing telegrams.
|
|
40
|
-
cli_config: Configuration for Conbus client connection.
|
|
41
|
-
reactor: Twisted reactor for event loop.
|
|
42
46
|
"""
|
|
43
|
-
|
|
47
|
+
self.conbus_protocol = conbus_protocol
|
|
44
48
|
self.telegram_service = telegram_service
|
|
49
|
+
|
|
50
|
+
# Connect protocol signals
|
|
51
|
+
self.conbus_protocol.on_connection_made.connect(self.connection_made)
|
|
52
|
+
self.conbus_protocol.on_telegram_sent.connect(self.telegram_sent)
|
|
53
|
+
self.conbus_protocol.on_telegram_received.connect(self.telegram_received)
|
|
54
|
+
self.conbus_protocol.on_timeout.connect(self.timeout)
|
|
55
|
+
self.conbus_protocol.on_failed.connect(self.failed)
|
|
56
|
+
|
|
45
57
|
self.serial_number: str = ""
|
|
46
58
|
self.datapoint_type: Optional[DataPointType] = None
|
|
47
|
-
self.datapoint_finished_callback: Optional[
|
|
48
|
-
Callable[[ConbusDatapointResponse], None]
|
|
49
|
-
] = None
|
|
50
59
|
self.service_response: ConbusDatapointResponse = ConbusDatapointResponse(
|
|
51
60
|
success=False,
|
|
52
61
|
serial_number=self.serial_number,
|
|
@@ -55,7 +64,7 @@ class ConbusDatapointService(ConbusProtocol):
|
|
|
55
64
|
# Set up logging
|
|
56
65
|
self.logger = logging.getLogger(__name__)
|
|
57
66
|
|
|
58
|
-
def
|
|
67
|
+
def connection_made(self) -> None:
|
|
59
68
|
"""Handle connection established event."""
|
|
60
69
|
self.logger.debug(
|
|
61
70
|
f"Connection established, querying datapoint {self.datapoint_type}."
|
|
@@ -64,7 +73,7 @@ class ConbusDatapointService(ConbusProtocol):
|
|
|
64
73
|
self.failed("Datapoint type not set")
|
|
65
74
|
return
|
|
66
75
|
|
|
67
|
-
self.send_telegram(
|
|
76
|
+
self.conbus_protocol.send_telegram(
|
|
68
77
|
telegram_type=TelegramType.SYSTEM,
|
|
69
78
|
serial_number=self.serial_number,
|
|
70
79
|
system_function=SystemFunction.READ_DATAPOINT,
|
|
@@ -128,9 +137,14 @@ class ConbusDatapointService(ConbusProtocol):
|
|
|
128
137
|
self.service_response.datapoint_type = self.datapoint_type
|
|
129
138
|
self.service_response.datapoint_telegram = datapoint_telegram
|
|
130
139
|
self.service_response.data_value = datapoint_telegram.data_value
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
self.
|
|
140
|
+
|
|
141
|
+
# Emit finish signal
|
|
142
|
+
self.on_finish.emit(self.service_response)
|
|
143
|
+
self.stop_reactor()
|
|
144
|
+
|
|
145
|
+
def timeout(self) -> None:
|
|
146
|
+
"""Handle timeout event."""
|
|
147
|
+
self.failed("Timeout")
|
|
134
148
|
|
|
135
149
|
def failed(self, message: str) -> None:
|
|
136
150
|
"""Handle failed connection event.
|
|
@@ -143,14 +157,14 @@ class ConbusDatapointService(ConbusProtocol):
|
|
|
143
157
|
self.service_response.timestamp = datetime.now()
|
|
144
158
|
self.service_response.serial_number = self.serial_number
|
|
145
159
|
self.service_response.error = message
|
|
146
|
-
|
|
147
|
-
|
|
160
|
+
|
|
161
|
+
# Emit finish signal
|
|
162
|
+
self.on_finish.emit(self.service_response)
|
|
148
163
|
|
|
149
164
|
def query_datapoint(
|
|
150
165
|
self,
|
|
151
166
|
serial_number: str,
|
|
152
167
|
datapoint_type: DataPointType,
|
|
153
|
-
finish_callback: Callable[[ConbusDatapointResponse], None],
|
|
154
168
|
timeout_seconds: Optional[float] = None,
|
|
155
169
|
) -> None:
|
|
156
170
|
"""Query a specific datapoint from a module.
|
|
@@ -158,13 +172,47 @@ class ConbusDatapointService(ConbusProtocol):
|
|
|
158
172
|
Args:
|
|
159
173
|
serial_number: 10-digit module serial number.
|
|
160
174
|
datapoint_type: Type of datapoint to query.
|
|
161
|
-
finish_callback: Callback function to call when the datapoint is received.
|
|
162
175
|
timeout_seconds: Timeout in seconds.
|
|
163
176
|
"""
|
|
164
177
|
self.logger.info("Starting query_datapoint")
|
|
165
178
|
if timeout_seconds:
|
|
166
|
-
self.timeout_seconds = timeout_seconds
|
|
167
|
-
self.datapoint_finished_callback = finish_callback
|
|
179
|
+
self.conbus_protocol.timeout_seconds = timeout_seconds
|
|
168
180
|
self.serial_number = serial_number
|
|
169
181
|
self.datapoint_type = datapoint_type
|
|
170
|
-
|
|
182
|
+
|
|
183
|
+
def set_timeout(self, timeout_seconds: float) -> None:
|
|
184
|
+
"""Set operation timeout.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
timeout_seconds: Timeout in seconds.
|
|
188
|
+
"""
|
|
189
|
+
self.conbus_protocol.timeout_seconds = timeout_seconds
|
|
190
|
+
|
|
191
|
+
def start_reactor(self) -> None:
|
|
192
|
+
"""Start the reactor."""
|
|
193
|
+
self.conbus_protocol.start_reactor()
|
|
194
|
+
|
|
195
|
+
def stop_reactor(self) -> None:
|
|
196
|
+
"""Stop the reactor."""
|
|
197
|
+
self.conbus_protocol.stop_reactor()
|
|
198
|
+
|
|
199
|
+
def __enter__(self) -> "ConbusDatapointService":
|
|
200
|
+
"""Enter context manager - reset state for singleton reuse.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
Self for context manager protocol.
|
|
204
|
+
"""
|
|
205
|
+
self.datapoint_response = ConbusDatapointResponse(success=False)
|
|
206
|
+
return self
|
|
207
|
+
|
|
208
|
+
def __exit__(
|
|
209
|
+
self, _exc_type: Optional[type], _exc_val: Optional[Exception], _exc_tb: Any
|
|
210
|
+
) -> None:
|
|
211
|
+
"""Exit context manager and disconnect signals."""
|
|
212
|
+
self.conbus_protocol.on_connection_made.disconnect(self.connection_made)
|
|
213
|
+
self.conbus_protocol.on_telegram_sent.disconnect(self.telegram_sent)
|
|
214
|
+
self.conbus_protocol.on_telegram_received.disconnect(self.telegram_received)
|
|
215
|
+
self.conbus_protocol.on_timeout.disconnect(self.timeout)
|
|
216
|
+
self.conbus_protocol.on_failed.disconnect(self.failed)
|
|
217
|
+
self.on_finish.disconnect()
|
|
218
|
+
self.stop_reactor()
|
|
@@ -6,18 +6,17 @@ and processing ACK/NAK responses.
|
|
|
6
6
|
|
|
7
7
|
import logging
|
|
8
8
|
from datetime import datetime
|
|
9
|
-
from typing import
|
|
9
|
+
from typing import Any, Optional
|
|
10
10
|
|
|
11
|
-
from
|
|
11
|
+
from psygnal import Signal
|
|
12
12
|
|
|
13
|
-
from xp.models import ConbusClientConfig
|
|
14
13
|
from xp.models.conbus.conbus_output import ConbusOutputResponse
|
|
15
14
|
from xp.models.protocol.conbus_protocol import TelegramReceivedEvent
|
|
16
15
|
from xp.models.telegram.action_type import ActionType
|
|
17
16
|
from xp.models.telegram.output_telegram import OutputTelegram
|
|
18
17
|
from xp.models.telegram.system_function import SystemFunction
|
|
19
18
|
from xp.models.telegram.telegram_type import TelegramType
|
|
20
|
-
from xp.services.protocol import
|
|
19
|
+
from xp.services.protocol.conbus_event_protocol import ConbusEventProtocol
|
|
21
20
|
from xp.services.telegram.telegram_output_service import (
|
|
22
21
|
TelegramOutputService,
|
|
23
22
|
XPOutputError,
|
|
@@ -30,33 +29,47 @@ class ConbusOutputError(Exception):
|
|
|
30
29
|
pass
|
|
31
30
|
|
|
32
31
|
|
|
33
|
-
class ConbusOutputService
|
|
32
|
+
class ConbusOutputService:
|
|
34
33
|
"""
|
|
35
34
|
Service for sending action telegrams to Conbus module outputs.
|
|
36
35
|
|
|
37
36
|
Manages action telegram transmission (ON/OFF) and processes
|
|
38
37
|
ACK/NAK responses from modules.
|
|
38
|
+
|
|
39
|
+
Attributes:
|
|
40
|
+
conbus_protocol: Protocol instance for Conbus communication.
|
|
41
|
+
on_finish: Signal emitted when operation finishes (with result).
|
|
39
42
|
"""
|
|
40
43
|
|
|
44
|
+
conbus_protocol: ConbusEventProtocol
|
|
45
|
+
on_finish: Signal = Signal(ConbusOutputResponse)
|
|
46
|
+
|
|
41
47
|
def __init__(
|
|
42
48
|
self,
|
|
49
|
+
conbus_protocol: ConbusEventProtocol,
|
|
43
50
|
telegram_output_service: TelegramOutputService,
|
|
44
|
-
cli_config: ConbusClientConfig,
|
|
45
|
-
reactor: PosixReactorBase,
|
|
46
51
|
):
|
|
47
52
|
"""Initialize the Conbus output service.
|
|
48
53
|
|
|
49
54
|
Args:
|
|
55
|
+
conbus_protocol: ConbusEventProtocol for communication.
|
|
50
56
|
telegram_output_service: TelegramOutputService for telegram generation/parsing.
|
|
51
|
-
cli_config: Conbus client configuration.
|
|
52
|
-
reactor: Twisted reactor for async operations.
|
|
53
57
|
"""
|
|
54
|
-
|
|
58
|
+
self.conbus_protocol = conbus_protocol
|
|
55
59
|
self.telegram_output_service = telegram_output_service
|
|
60
|
+
|
|
61
|
+
# Connect protocol signals
|
|
62
|
+
self.conbus_protocol.on_connection_made.connect(self.connection_made)
|
|
63
|
+
self.conbus_protocol.on_telegram_sent.connect(self.telegram_sent)
|
|
64
|
+
self.conbus_protocol.on_telegram_received.connect(self.telegram_received)
|
|
65
|
+
self.conbus_protocol.on_timeout.connect(self.timeout)
|
|
66
|
+
self.conbus_protocol.on_failed.connect(self.failed)
|
|
67
|
+
|
|
68
|
+
# Initialize state
|
|
56
69
|
self.serial_number: str = ""
|
|
57
70
|
self.output_number: int = 0
|
|
58
71
|
self.action_type: ActionType = ActionType.ON_RELEASE
|
|
59
|
-
self.
|
|
72
|
+
self.output_state: str = ""
|
|
60
73
|
self.service_response: ConbusOutputResponse = ConbusOutputResponse(
|
|
61
74
|
success=False,
|
|
62
75
|
serial_number=self.serial_number,
|
|
@@ -68,7 +81,7 @@ class ConbusOutputService(ConbusProtocol):
|
|
|
68
81
|
# Set up logging
|
|
69
82
|
self.logger = logging.getLogger(__name__)
|
|
70
83
|
|
|
71
|
-
def
|
|
84
|
+
def connection_made(self) -> None:
|
|
72
85
|
"""Handle connection established event."""
|
|
73
86
|
self.logger.debug(
|
|
74
87
|
f"Connection established, sending action {self.action_type} to output {self.output_number}."
|
|
@@ -84,7 +97,7 @@ class ConbusOutputService(ConbusProtocol):
|
|
|
84
97
|
|
|
85
98
|
# Send F27D{output:02d}{action} telegram
|
|
86
99
|
# F27 = ACTION, D = data with output number and action type
|
|
87
|
-
self.send_telegram(
|
|
100
|
+
self.conbus_protocol.send_telegram(
|
|
88
101
|
telegram_type=TelegramType.SYSTEM,
|
|
89
102
|
serial_number=self.serial_number,
|
|
90
103
|
system_function=SystemFunction.ACTION,
|
|
@@ -148,8 +161,12 @@ class ConbusOutputService(ConbusProtocol):
|
|
|
148
161
|
self.service_response.output_number = self.output_number
|
|
149
162
|
self.service_response.action_type = self.action_type
|
|
150
163
|
self.service_response.output_telegram = output_telegram
|
|
151
|
-
|
|
152
|
-
|
|
164
|
+
self.on_finish.emit(self.service_response)
|
|
165
|
+
|
|
166
|
+
def timeout(self) -> None:
|
|
167
|
+
"""Handle timeout event."""
|
|
168
|
+
self.logger.debug("Timeout occurred")
|
|
169
|
+
self.failed("Timeout")
|
|
153
170
|
|
|
154
171
|
def failed(self, message: str) -> None:
|
|
155
172
|
"""Handle failed connection event.
|
|
@@ -164,15 +181,13 @@ class ConbusOutputService(ConbusProtocol):
|
|
|
164
181
|
self.service_response.output_number = self.output_number
|
|
165
182
|
self.service_response.action_type = self.action_type
|
|
166
183
|
self.service_response.error = message
|
|
167
|
-
|
|
168
|
-
self.finish_callback(self.service_response)
|
|
184
|
+
self.on_finish.emit(self.service_response)
|
|
169
185
|
|
|
170
186
|
def send_action(
|
|
171
187
|
self,
|
|
172
188
|
serial_number: str,
|
|
173
189
|
output_number: int,
|
|
174
190
|
action_type: ActionType,
|
|
175
|
-
finish_callback: Callable[[ConbusOutputResponse], None],
|
|
176
191
|
timeout_seconds: Optional[float] = None,
|
|
177
192
|
) -> None:
|
|
178
193
|
"""Send an action telegram to a module output.
|
|
@@ -181,14 +196,59 @@ class ConbusOutputService(ConbusProtocol):
|
|
|
181
196
|
serial_number: 10-digit module serial number.
|
|
182
197
|
output_number: Output number (0-99).
|
|
183
198
|
action_type: Action to perform (ON_RELEASE, OFF_PRESS, etc.).
|
|
184
|
-
finish_callback: Callback function to call when operation completes.
|
|
185
199
|
timeout_seconds: Optional timeout in seconds.
|
|
186
200
|
"""
|
|
187
201
|
self.logger.info("Starting send_action")
|
|
188
202
|
if timeout_seconds:
|
|
189
|
-
self.timeout_seconds = timeout_seconds
|
|
203
|
+
self.conbus_protocol.timeout_seconds = timeout_seconds
|
|
190
204
|
self.serial_number = serial_number
|
|
191
205
|
self.output_number = output_number
|
|
192
206
|
self.action_type = action_type
|
|
193
|
-
|
|
194
|
-
|
|
207
|
+
|
|
208
|
+
def set_timeout(self, timeout_seconds: float) -> None:
|
|
209
|
+
"""Set operation timeout.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
timeout_seconds: Timeout in seconds.
|
|
213
|
+
"""
|
|
214
|
+
self.conbus_protocol.timeout_seconds = timeout_seconds
|
|
215
|
+
|
|
216
|
+
def start_reactor(self) -> None:
|
|
217
|
+
"""Start the reactor."""
|
|
218
|
+
self.conbus_protocol.start_reactor()
|
|
219
|
+
|
|
220
|
+
def stop_reactor(self) -> None:
|
|
221
|
+
"""Stop the reactor."""
|
|
222
|
+
self.conbus_protocol.stop_reactor()
|
|
223
|
+
|
|
224
|
+
def __enter__(self) -> "ConbusOutputService":
|
|
225
|
+
"""Enter context manager - reset state for singleton reuse.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Self for context manager protocol.
|
|
229
|
+
"""
|
|
230
|
+
# Reset state for singleton reuse
|
|
231
|
+
self.service_response = ConbusOutputResponse(
|
|
232
|
+
success=False,
|
|
233
|
+
serial_number="",
|
|
234
|
+
output_number=0,
|
|
235
|
+
action_type=ActionType.ON_RELEASE,
|
|
236
|
+
timestamp=datetime.now(),
|
|
237
|
+
)
|
|
238
|
+
self.output_state = ""
|
|
239
|
+
return self
|
|
240
|
+
|
|
241
|
+
def __exit__(
|
|
242
|
+
self, _exc_type: Optional[type], _exc_val: Optional[Exception], _exc_tb: Any
|
|
243
|
+
) -> None:
|
|
244
|
+
"""Exit context manager and disconnect signals."""
|
|
245
|
+
# Disconnect protocol signals
|
|
246
|
+
self.conbus_protocol.on_connection_made.disconnect(self.connection_made)
|
|
247
|
+
self.conbus_protocol.on_telegram_sent.disconnect(self.telegram_sent)
|
|
248
|
+
self.conbus_protocol.on_telegram_received.disconnect(self.telegram_received)
|
|
249
|
+
self.conbus_protocol.on_timeout.disconnect(self.timeout)
|
|
250
|
+
self.conbus_protocol.on_failed.disconnect(self.failed)
|
|
251
|
+
# Disconnect service signals
|
|
252
|
+
self.on_finish.disconnect()
|
|
253
|
+
# Stop reactor
|
|
254
|
+
self.stop_reactor()
|
|
@@ -5,49 +5,61 @@ This service handles sending raw telegram strings without prior validation.
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
from datetime import datetime
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import Any, Optional
|
|
9
9
|
|
|
10
|
-
from
|
|
10
|
+
from psygnal import Signal
|
|
11
11
|
|
|
12
|
-
from xp.models import ConbusClientConfig
|
|
13
12
|
from xp.models.conbus.conbus_raw import ConbusRawResponse
|
|
14
13
|
from xp.models.protocol.conbus_protocol import TelegramReceivedEvent
|
|
15
|
-
from xp.services.protocol import
|
|
14
|
+
from xp.services.protocol.conbus_event_protocol import ConbusEventProtocol
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
class ConbusRawService
|
|
17
|
+
class ConbusRawService:
|
|
19
18
|
"""
|
|
20
19
|
Service for sending raw telegram sequences to Conbus modules.
|
|
21
20
|
|
|
22
|
-
Uses
|
|
21
|
+
Uses ConbusEventProtocol to provide raw telegram functionality
|
|
23
22
|
for sending arbitrary telegram strings without validation.
|
|
23
|
+
|
|
24
|
+
Attributes:
|
|
25
|
+
conbus_protocol: Protocol instance for Conbus communication.
|
|
26
|
+
on_progress: Signal emitted when telegram is received (with frame).
|
|
27
|
+
on_finish: Signal emitted when operation finishes (with result).
|
|
24
28
|
"""
|
|
25
29
|
|
|
30
|
+
conbus_protocol: ConbusEventProtocol
|
|
31
|
+
on_progress: Signal = Signal(str)
|
|
32
|
+
on_finish: Signal = Signal(ConbusRawResponse)
|
|
33
|
+
|
|
26
34
|
def __init__(
|
|
27
35
|
self,
|
|
28
|
-
|
|
29
|
-
reactor: PosixReactorBase,
|
|
36
|
+
conbus_protocol: ConbusEventProtocol,
|
|
30
37
|
) -> None:
|
|
31
38
|
"""Initialize the Conbus raw service.
|
|
32
39
|
|
|
33
40
|
Args:
|
|
34
|
-
|
|
35
|
-
reactor: Twisted reactor for event loop.
|
|
41
|
+
conbus_protocol: ConbusEventProtocol instance.
|
|
36
42
|
"""
|
|
37
|
-
|
|
43
|
+
self.conbus_protocol = conbus_protocol
|
|
44
|
+
|
|
45
|
+
# Connect protocol signals
|
|
46
|
+
self.conbus_protocol.on_connection_made.connect(self.connection_made)
|
|
47
|
+
self.conbus_protocol.on_telegram_sent.connect(self.telegram_sent)
|
|
48
|
+
self.conbus_protocol.on_telegram_received.connect(self.telegram_received)
|
|
49
|
+
self.conbus_protocol.on_timeout.connect(self.timeout)
|
|
50
|
+
self.conbus_protocol.on_failed.connect(self.failed)
|
|
51
|
+
|
|
38
52
|
self.raw_input: str = ""
|
|
39
|
-
self.progress_callback: Optional[Callable[[str], None]] = None
|
|
40
|
-
self.finish_callback: Optional[Callable[[ConbusRawResponse], None]] = None
|
|
41
53
|
self.service_response: ConbusRawResponse = ConbusRawResponse(
|
|
42
54
|
success=False,
|
|
43
55
|
)
|
|
44
56
|
# Set up logging
|
|
45
57
|
self.logger = logging.getLogger(__name__)
|
|
46
58
|
|
|
47
|
-
def
|
|
59
|
+
def connection_made(self) -> None:
|
|
48
60
|
"""Handle connection established event."""
|
|
49
61
|
self.logger.debug(f"Connection established, sending {self.raw_input}")
|
|
50
|
-
self.
|
|
62
|
+
self.conbus_protocol.send_raw_telegram(self.raw_input)
|
|
51
63
|
|
|
52
64
|
def telegram_sent(self, telegram_sent: str) -> None:
|
|
53
65
|
"""Handle telegram sent event.
|
|
@@ -71,19 +83,13 @@ class ConbusRawService(ConbusProtocol):
|
|
|
71
83
|
self.service_response.received_telegrams = []
|
|
72
84
|
self.service_response.received_telegrams.append(telegram_received.frame)
|
|
73
85
|
|
|
74
|
-
|
|
75
|
-
self.progress_callback(telegram_received.frame)
|
|
76
|
-
|
|
77
|
-
def timeout(self) -> bool:
|
|
78
|
-
"""Handle timeout event.
|
|
86
|
+
self.on_progress.emit(telegram_received.frame)
|
|
79
87
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
self.logger.debug(f"Timeout: {
|
|
84
|
-
|
|
85
|
-
self.finish_callback(self.service_response)
|
|
86
|
-
return False
|
|
88
|
+
def timeout(self) -> None:
|
|
89
|
+
"""Handle timeout event."""
|
|
90
|
+
timeout_seconds = self.conbus_protocol.timeout_seconds
|
|
91
|
+
self.logger.debug(f"Timeout: {timeout_seconds}s")
|
|
92
|
+
self.on_finish.emit(self.service_response)
|
|
87
93
|
|
|
88
94
|
def failed(self, message: str) -> None:
|
|
89
95
|
"""Handle failed connection event.
|
|
@@ -95,28 +101,63 @@ class ConbusRawService(ConbusProtocol):
|
|
|
95
101
|
self.service_response.success = False
|
|
96
102
|
self.service_response.timestamp = datetime.now()
|
|
97
103
|
self.service_response.error = message
|
|
98
|
-
|
|
99
|
-
self.finish_callback(self.service_response)
|
|
104
|
+
self.on_finish.emit(self.service_response)
|
|
100
105
|
|
|
101
106
|
def send_raw_telegram(
|
|
102
107
|
self,
|
|
103
108
|
raw_input: str,
|
|
104
|
-
progress_callback: Callable[[str], None],
|
|
105
|
-
finish_callback: Callable[[ConbusRawResponse], None],
|
|
106
109
|
timeout_seconds: Optional[float] = None,
|
|
107
110
|
) -> None:
|
|
108
111
|
"""Send a raw telegram string to the Conbus server.
|
|
109
112
|
|
|
110
113
|
Args:
|
|
111
114
|
raw_input: Raw telegram string to send.
|
|
112
|
-
progress_callback: Callback to handle progress updates.
|
|
113
|
-
finish_callback: Callback function to call when the operation is complete.
|
|
114
115
|
timeout_seconds: Timeout in seconds.
|
|
115
116
|
"""
|
|
116
117
|
self.logger.info("Starting send_raw_telegram")
|
|
117
118
|
if timeout_seconds:
|
|
118
|
-
self.timeout_seconds = timeout_seconds
|
|
119
|
-
self.progress_callback = progress_callback
|
|
120
|
-
self.finish_callback = finish_callback
|
|
119
|
+
self.conbus_protocol.timeout_seconds = timeout_seconds
|
|
121
120
|
self.raw_input = raw_input
|
|
122
|
-
|
|
121
|
+
|
|
122
|
+
def set_timeout(self, timeout_seconds: float) -> None:
|
|
123
|
+
"""Set operation timeout.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
timeout_seconds: Timeout in seconds.
|
|
127
|
+
"""
|
|
128
|
+
self.conbus_protocol.timeout_seconds = timeout_seconds
|
|
129
|
+
|
|
130
|
+
def start_reactor(self) -> None:
|
|
131
|
+
"""Start the reactor."""
|
|
132
|
+
self.conbus_protocol.start_reactor()
|
|
133
|
+
|
|
134
|
+
def stop_reactor(self) -> None:
|
|
135
|
+
"""Stop the reactor."""
|
|
136
|
+
self.conbus_protocol.stop_reactor()
|
|
137
|
+
|
|
138
|
+
def __enter__(self) -> "ConbusRawService":
|
|
139
|
+
"""Enter context manager.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
Self for context manager protocol.
|
|
143
|
+
"""
|
|
144
|
+
# Reset state for singleton reuse
|
|
145
|
+
self.service_response = ConbusRawResponse(success=False)
|
|
146
|
+
self.raw_input = ""
|
|
147
|
+
return self
|
|
148
|
+
|
|
149
|
+
def __exit__(
|
|
150
|
+
self, _exc_type: Optional[type], _exc_val: Optional[Exception], _exc_tb: Any
|
|
151
|
+
) -> None:
|
|
152
|
+
"""Exit context manager and disconnect signals."""
|
|
153
|
+
# Disconnect protocol signals
|
|
154
|
+
self.conbus_protocol.on_connection_made.disconnect(self.connection_made)
|
|
155
|
+
self.conbus_protocol.on_telegram_sent.disconnect(self.telegram_sent)
|
|
156
|
+
self.conbus_protocol.on_telegram_received.disconnect(self.telegram_received)
|
|
157
|
+
self.conbus_protocol.on_timeout.disconnect(self.timeout)
|
|
158
|
+
self.conbus_protocol.on_failed.disconnect(self.failed)
|
|
159
|
+
# Disconnect service signals
|
|
160
|
+
self.on_progress.disconnect()
|
|
161
|
+
self.on_finish.disconnect()
|
|
162
|
+
# Stop reactor
|
|
163
|
+
self.stop_reactor()
|