syndesi 0.3.2__py3-none-any.whl → 0.4.1__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 +126 -165
- syndesi/adapters/auto.py +1 -1
- syndesi/adapters/backend/adapter_backend.py +96 -63
- syndesi/adapters/backend/adapter_session.py +53 -153
- syndesi/adapters/backend/descriptors.py +3 -2
- syndesi/adapters/backend/ip_backend.py +1 -0
- syndesi/adapters/backend/serialport_backend.py +19 -13
- syndesi/adapters/backend/stop_condition_backend.py +99 -243
- syndesi/adapters/backend/visa_backend.py +7 -7
- syndesi/adapters/ip.py +6 -10
- syndesi/adapters/serialport.py +4 -5
- syndesi/adapters/stop_condition.py +47 -26
- syndesi/adapters/timeout.py +2 -2
- syndesi/adapters/visa.py +2 -2
- syndesi/cli/shell_tools.py +95 -97
- syndesi/protocols/delimited.py +16 -21
- syndesi/protocols/modbus.py +17 -14
- syndesi/protocols/raw.py +20 -16
- syndesi/protocols/scpi.py +17 -15
- syndesi/tools/backend_api.py +15 -16
- syndesi/tools/errors.py +28 -0
- syndesi/version.py +1 -1
- {syndesi-0.3.2.dist-info → syndesi-0.4.1.dist-info}/METADATA +2 -1
- {syndesi-0.3.2.dist-info → syndesi-0.4.1.dist-info}/RECORD +28 -28
- {syndesi-0.3.2.dist-info → syndesi-0.4.1.dist-info}/WHEEL +0 -0
- {syndesi-0.3.2.dist-info → syndesi-0.4.1.dist-info}/entry_points.txt +0 -0
- {syndesi-0.3.2.dist-info → syndesi-0.4.1.dist-info}/licenses/LICENSE +0 -0
- {syndesi-0.3.2.dist-info → syndesi-0.4.1.dist-info}/top_level.txt +0 -0
|
@@ -10,6 +10,9 @@ class StopConditionType(Enum):
|
|
|
10
10
|
TERMINATION = 'termination'
|
|
11
11
|
LENGTH = 'length'
|
|
12
12
|
TIMEOUT = 'timeout'
|
|
13
|
+
#CONTINUATION = 'continuation'
|
|
14
|
+
#TOTAL = 'total'
|
|
15
|
+
|
|
13
16
|
|
|
14
17
|
|
|
15
18
|
|
|
@@ -109,34 +112,52 @@ class Length(StopCondition):
|
|
|
109
112
|
return StopConditionType.LENGTH
|
|
110
113
|
|
|
111
114
|
|
|
112
|
-
class
|
|
113
|
-
def __init__(
|
|
114
|
-
self, continuation: float | None = None, total: float | None = None
|
|
115
|
-
) -> None:
|
|
115
|
+
class Continuation(StopCondition):
|
|
116
|
+
def __init__(self, time : float) -> None:
|
|
116
117
|
super().__init__()
|
|
117
|
-
self.continuation =
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
# data = {
|
|
122
|
-
# JsonKey.TYPE.value: StopConditionType.TIMEOUT.value,
|
|
123
|
-
# JsonKey.TIMEOUT_CONTINUATION.value: self.continuation,
|
|
124
|
-
# JsonKey.TIMEOUT_TOTAL.value: self.total,
|
|
125
|
-
# }
|
|
126
|
-
# return json.dumps(data)
|
|
127
|
-
|
|
128
|
-
# def compose(self) -> dict:
|
|
129
|
-
# return {
|
|
130
|
-
# StopConditionDescriptorKey.TYPE.value: StopConditionType.TIMEOUT.value,
|
|
131
|
-
# StopConditionDescriptorKey.TIMEOUT_CONTINUATION.value: self.continuation,
|
|
132
|
-
# StopConditionDescriptorKey.TIMEOUT_TOTAL.value: self.total,
|
|
133
|
-
# }
|
|
134
|
-
|
|
135
|
-
def __repr__(self) -> str:
|
|
136
|
-
return super().__repr__()
|
|
118
|
+
self.continuation = time
|
|
119
|
+
|
|
120
|
+
def type(self) -> StopConditionType:
|
|
121
|
+
return StopConditionType.TIMEOUT
|
|
137
122
|
|
|
138
|
-
|
|
139
|
-
|
|
123
|
+
class Total(StopCondition):
|
|
124
|
+
def __init__(self, time : float) -> None:
|
|
125
|
+
super().__init__()
|
|
126
|
+
self.total = time
|
|
140
127
|
|
|
141
128
|
def type(self) -> StopConditionType:
|
|
142
129
|
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
|
syndesi/adapters/timeout.py
CHANGED
|
@@ -13,7 +13,7 @@ from ..tools.types import NumberLike, is_number
|
|
|
13
13
|
|
|
14
14
|
class TimeoutAction(Enum):
|
|
15
15
|
ERROR = "error"
|
|
16
|
-
|
|
16
|
+
RETURN_EMPTY = "return_empty"
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class IsInitialized(Protocol):
|
|
@@ -67,7 +67,7 @@ class Timeout:
|
|
|
67
67
|
|
|
68
68
|
def set_default(self, default_timeout: "Timeout") -> None:
|
|
69
69
|
if self._is_default_response:
|
|
70
|
-
self.
|
|
70
|
+
self._response = default_timeout.response()
|
|
71
71
|
if self._is_default_action:
|
|
72
72
|
self.action = default_timeout.action
|
|
73
73
|
|
syndesi/adapters/visa.py
CHANGED
|
@@ -20,7 +20,7 @@ class Visa(Adapter):
|
|
|
20
20
|
self,
|
|
21
21
|
descriptor: str,
|
|
22
22
|
alias: str = "",
|
|
23
|
-
|
|
23
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
24
24
|
timeout: None | float | Timeout | EllipsisType = ...,
|
|
25
25
|
encoding: str = "utf-8",
|
|
26
26
|
event_callback: Callable[[AdapterSignal], None] | None = None,
|
|
@@ -30,7 +30,7 @@ class Visa(Adapter):
|
|
|
30
30
|
super().__init__(
|
|
31
31
|
VisaDescriptor.from_string(descriptor),
|
|
32
32
|
alias=alias,
|
|
33
|
-
stop_conditions=
|
|
33
|
+
stop_conditions=stop_conditions,
|
|
34
34
|
timeout=timeout,
|
|
35
35
|
encoding=encoding,
|
|
36
36
|
event_callback=event_callback,
|
syndesi/cli/shell_tools.py
CHANGED
|
@@ -8,100 +8,98 @@ from dataclasses import dataclass
|
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
@dataclass
|
|
12
|
-
class CommandSpec:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# ---- Module-level registry (optional)
|
|
24
|
-
# If you like auto-discovery, classes decorated with @collect_cli_exports
|
|
25
|
-
# get added here at import time.
|
|
26
|
-
CLI_CLASS_REGISTRY: set[type] = set()
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def iter_all_cli_specs(classes: Iterable[type]) -> Iterable[CommandSpec]:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# ---- Decorators
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
CLI_CLASS_REGISTRY.add(cls)
|
|
107
|
-
return cls
|
|
11
|
+
# @dataclass
|
|
12
|
+
# class CommandSpec:
|
|
13
|
+
# name: str
|
|
14
|
+
# func: Callable[..., Any] # the underlying function object
|
|
15
|
+
# help: str = ""
|
|
16
|
+
# aliases: tuple[str, ...] = ()
|
|
17
|
+
# hidden: bool = False
|
|
18
|
+
# dangerous: bool = False
|
|
19
|
+
# owner_cls: type | None = None # populated when collected
|
|
20
|
+
# method_kind: str = "function" # "instance" | "class" | "static" | "function"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# # ---- Module-level registry (optional)
|
|
24
|
+
# # If you like auto-discovery, classes decorated with @collect_cli_exports
|
|
25
|
+
# # get added here at import time.
|
|
26
|
+
# CLI_CLASS_REGISTRY: set[type] = set()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# def iter_all_cli_specs(classes: Iterable[type]) -> Iterable[CommandSpec]:
|
|
30
|
+
# """Yield CommandSpec for the given classes (or CLI_CLASS_REGISTRY if you pass that)."""
|
|
31
|
+
# for cls in classes:
|
|
32
|
+
# for spec in getattr(cls, "__cli_exports__", ()):
|
|
33
|
+
# yield from spec
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# # ---- Decorators
|
|
37
|
+
# def cli_command(
|
|
38
|
+
# name: str | None = None,
|
|
39
|
+
# *,
|
|
40
|
+
# help: str = "",
|
|
41
|
+
# aliases: tuple[str, ...] = (),
|
|
42
|
+
# hidden: bool = False,
|
|
43
|
+
# dangerous: bool = False,
|
|
44
|
+
# ) -> None:
|
|
45
|
+
# """
|
|
46
|
+
# Decorate any callable (method or function) to mark it as CLI-visible.
|
|
47
|
+
# Attach a CommandSpec to the function object. Class binding is assigned later.
|
|
48
|
+
# """
|
|
49
|
+
|
|
50
|
+
# def deco(fn: Callable[..., Any]) -> None:
|
|
51
|
+
# # Note: we attach spec on the underlying function (works for instance funcs).
|
|
52
|
+
# spec = CommandSpec(
|
|
53
|
+
# name=(name or fn.__name__).replace("_", "-"),
|
|
54
|
+
# func=fn,
|
|
55
|
+
# help=help or (fn.__doc__ or "").strip(),
|
|
56
|
+
# aliases=aliases,
|
|
57
|
+
# hidden=hidden,
|
|
58
|
+
# dangerous=dangerous,
|
|
59
|
+
# )
|
|
60
|
+
# fn.__cli_export__ = spec
|
|
61
|
+
# return fn
|
|
62
|
+
|
|
63
|
+
# return deco
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# def collect_cli_exports(cls: type) -> None:
|
|
67
|
+
# """
|
|
68
|
+
# Class decorator: scan the class for decorated methods (instance, classmethod, staticmethod),
|
|
69
|
+
# create a stable list of CommandSpec, and attach it as __cli_exports__.
|
|
70
|
+
# Also registers the class in CLI_CLASS_REGISTRY for optional auto-discovery.
|
|
71
|
+
# """
|
|
72
|
+
# exports: list[CommandSpec] = []
|
|
73
|
+
|
|
74
|
+
# for _, obj in cls.__dict__.items():
|
|
75
|
+
# # instance method (function descriptor)
|
|
76
|
+
# if inspect.isfunction(obj):
|
|
77
|
+
# spec: CommandSpec | None = getattr(obj, "__cli_export__", None)
|
|
78
|
+
# if spec:
|
|
79
|
+
# spec.owner_cls = cls
|
|
80
|
+
# spec.method_kind = "instance"
|
|
81
|
+
# exports.append(spec)
|
|
82
|
+
# continue
|
|
83
|
+
|
|
84
|
+
# # classmethod / staticmethod wrap the underlying function in .__func__
|
|
85
|
+
# if isinstance(obj, classmethod):
|
|
86
|
+
# fn = obj.__func__
|
|
87
|
+
# spec = getattr(fn, "__cli_export__", None)
|
|
88
|
+
# if spec:
|
|
89
|
+
# spec.owner_cls = cls
|
|
90
|
+
# spec.method_kind = "class"
|
|
91
|
+
# exports.append(spec)
|
|
92
|
+
# continue
|
|
93
|
+
|
|
94
|
+
# if isinstance(obj, staticmethod):
|
|
95
|
+
# fn = obj.__func__
|
|
96
|
+
# spec = getattr(fn, "__cli_export__", None)
|
|
97
|
+
# if spec:
|
|
98
|
+
# spec.owner_cls = cls
|
|
99
|
+
# spec.method_kind = "static"
|
|
100
|
+
# exports.append(spec)
|
|
101
|
+
# continue
|
|
102
|
+
|
|
103
|
+
# cls.__cli_exports__ = tuple(exports)
|
|
104
|
+
# CLI_CLASS_REGISTRY.add(cls)
|
|
105
|
+
# return cls
|
syndesi/protocols/delimited.py
CHANGED
|
@@ -110,10 +110,8 @@ class Delimited(Protocol):
|
|
|
110
110
|
def query(
|
|
111
111
|
self,
|
|
112
112
|
data: str,
|
|
113
|
-
timeout: Timeout | None | EllipsisType =
|
|
114
|
-
|
|
115
|
-
full_output: bool = False,
|
|
116
|
-
) -> str | tuple[str, AdapterSignal]:
|
|
113
|
+
timeout: Timeout | None | EllipsisType = ...
|
|
114
|
+
) -> str:
|
|
117
115
|
"""
|
|
118
116
|
Writes then reads from the device and return the result
|
|
119
117
|
|
|
@@ -130,13 +128,13 @@ class Delimited(Protocol):
|
|
|
130
128
|
"""
|
|
131
129
|
self._adapter.flushRead()
|
|
132
130
|
self.write(data)
|
|
133
|
-
return self.read(timeout=timeout
|
|
131
|
+
return self.read(timeout=timeout)
|
|
134
132
|
|
|
135
133
|
def read_raw(
|
|
136
134
|
self,
|
|
137
135
|
timeout: Timeout | None | EllipsisType = ...,
|
|
138
|
-
|
|
139
|
-
) ->
|
|
136
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
137
|
+
) -> bytes:
|
|
140
138
|
"""
|
|
141
139
|
Reads command and formats it as a str
|
|
142
140
|
|
|
@@ -151,30 +149,27 @@ class Delimited(Protocol):
|
|
|
151
149
|
"""
|
|
152
150
|
|
|
153
151
|
# Send up to the termination
|
|
154
|
-
|
|
155
|
-
timeout=timeout,
|
|
152
|
+
signal = self._adapter.read_detailed(
|
|
153
|
+
timeout=timeout, stop_conditions=stop_conditions
|
|
156
154
|
)
|
|
157
|
-
|
|
158
|
-
return raw_data, signal
|
|
155
|
+
return signal.data()
|
|
159
156
|
|
|
160
157
|
def read_detailed(
|
|
161
158
|
self,
|
|
162
159
|
timeout: Timeout | None | EllipsisType = ...,
|
|
163
|
-
|
|
164
|
-
) ->
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
data_out = self._decode(raw_data)
|
|
168
|
-
return data_out, signal
|
|
160
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...
|
|
161
|
+
) -> AdapterReadPayload:
|
|
162
|
+
signal = self._adapter.read_detailed(timeout=timeout, stop_conditions=stop_conditions)
|
|
163
|
+
return signal
|
|
169
164
|
|
|
170
165
|
def read(
|
|
171
166
|
self,
|
|
172
167
|
timeout: Timeout | None | EllipsisType = ...,
|
|
173
|
-
|
|
174
|
-
decode: bool = True,
|
|
175
|
-
full_output: bool = False,
|
|
168
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...
|
|
176
169
|
) -> str:
|
|
177
|
-
|
|
170
|
+
signal = self.read_detailed(timeout=timeout, stop_conditions=stop_conditions)
|
|
171
|
+
return self._decode(signal.data())
|
|
172
|
+
|
|
178
173
|
|
|
179
174
|
def _decode(self, data: bytes) -> str:
|
|
180
175
|
try:
|
syndesi/protocols/modbus.py
CHANGED
|
@@ -14,7 +14,7 @@ from unittest.mock import DEFAULT
|
|
|
14
14
|
from ..adapters.adapter import Adapter
|
|
15
15
|
from ..adapters.ip import IP
|
|
16
16
|
from ..adapters.serialport import SerialPort
|
|
17
|
-
from ..adapters.stop_condition import Length
|
|
17
|
+
from ..adapters.stop_condition import Continuation, Length
|
|
18
18
|
from ..adapters.timeout import Timeout
|
|
19
19
|
from .protocol import Protocol
|
|
20
20
|
|
|
@@ -328,10 +328,12 @@ class Modbus(Protocol):
|
|
|
328
328
|
def _error_code(self, response: bytes) -> int:
|
|
329
329
|
return response[1]
|
|
330
330
|
|
|
331
|
-
def _parse_pdu(self, _pdu: bytes) -> bytes:
|
|
331
|
+
def _parse_pdu(self, _pdu: bytes | None) -> bytes:
|
|
332
332
|
"""
|
|
333
333
|
Return data from PDU
|
|
334
334
|
"""
|
|
335
|
+
if _pdu is None:
|
|
336
|
+
raise RuntimeError("Failed to read modbus data")
|
|
335
337
|
if self._modbus_type == ModbusType.TCP:
|
|
336
338
|
# Return raw data
|
|
337
339
|
# data = _pdu
|
|
@@ -391,12 +393,13 @@ class Modbus(Protocol):
|
|
|
391
393
|
)
|
|
392
394
|
|
|
393
395
|
n_coil_bytes = ceil(number_of_coils / 8)
|
|
394
|
-
pdu: bytes = self._adapter.query(
|
|
396
|
+
pdu: bytes | None = self._adapter.query(
|
|
395
397
|
self._make_pdu(query),
|
|
396
398
|
# timeout=Timeout(continuation=1),
|
|
397
|
-
|
|
398
|
-
self._length(n_coil_bytes + 2)
|
|
399
|
-
|
|
399
|
+
stop_conditions=[
|
|
400
|
+
Length(self._length(n_coil_bytes + 2)),
|
|
401
|
+
Continuation(time=1)
|
|
402
|
+
] # TODO : convert to multiple stop conditions here
|
|
400
403
|
)
|
|
401
404
|
response = self._parse_pdu(pdu)
|
|
402
405
|
self._raise_if_error(response, exception_codes=EXCEPTIONS)
|
|
@@ -465,7 +468,7 @@ class Modbus(Protocol):
|
|
|
465
468
|
response = self._parse_pdu(
|
|
466
469
|
self._adapter.query(
|
|
467
470
|
self._make_pdu(query),
|
|
468
|
-
|
|
471
|
+
stop_conditions=Length(self._length(byte_count + 2)),
|
|
469
472
|
)
|
|
470
473
|
)
|
|
471
474
|
self._raise_if_error(response, exception_codes=EXCEPTIONS)
|
|
@@ -515,7 +518,7 @@ class Modbus(Protocol):
|
|
|
515
518
|
response = self._parse_pdu(
|
|
516
519
|
self._adapter.query(
|
|
517
520
|
self._make_pdu(query),
|
|
518
|
-
|
|
521
|
+
stop_conditions=Length(self._length(2 + number_of_registers * 2)),
|
|
519
522
|
)
|
|
520
523
|
)
|
|
521
524
|
self._raise_if_error(response, exception_codes=EXCEPTIONS)
|
|
@@ -769,7 +772,7 @@ class Modbus(Protocol):
|
|
|
769
772
|
)
|
|
770
773
|
response = self._parse_pdu(
|
|
771
774
|
self._adapter.query(
|
|
772
|
-
self._make_pdu(query),
|
|
775
|
+
self._make_pdu(query), stop_conditions=Length(self._length(len(query)))
|
|
773
776
|
)
|
|
774
777
|
)
|
|
775
778
|
self._raise_if_error(response, EXCEPTIONS)
|
|
@@ -805,7 +808,7 @@ class Modbus(Protocol):
|
|
|
805
808
|
)
|
|
806
809
|
response = self._parse_pdu(
|
|
807
810
|
self._adapter.query(
|
|
808
|
-
self._make_pdu(query),
|
|
811
|
+
self._make_pdu(query), stop_conditions=Length(self._length(len(query)))
|
|
809
812
|
)
|
|
810
813
|
)
|
|
811
814
|
self._raise_if_error(response, EXCEPTIONS)
|
|
@@ -1198,7 +1201,7 @@ class Modbus(Protocol):
|
|
|
1198
1201
|
)
|
|
1199
1202
|
response = self._parse_pdu(
|
|
1200
1203
|
self._adapter.query(
|
|
1201
|
-
self._make_pdu(query),
|
|
1204
|
+
self._make_pdu(query), stop_conditions=Length(self._length(5))
|
|
1202
1205
|
)
|
|
1203
1206
|
)
|
|
1204
1207
|
self._raise_if_error(response, EXCEPTIONS)
|
|
@@ -1250,7 +1253,7 @@ class Modbus(Protocol):
|
|
|
1250
1253
|
)
|
|
1251
1254
|
response = self._parse_pdu(
|
|
1252
1255
|
self._adapter.query(
|
|
1253
|
-
self._make_pdu(query),
|
|
1256
|
+
self._make_pdu(query), stop_conditions=Length(self._length(5))
|
|
1254
1257
|
)
|
|
1255
1258
|
)
|
|
1256
1259
|
self._raise_if_error(response, EXCEPTIONS)
|
|
@@ -1451,7 +1454,7 @@ class Modbus(Protocol):
|
|
|
1451
1454
|
)
|
|
1452
1455
|
response = self._parse_pdu(
|
|
1453
1456
|
self._adapter.query(
|
|
1454
|
-
self._make_pdu(query),
|
|
1457
|
+
self._make_pdu(query), stop_conditions=Length(self._length(len(query)))
|
|
1455
1458
|
)
|
|
1456
1459
|
)
|
|
1457
1460
|
self._raise_if_error(response, EXCEPTIONS)
|
|
@@ -1521,7 +1524,7 @@ class Modbus(Protocol):
|
|
|
1521
1524
|
response = self._parse_pdu(
|
|
1522
1525
|
self._adapter.query(
|
|
1523
1526
|
self._make_pdu(query),
|
|
1524
|
-
|
|
1527
|
+
stop_conditions=Length(self._length(2 + number_of_read_registers * 2)),
|
|
1525
1528
|
)
|
|
1526
1529
|
)
|
|
1527
1530
|
self._raise_if_error(response, EXCEPTIONS)
|
syndesi/protocols/raw.py
CHANGED
|
@@ -49,33 +49,37 @@ class Raw(Protocol):
|
|
|
49
49
|
self,
|
|
50
50
|
data: bytes,
|
|
51
51
|
timeout: Timeout | None | EllipsisType = ...,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
) -> bytes | tuple[bytes, AdapterSignal]:
|
|
52
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
53
|
+
) -> bytes:
|
|
55
54
|
self._adapter.flushRead()
|
|
56
55
|
self.write(data)
|
|
57
|
-
return self.read(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
return self.read(timeout=timeout, stop_conditions=stop_conditions)
|
|
57
|
+
|
|
58
|
+
def query_detailed(
|
|
59
|
+
self,
|
|
60
|
+
data: bytes,
|
|
61
|
+
timeout: Timeout | None | EllipsisType = ...,
|
|
62
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
63
|
+
) -> AdapterReadPayload:
|
|
64
|
+
self._adapter.flushRead()
|
|
65
|
+
self.write(data)
|
|
66
|
+
return self.read_detailed(timeout=timeout, stop_conditions=stop_conditions)
|
|
62
67
|
|
|
63
68
|
def read(
|
|
64
69
|
self,
|
|
65
70
|
timeout: Timeout | None | EllipsisType = ...,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return self.read_detailed(timeout=timeout, stop_condition=stop_condition)[0]
|
|
71
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
72
|
+
) -> bytes:
|
|
73
|
+
signal = self.read_detailed(timeout=timeout, stop_conditions=stop_conditions)
|
|
74
|
+
return signal.data()
|
|
71
75
|
|
|
72
76
|
def read_detailed(
|
|
73
77
|
self,
|
|
74
78
|
timeout: Timeout | None | EllipsisType = ...,
|
|
75
|
-
|
|
76
|
-
) ->
|
|
79
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
80
|
+
) -> AdapterReadPayload:
|
|
77
81
|
return self._adapter.read_detailed(
|
|
78
|
-
timeout=timeout,
|
|
82
|
+
timeout=timeout, stop_conditions=stop_conditions
|
|
79
83
|
)
|
|
80
84
|
|
|
81
85
|
def _on_data_ready_event(self, data: AdapterReadPayload) -> None:
|
syndesi/protocols/scpi.py
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
from types import EllipsisType
|
|
7
7
|
|
|
8
|
-
from syndesi.adapters.backend.adapter_backend import AdapterSignal
|
|
8
|
+
from syndesi.adapters.backend.adapter_backend import AdapterReadPayload, AdapterSignal
|
|
9
9
|
|
|
10
10
|
from ..adapters.adapter import Adapter
|
|
11
11
|
from ..adapters.ip import IP
|
|
@@ -105,37 +105,39 @@ class SCPI(Protocol):
|
|
|
105
105
|
self,
|
|
106
106
|
command: str,
|
|
107
107
|
timeout: Timeout | None | EllipsisType = ...,
|
|
108
|
-
|
|
108
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
109
109
|
) -> str:
|
|
110
110
|
self._adapter.flushRead()
|
|
111
111
|
self.write(command)
|
|
112
112
|
|
|
113
|
-
return self.read(timeout=timeout,
|
|
113
|
+
return self.read(timeout=timeout, stop_conditions=stop_conditions)
|
|
114
114
|
|
|
115
115
|
def read_raw(
|
|
116
116
|
self,
|
|
117
117
|
timeout: Timeout | None | EllipsisType = ...,
|
|
118
|
-
|
|
119
|
-
) ->
|
|
120
|
-
|
|
118
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
119
|
+
) -> bytes:
|
|
120
|
+
signal = self.read_detailed(
|
|
121
121
|
timeout=timeout,
|
|
122
|
-
|
|
122
|
+
stop_conditions=stop_conditions,
|
|
123
123
|
)
|
|
124
|
+
return signal.data()
|
|
124
125
|
|
|
125
126
|
def read_detailed(
|
|
126
127
|
self,
|
|
127
128
|
timeout: Timeout | None | EllipsisType = ...,
|
|
128
|
-
|
|
129
|
-
) ->
|
|
129
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
130
|
+
) -> AdapterReadPayload:
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return data_out, signal
|
|
132
|
+
signal = self._adapter.read_detailed(timeout=timeout, stop_conditions=stop_conditions)
|
|
133
|
+
return signal
|
|
135
134
|
|
|
136
135
|
def read(
|
|
137
136
|
self,
|
|
138
137
|
timeout: Timeout | None | EllipsisType = ...,
|
|
139
|
-
|
|
138
|
+
stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
|
|
140
139
|
) -> str:
|
|
141
|
-
|
|
140
|
+
signal = self.read_detailed(timeout=timeout, stop_conditions=stop_conditions)
|
|
141
|
+
raw_data = signal.data()
|
|
142
|
+
return self._unformatCommand(self._from_bytes(raw_data))
|
|
143
|
+
|