sgr-commhandler 0.4.dev20250512__tar.gz
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-0.4.dev20250512/LICENSE.md +14 -0
- sgr_commhandler-0.4.dev20250512/PKG-INFO +111 -0
- sgr_commhandler-0.4.dev20250512/README.md +84 -0
- sgr_commhandler-0.4.dev20250512/pyproject.toml +47 -0
- sgr_commhandler-0.4.dev20250512/setup.cfg +4 -0
- sgr_commhandler-0.4.dev20250512/setup.py +26 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/__init__.py +0 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/api/__init__.py +18 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/api/configuration_parameter.py +71 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/api/data_point_api.py +316 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/api/data_types.py +14 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/api/device_api.py +226 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/api/functional_profile_api.py +90 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/device_builder.py +337 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/__init__.py +0 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/contact/__init__.py +7 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/contact/contact_interface_async.py +184 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/generic/__init__.py +7 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/generic/generic_interface_async.py +182 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/messaging/__init__.py +7 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/messaging/messaging_interface_async.py +197 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/modbus/__init__.py +7 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/modbus/modbus_client_async.py +403 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/modbus/modbus_interface_async.py +516 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/modbus/payload_decoder.py +108 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/modbus/shared_client.py +119 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/rest/__init__.py +7 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/rest/authentication.py +207 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/driver/rest/restapi_interface_async.py +492 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/utils/__init__.py +1 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/utils/value_util.py +39 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/validators/__init__.py +3 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/validators/resolver.py +71 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler/validators/validator.py +195 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler.egg-info/PKG-INFO +111 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler.egg-info/SOURCES.txt +37 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler.egg-info/dependency_links.txt +1 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler.egg-info/requires.txt +10 -0
- sgr_commhandler-0.4.dev20250512/src/sgr_commhandler.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Copyright(c) 2022 Verein SmartGridready Switzerland
|
|
2
|
+
|
|
3
|
+
This Open Source Software is BSD 3 clause licensed:
|
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
5
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
6
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
|
|
7
|
+
the documentation and/or other materials provided with the distribution.
|
|
8
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from
|
|
9
|
+
this software without specific prior written permission.
|
|
10
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
11
|
+
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
12
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
13
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
14
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: sgr-commhandler
|
|
3
|
+
Version: 0.4.dev20250512
|
|
4
|
+
Summary: SmartGridready CommHandler Library
|
|
5
|
+
Home-page: https://github.com/SmartGridready/SGrPython/commhandler#readme
|
|
6
|
+
Author: Robin Schoch, Matthias Krebs
|
|
7
|
+
Maintainer: Matthias Krebs
|
|
8
|
+
License: BSD-3-Clause
|
|
9
|
+
Project-URL: Homepage, https://www.smartgridready.ch/
|
|
10
|
+
Project-URL: Documentation, https://smartgridready.github.io/SGrPython/docs/commhandler/
|
|
11
|
+
Project-URL: Repository, https://github.com/SmartGridready/SGrPython.git
|
|
12
|
+
Project-URL: Issues, https://github.com/SmartGridready/SGrPython/issues
|
|
13
|
+
Project-URL: Changelog, https://github.com/SmartGridready/SGrPython/blob/master/commhandler/CHANGELOG.md
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE.md
|
|
17
|
+
Requires-Dist: Jinja2<4.0.0,>=3.0.0
|
|
18
|
+
Requires-Dist: jmespath<2.0.0,>=1.0.0
|
|
19
|
+
Requires-Dist: pymodbus<4.0.0,>=3.0.0
|
|
20
|
+
Requires-Dist: setuptools<70.0.0,>=68.0.0
|
|
21
|
+
Requires-Dist: xsdata<23.0.0,>=22.0.0
|
|
22
|
+
Requires-Dist: xmlschema<4.0.0,>=3.0.0
|
|
23
|
+
Requires-Dist: aiohttp<4.0.0,>=3.0.0
|
|
24
|
+
Requires-Dist: certifi
|
|
25
|
+
Requires-Dist: cachetools<6.0.0,>=5.0.0
|
|
26
|
+
Requires-Dist: sgr-specification<3.0.0,>=2.1.0
|
|
27
|
+
|
|
28
|
+
# SmartGridready CommHandler
|
|
29
|
+
|
|
30
|
+
The _commhandler_ library provides the interfaces and drivers to access devices.
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## Contents
|
|
34
|
+
|
|
35
|
+
- [Directory Structure](#directory-structure)
|
|
36
|
+
- [Build Instructions](#build-instructions)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## Directory Structure
|
|
40
|
+
|
|
41
|
+
- `pyproject.toml` is the main project configuration file.
|
|
42
|
+
- `setup.py` is used to build the library package using _setuptools_.
|
|
43
|
+
- `requirements.txt` contains the dependencies required to use the library.
|
|
44
|
+
- `requirements-dev.txt` contains the dependencies required to run tests.
|
|
45
|
+
- `src/sgr_commhandler` contains the source code of the library, with _sgr_commhandler_ being the root of the namespace.
|
|
46
|
+
- `tests` contains unit and integration tests.
|
|
47
|
+
- `examples` contains basic examples of using the library.
|
|
48
|
+
See [SGrPythonSamples](https://github.com/SmartGridready/SGrPythonSamples) for more detailed examples.
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
## Build Instructions
|
|
52
|
+
|
|
53
|
+
### Prerequisites
|
|
54
|
+
|
|
55
|
+
Check out the [SGrPython](https://github.com/SmartGridready/SGrPython) repository, e.g. in `SGrPython`.
|
|
56
|
+
|
|
57
|
+
Create and activate virtual environment:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cd SGrPython
|
|
61
|
+
python -m venv .venv
|
|
62
|
+
|
|
63
|
+
# On Linux call this:
|
|
64
|
+
source ./.venv/bin/activate
|
|
65
|
+
|
|
66
|
+
# On Windows call this:
|
|
67
|
+
.\.venv\Scripts\Activate.ps1
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Make sure you have the _specification_ library `sgr-specification` installed in your virtual environment.
|
|
71
|
+
See [specification](../specification/README.md) for instructions.
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
### Run Tests
|
|
75
|
+
|
|
76
|
+
You can run tests using `pytest` while in virtual environment.
|
|
77
|
+
|
|
78
|
+
It is not necessary to install the package locally, if you only want to run tests.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
cd SGrPython/commhandler
|
|
82
|
+
pip install -r requirements-dev.txt
|
|
83
|
+
|
|
84
|
+
pytest
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
### Build and Use Package
|
|
89
|
+
|
|
90
|
+
Build package and install in virtual environment:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
cd SGrPython/commhandler
|
|
94
|
+
pip install -e .
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
You can use the package `sgr-commhandler` from within the virtual environment now.
|
|
98
|
+
|
|
99
|
+
**Note:**
|
|
100
|
+
The designated package name `sgr-commhandler` must not be used until the _PyPI_ administrators have
|
|
101
|
+
approved a SmartGridready organization account!
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
### Clean Up
|
|
105
|
+
|
|
106
|
+
Deactivate the virtual environment after use:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
cd SGrPython
|
|
110
|
+
deactivate
|
|
111
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# SmartGridready CommHandler
|
|
2
|
+
|
|
3
|
+
The _commhandler_ library provides the interfaces and drivers to access devices.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Contents
|
|
7
|
+
|
|
8
|
+
- [Directory Structure](#directory-structure)
|
|
9
|
+
- [Build Instructions](#build-instructions)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## Directory Structure
|
|
13
|
+
|
|
14
|
+
- `pyproject.toml` is the main project configuration file.
|
|
15
|
+
- `setup.py` is used to build the library package using _setuptools_.
|
|
16
|
+
- `requirements.txt` contains the dependencies required to use the library.
|
|
17
|
+
- `requirements-dev.txt` contains the dependencies required to run tests.
|
|
18
|
+
- `src/sgr_commhandler` contains the source code of the library, with _sgr_commhandler_ being the root of the namespace.
|
|
19
|
+
- `tests` contains unit and integration tests.
|
|
20
|
+
- `examples` contains basic examples of using the library.
|
|
21
|
+
See [SGrPythonSamples](https://github.com/SmartGridready/SGrPythonSamples) for more detailed examples.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## Build Instructions
|
|
25
|
+
|
|
26
|
+
### Prerequisites
|
|
27
|
+
|
|
28
|
+
Check out the [SGrPython](https://github.com/SmartGridready/SGrPython) repository, e.g. in `SGrPython`.
|
|
29
|
+
|
|
30
|
+
Create and activate virtual environment:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd SGrPython
|
|
34
|
+
python -m venv .venv
|
|
35
|
+
|
|
36
|
+
# On Linux call this:
|
|
37
|
+
source ./.venv/bin/activate
|
|
38
|
+
|
|
39
|
+
# On Windows call this:
|
|
40
|
+
.\.venv\Scripts\Activate.ps1
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Make sure you have the _specification_ library `sgr-specification` installed in your virtual environment.
|
|
44
|
+
See [specification](../specification/README.md) for instructions.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### Run Tests
|
|
48
|
+
|
|
49
|
+
You can run tests using `pytest` while in virtual environment.
|
|
50
|
+
|
|
51
|
+
It is not necessary to install the package locally, if you only want to run tests.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
cd SGrPython/commhandler
|
|
55
|
+
pip install -r requirements-dev.txt
|
|
56
|
+
|
|
57
|
+
pytest
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
### Build and Use Package
|
|
62
|
+
|
|
63
|
+
Build package and install in virtual environment:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cd SGrPython/commhandler
|
|
67
|
+
pip install -e .
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
You can use the package `sgr-commhandler` from within the virtual environment now.
|
|
71
|
+
|
|
72
|
+
**Note:**
|
|
73
|
+
The designated package name `sgr-commhandler` must not be used until the _PyPI_ administrators have
|
|
74
|
+
approved a SmartGridready organization account!
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### Clean Up
|
|
78
|
+
|
|
79
|
+
Deactivate the virtual environment after use:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
cd SGrPython
|
|
83
|
+
deactivate
|
|
84
|
+
```
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sgr-commhandler"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "SmartGridready CommHandler Library"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "BSD-3-Clause" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Robin Schoch" },
|
|
14
|
+
{ name = "Matthias Krebs" }
|
|
15
|
+
]
|
|
16
|
+
maintainers = [
|
|
17
|
+
{ name = "Matthias Krebs" }
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
"Jinja2>=3.0.0,<4.0.0",
|
|
21
|
+
"jmespath>=1.0.0,<2.0.0",
|
|
22
|
+
"pymodbus>=3.0.0,<4.0.0",
|
|
23
|
+
"setuptools>=68.0.0,<70.0.0",
|
|
24
|
+
"xsdata>=22.0.0,<23.0.0",
|
|
25
|
+
"xmlschema>=3.0.0,<4.0.0",
|
|
26
|
+
"aiohttp>=3.0.0,<4.0.0",
|
|
27
|
+
"certifi",
|
|
28
|
+
"cachetools>=5.0.0,<6.0.0",
|
|
29
|
+
"sgr-specification>=2.1.0,<3.0.0"
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://www.smartgridready.ch/"
|
|
34
|
+
Documentation = "https://smartgridready.github.io/SGrPython/docs/commhandler/"
|
|
35
|
+
Repository = "https://github.com/SmartGridready/SGrPython.git"
|
|
36
|
+
Issues = "https://github.com/SmartGridready/SGrPython/issues"
|
|
37
|
+
Changelog = "https://github.com/SmartGridready/SGrPython/blob/master/commhandler/CHANGELOG.md"
|
|
38
|
+
|
|
39
|
+
[tool.pyright]
|
|
40
|
+
exclude = ["**/node_modules", "**/__pycache__", "examples"]
|
|
41
|
+
|
|
42
|
+
[tool.pytest.ini_options]
|
|
43
|
+
pythonpath = [ "src" ]
|
|
44
|
+
asyncio_default_fixture_loop_scope = "session"
|
|
45
|
+
asyncio_mode = "strict"
|
|
46
|
+
log_cli = true
|
|
47
|
+
log_cli_level = "DEBUG"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
def read_requirements() -> list[str]:
|
|
4
|
+
with open("./requirements.txt", "r") as file:
|
|
5
|
+
return file.read().splitlines()
|
|
6
|
+
|
|
7
|
+
setup(
|
|
8
|
+
name="sgr-commhandler",
|
|
9
|
+
version="0.4.dev20250512",
|
|
10
|
+
packages=find_packages(where="src"),
|
|
11
|
+
package_dir={"": "src"},
|
|
12
|
+
install_requires=read_requirements(),
|
|
13
|
+
url="https://github.com/SmartGridready/SGrPython/commhandler#readme",
|
|
14
|
+
project_urls={
|
|
15
|
+
"Issue Tracker": "https://github.com/SmartGridready/SGrPython/issues",
|
|
16
|
+
"Source": "https://github.com/SmartGridready/SGrPython",
|
|
17
|
+
"Docs": "https://smartgridready.github.io/SGrPython/docs/commhandler/"
|
|
18
|
+
},
|
|
19
|
+
license="BSD-3",
|
|
20
|
+
license_files=["LICENSE.md"],
|
|
21
|
+
author="Verein SmartGridready",
|
|
22
|
+
description="SGr Commhandler",
|
|
23
|
+
long_description="Communication Handler Library",
|
|
24
|
+
long_description_content_type="text/plain",
|
|
25
|
+
python_requires=">=3.9",
|
|
26
|
+
)
|
|
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()
|