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,189 @@
|
|
|
1
|
+
"""Implementation of the Source Mode Base Function.
|
|
2
|
+
|
|
3
|
+
This module implements the Source Mode Base Function as specified in PNO MTP 2.0
|
|
4
|
+
Part 3, Section 8.2.2.3. The SourceMode class manages the source mode states
|
|
5
|
+
(SrcChannel, SrcIntOp, SrcIntAut, SrcIntAct, SrcManOp, SrcManAut, SrcManAct)
|
|
6
|
+
and provides methods to control the source mode transitions.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__copyright__ = (
|
|
10
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
11
|
+
)
|
|
12
|
+
__license__ = "MIT"
|
|
13
|
+
|
|
14
|
+
import typing
|
|
15
|
+
from typing import ClassVar
|
|
16
|
+
|
|
17
|
+
from mtppy.utils.logging import logger
|
|
18
|
+
from mtppy.utils.data_item import DataItem, DataItemCollection
|
|
19
|
+
from mtppy.part3.definitions.mtp_access import MTPAccess
|
|
20
|
+
from mtppy.part5.definitions.w3c_xml_data_types import W3cXmlDataTypes
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SourceMode(DataItemCollection):
|
|
24
|
+
"""Implements the operation and source modes BaseFunction.
|
|
25
|
+
|
|
26
|
+
This class manages the source mode states and transitions according to
|
|
27
|
+
the MTP 2.0 specification. It handles the interaction between different
|
|
28
|
+
source mode components like channel, internal and manual modes.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
SRC_CHANNEL = "SrcChannel"
|
|
32
|
+
SRC_INT_OP = "SrcIntOp"
|
|
33
|
+
SRC_INT_AUT = "SrcIntAut"
|
|
34
|
+
SRC_INT_ACT = "SrcIntAct"
|
|
35
|
+
SRC_MAN_OP = "SrcManOp"
|
|
36
|
+
SRC_MAN_AUT = "SrcManAut"
|
|
37
|
+
SRC_MAN_ACT = "SrcManAct"
|
|
38
|
+
|
|
39
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
40
|
+
SRC_CHANNEL: DataItem(
|
|
41
|
+
SRC_CHANNEL,
|
|
42
|
+
W3cXmlDataTypes.BOOLEAN,
|
|
43
|
+
MTPAccess.ReadAccess,
|
|
44
|
+
init_value=False,
|
|
45
|
+
description="SourceMode channel - 0: operator (*Op) shall be used, 1: automatic (*Aut) shall be used.",
|
|
46
|
+
),
|
|
47
|
+
SRC_INT_OP: DataItem(
|
|
48
|
+
SRC_INT_OP,
|
|
49
|
+
W3cXmlDataTypes.BOOLEAN,
|
|
50
|
+
MTPAccess.ReadWriteAccess,
|
|
51
|
+
init_value=False,
|
|
52
|
+
description="Request SourceMode to Internal by operator (if SrcChannel is false) - 0: no operation, 1: request internal.",
|
|
53
|
+
),
|
|
54
|
+
SRC_INT_AUT: DataItem(
|
|
55
|
+
SRC_INT_AUT,
|
|
56
|
+
W3cXmlDataTypes.BOOLEAN,
|
|
57
|
+
MTPAccess.ReadAccess,
|
|
58
|
+
init_value=False,
|
|
59
|
+
description="Request SourceMode to Internal by automatic (if SrcChannel is true) - 0: no operation, 1: request internal",
|
|
60
|
+
),
|
|
61
|
+
SRC_INT_ACT: DataItem(
|
|
62
|
+
SRC_INT_ACT,
|
|
63
|
+
W3cXmlDataTypes.BOOLEAN,
|
|
64
|
+
MTPAccess.ReadAccess,
|
|
65
|
+
init_value=False,
|
|
66
|
+
description="Indicator for Internal Mode - 0: internal mode inactive, 1: internal mode active.",
|
|
67
|
+
),
|
|
68
|
+
SRC_MAN_OP: DataItem(
|
|
69
|
+
SRC_MAN_OP,
|
|
70
|
+
W3cXmlDataTypes.BOOLEAN,
|
|
71
|
+
MTPAccess.ReadWriteAccess,
|
|
72
|
+
init_value=False,
|
|
73
|
+
description="Request SourceMode to Manual by operator (if SrcChannel is false) - 0: no operation, 1: request manual.",
|
|
74
|
+
),
|
|
75
|
+
SRC_MAN_AUT: DataItem(
|
|
76
|
+
SRC_MAN_AUT,
|
|
77
|
+
W3cXmlDataTypes.BOOLEAN,
|
|
78
|
+
MTPAccess.ReadAccess,
|
|
79
|
+
init_value=False,
|
|
80
|
+
description="Request SourceMode to Manual by automatic (if SrcChannel is true) - 0: no operation, 1: request manual.",
|
|
81
|
+
),
|
|
82
|
+
SRC_MAN_ACT: DataItem(
|
|
83
|
+
SRC_MAN_ACT,
|
|
84
|
+
W3cXmlDataTypes.BOOLEAN,
|
|
85
|
+
MTPAccess.ReadAccess,
|
|
86
|
+
init_value=False,
|
|
87
|
+
),
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
def __init__(self) -> None:
|
|
91
|
+
"""Initialize the SourceMode instance.
|
|
92
|
+
|
|
93
|
+
The data items defined CLASS_DATA_ITEMS are set up by the
|
|
94
|
+
DataItemCollection. This class registers the callback functions for
|
|
95
|
+
automatic and manual operation mode changes.
|
|
96
|
+
|
|
97
|
+
"""
|
|
98
|
+
super().__init__()
|
|
99
|
+
# add callbacks to ReadWrit-e and WriteAccess variables
|
|
100
|
+
self.get_item(SourceMode.SRC_INT_OP).ext_wrt_cb = self.set_src_int_op
|
|
101
|
+
self.get_item(SourceMode.SRC_MAN_OP).ext_wrt_cb = self.set_src_man_op
|
|
102
|
+
|
|
103
|
+
self.get_item(SourceMode.SRC_MAN_AUT).int_wrt_cb = self.set_src_man_aut
|
|
104
|
+
self.get_item(SourceMode.SRC_INT_AUT).int_wrt_cb = self.set_src_int_aut
|
|
105
|
+
|
|
106
|
+
logger.debug("SourceMode initialized")
|
|
107
|
+
|
|
108
|
+
def _src_to_off(self) -> None:
|
|
109
|
+
self[SourceMode.SRC_INT_ACT] = False
|
|
110
|
+
self[SourceMode.SRC_MAN_ACT] = False
|
|
111
|
+
logger.mtp("SourceMode is now off")
|
|
112
|
+
|
|
113
|
+
def _src_to_int(self) -> None:
|
|
114
|
+
self[SourceMode.SRC_INT_ACT] = True
|
|
115
|
+
self[SourceMode.SRC_MAN_ACT] = False
|
|
116
|
+
logger.mtp("SourceMode is now int")
|
|
117
|
+
|
|
118
|
+
def _src_to_man(self) -> None:
|
|
119
|
+
self[SourceMode.SRC_INT_ACT] = False
|
|
120
|
+
self[SourceMode.SRC_MAN_ACT] = True
|
|
121
|
+
logger.mtp("SourceMode is now man")
|
|
122
|
+
|
|
123
|
+
@typing.override
|
|
124
|
+
def set_src_channel(self, value: bool) -> None:
|
|
125
|
+
"""Set the source channel value.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
value: The boolean value to set for the source channel.
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
self[SourceMode.SRC_CHANNEL] = value
|
|
132
|
+
logger.mtp(
|
|
133
|
+
f"SrcChannel is now {self[SourceMode.SRC_CHANNEL]}",
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
def set_src_man_aut(self, value: bool) -> None:
|
|
137
|
+
"""Set the manual automatic mode.
|
|
138
|
+
|
|
139
|
+
If the source channel is active and the value is True, transitions to
|
|
140
|
+
manual mode.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
value: The boolean value to set for the manual automatic mode.
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
if self[SourceMode.SRC_CHANNEL] and value:
|
|
147
|
+
self._src_to_man()
|
|
148
|
+
|
|
149
|
+
def set_src_man_op(self, value: bool) -> None:
|
|
150
|
+
"""Set the manual operation mode.
|
|
151
|
+
|
|
152
|
+
If the source channel is not active and the value is True, transitions to
|
|
153
|
+
manual mode. Also resets the manual operation mode to False.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
value: The boolean value to set for the manual operation mode.
|
|
157
|
+
|
|
158
|
+
"""
|
|
159
|
+
if not self[SourceMode.SRC_CHANNEL] and value:
|
|
160
|
+
self._src_to_man()
|
|
161
|
+
self[SourceMode.SRC_MAN_OP] = False
|
|
162
|
+
|
|
163
|
+
def set_src_int_aut(self, value: bool) -> None:
|
|
164
|
+
"""Set the internal automatic mode.
|
|
165
|
+
|
|
166
|
+
If the source channel is active and the value is True, transitions to
|
|
167
|
+
internal mode.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
value: The boolean value to set for the internal automatic mode.
|
|
171
|
+
|
|
172
|
+
"""
|
|
173
|
+
if self[SourceMode.SRC_CHANNEL] and value:
|
|
174
|
+
self._src_to_int()
|
|
175
|
+
|
|
176
|
+
def set_src_int_op(self, value: bool) -> None:
|
|
177
|
+
"""Set the internal operation mode.
|
|
178
|
+
|
|
179
|
+
If the source channel is not active and the value is True, transitions to
|
|
180
|
+
internal mode. Also resets the internal operation mode to False to prevent
|
|
181
|
+
infinite loops.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
value: The boolean value to set for the internal operation mode.
|
|
185
|
+
|
|
186
|
+
"""
|
|
187
|
+
if not self[SourceMode.SRC_CHANNEL] and value:
|
|
188
|
+
self._src_to_int() # already done, setting again results in infinite loop
|
|
189
|
+
self[SourceMode.SRC_INT_OP] = False
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""Test Suite for SourceMode."""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from mtppy.part3.data_assembly_set.base_functions.source_mode import SourceMode
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def init_source_mode(init_mode="int", src_channel=False):
|
|
14
|
+
src_mode = SourceMode()
|
|
15
|
+
src_mode.set_src_channel(src_channel)
|
|
16
|
+
|
|
17
|
+
if init_mode == "man":
|
|
18
|
+
src_mode[SourceMode.SRC_MAN_ACT] = True
|
|
19
|
+
elif init_mode == "int":
|
|
20
|
+
src_mode[SourceMode.SRC_INT_ACT] = True
|
|
21
|
+
else:
|
|
22
|
+
raise ValueError(f"Source mode {init_mode} is unknown")
|
|
23
|
+
|
|
24
|
+
return src_mode
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def source_mode_is_in_specific_mode(
|
|
28
|
+
src_mode, source_channel_assertion: bool, mode_assertion: str
|
|
29
|
+
):
|
|
30
|
+
return all(
|
|
31
|
+
[
|
|
32
|
+
src_mode[SourceMode.SRC_CHANNEL] == source_channel_assertion,
|
|
33
|
+
src_mode[SourceMode.SRC_MAN_AUT] == False,
|
|
34
|
+
src_mode[SourceMode.SRC_INT_OP] == False,
|
|
35
|
+
src_mode[SourceMode.SRC_INT_AUT] == False,
|
|
36
|
+
src_mode[SourceMode.SRC_MAN_OP] == False,
|
|
37
|
+
src_mode[SourceMode.SRC_INT_ACT] == (mode_assertion == "int"),
|
|
38
|
+
src_mode[SourceMode.SRC_MAN_ACT] == (mode_assertion == "man"),
|
|
39
|
+
]
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_initial_state():
|
|
44
|
+
# Initial mode
|
|
45
|
+
src_mode = init_source_mode(init_mode="int", src_channel=False)
|
|
46
|
+
assert source_mode_is_in_specific_mode(src_mode, False, "int") == True
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_source_channel_change():
|
|
50
|
+
# Initial mode
|
|
51
|
+
src_mode = init_source_mode()
|
|
52
|
+
# Trigger channel change
|
|
53
|
+
src_mode[SourceMode.SRC_CHANNEL] = True
|
|
54
|
+
assert source_mode_is_in_specific_mode(src_mode, True, "int") == True
|
|
55
|
+
# Trigger channel change back
|
|
56
|
+
src_mode[SourceMode.SRC_CHANNEL] = False
|
|
57
|
+
assert source_mode_is_in_specific_mode(src_mode, False, "int") == True
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_int_to_ext_src_channel_false():
|
|
61
|
+
# Initial mode
|
|
62
|
+
src_mode = init_source_mode()
|
|
63
|
+
assert source_mode_is_in_specific_mode(src_mode, False, "int") == True
|
|
64
|
+
# Trigger mode transition
|
|
65
|
+
src_mode.get_item(SourceMode.SRC_MAN_OP).ext_wrt_cb(True)
|
|
66
|
+
assert source_mode_is_in_specific_mode(src_mode, False, "man") == True
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_int_to_ext_src_channel_true():
|
|
70
|
+
# Initial mode
|
|
71
|
+
src_mode = init_source_mode(src_channel=True)
|
|
72
|
+
assert source_mode_is_in_specific_mode(src_mode, True, "int") == True
|
|
73
|
+
# Trigger mode transition
|
|
74
|
+
src_mode.SrcManAut = True
|
|
75
|
+
assert source_mode_is_in_specific_mode(src_mode, True, "man") == True
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_ext_to_int_src_channel_false():
|
|
79
|
+
# Initial mode
|
|
80
|
+
src_mode = init_source_mode(init_mode="man", src_channel=False)
|
|
81
|
+
assert source_mode_is_in_specific_mode(src_mode, False, "man") == True
|
|
82
|
+
# Trigger mode transition
|
|
83
|
+
src_mode.get_item(SourceMode.SRC_INT_OP).ext_wrt_cb(True)
|
|
84
|
+
assert source_mode_is_in_specific_mode(src_mode, False, "int") == True
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_ext_to_int_src_channel_true():
|
|
88
|
+
# Initial mode
|
|
89
|
+
src_mode = init_source_mode(init_mode="man", src_channel=True)
|
|
90
|
+
assert source_mode_is_in_specific_mode(src_mode, True, "man") == True
|
|
91
|
+
# Trigger mode transition
|
|
92
|
+
src_mode.SrcIntAut = True
|
|
93
|
+
assert source_mode_is_in_specific_mode(src_mode, True, "int") == True
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@pytest.mark.parametrize(
|
|
97
|
+
"state_request",
|
|
98
|
+
[SourceMode.SRC_INT_OP, SourceMode.SRC_MAN_OP],
|
|
99
|
+
)
|
|
100
|
+
def test_external_state_request_handshake(state_request: str) -> None:
|
|
101
|
+
src_mode = init_source_mode()
|
|
102
|
+
|
|
103
|
+
callback = src_mode.get_item(state_request).ext_wrt_cb
|
|
104
|
+
assert callback is not None
|
|
105
|
+
callback(True)
|
|
106
|
+
|
|
107
|
+
assert src_mode[state_request] is False
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
if __name__ == "__main__":
|
|
111
|
+
# This allows running the tests directly if needed
|
|
112
|
+
pytest.main([__file__, "-v"])
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Implementation of the WQC Base Function (PNO MTP 2.0 Part 3, Section 8.3.2).
|
|
2
|
+
|
|
3
|
+
The WQC (Worst Quality Control) base function provides a foundation for
|
|
4
|
+
write quality control operations. The base function provides the setter
|
|
5
|
+
`set_wqc` for internal writes that simply sets the value. This setter is
|
|
6
|
+
meant to be overwritten by derived classes with something semantically meaningful.
|
|
7
|
+
|
|
8
|
+
Note:
|
|
9
|
+
If no quality code is available 255 (=unspecified WQC) shall be used.
|
|
10
|
+
|
|
11
|
+
Example:
|
|
12
|
+
```python
|
|
13
|
+
wqc = WQCBaseFunction()
|
|
14
|
+
wqc.set_wqc(10)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
WQC_: Class constant representing the WQC alias of the PNO MTP 2.0 spec.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
__copyright__ = (
|
|
22
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
23
|
+
)
|
|
24
|
+
__license__ = "MIT"
|
|
25
|
+
|
|
26
|
+
from typing import ClassVar
|
|
27
|
+
|
|
28
|
+
import utils.type_conversion as tc
|
|
29
|
+
from mtppy.utils.data_item import DataItem, DataItemCollection
|
|
30
|
+
from mtppy.part3.definitions.mtp_access import MTPAccess
|
|
31
|
+
from mtppy.part5.definitions.w3c_xml_data_types import W3cXmlDataTypes
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class WQCBaseFunction(DataItemCollection):
|
|
35
|
+
"""Base function for Write Quality Control operations.
|
|
36
|
+
|
|
37
|
+
This class implements the basic WQC functionality that can be extended
|
|
38
|
+
by derived classes to provide specific write quality control behaviors.
|
|
39
|
+
|
|
40
|
+
Defines:
|
|
41
|
+
WQC_: Class constant representing the WQC data item name.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
WQC_ = "WQC"
|
|
45
|
+
|
|
46
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
47
|
+
WQC_: DataItem(
|
|
48
|
+
WQC_,
|
|
49
|
+
W3cXmlDataTypes.UNSIGNED_BYTE,
|
|
50
|
+
MTPAccess.ReadAccess,
|
|
51
|
+
init_value=255,
|
|
52
|
+
description="provides information about the conditions under \
|
|
53
|
+
which a value was determined.",
|
|
54
|
+
),
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
def __init__(self) -> None:
|
|
58
|
+
"""Initialize the WQC BaseFunction.
|
|
59
|
+
|
|
60
|
+
Sets up the WQC data item with the appropriate write callback.
|
|
61
|
+
"""
|
|
62
|
+
super().__init__()
|
|
63
|
+
|
|
64
|
+
self.get_item(WQCBaseFunction.WQC_).int_wrt_cb = self.set_wqc
|
|
65
|
+
|
|
66
|
+
def set_wqc(self, value: tc.ANY_TYPE) -> None:
|
|
67
|
+
"""Set the WQC value.
|
|
68
|
+
|
|
69
|
+
This method is intended to be overridden by derived classes to
|
|
70
|
+
provide specific write quality control behavior.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
value: The value to set for the WQC data item.
|
|
74
|
+
"""
|
|
75
|
+
self[WQCBaseFunction.WQC_] = value
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Test suite for the WQC (Work Quality Control) module."""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
import os
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
# Add the src directory to the Python path to import modules
|
|
13
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_wqc_module_import():
|
|
17
|
+
"""Test that the WQC module can be imported successfully."""
|
|
18
|
+
try:
|
|
19
|
+
from mtppy.part3.data_assembly_set.base_functions.wqc import WQCBaseFunction
|
|
20
|
+
|
|
21
|
+
assert True
|
|
22
|
+
except ImportError as e:
|
|
23
|
+
assert False, f"Failed to import WQC module: {e}"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_wqc_base_function_exists():
|
|
27
|
+
"""Test that WQCBaseFunction class exists."""
|
|
28
|
+
try:
|
|
29
|
+
from mtppy.part3.data_assembly_set.base_functions.wqc import WQCBaseFunction
|
|
30
|
+
|
|
31
|
+
assert WQCBaseFunction is not None
|
|
32
|
+
assert callable(WQCBaseFunction)
|
|
33
|
+
except ImportError as e:
|
|
34
|
+
pytest.fail(f"Failed to import WQCBaseFunction: {e}")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_wqc_base_function_inheritance():
|
|
38
|
+
"""Test that WQCBaseFunction has correct inheritance."""
|
|
39
|
+
try:
|
|
40
|
+
from mtppy.part3.data_assembly_set.base_functions.wqc import WQCBaseFunction
|
|
41
|
+
|
|
42
|
+
# Check if it's a class
|
|
43
|
+
assert isinstance(WQCBaseFunction, type)
|
|
44
|
+
|
|
45
|
+
# Check that it has expected attributes
|
|
46
|
+
assert hasattr(WQCBaseFunction, "__doc__")
|
|
47
|
+
|
|
48
|
+
except ImportError as e:
|
|
49
|
+
pytest.fail(f"Failed to test WQCBaseFunction inheritance: {e}")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_wqc_functionality():
|
|
53
|
+
"""Test basic WQC functionality."""
|
|
54
|
+
try:
|
|
55
|
+
from mtppy.part3.data_assembly_set.base_functions.wqc import WQCBaseFunction
|
|
56
|
+
|
|
57
|
+
# Try to instantiate the class
|
|
58
|
+
wqc_instance = WQCBaseFunction()
|
|
59
|
+
|
|
60
|
+
# Basic assertions
|
|
61
|
+
assert wqc_instance is not None
|
|
62
|
+
assert hasattr(wqc_instance, "__class__")
|
|
63
|
+
|
|
64
|
+
except Exception as e:
|
|
65
|
+
pytest.fail(f"Failed to test WQC functionality: {e}")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_wqc_snake_case_api():
|
|
69
|
+
"""Test basic WQC functionality."""
|
|
70
|
+
try:
|
|
71
|
+
from mtppy.part3.data_assembly_set.base_functions.wqc import WQCBaseFunction
|
|
72
|
+
|
|
73
|
+
# Try to instantiate the class
|
|
74
|
+
wqc_instance = WQCBaseFunction()
|
|
75
|
+
|
|
76
|
+
for wqc in range(0, 100, 10):
|
|
77
|
+
wqc_instance.WQC = wqc
|
|
78
|
+
assert wqc_instance.WQC == wqc
|
|
79
|
+
|
|
80
|
+
except Exception as e:
|
|
81
|
+
pytest.fail(f"Failed to test WQC functionality: {e}")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
# This allows running the tests directly if needed
|
|
86
|
+
pytest.main([__file__, "-v"])
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Implementation of the DataAssembly (PNO MTP 2.0 Part 1, 5.3)."""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
|
|
8
|
+
from typing import ClassVar
|
|
9
|
+
|
|
10
|
+
from mtppy.utils.data_item import DataItem, DataItemCollection
|
|
11
|
+
from mtppy.part3.definitions.mtp_access import MTPAccess
|
|
12
|
+
from mtppy.part5.definitions.w3c_xml_data_types import W3cXmlDataTypes
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DataAssembly(DataItemCollection):
|
|
16
|
+
"""DataAssembly is the base class for all the DataAssemblies that
|
|
17
|
+
serve as interface between POL and PEA and are specified in
|
|
18
|
+
PNO MTP 2.0 Part 3 (Library) and PNO MTP 2.0 Part 4 (Services).
|
|
19
|
+
|
|
20
|
+
It defines the aliases ``TagName`` and ``TagDescription``
|
|
21
|
+
|
|
22
|
+
DataAssembly itself is quite simple, the heavy lifting of providing
|
|
23
|
+
simple pythonic access paths (dict, attribute, setter/getter)
|
|
24
|
+
to the elements and managing the callback logic on change requests is
|
|
25
|
+
done by the baseclass [DataItemCollection][mtppy.utils.data_item.DataItemCollection].
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
TAG_NAME = "TagName"
|
|
29
|
+
TAG_DESCRIPTION = "TagDescription"
|
|
30
|
+
|
|
31
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
32
|
+
TAG_NAME: DataItem(
|
|
33
|
+
TAG_NAME,
|
|
34
|
+
W3cXmlDataTypes.STRING,
|
|
35
|
+
MTPAccess.ReadAccess,
|
|
36
|
+
init_value="untagged",
|
|
37
|
+
),
|
|
38
|
+
TAG_DESCRIPTION: DataItem(
|
|
39
|
+
TAG_DESCRIPTION,
|
|
40
|
+
W3cXmlDataTypes.STRING,
|
|
41
|
+
MTPAccess.ReadAccess,
|
|
42
|
+
init_value="undescribed",
|
|
43
|
+
),
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# class attributes
|
|
47
|
+
mtpObjectType: str
|
|
48
|
+
tag_name: str
|
|
49
|
+
tag_description: str
|
|
50
|
+
|
|
51
|
+
def __init__(self, tag_name: str, tag_description: str = "") -> None:
|
|
52
|
+
"""Initialize the DataAssembly.
|
|
53
|
+
|
|
54
|
+
Arguments:
|
|
55
|
+
tag_name: value for ``TagName`` (internal variable tag_name)
|
|
56
|
+
tag_description: value for ``TagDescription`` (internal variable
|
|
57
|
+
tag_description)
|
|
58
|
+
"""
|
|
59
|
+
super().__init__()
|
|
60
|
+
self.mtpObjectType = "MTPDataObjectSUCLib/DataAssembly"
|
|
61
|
+
self[DataAssembly.TAG_NAME] = tag_name
|
|
62
|
+
self[DataAssembly.TAG_DESCRIPTION] = tag_description
|
|
63
|
+
|
|
64
|
+
self.tag_name = tag_name
|
|
65
|
+
self.tag_description = tag_description
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Base Class for Diagnostic Elements."""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
from mtppy.part3.data_assembly_set.data_assembly import DataAssembly
|
|
8
|
+
from mtppy.part3.data_assembly_set.base_functions.wqc import WQCBaseFunction
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DiagnosticElement(DataAssembly):
|
|
12
|
+
|
|
13
|
+
wqc: WQCBaseFunction
|
|
14
|
+
|
|
15
|
+
def __init__(self, tag_name: str, tag_description: str):
|
|
16
|
+
super().__init__(tag_name, tag_description)
|
|
17
|
+
self.mtpObjectType = "MTPDataObjectSUCLib/DataAssembly/DiagnosticElement"
|
|
18
|
+
|
|
19
|
+
self.wqc = WQCBaseFunction()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Base Class for Indicators."""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
from mtppy.part3.data_assembly_set.data_assembly import DataAssembly
|
|
8
|
+
from mtppy.part3.data_assembly_set.base_functions.oslevel import OSLevelBaseFunction
|
|
9
|
+
from mtppy.part3.data_assembly_set.base_functions.wqc import WQCBaseFunction
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class IndicatorElement(DataAssembly):
|
|
13
|
+
|
|
14
|
+
os_level: OSLevelBaseFunction
|
|
15
|
+
wqc: WQCBaseFunction
|
|
16
|
+
|
|
17
|
+
def __init__(self, tag_name: str, tag_description: str):
|
|
18
|
+
super().__init__(tag_name, tag_description)
|
|
19
|
+
self.mtpObjectType = "MTPDataAssemblySUCLib/DataAssembly/IndicatorElement"
|
|
20
|
+
|
|
21
|
+
self.os_level = OSLevelBaseFunction()
|
|
22
|
+
self.wqc = WQCBaseFunction()
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Implementation of AnaView"""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
|
|
8
|
+
from typing import ClassVar
|
|
9
|
+
|
|
10
|
+
from mtppy.utils.logging import logger
|
|
11
|
+
from mtppy.utils.data_item import DataItem
|
|
12
|
+
from mtppy.part3.definitions.mtp_access import MTPAccess
|
|
13
|
+
from mtppy.part5.definitions.w3c_xml_data_types import W3cXmlDataTypes
|
|
14
|
+
from mtppy.part3.data_assembly_set.indicator_elements.indicator_element import (
|
|
15
|
+
IndicatorElement,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AnaView(IndicatorElement):
|
|
20
|
+
# DataItem constant definitions
|
|
21
|
+
V_ = "V"
|
|
22
|
+
V_UNIT = "VUnit"
|
|
23
|
+
VSCL_MIN = "VSclMin"
|
|
24
|
+
VSCL_MAX = "VSclMax"
|
|
25
|
+
|
|
26
|
+
# Class-level data items dictionary
|
|
27
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
28
|
+
V_: DataItem(V_, W3cXmlDataTypes.FLOAT, MTPAccess.ReadAccess, 0),
|
|
29
|
+
V_UNIT: DataItem(V_UNIT, W3cXmlDataTypes.SHORT, MTPAccess.ReadAccess, None),
|
|
30
|
+
VSCL_MIN: DataItem(VSCL_MIN, W3cXmlDataTypes.FLOAT, MTPAccess.ReadAccess, None),
|
|
31
|
+
VSCL_MAX: DataItem(VSCL_MAX, W3cXmlDataTypes.FLOAT, MTPAccess.ReadAccess, None),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
v_scl_min: float
|
|
35
|
+
v_scl_max: float
|
|
36
|
+
v_unit: int
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
tag_name: str,
|
|
41
|
+
tag_description: str = "",
|
|
42
|
+
v_scl_min: float = 0,
|
|
43
|
+
v_scl_max: float = 100,
|
|
44
|
+
v_unit: int = 1998,
|
|
45
|
+
):
|
|
46
|
+
"""
|
|
47
|
+
Analog View (AnaView).
|
|
48
|
+
"""
|
|
49
|
+
super().__init__(tag_name, tag_description)
|
|
50
|
+
self.mtpObjectType = (
|
|
51
|
+
"MTPDataAssemblySUCLib/DataAssembly/IndicatorElement/AnaView"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
self.v_scl_min = v_scl_min
|
|
55
|
+
self.v_scl_max = v_scl_max
|
|
56
|
+
self.v_unit = v_unit
|
|
57
|
+
|
|
58
|
+
# Initialize data items with dynamic values (using class-defined data items)
|
|
59
|
+
self[AnaView.V_] = 0
|
|
60
|
+
self[AnaView.V_UNIT] = self.v_unit
|
|
61
|
+
self[AnaView.VSCL_MIN] = self.v_scl_min
|
|
62
|
+
self[AnaView.VSCL_MAX] = self.v_scl_max
|
|
63
|
+
|
|
64
|
+
# Add callbacks for ReadWrite Variables
|
|
65
|
+
|
|
66
|
+
def set_v(self, value):
|
|
67
|
+
self[AnaView.V_] = value
|
|
68
|
+
logger.mtp(f"V set to {value}")
|