sgr-commhandler 0.4.dev20250512__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.
- sgr_commhandler/__init__.py +0 -0
- sgr_commhandler/api/__init__.py +18 -0
- sgr_commhandler/api/configuration_parameter.py +71 -0
- sgr_commhandler/api/data_point_api.py +316 -0
- sgr_commhandler/api/data_types.py +14 -0
- sgr_commhandler/api/device_api.py +226 -0
- sgr_commhandler/api/functional_profile_api.py +90 -0
- sgr_commhandler/device_builder.py +337 -0
- sgr_commhandler/driver/__init__.py +0 -0
- sgr_commhandler/driver/contact/__init__.py +7 -0
- sgr_commhandler/driver/contact/contact_interface_async.py +184 -0
- sgr_commhandler/driver/generic/__init__.py +7 -0
- sgr_commhandler/driver/generic/generic_interface_async.py +182 -0
- sgr_commhandler/driver/messaging/__init__.py +7 -0
- sgr_commhandler/driver/messaging/messaging_interface_async.py +197 -0
- sgr_commhandler/driver/modbus/__init__.py +7 -0
- sgr_commhandler/driver/modbus/modbus_client_async.py +403 -0
- sgr_commhandler/driver/modbus/modbus_interface_async.py +516 -0
- sgr_commhandler/driver/modbus/payload_decoder.py +108 -0
- sgr_commhandler/driver/modbus/shared_client.py +119 -0
- sgr_commhandler/driver/rest/__init__.py +7 -0
- sgr_commhandler/driver/rest/authentication.py +207 -0
- sgr_commhandler/driver/rest/restapi_interface_async.py +492 -0
- sgr_commhandler/utils/__init__.py +1 -0
- sgr_commhandler/utils/value_util.py +39 -0
- sgr_commhandler/validators/__init__.py +3 -0
- sgr_commhandler/validators/resolver.py +71 -0
- sgr_commhandler/validators/validator.py +195 -0
- sgr_commhandler-0.4.dev20250512.dist-info/LICENSE.md +14 -0
- sgr_commhandler-0.4.dev20250512.dist-info/METADATA +111 -0
- sgr_commhandler-0.4.dev20250512.dist-info/RECORD +33 -0
- sgr_commhandler-0.4.dev20250512.dist-info/WHEEL +5 -0
- sgr_commhandler-0.4.dev20250512.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
__all__ = [
|
|
2
|
+
"SGrBaseInterface",
|
|
3
|
+
"FunctionalProfile",
|
|
4
|
+
"DataPoint",
|
|
5
|
+
"DataPointProtocol",
|
|
6
|
+
"DataPointValidator",
|
|
7
|
+
"DeviceInformation",
|
|
8
|
+
"ConfigurationParameter",
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
from sgr_commhandler.api.configuration_parameter import ConfigurationParameter
|
|
12
|
+
from sgr_commhandler.api.data_point_api import (
|
|
13
|
+
DataPoint,
|
|
14
|
+
DataPointProtocol,
|
|
15
|
+
DataPointValidator,
|
|
16
|
+
)
|
|
17
|
+
from sgr_commhandler.api.device_api import DeviceInformation, SGrBaseInterface
|
|
18
|
+
from sgr_commhandler.api.functional_profile_api import FunctionalProfile
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from sgr_specification.v0.product import (
|
|
4
|
+
ConfigurationList,
|
|
5
|
+
ConfigurationListElement,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def build_configuration_parameters(params: Optional[ConfigurationList]) -> list['ConfigurationParameter']:
|
|
10
|
+
"""
|
|
11
|
+
Constructs a configuration parameter list.
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
params : Optional[ConfigurationList]
|
|
16
|
+
The configuration list of an EID
|
|
17
|
+
|
|
18
|
+
Returns
|
|
19
|
+
-------
|
|
20
|
+
list[ConfigurationParameter]
|
|
21
|
+
a list of configuration parameters
|
|
22
|
+
"""
|
|
23
|
+
if params is None:
|
|
24
|
+
return []
|
|
25
|
+
return [
|
|
26
|
+
ConfigurationParameter(x) for x in params.configuration_list_element
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ConfigurationParameter:
|
|
31
|
+
"""
|
|
32
|
+
Implements an EID configuration parameter.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, parameter: ConfigurationListElement):
|
|
36
|
+
"""
|
|
37
|
+
Constructs a configuration parameter.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
parameter : ConfigurationListElement
|
|
42
|
+
A configuration list element of the SGr specification
|
|
43
|
+
"""
|
|
44
|
+
translation = parameter.configuration_description
|
|
45
|
+
self.label = translation[0].label
|
|
46
|
+
self.name = parameter.name
|
|
47
|
+
self.type = parameter.data_type
|
|
48
|
+
self.description = translation[0].text_element
|
|
49
|
+
self.default_value = parameter.default_value
|
|
50
|
+
|
|
51
|
+
def __str__(self) -> str:
|
|
52
|
+
"""
|
|
53
|
+
Converts to string.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
----------
|
|
57
|
+
str
|
|
58
|
+
A string
|
|
59
|
+
"""
|
|
60
|
+
return f'{self.label} - {self.name}'
|
|
61
|
+
|
|
62
|
+
def __repr__(self):
|
|
63
|
+
"""
|
|
64
|
+
Gets an object description as string.
|
|
65
|
+
|
|
66
|
+
Returns
|
|
67
|
+
----------
|
|
68
|
+
str
|
|
69
|
+
A string
|
|
70
|
+
"""
|
|
71
|
+
return f'{self.label} - {self.name}'
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
from asyncio import run
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from typing import Any, Generic, Protocol, TypeVar
|
|
4
|
+
|
|
5
|
+
from sgr_specification.v0.generic import DataDirectionProduct, Units
|
|
6
|
+
|
|
7
|
+
from sgr_commhandler.api.data_types import DataTypes
|
|
8
|
+
|
|
9
|
+
"""Defines a generic data type."""
|
|
10
|
+
T = TypeVar('T')
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DataPointValidator(Protocol):
|
|
14
|
+
"""
|
|
15
|
+
Defines an interface for data point validators.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def validate(self, value: Any) -> bool:
|
|
19
|
+
"""
|
|
20
|
+
Validates the compatibility of a value.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
value : Any
|
|
25
|
+
the value to validate
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
bool
|
|
30
|
+
true if value is compatible, false otherwise
|
|
31
|
+
"""
|
|
32
|
+
...
|
|
33
|
+
|
|
34
|
+
def data_type(self) -> DataTypes:
|
|
35
|
+
"""
|
|
36
|
+
Gets the validator's data type.
|
|
37
|
+
|
|
38
|
+
Returns
|
|
39
|
+
-------
|
|
40
|
+
DataTypes
|
|
41
|
+
the data type enumeration
|
|
42
|
+
"""
|
|
43
|
+
...
|
|
44
|
+
|
|
45
|
+
def options(self) -> list[Any]:
|
|
46
|
+
"""
|
|
47
|
+
Gets the validator's options.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
list[Any]
|
|
52
|
+
the options
|
|
53
|
+
"""
|
|
54
|
+
return []
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class DataPointProtocol(Protocol):
|
|
58
|
+
"""
|
|
59
|
+
Defines an interface for data point protocols.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
async def set_val(self, value: Any):
|
|
63
|
+
"""
|
|
64
|
+
Writes the data point value.
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
value : Any
|
|
69
|
+
the data point value to write
|
|
70
|
+
"""
|
|
71
|
+
...
|
|
72
|
+
|
|
73
|
+
async def get_val(self, skip_cache: bool = False) -> Any:
|
|
74
|
+
"""
|
|
75
|
+
Reads the data point value.
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
skip_cache : bool
|
|
80
|
+
does not use cache if true
|
|
81
|
+
|
|
82
|
+
Returns
|
|
83
|
+
-------
|
|
84
|
+
Any
|
|
85
|
+
the data point value
|
|
86
|
+
"""
|
|
87
|
+
...
|
|
88
|
+
|
|
89
|
+
def name(self) -> tuple[str, str]:
|
|
90
|
+
"""
|
|
91
|
+
Gets the functional profile and data point names.
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
-------
|
|
95
|
+
tuple[str, str]
|
|
96
|
+
the functional profile and data point names as tuple
|
|
97
|
+
"""
|
|
98
|
+
...
|
|
99
|
+
|
|
100
|
+
def direction(self) -> DataDirectionProduct:
|
|
101
|
+
"""
|
|
102
|
+
Gets the data direction of the data point.
|
|
103
|
+
|
|
104
|
+
Returns
|
|
105
|
+
-------
|
|
106
|
+
DataDirectionProduct
|
|
107
|
+
the data point direction
|
|
108
|
+
"""
|
|
109
|
+
...
|
|
110
|
+
|
|
111
|
+
def unit(self) -> Units:
|
|
112
|
+
"""
|
|
113
|
+
Gets the unit of measurement of the data point.
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
Units
|
|
118
|
+
the unit
|
|
119
|
+
"""
|
|
120
|
+
...
|
|
121
|
+
|
|
122
|
+
def can_subscribe(self) -> bool:
|
|
123
|
+
"""
|
|
124
|
+
Defines if subscribe() is allowed.
|
|
125
|
+
|
|
126
|
+
Returns
|
|
127
|
+
-------
|
|
128
|
+
bool
|
|
129
|
+
True if allowed, False otherwise
|
|
130
|
+
"""
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
def subscribe(self, fn: Callable[[Any], None]):
|
|
134
|
+
"""
|
|
135
|
+
Subscribes to changes of the data point value.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
fn : Callable[[Any], None]
|
|
140
|
+
the callback method
|
|
141
|
+
"""
|
|
142
|
+
raise Exception('Unsupported operation')
|
|
143
|
+
|
|
144
|
+
def unsubscribe(self):
|
|
145
|
+
"""
|
|
146
|
+
Unsubscribes from changes of the data point value.
|
|
147
|
+
"""
|
|
148
|
+
raise Exception('Unsupported operation')
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class DataPoint(Generic[T]):
|
|
152
|
+
"""
|
|
153
|
+
Implements a data point of a generic data type.
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
def __init__(
|
|
157
|
+
self, protocol: DataPointProtocol, validator: DataPointValidator
|
|
158
|
+
):
|
|
159
|
+
"""
|
|
160
|
+
Constructs a data point.
|
|
161
|
+
|
|
162
|
+
Parameters
|
|
163
|
+
----------
|
|
164
|
+
protocol : DataPointProtocol
|
|
165
|
+
the underlying protocol
|
|
166
|
+
validator : DataPointValidator
|
|
167
|
+
the data point's value validator
|
|
168
|
+
"""
|
|
169
|
+
self._protocol = protocol
|
|
170
|
+
self._validator = validator
|
|
171
|
+
|
|
172
|
+
def name(self) -> tuple[str, str]:
|
|
173
|
+
"""
|
|
174
|
+
Gets the data point name.
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
tuple[str, str]
|
|
179
|
+
the functional profile and data point name
|
|
180
|
+
"""
|
|
181
|
+
return self._protocol.name()
|
|
182
|
+
|
|
183
|
+
async def get_value_async(self) -> T:
|
|
184
|
+
"""
|
|
185
|
+
Gets the data point value asynchronously.
|
|
186
|
+
|
|
187
|
+
Returns
|
|
188
|
+
-------
|
|
189
|
+
T
|
|
190
|
+
the data point value
|
|
191
|
+
|
|
192
|
+
Raises
|
|
193
|
+
------
|
|
194
|
+
Exception
|
|
195
|
+
when read value is not compatible with data type
|
|
196
|
+
"""
|
|
197
|
+
value = await self._protocol.get_val()
|
|
198
|
+
if self._validator.validate(value):
|
|
199
|
+
return value
|
|
200
|
+
raise Exception(
|
|
201
|
+
f'invalid value read from device, {value}, validator: {self._validator.data_type()}'
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
def get_value(self) -> T:
|
|
205
|
+
"""
|
|
206
|
+
Gets the data point value synchronously.
|
|
207
|
+
|
|
208
|
+
Returns
|
|
209
|
+
-------
|
|
210
|
+
T
|
|
211
|
+
the data point value
|
|
212
|
+
|
|
213
|
+
Raises
|
|
214
|
+
------
|
|
215
|
+
Exception
|
|
216
|
+
when read value is not compatible with data type
|
|
217
|
+
"""
|
|
218
|
+
return run(self.get_value_async())
|
|
219
|
+
|
|
220
|
+
async def set_value_async(self, value: T):
|
|
221
|
+
"""
|
|
222
|
+
Sets the data point value asynchronously.
|
|
223
|
+
|
|
224
|
+
Parameters
|
|
225
|
+
----------
|
|
226
|
+
value: T
|
|
227
|
+
the data point value
|
|
228
|
+
"""
|
|
229
|
+
if self._validator.validate(value):
|
|
230
|
+
return await self._protocol.set_val(value)
|
|
231
|
+
raise Exception('invalid data to write to device')
|
|
232
|
+
|
|
233
|
+
def set_value(self, value: T):
|
|
234
|
+
"""
|
|
235
|
+
Sets the data point value synchronously.
|
|
236
|
+
|
|
237
|
+
Parameters
|
|
238
|
+
----------
|
|
239
|
+
value: T
|
|
240
|
+
the data point value
|
|
241
|
+
"""
|
|
242
|
+
return run(self.set_value_async(value))
|
|
243
|
+
|
|
244
|
+
def subscribe(self, fn: Callable[[Any], None]):
|
|
245
|
+
"""
|
|
246
|
+
Subscribes to data point value changes.
|
|
247
|
+
|
|
248
|
+
Parameters
|
|
249
|
+
----------
|
|
250
|
+
fn : Callable[[Any], None]
|
|
251
|
+
the handler method
|
|
252
|
+
"""
|
|
253
|
+
self._protocol.subscribe(fn)
|
|
254
|
+
|
|
255
|
+
def unsubscribe(self):
|
|
256
|
+
"""
|
|
257
|
+
Unsubscribes from data point value changes.
|
|
258
|
+
"""
|
|
259
|
+
self._protocol.unsubscribe()
|
|
260
|
+
|
|
261
|
+
def direction(self) -> DataDirectionProduct:
|
|
262
|
+
"""
|
|
263
|
+
Gets the data point direction.
|
|
264
|
+
|
|
265
|
+
Returns
|
|
266
|
+
-------
|
|
267
|
+
DataDirectionProduct
|
|
268
|
+
the data point direction
|
|
269
|
+
"""
|
|
270
|
+
return self._protocol.direction()
|
|
271
|
+
|
|
272
|
+
def data_type(self) -> DataTypes:
|
|
273
|
+
"""
|
|
274
|
+
Gets the data point data type.
|
|
275
|
+
|
|
276
|
+
Returns
|
|
277
|
+
-------
|
|
278
|
+
DataTypes
|
|
279
|
+
the data point data type
|
|
280
|
+
"""
|
|
281
|
+
return self._validator.data_type()
|
|
282
|
+
|
|
283
|
+
def unit(self) -> Units:
|
|
284
|
+
"""
|
|
285
|
+
Gets the unit of measurement of the data point.
|
|
286
|
+
|
|
287
|
+
Returns
|
|
288
|
+
-------
|
|
289
|
+
Units
|
|
290
|
+
the unit
|
|
291
|
+
"""
|
|
292
|
+
return self._protocol.unit()
|
|
293
|
+
|
|
294
|
+
def describe(
|
|
295
|
+
self,
|
|
296
|
+
) -> tuple[tuple[str, str], DataDirectionProduct, DataTypes, Units]:
|
|
297
|
+
"""
|
|
298
|
+
Describes the data point.
|
|
299
|
+
|
|
300
|
+
Returns
|
|
301
|
+
-------
|
|
302
|
+
tuple[tuple[str, str], DataDirectionProduct, DataTypes, Units]
|
|
303
|
+
the data point information
|
|
304
|
+
"""
|
|
305
|
+
return self.name(), self.direction(), self.data_type(), self.unit()
|
|
306
|
+
|
|
307
|
+
def options(self) -> list[Any]:
|
|
308
|
+
"""
|
|
309
|
+
Describes the data point options.
|
|
310
|
+
|
|
311
|
+
Returns
|
|
312
|
+
-------
|
|
313
|
+
list[Any]
|
|
314
|
+
the data point options
|
|
315
|
+
"""
|
|
316
|
+
return self._validator.options()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DataTypes(Enum):
|
|
5
|
+
"""Defines the data point data types supported by the SGr specification."""
|
|
6
|
+
|
|
7
|
+
INT = "INT"
|
|
8
|
+
FLOAT = "FLOAT"
|
|
9
|
+
STRING = "STRING"
|
|
10
|
+
ENUM = "ENUM"
|
|
11
|
+
BOOLEAN = "BOOLEAN"
|
|
12
|
+
BITMAP = "BITMAP"
|
|
13
|
+
DATE_TIME = "DATE_TIME"
|
|
14
|
+
JSON = "JSON"
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
from asyncio import run
|
|
2
|
+
from collections.abc import Mapping
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Protocol
|
|
5
|
+
|
|
6
|
+
from sgr_specification.v0.generic import DataDirectionProduct, DeviceCategory
|
|
7
|
+
from sgr_specification.v0.product.product import DeviceFrame
|
|
8
|
+
|
|
9
|
+
from sgr_commhandler.api import DataPoint
|
|
10
|
+
from sgr_commhandler.api.configuration_parameter import (
|
|
11
|
+
ConfigurationParameter,
|
|
12
|
+
build_configuration_parameters,
|
|
13
|
+
)
|
|
14
|
+
from sgr_commhandler.api.data_types import DataTypes
|
|
15
|
+
from sgr_commhandler.api.functional_profile_api import FunctionalProfile
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class DeviceInformation:
|
|
20
|
+
"""
|
|
21
|
+
Implements a device information container.
|
|
22
|
+
|
|
23
|
+
Attributes
|
|
24
|
+
----------
|
|
25
|
+
name : str
|
|
26
|
+
Defines the device name
|
|
27
|
+
manufacturer : str
|
|
28
|
+
Defines the manufacturer's name
|
|
29
|
+
software_revision : str
|
|
30
|
+
Defines the device software version
|
|
31
|
+
hardware_revision : str
|
|
32
|
+
Defines the device hardware version
|
|
33
|
+
device_category : DeviceCategory
|
|
34
|
+
Defines the device category
|
|
35
|
+
is_local : bool
|
|
36
|
+
Defines if the device is controlled locally or via cloud
|
|
37
|
+
"""
|
|
38
|
+
name: str
|
|
39
|
+
manufacturer: str
|
|
40
|
+
software_revision: str
|
|
41
|
+
hardware_revision: str
|
|
42
|
+
device_category: DeviceCategory
|
|
43
|
+
is_local: bool
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class SGrBaseInterface(Protocol):
|
|
47
|
+
"""
|
|
48
|
+
Defines an abstract base class for all SGr device interfaces.
|
|
49
|
+
|
|
50
|
+
Attributes
|
|
51
|
+
----------
|
|
52
|
+
device_frame : DeviceFrame
|
|
53
|
+
the device specification
|
|
54
|
+
configuration_parameters : list[ConfigurationParameter]
|
|
55
|
+
the configuration parameters with default values
|
|
56
|
+
device_information : DeviceInformation
|
|
57
|
+
the device information
|
|
58
|
+
functional_profiles : Mapping[str, FunctionalProfile]
|
|
59
|
+
the configured functional profiles
|
|
60
|
+
"""
|
|
61
|
+
device_frame: DeviceFrame
|
|
62
|
+
configuration_parameters: list[ConfigurationParameter]
|
|
63
|
+
device_information: DeviceInformation
|
|
64
|
+
functional_profiles: Mapping[str, FunctionalProfile]
|
|
65
|
+
|
|
66
|
+
def _inititalize_device(
|
|
67
|
+
self, frame: DeviceFrame
|
|
68
|
+
):
|
|
69
|
+
self.device_frame = frame
|
|
70
|
+
self.configuration_parameters = build_configuration_parameters(
|
|
71
|
+
frame.configuration_list
|
|
72
|
+
)
|
|
73
|
+
self.device_information = DeviceInformation(
|
|
74
|
+
name=frame.device_name if frame.device_name else '',
|
|
75
|
+
manufacturer=frame.manufacturer_name
|
|
76
|
+
if frame.manufacturer_name
|
|
77
|
+
else '',
|
|
78
|
+
software_revision=frame.device_information.software_revision
|
|
79
|
+
if frame.device_information
|
|
80
|
+
and frame.device_information.software_revision
|
|
81
|
+
else '',
|
|
82
|
+
hardware_revision=frame.device_information.hardware_revision
|
|
83
|
+
if frame.device_information
|
|
84
|
+
and frame.device_information.hardware_revision
|
|
85
|
+
else '',
|
|
86
|
+
device_category=frame.device_information.device_category
|
|
87
|
+
if frame.device_information
|
|
88
|
+
and frame.device_information.device_category
|
|
89
|
+
else DeviceCategory.DEVICE_INFORMATION,
|
|
90
|
+
is_local=frame.device_information.is_local_control
|
|
91
|
+
if frame.device_information
|
|
92
|
+
and frame.device_information.is_local_control
|
|
93
|
+
else False,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def connect(self):
|
|
97
|
+
"""
|
|
98
|
+
Connects the device synchronously.
|
|
99
|
+
"""
|
|
100
|
+
run(self.connect_async())
|
|
101
|
+
|
|
102
|
+
async def connect_async(self):
|
|
103
|
+
"""
|
|
104
|
+
Connects the device asynchronously.
|
|
105
|
+
"""
|
|
106
|
+
...
|
|
107
|
+
|
|
108
|
+
def disconnect(self):
|
|
109
|
+
"""
|
|
110
|
+
Disconnects the device synchronously.
|
|
111
|
+
"""
|
|
112
|
+
run(self.disconnect_async())
|
|
113
|
+
|
|
114
|
+
async def disconnect_async(self):
|
|
115
|
+
"""
|
|
116
|
+
Disconnects the device asynchronously.
|
|
117
|
+
"""
|
|
118
|
+
...
|
|
119
|
+
|
|
120
|
+
def is_connected(self) -> bool:
|
|
121
|
+
"""
|
|
122
|
+
Gets the connection state.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
bool
|
|
127
|
+
the connection state
|
|
128
|
+
"""
|
|
129
|
+
...
|
|
130
|
+
|
|
131
|
+
def get_functional_profile(
|
|
132
|
+
self, functional_profile_name: str
|
|
133
|
+
) -> FunctionalProfile:
|
|
134
|
+
"""
|
|
135
|
+
Gets a functional profile.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
functional_profile_name : str
|
|
140
|
+
the functional profile name
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
FunctionalProfile
|
|
145
|
+
a functional profile
|
|
146
|
+
"""
|
|
147
|
+
return self.functional_profiles[functional_profile_name]
|
|
148
|
+
|
|
149
|
+
def get_data_point(self, dp: tuple[str, str]) -> DataPoint:
|
|
150
|
+
"""
|
|
151
|
+
Gets a data point.
|
|
152
|
+
|
|
153
|
+
Parameters
|
|
154
|
+
----------
|
|
155
|
+
dp : tuple[str, str]
|
|
156
|
+
the functional profile and data point name
|
|
157
|
+
|
|
158
|
+
Returns
|
|
159
|
+
-------
|
|
160
|
+
DataPoint
|
|
161
|
+
a data point
|
|
162
|
+
"""
|
|
163
|
+
return self.get_functional_profile(dp[0]).get_data_point(dp[1])
|
|
164
|
+
|
|
165
|
+
def get_data_points(self) -> dict[tuple[str, str], DataPoint]:
|
|
166
|
+
"""
|
|
167
|
+
Gets all data points.
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
dict[tuple[str, str], DataPoint]
|
|
172
|
+
all data points
|
|
173
|
+
"""
|
|
174
|
+
data_points = {}
|
|
175
|
+
for fp in self.functional_profiles.values():
|
|
176
|
+
data_points.update(fp.get_data_points())
|
|
177
|
+
return data_points
|
|
178
|
+
|
|
179
|
+
def get_values(self) -> dict[tuple[str, str], Any]:
|
|
180
|
+
"""
|
|
181
|
+
Gets all data point values synchronously.
|
|
182
|
+
|
|
183
|
+
Returns
|
|
184
|
+
-------
|
|
185
|
+
dict[tuple[str, str], Any]
|
|
186
|
+
all data point values
|
|
187
|
+
"""
|
|
188
|
+
return run(self.get_values_async())
|
|
189
|
+
|
|
190
|
+
async def get_values_async(self) -> dict[tuple[str, str], Any]:
|
|
191
|
+
"""
|
|
192
|
+
Gets all data point values asynchronously.
|
|
193
|
+
|
|
194
|
+
Returns
|
|
195
|
+
-------
|
|
196
|
+
dict[tuple[str, str], Any]
|
|
197
|
+
all data point values
|
|
198
|
+
"""
|
|
199
|
+
data = {}
|
|
200
|
+
for fp in self.functional_profiles.values():
|
|
201
|
+
data.update(
|
|
202
|
+
{
|
|
203
|
+
(fp.name(), key): value
|
|
204
|
+
for key, value in (await fp.get_value_async()).items()
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
return data
|
|
208
|
+
|
|
209
|
+
def describe(
|
|
210
|
+
self,
|
|
211
|
+
) -> tuple[
|
|
212
|
+
str, dict[str, dict[str, tuple[DataDirectionProduct, DataTypes]]]
|
|
213
|
+
]:
|
|
214
|
+
"""
|
|
215
|
+
Gets the device description and all data.
|
|
216
|
+
|
|
217
|
+
Returns
|
|
218
|
+
-------
|
|
219
|
+
tuple[str, dict[str, dict[str, tuple[DataDirectionProduct, DataTypes]]]]
|
|
220
|
+
a tuple of device name and all data point values
|
|
221
|
+
"""
|
|
222
|
+
data = {}
|
|
223
|
+
for fp in self.functional_profiles.values():
|
|
224
|
+
key, dps = fp.describe()
|
|
225
|
+
data[key] = dps
|
|
226
|
+
return self.device_information.name, data
|