syndesi 0.4.0__py3-none-any.whl → 0.4.2__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.
- syndesi/adapters/adapter.py +91 -158
- syndesi/adapters/auto.py +1 -1
- syndesi/adapters/backend/adapter_backend.py +54 -37
- syndesi/adapters/backend/adapter_session.py +26 -27
- syndesi/adapters/backend/backend_status.py +0 -0
- syndesi/adapters/backend/backend_tools.py +1 -1
- syndesi/adapters/backend/descriptors.py +3 -2
- syndesi/adapters/backend/ip_backend.py +1 -0
- syndesi/adapters/backend/serialport_backend.py +9 -10
- syndesi/adapters/backend/stop_condition_backend.py +47 -26
- syndesi/adapters/backend/visa_backend.py +7 -7
- syndesi/adapters/ip.py +6 -10
- syndesi/adapters/stop_condition.py +10 -83
- syndesi/adapters/timeout.py +3 -30
- syndesi/adapters/visa.py +2 -2
- syndesi/cli/backend_status.py +7 -9
- syndesi/cli/console.py +1 -54
- syndesi/cli/shell.py +1 -14
- syndesi/cli/shell_tools.py +0 -5
- syndesi/protocols/delimited.py +17 -37
- syndesi/protocols/modbus.py +17 -14
- syndesi/protocols/raw.py +20 -16
- syndesi/protocols/scpi.py +18 -15
- syndesi/scripts/syndesi.py +1 -3
- syndesi/tools/backend_api.py +5 -38
- syndesi/tools/backend_logger.py +0 -1
- syndesi/tools/errors.py +4 -5
- syndesi/tools/log.py +0 -88
- syndesi/tools/types.py +0 -44
- syndesi/version.py +1 -1
- syndesi-0.4.2.dist-info/METADATA +96 -0
- syndesi-0.4.2.dist-info/RECORD +60 -0
- syndesi-0.4.0.dist-info/METADATA +0 -123
- syndesi-0.4.0.dist-info/RECORD +0 -59
- {syndesi-0.4.0.dist-info → syndesi-0.4.2.dist-info}/WHEEL +0 -0
- {syndesi-0.4.0.dist-info → syndesi-0.4.2.dist-info}/entry_points.txt +0 -0
- {syndesi-0.4.0.dist-info → syndesi-0.4.2.dist-info}/licenses/LICENSE +0 -0
- {syndesi-0.4.0.dist-info → syndesi-0.4.2.dist-info}/top_level.txt +0 -0
|
@@ -11,9 +11,11 @@ import threading
|
|
|
11
11
|
import time
|
|
12
12
|
from enum import Enum
|
|
13
13
|
from multiprocessing.connection import Pipe, wait
|
|
14
|
-
from typing import Any
|
|
14
|
+
from typing import Any
|
|
15
15
|
|
|
16
|
-
from syndesi.adapters.backend.stop_condition_backend import
|
|
16
|
+
from syndesi.adapters.backend.stop_condition_backend import (
|
|
17
|
+
stop_condition_to_backend,
|
|
18
|
+
)
|
|
17
19
|
from syndesi.tools.errors import make_error_description
|
|
18
20
|
from syndesi.tools.types import NumberLike
|
|
19
21
|
|
|
@@ -21,9 +23,6 @@ from ...tools.backend_api import Action, frontend_send
|
|
|
21
23
|
from ...tools.log_settings import LoggerAlias
|
|
22
24
|
from .adapter_backend import (
|
|
23
25
|
AdapterBackend,
|
|
24
|
-
AdapterDisconnected,
|
|
25
|
-
#AdapterReadInit,
|
|
26
|
-
AdapterReadPayload,
|
|
27
26
|
Selectable,
|
|
28
27
|
nmin,
|
|
29
28
|
)
|
|
@@ -37,15 +36,16 @@ from .descriptors import (
|
|
|
37
36
|
)
|
|
38
37
|
from .ip_backend import IPBackend
|
|
39
38
|
from .serialport_backend import SerialPortBackend
|
|
40
|
-
|
|
39
|
+
|
|
40
|
+
# from .stop_condition_backend import stop_condition_from_list
|
|
41
41
|
from .visa_backend import VisaBackend
|
|
42
|
-
from pathlib import Path
|
|
43
42
|
|
|
44
43
|
|
|
45
44
|
class TimeoutEvent(Enum):
|
|
46
45
|
MONITORING = 0
|
|
47
46
|
ADAPTER = 1
|
|
48
|
-
#CONNECTIONS = 2
|
|
47
|
+
# CONNECTIONS = 2
|
|
48
|
+
|
|
49
49
|
|
|
50
50
|
def get_adapter(descriptor: Descriptor) -> AdapterBackend:
|
|
51
51
|
# The adapter doesn't exist, create it
|
|
@@ -99,12 +99,10 @@ class AdapterSession(threading.Thread):
|
|
|
99
99
|
self._shutdown_counter_top = None
|
|
100
100
|
self._shutdown_counter = None
|
|
101
101
|
|
|
102
|
-
#self._timeout_events: list[tuple[TimeoutEvent, float]] = []
|
|
102
|
+
# self._timeout_events: list[tuple[TimeoutEvent, float]] = []
|
|
103
103
|
|
|
104
104
|
self._read_init_id = 0
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
106
|
def add_connection(self, conn: NamedConnection) -> None:
|
|
109
107
|
with self._connections_lock:
|
|
110
108
|
self.connections.append(conn)
|
|
@@ -142,13 +140,12 @@ class AdapterSession(threading.Thread):
|
|
|
142
140
|
except Exception as e:
|
|
143
141
|
error_message = make_error_description(e)
|
|
144
142
|
|
|
145
|
-
|
|
146
143
|
self._logger.critical(
|
|
147
144
|
f"Error in {self._adapter.descriptor} session loop : {error_message}"
|
|
148
145
|
)
|
|
149
146
|
try:
|
|
150
147
|
error_message = make_error_description(e)
|
|
151
|
-
|
|
148
|
+
|
|
152
149
|
for conn in self.connections:
|
|
153
150
|
frontend_send(conn.conn, Action.ERROR_GENERIC, error_message)
|
|
154
151
|
except Exception:
|
|
@@ -167,15 +164,13 @@ class AdapterSession(threading.Thread):
|
|
|
167
164
|
# The wait has a timeout set by the adapter, it corresponds to the current continuation/total timeout
|
|
168
165
|
|
|
169
166
|
# Create a list of what is awaited
|
|
170
|
-
wait_list: list[Selectable] = [
|
|
171
|
-
conn.conn for conn in self.connections
|
|
172
|
-
]
|
|
167
|
+
wait_list: list[Selectable] = [conn.conn for conn in self.connections]
|
|
173
168
|
adapter_fd = self._adapter.selectable()
|
|
174
169
|
if adapter_fd is not None and adapter_fd.fileno() >= 0:
|
|
175
170
|
wait_list.append(adapter_fd)
|
|
176
171
|
|
|
177
172
|
wait_list.append(self._new_connection_r)
|
|
178
|
-
|
|
173
|
+
|
|
179
174
|
timeout_timestamp = None
|
|
180
175
|
event = None
|
|
181
176
|
|
|
@@ -183,8 +178,11 @@ class AdapterSession(threading.Thread):
|
|
|
183
178
|
if adapter_timestamp is not None:
|
|
184
179
|
timeout_timestamp = nmin(timeout_timestamp, adapter_timestamp)
|
|
185
180
|
event = TimeoutEvent.ADAPTER
|
|
186
|
-
|
|
187
|
-
if
|
|
181
|
+
|
|
182
|
+
if (
|
|
183
|
+
timeout_timestamp is None
|
|
184
|
+
or self._next_monitoring_timestamp < timeout_timestamp
|
|
185
|
+
):
|
|
188
186
|
timeout_timestamp = self._next_monitoring_timestamp
|
|
189
187
|
event = TimeoutEvent.MONITORING
|
|
190
188
|
|
|
@@ -253,7 +251,6 @@ class AdapterSession(threading.Thread):
|
|
|
253
251
|
return
|
|
254
252
|
try:
|
|
255
253
|
request = conn.conn.recv()
|
|
256
|
-
request_timestamp = time.time()
|
|
257
254
|
except (EOFError, ConnectionResetError) as e:
|
|
258
255
|
# Probably a ping or an error
|
|
259
256
|
self._logger.warning(
|
|
@@ -280,7 +277,7 @@ class AdapterSession(threading.Thread):
|
|
|
280
277
|
response_action = Action.OPEN
|
|
281
278
|
else:
|
|
282
279
|
response_action = Action.ERROR_FAILED_TO_OPEN
|
|
283
|
-
extra_arguments = ("",)
|
|
280
|
+
extra_arguments = ("",)
|
|
284
281
|
case Action.WRITE:
|
|
285
282
|
data = request[1]
|
|
286
283
|
if self._adapter.is_opened():
|
|
@@ -301,12 +298,12 @@ class AdapterSession(threading.Thread):
|
|
|
301
298
|
self._logger.error("Could not write, adapter is closed")
|
|
302
299
|
case Action.PING:
|
|
303
300
|
response_action, extra_arguments = Action.PING, ()
|
|
304
|
-
case Action.
|
|
305
|
-
self._adapter.set_stop_conditions(
|
|
306
|
-
stop_condition_to_backend(sc) for sc in request[1]
|
|
307
|
-
|
|
301
|
+
case Action.SET_STOP_CONDITIONs:
|
|
302
|
+
self._adapter.set_stop_conditions(
|
|
303
|
+
[stop_condition_to_backend(sc) for sc in request[1]]
|
|
304
|
+
)
|
|
308
305
|
response_action, extra_arguments = (
|
|
309
|
-
Action.
|
|
306
|
+
Action.SET_STOP_CONDITIONs,
|
|
310
307
|
(),
|
|
311
308
|
)
|
|
312
309
|
case Action.FLUSHREAD:
|
|
@@ -315,7 +312,9 @@ class AdapterSession(threading.Thread):
|
|
|
315
312
|
case Action.START_READ:
|
|
316
313
|
response_time = float(request[1])
|
|
317
314
|
self._adapter.start_read(response_time, self._read_init_id)
|
|
318
|
-
response_action, extra_arguments = Action.START_READ, (
|
|
315
|
+
response_action, extra_arguments = Action.START_READ, (
|
|
316
|
+
self._read_init_id,
|
|
317
|
+
)
|
|
319
318
|
self._read_init_id += 1
|
|
320
319
|
|
|
321
320
|
# case Action.GET_BACKEND_TIME:
|
|
File without changes
|
|
@@ -69,8 +69,9 @@ class IPDescriptor(Descriptor):
|
|
|
69
69
|
|
|
70
70
|
DETECTION_PATTERN = r"(\d+.\d+.\d+.\d+|[\w\.]+):\d+:(UDP|TCP)"
|
|
71
71
|
address: str
|
|
72
|
+
transport: Transport
|
|
72
73
|
port: int | None = None
|
|
73
|
-
transport: Transport | None = None
|
|
74
|
+
# transport: Transport | None = None
|
|
74
75
|
|
|
75
76
|
@staticmethod
|
|
76
77
|
def from_string(string: str) -> "IPDescriptor":
|
|
@@ -78,7 +79,7 @@ class IPDescriptor(Descriptor):
|
|
|
78
79
|
address = parts[0]
|
|
79
80
|
port = int(parts[1])
|
|
80
81
|
transport = IPDescriptor.Transport(parts[2])
|
|
81
|
-
return IPDescriptor(address,
|
|
82
|
+
return IPDescriptor(address, transport, port)
|
|
82
83
|
|
|
83
84
|
def __str__(self) -> str:
|
|
84
85
|
return f"{self.address}:{self.port}:{self.Transport(self.transport).value}"
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import time
|
|
8
8
|
|
|
9
|
-
import serial
|
|
9
|
+
import serial
|
|
10
10
|
from serial.serialutil import PortNotOpenError
|
|
11
11
|
|
|
12
12
|
from syndesi.tools.backend_api import AdapterBackendStatus, Fragment
|
|
@@ -33,7 +33,6 @@ class SerialPortBackend(AdapterBackend):
|
|
|
33
33
|
|
|
34
34
|
self.open()
|
|
35
35
|
|
|
36
|
-
|
|
37
36
|
def set_baudrate(self, baudrate: int) -> None:
|
|
38
37
|
"""
|
|
39
38
|
Set baudrate
|
|
@@ -83,10 +82,10 @@ class SerialPortBackend(AdapterBackend):
|
|
|
83
82
|
baudrate=self.descriptor.baudrate,
|
|
84
83
|
rtscts=self._rts_cts,
|
|
85
84
|
)
|
|
86
|
-
elif not self._port.isOpen():
|
|
85
|
+
elif not self._port.isOpen(): # type: ignore
|
|
87
86
|
self._port.open()
|
|
88
87
|
|
|
89
|
-
if self._port.isOpen():
|
|
88
|
+
if self._port.isOpen(): # type: ignore
|
|
90
89
|
self._logger.info(f"Adapter {self.descriptor} opened")
|
|
91
90
|
self._status = AdapterBackendStatus.CONNECTED
|
|
92
91
|
return True
|
|
@@ -112,17 +111,17 @@ class SerialPortBackend(AdapterBackend):
|
|
|
112
111
|
return False
|
|
113
112
|
else:
|
|
114
113
|
if self._rts_cts: # Experimental
|
|
115
|
-
self._port.setRTS(True) # type
|
|
114
|
+
self._port.setRTS(True) # type: ignore
|
|
116
115
|
# TODO : Implement auto open
|
|
117
116
|
# if self._status == AdapterBackendStatus.DISCONNECTED:
|
|
118
117
|
# self.open()
|
|
119
|
-
#write_start = time.time()
|
|
118
|
+
# write_start = time.time()
|
|
120
119
|
try:
|
|
121
120
|
self._port.write(data)
|
|
122
121
|
except (OSError, PortNotOpenError):
|
|
123
122
|
return False
|
|
124
|
-
# write_duration = time.time() - write_start
|
|
125
|
-
#self._logger.debug(f"Write [{write_duration * 1e3:.3f}ms]: {repr(data)}")
|
|
123
|
+
# write_duration = time.time() - write_start
|
|
124
|
+
# self._logger.debug(f"Write [{write_duration * 1e3:.3f}ms]: {repr(data)}")
|
|
126
125
|
|
|
127
126
|
return True
|
|
128
127
|
|
|
@@ -144,7 +143,7 @@ class SerialPortBackend(AdapterBackend):
|
|
|
144
143
|
return Fragment(data, t)
|
|
145
144
|
else:
|
|
146
145
|
return Fragment(b"", t)
|
|
147
|
-
#self._logger.debug('Data is none -> b""')
|
|
146
|
+
# self._logger.debug('Data is none -> b""')
|
|
148
147
|
# else:
|
|
149
148
|
# self._logger.debug(f'{data=}')
|
|
150
149
|
|
|
@@ -230,7 +229,7 @@ class SerialPortBackend(AdapterBackend):
|
|
|
230
229
|
|
|
231
230
|
def is_opened(self) -> bool:
|
|
232
231
|
if self._port is not None:
|
|
233
|
-
if self._port.isOpen(): # type
|
|
232
|
+
if self._port.isOpen(): # type: ignore
|
|
234
233
|
return True
|
|
235
234
|
|
|
236
235
|
return False
|
|
@@ -7,12 +7,19 @@
|
|
|
7
7
|
# A stop-condition can also format the data if necessary (remove termination for example)
|
|
8
8
|
|
|
9
9
|
import time
|
|
10
|
-
from abc import abstractmethod
|
|
11
|
-
from enum import Enum
|
|
12
10
|
|
|
13
|
-
from syndesi.adapters.stop_condition import
|
|
11
|
+
from syndesi.adapters.stop_condition import (
|
|
12
|
+
Continuation,
|
|
13
|
+
Length,
|
|
14
|
+
StopCondition,
|
|
15
|
+
StopConditionType,
|
|
16
|
+
Termination,
|
|
17
|
+
Total,
|
|
18
|
+
)
|
|
14
19
|
|
|
15
20
|
from ...tools.backend_api import Fragment
|
|
21
|
+
|
|
22
|
+
|
|
16
23
|
def termination_in_data(termination: bytes, data: bytes) -> tuple[int | None, int]:
|
|
17
24
|
"""
|
|
18
25
|
Return the position (if it exists) and length of the termination (or part of it) inside data
|
|
@@ -29,7 +36,7 @@ def termination_in_data(termination: bytes, data: bytes) -> tuple[int | None, in
|
|
|
29
36
|
L -= 1
|
|
30
37
|
while L > 0:
|
|
31
38
|
if data[-L:] == termination[:L]:
|
|
32
|
-
p = len(data) - L# - 1
|
|
39
|
+
p = len(data) - L # - 1
|
|
33
40
|
break
|
|
34
41
|
L -= 1
|
|
35
42
|
|
|
@@ -44,17 +51,19 @@ class StopConditionBackend:
|
|
|
44
51
|
raise NotImplementedError()
|
|
45
52
|
|
|
46
53
|
def evaluate(
|
|
47
|
-
self, raw_fragment: Fragment
|
|
54
|
+
self, raw_fragment: Fragment
|
|
55
|
+
) -> tuple[bool, Fragment, Fragment, float | None]:
|
|
48
56
|
raise NotImplementedError()
|
|
49
57
|
|
|
50
58
|
def type(self) -> StopConditionType:
|
|
51
59
|
raise NotImplementedError()
|
|
52
|
-
|
|
60
|
+
|
|
53
61
|
def flush_read(self) -> None:
|
|
54
62
|
raise NotImplementedError()
|
|
55
63
|
|
|
64
|
+
|
|
56
65
|
class TerminationBackend(StopConditionBackend):
|
|
57
|
-
def __init__(self, sequence
|
|
66
|
+
def __init__(self, sequence: bytes) -> None:
|
|
58
67
|
super().__init__()
|
|
59
68
|
self._sequence = sequence
|
|
60
69
|
self._sequence_found_length = 0
|
|
@@ -66,10 +75,12 @@ class TerminationBackend(StopConditionBackend):
|
|
|
66
75
|
def flush_read(self) -> None:
|
|
67
76
|
self._sequence_found_length = 0
|
|
68
77
|
|
|
69
|
-
def evaluate(
|
|
78
|
+
def evaluate(
|
|
79
|
+
self, raw_fragment: Fragment
|
|
80
|
+
) -> tuple[bool, Fragment, Fragment, float | None]:
|
|
70
81
|
if raw_fragment.data is None:
|
|
71
82
|
raise RuntimeError("Trying to evaluate an invalid fragment")
|
|
72
|
-
|
|
83
|
+
|
|
73
84
|
position, length = termination_in_data(
|
|
74
85
|
self._sequence[self._sequence_found_length :], raw_fragment.data
|
|
75
86
|
)
|
|
@@ -93,26 +104,29 @@ class TerminationBackend(StopConditionBackend):
|
|
|
93
104
|
deferred = Fragment(b"", None)
|
|
94
105
|
|
|
95
106
|
kept = raw_fragment[:position]
|
|
96
|
-
|
|
107
|
+
|
|
97
108
|
return stop, kept, deferred, None
|
|
98
|
-
|
|
109
|
+
|
|
99
110
|
def type(self) -> StopConditionType:
|
|
100
111
|
return StopConditionType.TERMINATION
|
|
101
112
|
|
|
113
|
+
|
|
102
114
|
class LengthBackend(StopConditionBackend):
|
|
103
|
-
def __init__(self, N
|
|
115
|
+
def __init__(self, N: int) -> None:
|
|
104
116
|
super().__init__()
|
|
105
117
|
self._N = N
|
|
106
118
|
self._counter = 0
|
|
107
|
-
|
|
119
|
+
|
|
108
120
|
def initiate_read(self) -> None:
|
|
109
121
|
# Length
|
|
110
122
|
self._counter = 0
|
|
111
|
-
|
|
123
|
+
|
|
112
124
|
def flush_read(self) -> None:
|
|
113
125
|
self._counter = 0
|
|
114
126
|
|
|
115
|
-
def evaluate(
|
|
127
|
+
def evaluate(
|
|
128
|
+
self, raw_fragment: Fragment
|
|
129
|
+
) -> tuple[bool, Fragment, Fragment, float | None]:
|
|
116
130
|
remaining_bytes = self._N - self._counter
|
|
117
131
|
kept_fragment = raw_fragment[:remaining_bytes]
|
|
118
132
|
deferred_fragment = raw_fragment[remaining_bytes:]
|
|
@@ -120,23 +134,26 @@ class LengthBackend(StopConditionBackend):
|
|
|
120
134
|
remaining_bytes = self._N - self._counter
|
|
121
135
|
# TODO : remaining_bytes <= 0 ? Alongside above TODO maybe
|
|
122
136
|
return remaining_bytes == 0, kept_fragment, deferred_fragment, None
|
|
123
|
-
|
|
137
|
+
|
|
124
138
|
def type(self) -> StopConditionType:
|
|
125
139
|
return StopConditionType.LENGTH
|
|
126
140
|
|
|
141
|
+
|
|
127
142
|
class ContinuationBackend(StopConditionBackend):
|
|
128
|
-
def __init__(self, time
|
|
143
|
+
def __init__(self, time: float) -> None:
|
|
129
144
|
super().__init__()
|
|
130
145
|
self._continuation = time
|
|
131
146
|
self._last_fragment: float | None = None
|
|
132
|
-
|
|
147
|
+
|
|
133
148
|
def initiate_read(self) -> None:
|
|
134
149
|
self._last_fragment = time.time()
|
|
135
150
|
|
|
136
151
|
def flush_read(self) -> None:
|
|
137
152
|
self._last_fragment = None
|
|
138
153
|
|
|
139
|
-
def evaluate(
|
|
154
|
+
def evaluate(
|
|
155
|
+
self, raw_fragment: Fragment
|
|
156
|
+
) -> tuple[bool, Fragment, Fragment, float | None]:
|
|
140
157
|
deferred = Fragment(b"", None)
|
|
141
158
|
kept = raw_fragment
|
|
142
159
|
|
|
@@ -152,15 +169,16 @@ class ContinuationBackend(StopConditionBackend):
|
|
|
152
169
|
next_event_timeout = None
|
|
153
170
|
|
|
154
171
|
return stop, kept, deferred, next_event_timeout
|
|
155
|
-
|
|
172
|
+
|
|
156
173
|
def type(self) -> StopConditionType:
|
|
157
174
|
return StopConditionType.TIMEOUT
|
|
158
175
|
|
|
176
|
+
|
|
159
177
|
class TotalBackend(StopConditionBackend):
|
|
160
|
-
def __init__(self, time
|
|
178
|
+
def __init__(self, time: float) -> None:
|
|
161
179
|
super().__init__()
|
|
162
180
|
self._total = time
|
|
163
|
-
self._start_time
|
|
181
|
+
self._start_time: float | None = None
|
|
164
182
|
|
|
165
183
|
def initiate_read(self) -> None:
|
|
166
184
|
self._start_time = time.time()
|
|
@@ -168,7 +186,9 @@ class TotalBackend(StopConditionBackend):
|
|
|
168
186
|
def flush_read(self) -> None:
|
|
169
187
|
self._start_time = None
|
|
170
188
|
|
|
171
|
-
def evaluate(
|
|
189
|
+
def evaluate(
|
|
190
|
+
self, raw_fragment: Fragment
|
|
191
|
+
) -> tuple[bool, Fragment, Fragment, float | None]:
|
|
172
192
|
kept = raw_fragment
|
|
173
193
|
deferred = Fragment(b"", None)
|
|
174
194
|
|
|
@@ -181,11 +201,12 @@ class TotalBackend(StopConditionBackend):
|
|
|
181
201
|
stop = total_timestamp <= raw_fragment.timestamp
|
|
182
202
|
|
|
183
203
|
return stop, kept, deferred, total_timestamp
|
|
184
|
-
|
|
204
|
+
|
|
185
205
|
def type(self) -> StopConditionType:
|
|
186
206
|
return StopConditionType.TIMEOUT
|
|
187
207
|
|
|
188
|
-
|
|
208
|
+
|
|
209
|
+
def stop_condition_to_backend(stop_condition: StopCondition) -> StopConditionBackend:
|
|
189
210
|
if isinstance(stop_condition, Termination):
|
|
190
211
|
return TerminationBackend(stop_condition.sequence)
|
|
191
212
|
elif isinstance(stop_condition, Length):
|
|
@@ -195,4 +216,4 @@ def stop_condition_to_backend(stop_condition : StopCondition) -> StopConditionBa
|
|
|
195
216
|
elif isinstance(stop_condition, Total):
|
|
196
217
|
return TotalBackend(stop_condition.total)
|
|
197
218
|
else:
|
|
198
|
-
raise RuntimeError(f
|
|
219
|
+
raise RuntimeError(f"Invalid stop condition : {stop_condition}")
|
|
@@ -24,14 +24,14 @@ from .descriptors import VisaDescriptor
|
|
|
24
24
|
|
|
25
25
|
# --- Typing-only imports so mypy knows pyvisa symbols without requiring it at runtime
|
|
26
26
|
if TYPE_CHECKING:
|
|
27
|
-
import pyvisa
|
|
28
|
-
from pyvisa.resources import Resource
|
|
27
|
+
import pyvisa # type: ignore
|
|
28
|
+
from pyvisa.resources import Resource # type: ignore
|
|
29
29
|
|
|
30
30
|
# --- Runtime optional import
|
|
31
31
|
try:
|
|
32
32
|
import pyvisa as _pyvisa_runtime
|
|
33
33
|
except Exception:
|
|
34
|
-
_pyvisa_runtime = None
|
|
34
|
+
_pyvisa_runtime = None
|
|
35
35
|
|
|
36
36
|
pyvisa: ModuleType | None = _pyvisa_runtime # type: ignore
|
|
37
37
|
|
|
@@ -105,8 +105,8 @@ class VisaBackend(AdapterBackend):
|
|
|
105
105
|
|
|
106
106
|
if self._status == AdapterBackendStatus.DISCONNECTED:
|
|
107
107
|
# These attributes exist on pyvisa resources
|
|
108
|
-
self._inst.write_termination = ""
|
|
109
|
-
self._inst.read_termination = None
|
|
108
|
+
self._inst.write_termination = ""
|
|
109
|
+
self._inst.read_termination = None
|
|
110
110
|
|
|
111
111
|
self._inst_lock = threading.Lock()
|
|
112
112
|
self._status = AdapterBackendStatus.CONNECTED
|
|
@@ -136,7 +136,7 @@ class VisaBackend(AdapterBackend):
|
|
|
136
136
|
super().write(data)
|
|
137
137
|
with self._inst_lock:
|
|
138
138
|
if self._inst is not None:
|
|
139
|
-
self._inst.write_raw(data)
|
|
139
|
+
self._inst.write_raw(data)
|
|
140
140
|
return True
|
|
141
141
|
|
|
142
142
|
def _socket_read(self) -> Fragment:
|
|
@@ -169,7 +169,7 @@ class VisaBackend(AdapterBackend):
|
|
|
169
169
|
try:
|
|
170
170
|
while True:
|
|
171
171
|
# Read up to an error
|
|
172
|
-
payload += inst.read_bytes(1)
|
|
172
|
+
payload += inst.read_bytes(1)
|
|
173
173
|
inst.timeout = 0
|
|
174
174
|
except pyvisa.VisaIOError:
|
|
175
175
|
# Timeout
|
syndesi/adapters/ip.py
CHANGED
|
@@ -28,9 +28,9 @@ class IP(Adapter):
|
|
|
28
28
|
self,
|
|
29
29
|
address: str,
|
|
30
30
|
port: int | None = None,
|
|
31
|
-
transport: str =
|
|
31
|
+
transport: str = DEFAULT_PROTOCOL.value,
|
|
32
32
|
timeout: Timeout | NumberLike | None | EllipsisType = ...,
|
|
33
|
-
stop_conditions: StopCondition |
|
|
33
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
34
34
|
alias: str = "",
|
|
35
35
|
encoding: str = "utf-8",
|
|
36
36
|
event_callback: Callable[[AdapterSignal], None] | None = None,
|
|
@@ -63,11 +63,7 @@ class IP(Adapter):
|
|
|
63
63
|
descriptor=IPDescriptor(
|
|
64
64
|
address=address,
|
|
65
65
|
port=port,
|
|
66
|
-
transport=(
|
|
67
|
-
IPDescriptor.Transport(transport.upper())
|
|
68
|
-
if transport is not None
|
|
69
|
-
else self.DEFAULT_PROTOCOL
|
|
70
|
-
),
|
|
66
|
+
transport=IPDescriptor.Transport(transport.upper()),
|
|
71
67
|
),
|
|
72
68
|
alias=alias,
|
|
73
69
|
timeout=timeout,
|
|
@@ -80,8 +76,8 @@ class IP(Adapter):
|
|
|
80
76
|
)
|
|
81
77
|
self.descriptor: IPDescriptor
|
|
82
78
|
|
|
83
|
-
if self.descriptor.transport is None:
|
|
84
|
-
|
|
79
|
+
# if self.descriptor.transport is not None:
|
|
80
|
+
self._logger.info(f"Setting up {self.descriptor.transport.value} IP adapter")
|
|
85
81
|
|
|
86
82
|
self.set_default_timeout(self._default_timeout())
|
|
87
83
|
|
|
@@ -102,7 +98,7 @@ class IP(Adapter):
|
|
|
102
98
|
if self.descriptor.port is None:
|
|
103
99
|
self.descriptor.port = port
|
|
104
100
|
|
|
105
|
-
def set_default_transport(self, transport
|
|
101
|
+
def set_default_transport(self, transport: str | IPDescriptor.Transport) -> None:
|
|
106
102
|
"""
|
|
107
103
|
Sets the default IP transport protocol
|
|
108
104
|
|
|
@@ -2,26 +2,19 @@
|
|
|
2
2
|
# Author : Sébastien Deriaz
|
|
3
3
|
# License : GPL
|
|
4
4
|
|
|
5
|
-
import json
|
|
6
5
|
from abc import abstractmethod
|
|
7
6
|
from enum import Enum
|
|
8
7
|
|
|
9
8
|
class StopConditionType(Enum):
|
|
10
|
-
TERMINATION =
|
|
11
|
-
LENGTH =
|
|
12
|
-
TIMEOUT =
|
|
13
|
-
#CONTINUATION = 'continuation'
|
|
14
|
-
#TOTAL = 'total'
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
TERMINATION = "termination"
|
|
10
|
+
LENGTH = "length"
|
|
11
|
+
TIMEOUT = "timeout"
|
|
18
12
|
|
|
19
13
|
class StopCondition:
|
|
20
14
|
@abstractmethod
|
|
21
15
|
def type(self) -> StopConditionType:
|
|
22
16
|
pass
|
|
23
17
|
|
|
24
|
-
|
|
25
18
|
def __init__(self) -> None:
|
|
26
19
|
"""
|
|
27
20
|
A condition to stop reading from a device
|
|
@@ -29,13 +22,6 @@ class StopCondition:
|
|
|
29
22
|
Cannot be used on its own
|
|
30
23
|
"""
|
|
31
24
|
|
|
32
|
-
# @abstractmethod
|
|
33
|
-
# def compose_json(self) -> str:
|
|
34
|
-
# raise NotImplementedError
|
|
35
|
-
|
|
36
|
-
# def compose(self) -> dict:
|
|
37
|
-
# raise NotImplementedError
|
|
38
|
-
|
|
39
25
|
|
|
40
26
|
class Termination(StopCondition):
|
|
41
27
|
def __init__(self, sequence: bytes | str) -> None:
|
|
@@ -54,25 +40,12 @@ class Termination(StopCondition):
|
|
|
54
40
|
else:
|
|
55
41
|
raise ValueError(f"Invalid termination sequence type : {type(sequence)}")
|
|
56
42
|
|
|
57
|
-
# def compose_json(self) -> str:
|
|
58
|
-
# data = {
|
|
59
|
-
# JsonKey.TYPE.value: StopConditionType.TERMINATION.value,
|
|
60
|
-
# JsonKey.TERMINATION_SEQUENCE.value: self._sequence.decode("utf-8"),
|
|
61
|
-
# }
|
|
62
|
-
# return json.dumps(data)
|
|
63
|
-
|
|
64
|
-
# def compose(self) -> dict:
|
|
65
|
-
# return {
|
|
66
|
-
# StopConditionDescriptorKey.TYPE.value: StopConditionType.TERMINATION.value,
|
|
67
|
-
# StopConditionDescriptorKey.TERMINATION_SEQUENCE.value: self.sequence.decode("utf-8"),
|
|
68
|
-
# }
|
|
69
|
-
|
|
70
43
|
def __repr__(self) -> str:
|
|
71
44
|
return self.__str__()
|
|
72
45
|
|
|
73
46
|
def __str__(self) -> str:
|
|
74
47
|
return f"Termination({repr(self.sequence)})"
|
|
75
|
-
|
|
48
|
+
|
|
76
49
|
def type(self) -> StopConditionType:
|
|
77
50
|
return StopConditionType.TERMINATION
|
|
78
51
|
|
|
@@ -89,75 +62,29 @@ class Length(StopCondition):
|
|
|
89
62
|
"""
|
|
90
63
|
self.N = N
|
|
91
64
|
|
|
92
|
-
# def compose_json(self) -> str:
|
|
93
|
-
# data = {
|
|
94
|
-
# JsonKey.TYPE.value: StopConditionType.LENGTH.value,
|
|
95
|
-
# JsonKey.LENGTH_N.value: self._N,
|
|
96
|
-
# }
|
|
97
|
-
# return json.dumps(data)
|
|
98
|
-
|
|
99
|
-
# def compose(self) -> dict:
|
|
100
|
-
# return {
|
|
101
|
-
# StopConditionDescriptorKey.TYPE.value: StopConditionType.LENGTH.value,
|
|
102
|
-
# StopConditionDescriptorKey.LENGTH_N.value: self.N,
|
|
103
|
-
# }
|
|
104
|
-
|
|
105
65
|
def __repr__(self) -> str:
|
|
106
66
|
return self.__str__()
|
|
107
67
|
|
|
108
68
|
def __str__(self) -> str:
|
|
109
69
|
return f"Length({self.N})"
|
|
110
|
-
|
|
70
|
+
|
|
111
71
|
def type(self) -> StopConditionType:
|
|
112
72
|
return StopConditionType.LENGTH
|
|
113
73
|
|
|
114
74
|
|
|
115
75
|
class Continuation(StopCondition):
|
|
116
|
-
def __init__(self, time
|
|
76
|
+
def __init__(self, time: float) -> None:
|
|
117
77
|
super().__init__()
|
|
118
78
|
self.continuation = time
|
|
119
|
-
|
|
79
|
+
|
|
120
80
|
def type(self) -> StopConditionType:
|
|
121
81
|
return StopConditionType.TIMEOUT
|
|
122
82
|
|
|
83
|
+
|
|
123
84
|
class Total(StopCondition):
|
|
124
|
-
def __init__(self, time
|
|
85
|
+
def __init__(self, time: float) -> None:
|
|
125
86
|
super().__init__()
|
|
126
87
|
self.total = time
|
|
127
|
-
|
|
88
|
+
|
|
128
89
|
def type(self) -> StopConditionType:
|
|
129
90
|
return StopConditionType.TIMEOUT
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
# class TimeoutStopCondition(StopCondition):
|
|
134
|
-
# def __init__(
|
|
135
|
-
# self, continuation: float | None = None, total: float | None = None
|
|
136
|
-
# ) -> None:
|
|
137
|
-
# super().__init__()
|
|
138
|
-
# self.continuation = continuation
|
|
139
|
-
# self.total = total
|
|
140
|
-
|
|
141
|
-
# # def compose_json(self) -> str:
|
|
142
|
-
# # data = {
|
|
143
|
-
# # JsonKey.TYPE.value: StopConditionType.TIMEOUT.value,
|
|
144
|
-
# # JsonKey.TIMEOUT_CONTINUATION.value: self.continuation,
|
|
145
|
-
# # JsonKey.TIMEOUT_TOTAL.value: self.total,
|
|
146
|
-
# # }
|
|
147
|
-
# # return json.dumps(data)
|
|
148
|
-
|
|
149
|
-
# # def compose(self) -> dict:
|
|
150
|
-
# # return {
|
|
151
|
-
# # StopConditionDescriptorKey.TYPE.value: StopConditionType.TIMEOUT.value,
|
|
152
|
-
# # StopConditionDescriptorKey.TIMEOUT_CONTINUATION.value: self.continuation,
|
|
153
|
-
# # StopConditionDescriptorKey.TIMEOUT_TOTAL.value: self.total,
|
|
154
|
-
# # }
|
|
155
|
-
|
|
156
|
-
# def __repr__(self) -> str:
|
|
157
|
-
# return super().__repr__()
|
|
158
|
-
|
|
159
|
-
# def __str__(self) -> str:
|
|
160
|
-
# return super().__str__()
|
|
161
|
-
|
|
162
|
-
# def type(self) -> StopConditionType:
|
|
163
|
-
# return StopConditionType.TIMEOUT
|