MTPPy2.0 0.1.5__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.
- examples/__init__.py +0 -0
- examples/minimal+pid.py +82 -0
- examples/minimal.py +32 -0
- examples/minimal_recipe.py +117 -0
- examples/pea_alarm_base.py +47 -0
- examples/pea_minimal.py +258 -0
- mtppy/__init__.py +1 -0
- mtppy/part1/__init__.py +4 -0
- mtppy/part1/empty_folder_test.py +7 -0
- mtppy/part3/__init__.py +4 -0
- mtppy/part3/data_assembly_set/__init__.py +4 -0
- mtppy/part3/data_assembly_set/active_elements/__init__.py +4 -0
- mtppy/part3/data_assembly_set/active_elements/active_element.py +22 -0
- mtppy/part3/data_assembly_set/active_elements/drives/__init__.py +4 -0
- mtppy/part3/data_assembly_set/active_elements/drives/ana_drv.py +446 -0
- mtppy/part3/data_assembly_set/active_elements/drives/ana_drv_test.py +567 -0
- mtppy/part3/data_assembly_set/active_elements/drives/bin_drv.py +365 -0
- mtppy/part3/data_assembly_set/active_elements/drives/bin_drv_test.py +503 -0
- mtppy/part3/data_assembly_set/active_elements/drives/mon_ana_drv.py +469 -0
- mtppy/part3/data_assembly_set/active_elements/drives/mon_ana_drv_test.py +418 -0
- mtppy/part3/data_assembly_set/active_elements/drives/mon_bin_drv.py +295 -0
- mtppy/part3/data_assembly_set/active_elements/drives/mon_bin_drv_test.py +265 -0
- mtppy/part3/data_assembly_set/active_elements/pid/__init__.py +4 -0
- mtppy/part3/data_assembly_set/active_elements/pid/pid_ctrl.py +333 -0
- mtppy/part3/data_assembly_set/active_elements/pid/pid_ctrl_test.py +156 -0
- mtppy/part3/data_assembly_set/active_elements/valves/__init__.py +4 -0
- mtppy/part3/data_assembly_set/active_elements/valves/ana_vlv.py +402 -0
- mtppy/part3/data_assembly_set/active_elements/valves/ana_vlv_test.py +732 -0
- mtppy/part3/data_assembly_set/active_elements/valves/bin_vlv.py +279 -0
- mtppy/part3/data_assembly_set/active_elements/valves/bin_vlv_test.py +585 -0
- mtppy/part3/data_assembly_set/active_elements/valves/mon_ana_vlv.py +402 -0
- mtppy/part3/data_assembly_set/active_elements/valves/mon_ana_vlv_test.py +270 -0
- mtppy/part3/data_assembly_set/active_elements/valves/mon_bin_vlv.py +286 -0
- mtppy/part3/data_assembly_set/active_elements/valves/mon_bin_vlv_test.py +224 -0
- mtppy/part3/data_assembly_set/base_functions/__init__.py +4 -0
- mtppy/part3/data_assembly_set/base_functions/operation_mode.py +252 -0
- mtppy/part3/data_assembly_set/base_functions/operation_mode_test.py +260 -0
- mtppy/part3/data_assembly_set/base_functions/oslevel.py +35 -0
- mtppy/part3/data_assembly_set/base_functions/source_mode.py +189 -0
- mtppy/part3/data_assembly_set/base_functions/source_mode_test.py +112 -0
- mtppy/part3/data_assembly_set/base_functions/wqc.py +75 -0
- mtppy/part3/data_assembly_set/base_functions/wqc_test.py +86 -0
- mtppy/part3/data_assembly_set/data_assembly.py +65 -0
- mtppy/part3/data_assembly_set/diagnostic_elements/__init__.py +4 -0
- mtppy/part3/data_assembly_set/diagnostic_elements/diagnostic_element.py +19 -0
- mtppy/part3/data_assembly_set/indicator_elements/__init__.py +4 -0
- mtppy/part3/data_assembly_set/indicator_elements/indicator_element.py +22 -0
- mtppy/part3/data_assembly_set/indicator_elements/views/__init__.py +4 -0
- mtppy/part3/data_assembly_set/indicator_elements/views/ana_view.py +68 -0
- mtppy/part3/data_assembly_set/indicator_elements/views/bin_view.py +73 -0
- mtppy/part3/data_assembly_set/indicator_elements/views/dint_view.py +76 -0
- mtppy/part3/data_assembly_set/indicator_elements/views/string_view.py +55 -0
- mtppy/part3/data_assembly_set/operation_elements/__init__.py +4 -0
- mtppy/part3/data_assembly_set/operation_elements/operation_element.py +19 -0
- mtppy/part3/data_assembly_set/pea_elements/__init__.py +4 -0
- mtppy/part3/data_assembly_set/pea_elements/pea_element.py +28 -0
- mtppy/part3/data_assembly_set/pea_elements/pea_information_label/__init__.py +4 -0
- mtppy/part3/data_assembly_set/pea_elements/pea_information_label/pea_information_label.py +231 -0
- mtppy/part3/data_assembly_set/pea_elements/web_server_url_info/__init__.py +4 -0
- mtppy/part3/data_assembly_set/pea_elements/web_server_url_info/web_server_url_info.py +42 -0
- mtppy/part3/definitions/__init__.py +4 -0
- mtppy/part3/definitions/mtp_access.py +15 -0
- mtppy/part4/__init__.py +4 -0
- mtppy/part4/automation_services/__init__.py +4 -0
- mtppy/part4/automation_services/base_functions/__init__.py +4 -0
- mtppy/part4/automation_services/base_functions/service_operation_mode.py +368 -0
- mtppy/part4/automation_services/base_functions/service_operation_mode_test.py +242 -0
- mtppy/part4/automation_services/base_functions/service_operator_interaction.py +62 -0
- mtppy/part4/automation_services/base_functions/service_source_mode.py +138 -0
- mtppy/part4/automation_services/base_functions/service_source_mode_test.py +179 -0
- mtppy/part4/automation_services/helpers/__init__.py +4 -0
- mtppy/part4/automation_services/helpers/command_en_control.py +330 -0
- mtppy/part4/automation_services/helpers/command_en_control_test.py +302 -0
- mtppy/part4/automation_services/helpers/state_machine.py +167 -0
- mtppy/part4/automation_services/helpers/state_machine_test.py +294 -0
- mtppy/part4/automation_services/helpers/thread_control.py +39 -0
- mtppy/part4/automation_services/helpers/thread_control_test.py +80 -0
- mtppy/part4/automation_services/procedure.py +111 -0
- mtppy/part4/automation_services/procedure_test.py +185 -0
- mtppy/part4/automation_services/service.py +463 -0
- mtppy/part4/automation_services/service_elements/__init__.py +4 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/__init__.py +4 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/ana_serv_param.py +108 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/ana_serv_param_test.py +59 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/bin_serv_param.py +70 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/bin_serv_param_test.py +39 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/common_serv_param.py +111 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/dint_serv_param.py +77 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/dint_serv_param_test.py +58 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/parameter_element.py +175 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/parameter_element_test.py +246 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/string_serv_param.py +48 -0
- mtppy/part4/automation_services/service_elements/parameter_elements/string_serv_param_test.py +37 -0
- mtppy/part4/automation_services/service_elements/procedure_health_view.py +36 -0
- mtppy/part4/automation_services/service_elements/service_control.py +473 -0
- mtppy/part4/automation_services/service_elements/service_control_test.py +150 -0
- mtppy/part4/automation_services/service_elements/service_element.py +20 -0
- mtppy/part4/automation_services/service_test.py +407 -0
- mtppy/part4/definitions/__init__.py +4 -0
- mtppy/part4/definitions/command_codes.py +58 -0
- mtppy/part4/definitions/command_codes_test.py +44 -0
- mtppy/part4/definitions/state_codes.py +65 -0
- mtppy/part4/definitions/state_codes_test.py +44 -0
- mtppy/part4/process_values/__init__.py +4 -0
- mtppy/part4/process_values/base_functions/__init__.py +4 -0
- mtppy/part4/process_values/base_functions/vqc.py +48 -0
- mtppy/part4/process_values/input_elements/__init__.py +4 -0
- mtppy/part4/process_values/input_elements/ana_process_value_in.py +160 -0
- mtppy/part4/process_values/input_elements/bin_process_value_in.py +83 -0
- mtppy/part4/process_values/input_elements/dint_process_value_in.py +159 -0
- mtppy/part4/process_values/input_elements/input_element.py +40 -0
- mtppy/part4/process_values/input_elements/string_process_value_in.py +45 -0
- mtppy/part5/__init__.py +4 -0
- mtppy/part5/communication_object.py +99 -0
- mtppy/part5/communication_object_test.py +59 -0
- mtppy/part5/definitions/__init__.py +4 -0
- mtppy/part5/definitions/iec61131_data_types.py +31 -0
- mtppy/part5/definitions/iec61131_data_types_test.py +82 -0
- mtppy/part5/definitions/opcua_data_types.py +36 -0
- mtppy/part5/definitions/opcua_data_types_test.py +90 -0
- mtppy/part5/definitions/w3c_xml_data_types.py +177 -0
- mtppy/part5/definitions/w3c_xml_data_types_test.py +143 -0
- mtppy/part5/server_assembly_set/__init__.py +5 -0
- mtppy/part6/__init__.py +4 -0
- mtppy/part6/alarm_set/__init__.py +4 -0
- mtppy/part6/alarm_set/alarm.py +132 -0
- mtppy/part6/alarm_set/alarm_test.py +265 -0
- mtppy/pea/__init__.py +19 -0
- mtppy/pea/data_assembly_factory.py +124 -0
- mtppy/pea/data_assembly_factory_test.py +229 -0
- mtppy/pea/mtp_generator/__init__.py +4 -0
- mtppy/pea/mtp_generator/mtp_generator.py +1183 -0
- mtppy/pea/mtp_generator/mtp_generator_test.py +518 -0
- mtppy/pea/pea.py +139 -0
- mtppy/pea/pea_opcua_server/__init__.py +4 -0
- mtppy/pea/pea_opcua_server/marshalling.py +60 -0
- mtppy/pea/pea_opcua_server/opcua_options_provider/__init__.py +4 -0
- mtppy/pea/pea_opcua_server/opcua_options_provider/instances/basic_opcua_options_provider.py +50 -0
- mtppy/pea/pea_opcua_server/opcua_options_provider/opcua_options_provider.py +103 -0
- mtppy/pea/pea_opcua_server/pea_opcua_server.py +492 -0
- mtppy/pea/pea_opcua_server/subscription_list.py +55 -0
- mtppy/pea/pea_test.py +59 -0
- mtppy/pea/rmtp_pea.py +155 -0
- mtppy/pea/rmtp_pea_test.py +27 -0
- mtppy/pea/service_factory.py +178 -0
- mtppy/pea/service_factory_test.py +156 -0
- mtppy/pea/user_logic/__init__.py +4 -0
- mtppy/pea/user_logic/user_logic_pea.py +72 -0
- mtppy/pea/user_logic/user_logic_registry.py +106 -0
- mtppy/pea/user_logic/user_logic_registry_test.py +167 -0
- mtppy/pea/user_logic/user_logic_service.py +228 -0
- mtppy/pea/user_logic/user_logic_service_test.py +289 -0
- mtppy/utils/__init__.py +4 -0
- mtppy/utils/data_assembly_dict.py +61 -0
- mtppy/utils/data_assembly_dict_test.py +107 -0
- mtppy/utils/data_item.py +446 -0
- mtppy/utils/data_item_com_test.py +82 -0
- mtppy/utils/data_item_test.py +325 -0
- mtppy/utils/logging.py +23 -0
- mtppy/utils/logging_test.py +26 -0
- mtppy/utils/mtp_file_handling/__init__.py +4 -0
- mtppy/utils/mtp_file_handling/extract_manifest_from_mtp_file.py +22 -0
- mtppy/utils/mtp_file_handling/extract_mtp_file.py +22 -0
- mtppy/utils/mtp_file_handling/is_valid_mtp.py +22 -0
- mtppy/utils/mtp_file_handling/is_valid_path_for_manifest.py +15 -0
- mtppy/utils/mtp_file_handling/is_valid_path_to_manifest.py +17 -0
- mtppy/utils/mtp_file_handling/is_valid_path_to_mtp.py +17 -0
- mtppy/utils/mtp_file_handling/load_manifest_file.py +24 -0
- mtppy/utils/mtp_file_handling/mtp_reader/__init__.py +4 -0
- mtppy/utils/mtp_file_handling/mtp_reader/mtp_reader.py +103 -0
- mtppy/utils/mtp_file_handling/mtp_reader/mtp_reader_test.py +96 -0
- mtppy/utils/mtp_file_handling/mtp_reader/mtp_xml.py +226 -0
- mtppy/utils/mtp_file_handling/mtp_reader/mtp_xml_test.py +108 -0
- mtppy/utils/mtp_file_handling/mtp_writer/__init__.py +4 -0
- mtppy/utils/mtp_file_handling/mtp_writer/mtp_writer.py +77 -0
- mtppy/utils/mtp_file_handling/mtp_writer/ressources/get_content_types.py +10 -0
- mtppy/utils/mtp_file_handling/mtp_writer/ressources/get_rels.py +11 -0
- mtppy/utils/mtp_file_handling/mtp_writer/test_mtp_writer.py +25 -0
- mtppy/utils/mtp_file_handling/write_manifest_file.py +29 -0
- mtppy/utils/mtp_file_handling/write_manifest_file_test.py +22 -0
- mtppy/utils/mtp_file_handling/write_mtp_file.py +43 -0
- mtppy/utils/mtp_file_handling/write_mtp_file_test.py +22 -0
- mtppy/utils/testing.py +31 -0
- mtppy2_0-0.1.5.dist-info/METADATA +75 -0
- mtppy2_0-0.1.5.dist-info/RECORD +214 -0
- mtppy2_0-0.1.5.dist-info/WHEEL +5 -0
- mtppy2_0-0.1.5.dist-info/entry_points.txt +3 -0
- mtppy2_0-0.1.5.dist-info/licenses/LICENSE +21 -0
- mtppy2_0-0.1.5.dist-info/top_level.txt +4 -0
- tools/__init__.py +0 -0
- tools/create_bugreport.py +150 -0
- tools/inspect_mtp.py +110 -0
- utils/__init__.py +1 -0
- utils/file_handling/__init__.py +4 -0
- utils/file_handling/cleanup_folder.py +9 -0
- utils/file_handling/get_utc_foldername_with_ms.py +15 -0
- utils/file_handling/get_work_dir.py +9 -0
- utils/file_handling/is_valid_path_for_json.py +11 -0
- utils/file_handling/is_valid_path_to_json.py +17 -0
- utils/file_handling/load_json_file.py +18 -0
- utils/file_handling/read_file_from_file_archive.py +43 -0
- utils/file_handling/read_file_string.py +10 -0
- utils/file_handling/validate_json_data.py +28 -0
- utils/file_handling/write_json_file.py +23 -0
- utils/get_uuid.py +18 -0
- utils/get_uuid_test.py +17 -0
- utils/logging.py +100 -0
- utils/logging_test.py +67 -0
- utils/opcua/check_node.py +79 -0
- utils/resolve_unit/resolve_unit.py +11 -0
- utils/resolve_unit/unit_lib.py +2101 -0
- utils/resolve_unit/unit_lib_test.py +36 -0
- utils/type_conversion.py +236 -0
- utils/type_conversion_test.py +114 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Implementation of Analog Process Value Input.
|
|
2
|
+
|
|
3
|
+
This module implements the AnaProcessValueIn class which represents an analog process value input
|
|
4
|
+
element in accordance with the MTP 2.0 specification.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__copyright__ = (
|
|
8
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
9
|
+
)
|
|
10
|
+
__license__ = "MIT"
|
|
11
|
+
|
|
12
|
+
from typing import ClassVar
|
|
13
|
+
|
|
14
|
+
from mtppy.utils.logging import logger
|
|
15
|
+
from mtppy.utils.data_item import DataItem
|
|
16
|
+
from mtppy.part3.definitions.mtp_access import MTPAccess
|
|
17
|
+
from mtppy.part5.definitions.w3c_xml_data_types import W3cXmlDataTypes
|
|
18
|
+
from mtppy.part3.data_assembly_set.base_functions.oslevel import OSLevelBaseFunction
|
|
19
|
+
from mtppy.part4.process_values.input_elements.input_element import InputElement
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AnaProcessValueIn(InputElement):
|
|
23
|
+
"""Analog Process Value Input (AnaProcessValueIn).
|
|
24
|
+
|
|
25
|
+
Implements an analog process value input element according to MTP 2.0 specification.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
V_ = "V"
|
|
29
|
+
UNIT_CUR = "UnitCur"
|
|
30
|
+
SCL_MIN_CUR = "SclMinCur"
|
|
31
|
+
SCL_MAX_CUR = "SclMaxCur"
|
|
32
|
+
UNIT_EXT = "UnitExt"
|
|
33
|
+
SCL_MIN_EXT = "SclMinExt"
|
|
34
|
+
SCL_MAX_EXT = "SclMaxExt"
|
|
35
|
+
APPLY_EN = "ApplyEn"
|
|
36
|
+
APPLY_ = "Apply"
|
|
37
|
+
|
|
38
|
+
# Class-level data items dictionary
|
|
39
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
40
|
+
V_: DataItem(V_, W3cXmlDataTypes.FLOAT, MTPAccess.ReadWriteAccess, 0),
|
|
41
|
+
UNIT_CUR: DataItem(UNIT_CUR, W3cXmlDataTypes.SHORT, MTPAccess.ReadAccess, 0),
|
|
42
|
+
SCL_MIN_CUR: DataItem(
|
|
43
|
+
SCL_MIN_CUR, W3cXmlDataTypes.FLOAT, MTPAccess.ReadAccess, 0
|
|
44
|
+
),
|
|
45
|
+
SCL_MAX_CUR: DataItem(
|
|
46
|
+
SCL_MAX_CUR, W3cXmlDataTypes.FLOAT, MTPAccess.ReadAccess, 0
|
|
47
|
+
),
|
|
48
|
+
UNIT_EXT: DataItem(
|
|
49
|
+
UNIT_EXT, W3cXmlDataTypes.SHORT, MTPAccess.ReadWriteAccess, 0, None
|
|
50
|
+
),
|
|
51
|
+
SCL_MIN_EXT: DataItem(
|
|
52
|
+
SCL_MIN_EXT, W3cXmlDataTypes.FLOAT, MTPAccess.ReadWriteAccess, 0, None
|
|
53
|
+
),
|
|
54
|
+
SCL_MAX_EXT: DataItem(
|
|
55
|
+
SCL_MAX_EXT, W3cXmlDataTypes.FLOAT, MTPAccess.ReadWriteAccess, 0, None
|
|
56
|
+
),
|
|
57
|
+
APPLY_EN: DataItem(
|
|
58
|
+
APPLY_EN, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, False
|
|
59
|
+
),
|
|
60
|
+
APPLY_: DataItem(
|
|
61
|
+
APPLY_, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadWriteAccess, False, None
|
|
62
|
+
),
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
os_level: OSLevelBaseFunction
|
|
66
|
+
|
|
67
|
+
def __init__(
|
|
68
|
+
self,
|
|
69
|
+
tag_name: str,
|
|
70
|
+
tag_description: str,
|
|
71
|
+
v: float = 0,
|
|
72
|
+
scl_min_cur: float = 0,
|
|
73
|
+
scl_max_cur: float = 100,
|
|
74
|
+
unit_cur: int = 1998,
|
|
75
|
+
apply_en: bool = False,
|
|
76
|
+
) -> None:
|
|
77
|
+
"""Initialize the AnaProcessValueIn element.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
tag_name: Name of the tag.
|
|
81
|
+
tag_description: Description of the tag.
|
|
82
|
+
v: Initial value for the V data item.
|
|
83
|
+
scl_min_cur: Current scale minimum value.
|
|
84
|
+
scl_max_cur: Current scale maximum value.
|
|
85
|
+
unit_cur: Current unit value.
|
|
86
|
+
apply_en: Apply enable flag.
|
|
87
|
+
"""
|
|
88
|
+
super().__init__(tag_name, tag_description)
|
|
89
|
+
self.mtpObjectType = (
|
|
90
|
+
"MTPDataAssemblySUCLib/DataAssembly/InputElement/AnaProcessValueIn"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
self.os_level = OSLevelBaseFunction()
|
|
94
|
+
|
|
95
|
+
# Set initial values for data items
|
|
96
|
+
self[self.V_] = v
|
|
97
|
+
self[self.UNIT_CUR] = unit_cur
|
|
98
|
+
self[self.SCL_MIN_CUR] = scl_min_cur
|
|
99
|
+
self[self.SCL_MAX_CUR] = scl_max_cur
|
|
100
|
+
self[self.UNIT_EXT] = 0
|
|
101
|
+
self[self.SCL_MIN_EXT] = 0
|
|
102
|
+
self[self.SCL_MAX_EXT] = 0
|
|
103
|
+
self[self.APPLY_EN] = apply_en
|
|
104
|
+
|
|
105
|
+
self.get_item(self.V_).ext_wrt_cb = self.set_v
|
|
106
|
+
self.get_item(self.UNIT_EXT).ext_wrt_cb = self._set_unit_ext
|
|
107
|
+
self.get_item(self.SCL_MIN_EXT).ext_wrt_cb = self._set_scl_min_ext
|
|
108
|
+
self.get_item(self.SCL_MAX_EXT).ext_wrt_cb = self._set_scl_max_ext
|
|
109
|
+
self.get_item(self.APPLY_).ext_wrt_cb = self.apply
|
|
110
|
+
|
|
111
|
+
def set_v(self, value: float) -> None:
|
|
112
|
+
"""Set the V data item value.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
value: The value to set for the V data item.
|
|
116
|
+
"""
|
|
117
|
+
logger.debug(f"V set to {value}")
|
|
118
|
+
self[self.V_] = value
|
|
119
|
+
|
|
120
|
+
def _set_unit_ext(self, value: int) -> None:
|
|
121
|
+
"""Set the UnitExt data item value.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
value: The value to set for the UnitExt data item.
|
|
125
|
+
"""
|
|
126
|
+
logger.debug(f"UnitExt set to {value}")
|
|
127
|
+
self[self.UNIT_EXT] = value
|
|
128
|
+
|
|
129
|
+
def _set_scl_min_ext(self, value: float) -> None:
|
|
130
|
+
"""Set the SclMinExt data item value.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
value: The value to set for the SclMinExt data item.
|
|
134
|
+
"""
|
|
135
|
+
logger.debug("SclMinExt set to {value}")
|
|
136
|
+
self[self.SCL_MIN_EXT] = value
|
|
137
|
+
|
|
138
|
+
def _set_scl_max_ext(self, value: float) -> None:
|
|
139
|
+
"""Set the SclMaxExt data item value.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
value: The value to set for the SclMaxExt data item.
|
|
143
|
+
"""
|
|
144
|
+
logger.debug(f"SclMaxExt set to {value}")
|
|
145
|
+
self[self.SCL_MAX_EXT] = value
|
|
146
|
+
|
|
147
|
+
def set_apply_en(self, value: bool) -> None:
|
|
148
|
+
"""Set the ApplyEn data item value.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
value: The boolean value to set for the ApplyEn data item.
|
|
152
|
+
"""
|
|
153
|
+
self[self.APPLY_EN] = value
|
|
154
|
+
|
|
155
|
+
def apply(self) -> None:
|
|
156
|
+
"""Apply the external values to current values."""
|
|
157
|
+
self[self.UNIT_CUR] = self[self.UNIT_EXT]
|
|
158
|
+
self[self.SCL_MIN_CUR] = self[self.SCL_MIN_EXT]
|
|
159
|
+
self[self.SCL_MAX_CUR] = self[self.SCL_MAX_EXT]
|
|
160
|
+
self[self.APPLY_] = False
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Implements Binary Process Value Input.
|
|
2
|
+
|
|
3
|
+
This module implements the BinProcessValueIn class which represents a binary process value input
|
|
4
|
+
element in accordance with the MTP 2.0 specification.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__copyright__ = (
|
|
8
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
9
|
+
)
|
|
10
|
+
__license__ = "MIT"
|
|
11
|
+
|
|
12
|
+
from typing import ClassVar
|
|
13
|
+
|
|
14
|
+
from mtppy.utils.logging import logger
|
|
15
|
+
from mtppy.utils.data_item import DataItem
|
|
16
|
+
from mtppy.part3.definitions.mtp_access import MTPAccess
|
|
17
|
+
from mtppy.part5.definitions.w3c_xml_data_types import W3cXmlDataTypes
|
|
18
|
+
from mtppy.part3.data_assembly_set.base_functions.oslevel import OSLevelBaseFunction
|
|
19
|
+
from mtppy.part4.process_values.input_elements.input_element import InputElement
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BinProcessValueIn(InputElement):
|
|
23
|
+
"""Binary Process Value Input (BinProcessValueIn).
|
|
24
|
+
|
|
25
|
+
Implements a binary process value input element according to MTP 2.0 specification.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
V_ = "V"
|
|
29
|
+
V_STATE_0 = "VState0"
|
|
30
|
+
V_STATE_1 = "VState1"
|
|
31
|
+
|
|
32
|
+
# Class-level data items dictionary
|
|
33
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
34
|
+
V_: DataItem(V_, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadWriteAccess, False),
|
|
35
|
+
V_STATE_0: DataItem(
|
|
36
|
+
V_STATE_0, W3cXmlDataTypes.STRING, MTPAccess.ReadAccess, ""
|
|
37
|
+
),
|
|
38
|
+
V_STATE_1: DataItem(
|
|
39
|
+
V_STATE_1, W3cXmlDataTypes.STRING, MTPAccess.ReadAccess, ""
|
|
40
|
+
),
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
os_level: OSLevelBaseFunction
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
tag_name: str,
|
|
48
|
+
tag_description: str,
|
|
49
|
+
v: bool = False,
|
|
50
|
+
v_state_0: str = "False",
|
|
51
|
+
v_state_1: str = "True",
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Initialize the BinProcessValueIn element.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
tag_name: Name of the tag.
|
|
57
|
+
tag_description: Description of the tag.
|
|
58
|
+
v: Initial value for the V data item.
|
|
59
|
+
v_state_0: Value for VState0 data item.
|
|
60
|
+
v_state_1: Value for VState1 data item.
|
|
61
|
+
"""
|
|
62
|
+
super().__init__(tag_name, tag_description)
|
|
63
|
+
self.mtpObjectType = (
|
|
64
|
+
"MTPDataAssemblySUCLib/DataAssembly/InputElement/BinProcessValueIn"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
self.os_level = OSLevelBaseFunction()
|
|
68
|
+
|
|
69
|
+
# Set initial values for data items
|
|
70
|
+
self[self.V_] = v
|
|
71
|
+
self[self.V_STATE_0] = v_state_0
|
|
72
|
+
self[self.V_STATE_1] = v_state_1
|
|
73
|
+
|
|
74
|
+
self.get_item(self.V_).ext_wrt_cb = self.set_v
|
|
75
|
+
|
|
76
|
+
def set_v(self, value: bool) -> None:
|
|
77
|
+
"""Set the V data item value.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
value: The boolean value to set for the V data item.
|
|
81
|
+
"""
|
|
82
|
+
logger.debug(f"V set to {value}")
|
|
83
|
+
self[self.V_] = value
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""Implementation of DIntProcessValueIn
|
|
2
|
+
|
|
3
|
+
This module implements the DIntProcessValueIn class which represents a discrete integer
|
|
4
|
+
process value input element in accordance with the MTP 2.0 specification.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__copyright__ = (
|
|
8
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
9
|
+
)
|
|
10
|
+
__license__ = "MIT"
|
|
11
|
+
|
|
12
|
+
from typing import ClassVar
|
|
13
|
+
|
|
14
|
+
from mtppy.utils.logging import logger
|
|
15
|
+
from mtppy.utils.data_item import DataItem
|
|
16
|
+
from mtppy.part3.definitions.mtp_access import MTPAccess
|
|
17
|
+
from mtppy.part5.definitions.w3c_xml_data_types import W3cXmlDataTypes
|
|
18
|
+
from mtppy.part3.data_assembly_set.base_functions.oslevel import OSLevelBaseFunction
|
|
19
|
+
from mtppy.part4.process_values.input_elements.input_element import InputElement
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class DIntProcessValueIn(InputElement):
|
|
23
|
+
"""Discrete Integer Process Value Input (DIntProcessValueIn)."""
|
|
24
|
+
|
|
25
|
+
V_ = "V"
|
|
26
|
+
UNIT_CUR = "UnitCur"
|
|
27
|
+
SCL_MIN_CUR = "SclMinCur"
|
|
28
|
+
SCL_MAX_CUR = "SclMaxCur"
|
|
29
|
+
UNIT_EXT = "UnitExt"
|
|
30
|
+
SCL_MIN_EXT = "SclMinExt"
|
|
31
|
+
SCL_MAX_EXT = "SclMaxExt"
|
|
32
|
+
APPLY_EN = "ApplyEn"
|
|
33
|
+
APPLY_ = "Apply"
|
|
34
|
+
|
|
35
|
+
# Class-level data items dictionary
|
|
36
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
37
|
+
V_: DataItem(V_, W3cXmlDataTypes.SHORT, MTPAccess.ReadWriteAccess, 0),
|
|
38
|
+
UNIT_CUR: DataItem(UNIT_CUR, W3cXmlDataTypes.SHORT, MTPAccess.ReadAccess, 0),
|
|
39
|
+
SCL_MIN_CUR: DataItem(
|
|
40
|
+
SCL_MIN_CUR, W3cXmlDataTypes.SHORT, MTPAccess.ReadAccess, 0
|
|
41
|
+
),
|
|
42
|
+
SCL_MAX_CUR: DataItem(
|
|
43
|
+
SCL_MAX_CUR, W3cXmlDataTypes.SHORT, MTPAccess.ReadAccess, 0
|
|
44
|
+
),
|
|
45
|
+
UNIT_EXT: DataItem(
|
|
46
|
+
UNIT_EXT, W3cXmlDataTypes.SHORT, MTPAccess.ReadWriteAccess, 0
|
|
47
|
+
),
|
|
48
|
+
SCL_MIN_EXT: DataItem(
|
|
49
|
+
SCL_MIN_EXT, W3cXmlDataTypes.SHORT, MTPAccess.ReadWriteAccess, 0
|
|
50
|
+
),
|
|
51
|
+
SCL_MAX_EXT: DataItem(
|
|
52
|
+
SCL_MAX_EXT, W3cXmlDataTypes.SHORT, MTPAccess.ReadWriteAccess, 0
|
|
53
|
+
),
|
|
54
|
+
APPLY_EN: DataItem(
|
|
55
|
+
APPLY_EN, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, False
|
|
56
|
+
),
|
|
57
|
+
APPLY_: DataItem(
|
|
58
|
+
APPLY_, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadWriteAccess, False
|
|
59
|
+
),
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
os_level: OSLevelBaseFunction
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
tag_name: str,
|
|
67
|
+
tag_description: str,
|
|
68
|
+
v: int = 0,
|
|
69
|
+
scl_min_cur: int = 0,
|
|
70
|
+
scl_max_cur: int = 100,
|
|
71
|
+
unit_cur: int = 1998,
|
|
72
|
+
apply_en: bool = False,
|
|
73
|
+
) -> None:
|
|
74
|
+
"""Initialize the DIntProcessValueIn element.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
tag_name: Name of the tag.
|
|
78
|
+
tag_description: Description of the tag.
|
|
79
|
+
v: Initial value for the V data item.
|
|
80
|
+
scl_min_cur: Current scale minimum value.
|
|
81
|
+
scl_max_cur: Current scale maximum value.
|
|
82
|
+
unit_cur: Current unit value.
|
|
83
|
+
apply_en: Apply enable flag.
|
|
84
|
+
"""
|
|
85
|
+
super().__init__(tag_name, tag_description)
|
|
86
|
+
self.mtpObjectType = (
|
|
87
|
+
"MTPDataAssemblySUCLib/DataAssembly/InputElement/DIntProcessValueIn"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
self.os_level = OSLevelBaseFunction()
|
|
91
|
+
|
|
92
|
+
# Set initial values for data items
|
|
93
|
+
self[self.V_] = v
|
|
94
|
+
self[self.UNIT_CUR] = unit_cur
|
|
95
|
+
self[self.SCL_MIN_CUR] = scl_min_cur
|
|
96
|
+
self[self.SCL_MAX_CUR] = scl_max_cur
|
|
97
|
+
self[self.UNIT_EXT] = 0
|
|
98
|
+
self[self.SCL_MIN_EXT] = 0
|
|
99
|
+
self[self.SCL_MAX_EXT] = 0
|
|
100
|
+
self[self.APPLY_EN] = apply_en
|
|
101
|
+
self[self.APPLY_] = False
|
|
102
|
+
|
|
103
|
+
# Setup callbacks
|
|
104
|
+
self.get_item(self.V_).ext_wrt_cb = self.set_v
|
|
105
|
+
self.get_item(self.UNIT_EXT).ext_wrt_cb = self.set_unit_ext
|
|
106
|
+
self.get_item(self.SCL_MIN_EXT).ext_wrt_cb = self.set_scl_min_ext
|
|
107
|
+
self.get_item(self.SCL_MAX_EXT).ext_wrt_cb = self.set_scl_max_ext
|
|
108
|
+
self.get_item(self.APPLY_).ext_wrt_cb = self.apply
|
|
109
|
+
|
|
110
|
+
def set_v(self, value: int) -> None:
|
|
111
|
+
"""Set the V data item value.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
value: The value to set for the V data item.
|
|
115
|
+
"""
|
|
116
|
+
logger.debug(f"V set to {value}")
|
|
117
|
+
self[self.V_] = value
|
|
118
|
+
|
|
119
|
+
def set_unit_ext(self, value: int) -> None:
|
|
120
|
+
"""Set the UnitExt data item value.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
value: The value to set for the UnitExt data item.
|
|
124
|
+
"""
|
|
125
|
+
logger.debug(f"UnitExt set to {value}")
|
|
126
|
+
self[self.UNIT_EXT] = value
|
|
127
|
+
|
|
128
|
+
def set_scl_min_ext(self, value: int) -> None:
|
|
129
|
+
"""Set the SclMinExt data item value.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
value: The value to set for the SclMinExt data item.
|
|
133
|
+
"""
|
|
134
|
+
logger.debug(f"SclMinExt set to {value}")
|
|
135
|
+
self[self.SCL_MIN_EXT] = value
|
|
136
|
+
|
|
137
|
+
def set_scl_max_ext(self, value: int) -> None:
|
|
138
|
+
"""Set the SclMaxExt data item value.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
value: The value to set for the SclMaxExt data item.
|
|
142
|
+
"""
|
|
143
|
+
logger.debug(f"SclMaxExt set to {value}")
|
|
144
|
+
self[self.SCL_MAX_EXT] = value
|
|
145
|
+
|
|
146
|
+
def set_apply_en(self, value: bool) -> None:
|
|
147
|
+
"""Set the ApplyEn data item value.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
value: The boolean value to set for the ApplyEn data item.
|
|
151
|
+
"""
|
|
152
|
+
self[self.APPLY_EN] = value
|
|
153
|
+
|
|
154
|
+
def apply(self) -> None:
|
|
155
|
+
"""Apply the external values to current values."""
|
|
156
|
+
self[self.UNIT_CUR] = self[self.UNIT_EXT]
|
|
157
|
+
self[self.SCL_MIN_CUR] = self[self.SCL_MIN_EXT]
|
|
158
|
+
self[self.SCL_MAX_CUR] = self[self.SCL_MAX_EXT]
|
|
159
|
+
self[self.APPLY_] = False
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Base Class for Input Elements."""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
|
|
8
|
+
from mtppy.part3.data_assembly_set.data_assembly import DataAssembly
|
|
9
|
+
from mtppy.part3.data_assembly_set.base_functions.wqc import WQCBaseFunction
|
|
10
|
+
from mtppy.part4.process_values.base_functions.vqc import VQCBaseFunction
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class InputElement(DataAssembly):
|
|
14
|
+
"""Base class for input elements in the process value framework.
|
|
15
|
+
|
|
16
|
+
Input elements provide data input capabilities with integrated quality control
|
|
17
|
+
through WQC (Write Quality Control) and VQC (Validation Quality Control) functions.
|
|
18
|
+
They inherit from DataAssembly and serve as the foundation for various input
|
|
19
|
+
element types in the system.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
wqc: Write Quality Control function instance for managing write operations
|
|
23
|
+
vqc: Validation Quality Control function instance for validating data
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
wqc: WQCBaseFunction
|
|
27
|
+
vqc: VQCBaseFunction
|
|
28
|
+
|
|
29
|
+
def __init__(self, tag_name: str, tag_description: str):
|
|
30
|
+
"""Initialize an InputElement instance.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
tag_name: The name identifier for the input element
|
|
34
|
+
tag_description: A descriptive text for the input element
|
|
35
|
+
"""
|
|
36
|
+
super().__init__(tag_name, tag_description)
|
|
37
|
+
self.mtpObjectType = "MTPDataAssemblySUCLib/DataAssembly/InputElement"
|
|
38
|
+
|
|
39
|
+
self.wqc = WQCBaseFunction()
|
|
40
|
+
self.vqc = VQCBaseFunction()
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Implementation of String Process Value Input.
|
|
2
|
+
|
|
3
|
+
This module implements the StringProcessValueIn class which represents an analog process value input
|
|
4
|
+
element in accordance with the MTP 2.0 specification.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__copyright__ = (
|
|
8
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
9
|
+
)
|
|
10
|
+
__license__ = "MIT"
|
|
11
|
+
|
|
12
|
+
from typing import ClassVar
|
|
13
|
+
|
|
14
|
+
from mtppy.utils.logging import logger
|
|
15
|
+
from mtppy.utils.data_item import DataItem
|
|
16
|
+
from mtppy.part3.definitions.mtp_access import MTPAccess
|
|
17
|
+
from mtppy.part5.definitions.w3c_xml_data_types import W3cXmlDataTypes
|
|
18
|
+
from mtppy.part3.data_assembly_set.base_functions.oslevel import OSLevelBaseFunction
|
|
19
|
+
from mtppy.part4.process_values.input_elements.input_element import InputElement
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class StringProcessValueIn(InputElement):
|
|
23
|
+
V_ = "V"
|
|
24
|
+
|
|
25
|
+
# Class-level data items dictionary
|
|
26
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
27
|
+
V_: DataItem(V_, W3cXmlDataTypes.STRING, MTPAccess.ReadWriteAccess, "")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
os_level: OSLevelBaseFunction
|
|
31
|
+
|
|
32
|
+
def __init__(self, tag_name: str, tag_description: str, v: str = ""):
|
|
33
|
+
super().__init__(tag_name, tag_description)
|
|
34
|
+
self.mtpObjectType = (
|
|
35
|
+
"MTPDataAssemblySUCLib/DataAssembly/InputElement/StringProcessValueIn"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
self.os_level = OSLevelBaseFunction()
|
|
39
|
+
|
|
40
|
+
self[self.V_] = v
|
|
41
|
+
self.get_item(self.V_).ext_wrt_cb = self.set_v
|
|
42
|
+
|
|
43
|
+
def set_v(self, value):
|
|
44
|
+
logger.debug(f"V set to {value}")
|
|
45
|
+
self[self.V_] = value
|
mtppy/part5/__init__.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Communication objects encapsulate value updates for external protocols."""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from opcua import ua
|
|
12
|
+
from opcua.common.node import Node as OPCUA_Node
|
|
13
|
+
|
|
14
|
+
import utils.type_conversion as tc
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CommunicationObject(ABC):
|
|
18
|
+
"""Base class for protocol-specific communication objects.
|
|
19
|
+
|
|
20
|
+
A communication object binds a protocol-specific node to a callback that a
|
|
21
|
+
DataItem can use to publish value changes.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
write_value_callback: Public callback that delegates to the concrete
|
|
25
|
+
protocol-specific write implementation.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, node_obj: Any, node_id: str) -> None:
|
|
29
|
+
"""Initialize a communication object.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
node_obj: Protocol-specific node or client object used to write
|
|
33
|
+
values.
|
|
34
|
+
node_id: Identifier of the associated node or register. Its
|
|
35
|
+
interpretation is defined by the concrete subclass.
|
|
36
|
+
"""
|
|
37
|
+
self._node_obj = node_obj
|
|
38
|
+
self._node_id = node_id
|
|
39
|
+
self.write_value_callback = self._set_value
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def _set_value(self, value: tc.ANY_TYPE) -> None:
|
|
43
|
+
"""Write a value using the protocol-specific implementation.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
value: Value to write to the associated external node.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class OPCUACommunicationObject(CommunicationObject):
|
|
51
|
+
"""Write DataItem values to an OPC UA node.
|
|
52
|
+
|
|
53
|
+
Values are wrapped in an ``opcua.ua.Variant`` before being passed to the
|
|
54
|
+
node's ``set_value`` method.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def __init__(self, opcua_node_obj: OPCUA_Node, node_id: str) -> None:
|
|
58
|
+
"""Initialize an OPC UA communication object.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
opcua_node_obj: OPC UA node that receives written values.
|
|
62
|
+
node_id: OPC UA node identifier retained for diagnostics and model
|
|
63
|
+
generation.
|
|
64
|
+
"""
|
|
65
|
+
super().__init__(opcua_node_obj, node_id)
|
|
66
|
+
|
|
67
|
+
def _set_value(self, value: tc.ANY_TYPE) -> None:
|
|
68
|
+
"""Set a value on the OPC UA node.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
value: Value to wrap in an OPC UA Variant and write to the node.
|
|
72
|
+
"""
|
|
73
|
+
self._node_obj.set_value(ua.Variant(value))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class MODBUSCommunicationObject(CommunicationObject):
|
|
77
|
+
"""Write DataItem values to a Modbus holding register.
|
|
78
|
+
|
|
79
|
+
The ``node_obj`` is expected to be a pymodbus client exposing
|
|
80
|
+
``write_register``. The string ``node_id`` is converted to an integer
|
|
81
|
+
register address for each write.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
def __init__(self, modbus_client: Any, node_id: str) -> None:
|
|
85
|
+
"""Initialize a Modbus communication object.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
modbus_client: Pymodbus client used to write the register.
|
|
89
|
+
node_id: Register address represented as a string.
|
|
90
|
+
"""
|
|
91
|
+
super().__init__(modbus_client, node_id)
|
|
92
|
+
|
|
93
|
+
def _set_value(self, value: tc.ANY_TYPE) -> None:
|
|
94
|
+
"""Write a value to the configured Modbus holding register.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
value: Integer-compatible value accepted by pymodbus.
|
|
98
|
+
"""
|
|
99
|
+
self._node_obj.write_register(address=int(self._node_id), value=value)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Test suite for the OPC UA communication object."""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
|
|
8
|
+
from unittest.mock import Mock
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from opcua import ua
|
|
12
|
+
|
|
13
|
+
from mtppy.part5.communication_object import (
|
|
14
|
+
CommunicationObject,
|
|
15
|
+
MODBUSCommunicationObject,
|
|
16
|
+
OPCUACommunicationObject,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TestCommunicationObject(CommunicationObject):
|
|
21
|
+
def _set_value(self, value: Any) -> None:
|
|
22
|
+
self.written_value = value
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_initializes_with_node_and_node_id() -> None:
|
|
26
|
+
node = Mock()
|
|
27
|
+
|
|
28
|
+
communication_object = OPCUACommunicationObject(node, "ns=2;s=Test")
|
|
29
|
+
|
|
30
|
+
assert callable(communication_object.write_value_callback)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_base_callback_delegates_to_protocol_specific_writer() -> None:
|
|
34
|
+
communication_object = TestCommunicationObject(Mock(), "test")
|
|
35
|
+
|
|
36
|
+
communication_object.write_value_callback("value")
|
|
37
|
+
|
|
38
|
+
assert communication_object.written_value == "value"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_write_value_callback_sets_variant_on_node() -> None:
|
|
42
|
+
node = Mock()
|
|
43
|
+
communication_object = OPCUACommunicationObject(node, "ns=2;s=Test")
|
|
44
|
+
|
|
45
|
+
communication_object.write_value_callback(42)
|
|
46
|
+
|
|
47
|
+
node.set_value.assert_called_once()
|
|
48
|
+
value = node.set_value.call_args.args[0]
|
|
49
|
+
assert isinstance(value, ua.Variant)
|
|
50
|
+
assert getattr(value, "Value") == 42
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_modbus_write_value_callback_writes_to_register() -> None:
|
|
54
|
+
client = Mock()
|
|
55
|
+
communication_object = MODBUSCommunicationObject(client, "42")
|
|
56
|
+
|
|
57
|
+
communication_object.write_value_callback(7)
|
|
58
|
+
|
|
59
|
+
client.write_register.assert_called_once_with(address=42, value=7)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Implementation of IEC-61131 Data Types."""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
|
|
8
|
+
from enum import Enum
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class IEC61131DataTypes(Enum):
|
|
12
|
+
BOOL = ("BOOL",)
|
|
13
|
+
BYTE = ("BYTE",)
|
|
14
|
+
WORD = ("WORD",)
|
|
15
|
+
DWORD = ("DWORD",)
|
|
16
|
+
LWORD = ("LWORD",)
|
|
17
|
+
SINT = ("SINT",)
|
|
18
|
+
INT = ("INT",)
|
|
19
|
+
DINT = ("DINT",)
|
|
20
|
+
LINT = ("LINT",)
|
|
21
|
+
USINT = ("USINT",)
|
|
22
|
+
UINT = ("UINT",)
|
|
23
|
+
UDINT = ("UDINT",)
|
|
24
|
+
ULINT = ("ULINT",)
|
|
25
|
+
REAL = ("REAL",)
|
|
26
|
+
LREAL = ("LREAL",)
|
|
27
|
+
STRING = ("STRING",)
|
|
28
|
+
WSTRING = ("WSTRING",)
|
|
29
|
+
DATE = ("DATE",)
|
|
30
|
+
TIME_OF_DAY = ("TIME_OF_DAY",)
|
|
31
|
+
DATE_AND_TIME = "DATE_AND_TIME"
|