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,286 @@
|
|
|
1
|
+
"""Implementation of MonBinVlv."""
|
|
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, SupportsFloat, SupportsIndex
|
|
9
|
+
|
|
10
|
+
from mtppy.utils.logging import logger
|
|
11
|
+
import threading
|
|
12
|
+
from time import sleep
|
|
13
|
+
|
|
14
|
+
from mtppy.utils.data_item import DataItem
|
|
15
|
+
from mtppy.part3.definitions.mtp_access import MTPAccess
|
|
16
|
+
from mtppy.part5.definitions.w3c_xml_data_types import W3cXmlDataTypes
|
|
17
|
+
from mtppy.part3.data_assembly_set.active_elements.valves.bin_vlv import BinVlv
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MonBinVlvValues:
|
|
21
|
+
def __init__(self, open_aut, open_op, close_aut, close_op, reset_aut, reset_op):
|
|
22
|
+
self.open_aut = open_aut
|
|
23
|
+
self.open_op = open_op
|
|
24
|
+
self.close_aut = close_aut
|
|
25
|
+
self.close_op = close_op
|
|
26
|
+
self.reset_aut = reset_aut
|
|
27
|
+
self.reset_op = reset_op
|
|
28
|
+
self.lock = threading.Lock()
|
|
29
|
+
self.stop_event_lock = threading.Event()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class MonBinVlv(BinVlv):
|
|
33
|
+
# DataItem constant definitions
|
|
34
|
+
MON_EN = "MonEn"
|
|
35
|
+
MON_SAFE_POS = "MonSafePos"
|
|
36
|
+
MON_STAT_ERR = "MonStatErr"
|
|
37
|
+
MON_DYN_ERR = "MonDynErr"
|
|
38
|
+
MON_STAT_TI = "MonStatTi"
|
|
39
|
+
MON_DYN_TI = "MonDynTi"
|
|
40
|
+
|
|
41
|
+
# Class-level data items dictionary
|
|
42
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
43
|
+
MON_EN: DataItem(MON_EN, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, None),
|
|
44
|
+
MON_SAFE_POS: DataItem(
|
|
45
|
+
MON_SAFE_POS, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, None
|
|
46
|
+
),
|
|
47
|
+
MON_STAT_ERR: DataItem(
|
|
48
|
+
MON_STAT_ERR, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, None
|
|
49
|
+
),
|
|
50
|
+
MON_DYN_ERR: DataItem(
|
|
51
|
+
MON_DYN_ERR, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, None
|
|
52
|
+
),
|
|
53
|
+
MON_STAT_TI: DataItem(
|
|
54
|
+
MON_STAT_TI, W3cXmlDataTypes.FLOAT, MTPAccess.ReadAccess, None
|
|
55
|
+
),
|
|
56
|
+
MON_DYN_TI: DataItem(
|
|
57
|
+
MON_DYN_TI, W3cXmlDataTypes.FLOAT, MTPAccess.ReadAccess, None
|
|
58
|
+
),
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
monitored_values: MonBinVlvValues
|
|
62
|
+
monitor_static_thread = threading.Thread
|
|
63
|
+
monitor_dynamic_thread = threading.Thread
|
|
64
|
+
|
|
65
|
+
def __init__(
|
|
66
|
+
self,
|
|
67
|
+
tag_name,
|
|
68
|
+
tag_description="",
|
|
69
|
+
open_fbk_calc=True,
|
|
70
|
+
close_fbk_calc=True,
|
|
71
|
+
safe_pos=0,
|
|
72
|
+
safe_pos_en=False,
|
|
73
|
+
perm_en=False,
|
|
74
|
+
intl_en=False,
|
|
75
|
+
prot_en=False,
|
|
76
|
+
mon_en=True,
|
|
77
|
+
mon_safe_pos=True,
|
|
78
|
+
mon_stat_ti=1,
|
|
79
|
+
mon_dyn_ti=1,
|
|
80
|
+
):
|
|
81
|
+
super().__init__(
|
|
82
|
+
tag_name,
|
|
83
|
+
tag_description,
|
|
84
|
+
open_fbk_calc,
|
|
85
|
+
close_fbk_calc,
|
|
86
|
+
safe_pos,
|
|
87
|
+
safe_pos_en,
|
|
88
|
+
perm_en,
|
|
89
|
+
intl_en,
|
|
90
|
+
prot_en,
|
|
91
|
+
)
|
|
92
|
+
self.mtpObjectType = (
|
|
93
|
+
"MTPDataObjectSUCLib/DataAssembly/ActiveElement/BinVlv/MonBinVlv"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Initialize data items with dynamic values (using class-defined data items)
|
|
97
|
+
self[MonBinVlv.MON_EN] = mon_en
|
|
98
|
+
self[MonBinVlv.MON_SAFE_POS] = mon_safe_pos
|
|
99
|
+
self[MonBinVlv.MON_STAT_ERR] = False
|
|
100
|
+
self[MonBinVlv.MON_DYN_ERR] = False
|
|
101
|
+
self[MonBinVlv.MON_STAT_TI] = mon_stat_ti
|
|
102
|
+
self[MonBinVlv.MON_DYN_TI] = mon_dyn_ti
|
|
103
|
+
|
|
104
|
+
self.monitored_values = MonBinVlvValues(
|
|
105
|
+
self[BinVlv.OPEN_AUT],
|
|
106
|
+
self[BinVlv.OPEN_OP],
|
|
107
|
+
self[BinVlv.CLOSE_AUT],
|
|
108
|
+
self[BinVlv.CLOSE_OP],
|
|
109
|
+
self[BinVlv.RESET_AUT],
|
|
110
|
+
self[BinVlv.RESET_OP],
|
|
111
|
+
)
|
|
112
|
+
self.monitor_static_thread = None
|
|
113
|
+
self.monitor_dynamic_thread = None
|
|
114
|
+
|
|
115
|
+
def compare_states_control_signals(
|
|
116
|
+
self,
|
|
117
|
+
monitor_time: SupportsFloat | SupportsIndex,
|
|
118
|
+
) -> tuple[list[bool], list[bool]]:
|
|
119
|
+
"""
|
|
120
|
+
compare states of valve and control signals
|
|
121
|
+
|
|
122
|
+
Arguments:
|
|
123
|
+
monitor_time: MonStatTi or MonDynTi times
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
results of states and control signals comparisons (a list including True or False)
|
|
127
|
+
"""
|
|
128
|
+
self.monitored_values.lock.acquire()
|
|
129
|
+
open_fbk1 = self[BinVlv.OPEN_FBK]
|
|
130
|
+
close_fbk1 = self[BinVlv.CLOSE_FBK]
|
|
131
|
+
open_op1 = self.monitored_values.open_op
|
|
132
|
+
open_aut1 = self.monitored_values.open_aut
|
|
133
|
+
close_op1 = self.monitored_values.close_op
|
|
134
|
+
close_aut1 = self.monitored_values.close_aut
|
|
135
|
+
reset_op1 = self.monitored_values.reset_op
|
|
136
|
+
reset_aut1 = self.monitored_values.reset_aut
|
|
137
|
+
self.monitored_values.lock.release()
|
|
138
|
+
|
|
139
|
+
sleep(monitor_time)
|
|
140
|
+
|
|
141
|
+
self.monitored_values.lock.acquire()
|
|
142
|
+
open_fbk2 = self[BinVlv.OPEN_FBK]
|
|
143
|
+
close_fbk2 = self[BinVlv.CLOSE_FBK]
|
|
144
|
+
open_op2 = self.monitored_values.open_op
|
|
145
|
+
open_aut2 = self.monitored_values.open_aut
|
|
146
|
+
close_op2 = self.monitored_values.close_op
|
|
147
|
+
close_aut2 = self.monitored_values.close_aut
|
|
148
|
+
reset_op2 = self.monitored_values.reset_op
|
|
149
|
+
reset_aut2 = self.monitored_values.reset_aut
|
|
150
|
+
self.monitored_values.lock.release()
|
|
151
|
+
|
|
152
|
+
control_signals_comparison = [
|
|
153
|
+
open_op1 == open_op2,
|
|
154
|
+
open_aut1 == open_aut2,
|
|
155
|
+
close_op1 == close_op2,
|
|
156
|
+
close_aut1 == close_aut2,
|
|
157
|
+
reset_op1 == reset_op2,
|
|
158
|
+
reset_aut1 == reset_aut2,
|
|
159
|
+
]
|
|
160
|
+
state_comparison = [open_fbk1 == open_fbk2, close_fbk1 == close_fbk2]
|
|
161
|
+
return state_comparison, control_signals_comparison
|
|
162
|
+
|
|
163
|
+
def monitor_static_error(self):
|
|
164
|
+
"""
|
|
165
|
+
monitor static error
|
|
166
|
+
"""
|
|
167
|
+
while True:
|
|
168
|
+
if self.monitored_values.stop_event_lock.is_set():
|
|
169
|
+
logger.debug("static monitoring stopped")
|
|
170
|
+
break
|
|
171
|
+
states, control_signals = self.compare_states_control_signals(
|
|
172
|
+
self[MonBinVlv.MON_STAT_TI]
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
if not all(states): # if the states of valve changed
|
|
176
|
+
if all(control_signals): # but the control signals did not change
|
|
177
|
+
self[MonBinVlv.MON_STAT_ERR] = True
|
|
178
|
+
logger.debug("Static error set to True")
|
|
179
|
+
self._handle_monitored_error()
|
|
180
|
+
|
|
181
|
+
def monitor_dynamic_error(self):
|
|
182
|
+
"""
|
|
183
|
+
monitor dynamic error
|
|
184
|
+
"""
|
|
185
|
+
while True:
|
|
186
|
+
if self.monitored_values.stop_event_lock.is_set():
|
|
187
|
+
logger.debug("dynamic monitoring stopped")
|
|
188
|
+
break
|
|
189
|
+
states, control_signals = self.compare_states_control_signals(
|
|
190
|
+
self[MonBinVlv.MON_DYN_TI]
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
if all(states): # if the states of valve did not change
|
|
194
|
+
if not all(control_signals): # but a control command is executed
|
|
195
|
+
self[MonBinVlv.MON_DYN_ERR] = True
|
|
196
|
+
logger.debug("Dynamic error set to True")
|
|
197
|
+
self._handle_monitored_error()
|
|
198
|
+
|
|
199
|
+
def _handle_monitored_error(self):
|
|
200
|
+
if self[MonBinVlv.MON_SAFE_POS]:
|
|
201
|
+
logger.debug("set valve to safety position")
|
|
202
|
+
if self[BinVlv.SAFE_POS_EN]:
|
|
203
|
+
self._go_safe_pos()
|
|
204
|
+
else:
|
|
205
|
+
logger.debug("Device has no safe position")
|
|
206
|
+
self[BinVlv.SAFE_POS_ACT] = True
|
|
207
|
+
|
|
208
|
+
def start_monitor(self):
|
|
209
|
+
"""
|
|
210
|
+
start static and dynamic error monitoring thread
|
|
211
|
+
"""
|
|
212
|
+
if self["MonEn"]:
|
|
213
|
+
self.monitor_static_thread = threading.Thread(
|
|
214
|
+
target=self.monitor_static_error, daemon=True
|
|
215
|
+
)
|
|
216
|
+
self.monitor_static_thread.start()
|
|
217
|
+
logger.debug("static monitoring start")
|
|
218
|
+
self.monitor_dynamic_thread = threading.Thread(
|
|
219
|
+
target=self.monitor_dynamic_error, daemon=True
|
|
220
|
+
)
|
|
221
|
+
self.monitor_dynamic_thread.start()
|
|
222
|
+
logger.debug("dynamic monitoring start")
|
|
223
|
+
|
|
224
|
+
def set_open_aut(self, value: bool):
|
|
225
|
+
logger.debug(f"OpenAut set to {value}")
|
|
226
|
+
if self.op_mode["StateAutAct"]:
|
|
227
|
+
if value and self._run_allowed():
|
|
228
|
+
if self["MonEn"]:
|
|
229
|
+
self.monitored_values.lock.acquire()
|
|
230
|
+
self.monitored_values.open_aut = value
|
|
231
|
+
self.monitored_values.lock.release()
|
|
232
|
+
self._run_open_vlv()
|
|
233
|
+
|
|
234
|
+
def set_close_aut(self, value: bool):
|
|
235
|
+
if self.op_mode["StateAutAct"]:
|
|
236
|
+
if value and self._run_allowed():
|
|
237
|
+
if self["MonEn"]:
|
|
238
|
+
self.monitored_values.lock.acquire()
|
|
239
|
+
self.monitored_values.close_aut = value
|
|
240
|
+
self.monitored_values.lock.release()
|
|
241
|
+
logger.debug(f"CloseAut set to {value}")
|
|
242
|
+
self._run_close_vlv()
|
|
243
|
+
|
|
244
|
+
def set_reset_aut(self, value: bool):
|
|
245
|
+
logger.debug(f"ResetAut set to {value}")
|
|
246
|
+
if self.op_mode["StateAutAct"] and value:
|
|
247
|
+
if self["MonEn"]:
|
|
248
|
+
self.monitored_values.lock.acquire()
|
|
249
|
+
self.monitored_values.reset_aut = value
|
|
250
|
+
self.monitored_values.lock.release()
|
|
251
|
+
self._reset_vlv()
|
|
252
|
+
|
|
253
|
+
def set_open_op(self, value: bool):
|
|
254
|
+
logger.debug(f"OpenOp set to {value}")
|
|
255
|
+
if self.op_mode["StateOpAct"]:
|
|
256
|
+
if value and self._run_allowed():
|
|
257
|
+
if self["MonEn"]:
|
|
258
|
+
self.monitored_values.lock.acquire()
|
|
259
|
+
self.monitored_values.open_op = value
|
|
260
|
+
self.monitored_values.lock.release()
|
|
261
|
+
self._run_open_vlv()
|
|
262
|
+
self["OpenOp"] = False
|
|
263
|
+
|
|
264
|
+
def set_close_op(self, value: bool):
|
|
265
|
+
logger.debug(f"CloseOp set to {value}")
|
|
266
|
+
if self.op_mode["StateOpAct"]:
|
|
267
|
+
if value and self._run_allowed():
|
|
268
|
+
if self["MonEn"]:
|
|
269
|
+
self.monitored_values.lock.acquire()
|
|
270
|
+
self.monitored_values.close_op = value
|
|
271
|
+
self.monitored_values.lock.release()
|
|
272
|
+
self._run_close_vlv()
|
|
273
|
+
self["CloseOp"] = False
|
|
274
|
+
|
|
275
|
+
def set_reset_op(self, value: bool):
|
|
276
|
+
logger.debug(f"ResetOp set to {value}")
|
|
277
|
+
if self.op_mode["StateOpAct"] and value:
|
|
278
|
+
if self["MonEn"]:
|
|
279
|
+
self.monitored_values.lock.acquire()
|
|
280
|
+
self.monitored_values.reset_op = value
|
|
281
|
+
self.monitored_values.lock.release()
|
|
282
|
+
self._reset_vlv()
|
|
283
|
+
self["ResetOp"] = False
|
|
284
|
+
|
|
285
|
+
def set_stop_monitor(self):
|
|
286
|
+
self.monitored_values.stop_event_lock.set()
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"""Test Suite for MonBinValve."""
|
|
2
|
+
|
|
3
|
+
__copyright__ = (
|
|
4
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
5
|
+
)
|
|
6
|
+
__license__ = "MIT"
|
|
7
|
+
import pytest
|
|
8
|
+
import time
|
|
9
|
+
|
|
10
|
+
from mtppy.part3.data_assembly_set.active_elements.valves.bin_vlv import BinVlv
|
|
11
|
+
from mtppy.part3.data_assembly_set.active_elements.valves.mon_bin_vlv import MonBinVlv
|
|
12
|
+
from mtppy.utils.testing import data_object_set_modes
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def init_mon_bin_vlv(
|
|
16
|
+
init_op_mode="off",
|
|
17
|
+
init_src_mode="int",
|
|
18
|
+
open_fbk_calc=True,
|
|
19
|
+
close_fbk_calc=True,
|
|
20
|
+
safe_pos=1,
|
|
21
|
+
safe_pos_en=True,
|
|
22
|
+
perm_en=False,
|
|
23
|
+
intl_en=False,
|
|
24
|
+
prot_en=False,
|
|
25
|
+
mon_en=True,
|
|
26
|
+
mon_safe_pos=1,
|
|
27
|
+
mon_stat_ti=0.5,
|
|
28
|
+
mon_dyn_ti=0.4,
|
|
29
|
+
):
|
|
30
|
+
instance = MonBinVlv(
|
|
31
|
+
"tag",
|
|
32
|
+
tag_description="",
|
|
33
|
+
open_fbk_calc=open_fbk_calc,
|
|
34
|
+
close_fbk_calc=close_fbk_calc,
|
|
35
|
+
safe_pos=safe_pos,
|
|
36
|
+
safe_pos_en=safe_pos_en,
|
|
37
|
+
perm_en=perm_en,
|
|
38
|
+
intl_en=intl_en,
|
|
39
|
+
prot_en=prot_en,
|
|
40
|
+
mon_en=mon_en,
|
|
41
|
+
mon_safe_pos=mon_safe_pos,
|
|
42
|
+
mon_stat_ti=mon_stat_ti,
|
|
43
|
+
mon_dyn_ti=mon_dyn_ti,
|
|
44
|
+
)
|
|
45
|
+
data_object_set_modes(instance, init_op_mode, init_src_mode)
|
|
46
|
+
return instance
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
test_scenario_no_control_signals = [
|
|
50
|
+
("off", "int", "set_open_op"),
|
|
51
|
+
("off", "man", "set_open_op"),
|
|
52
|
+
("aut", "int", "set_open_op"),
|
|
53
|
+
("aut", "man", "set_open_op"),
|
|
54
|
+
("off", "int", "set_open_aut"),
|
|
55
|
+
("off", "man", "set_open_aut"),
|
|
56
|
+
("op", "int", "set_open_aut"),
|
|
57
|
+
("op", "man", "set_open_aut"),
|
|
58
|
+
("off", "int", "set_close_op"),
|
|
59
|
+
("off", "man", "set_close_op"),
|
|
60
|
+
("aut", "int", "set_close_op"),
|
|
61
|
+
("aut", "man", "set_close_op"),
|
|
62
|
+
("off", "int", "set_close_aut"),
|
|
63
|
+
("off", "man", "set_close_aut"),
|
|
64
|
+
("op", "int", "set_close_aut"),
|
|
65
|
+
("op", "man", "set_close_aut"),
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@pytest.mark.parametrize(
|
|
70
|
+
"op_mode, src_mode, set_command", test_scenario_no_control_signals
|
|
71
|
+
)
|
|
72
|
+
def test_static_error(op_mode, src_mode, set_command):
|
|
73
|
+
for command in [True, False]:
|
|
74
|
+
mon_bin_vlv = init_mon_bin_vlv(init_op_mode=op_mode, init_src_mode=src_mode)
|
|
75
|
+
try:
|
|
76
|
+
mon_bin_vlv.start_monitor()
|
|
77
|
+
eval(f"mon_bin_vlv.{set_command}({command})")
|
|
78
|
+
print(f"Scenario: mode {op_mode} {src_mode}, {set_command}")
|
|
79
|
+
|
|
80
|
+
# mimic an error situation: OpenFbk changes to True without any change in control signal
|
|
81
|
+
mon_bin_vlv[BinVlv.OPEN_FBK] = True
|
|
82
|
+
time.sleep(mon_bin_vlv[MonBinVlv.MON_STAT_TI] * 2)
|
|
83
|
+
|
|
84
|
+
assert mon_bin_vlv[MonBinVlv.MON_STAT_ERR] == True
|
|
85
|
+
assert mon_bin_vlv[MonBinVlv.MON_DYN_ERR] == False
|
|
86
|
+
assert mon_bin_vlv[BinVlv.SAFE_POS_ACT] == True
|
|
87
|
+
assert (
|
|
88
|
+
mon_bin_vlv[BinVlv.OPEN_FBK] == True
|
|
89
|
+
) # safe position of valve is open
|
|
90
|
+
|
|
91
|
+
time.sleep(mon_bin_vlv[MonBinVlv.MON_STAT_TI])
|
|
92
|
+
|
|
93
|
+
# after valve is set to safe position (open), the OpenFbk becomes to False --> another static error
|
|
94
|
+
mon_bin_vlv[BinVlv.OPEN_FBK] = False
|
|
95
|
+
time.sleep(mon_bin_vlv[MonBinVlv.MON_STAT_TI] * 1.5)
|
|
96
|
+
|
|
97
|
+
assert mon_bin_vlv[MonBinVlv.MON_STAT_ERR] == True
|
|
98
|
+
assert mon_bin_vlv[MonBinVlv.MON_DYN_ERR] == False
|
|
99
|
+
assert mon_bin_vlv[BinVlv.SAFE_POS_ACT] == True
|
|
100
|
+
assert (
|
|
101
|
+
mon_bin_vlv[BinVlv.OPEN_FBK] == True
|
|
102
|
+
) # safe position of valve is open
|
|
103
|
+
finally:
|
|
104
|
+
mon_bin_vlv.set_stop_monitor()
|
|
105
|
+
mon_bin_vlv.monitor_static_thread.join()
|
|
106
|
+
mon_bin_vlv.monitor_dynamic_thread.join()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@pytest.mark.parametrize(
|
|
110
|
+
"op_mode, src_mode, set_command", test_scenario_no_control_signals
|
|
111
|
+
)
|
|
112
|
+
def test_static_error_within_monitor_time(op_mode, src_mode, set_command):
|
|
113
|
+
"""If the required state is set on the interface before the time has expired (wait tme < 0.5s in this test),
|
|
114
|
+
there is no error"""
|
|
115
|
+
|
|
116
|
+
for command in [True, False]:
|
|
117
|
+
mon_bin_vlv = init_mon_bin_vlv(init_op_mode=op_mode, init_src_mode=src_mode)
|
|
118
|
+
try:
|
|
119
|
+
mon_bin_vlv.start_monitor()
|
|
120
|
+
eval(f"mon_bin_vlv.{set_command}({command})")
|
|
121
|
+
print(f"Scenario: mode {op_mode} {src_mode}, {set_command}")
|
|
122
|
+
|
|
123
|
+
# mimic an error situation: OpenFbk changes to True without any change in control signal
|
|
124
|
+
mon_bin_vlv[BinVlv.OPEN_FBK] = True
|
|
125
|
+
time.sleep(
|
|
126
|
+
mon_bin_vlv[MonBinVlv.MON_STAT_TI] * 0.5
|
|
127
|
+
) # monitor time has not expired (0.5s)
|
|
128
|
+
|
|
129
|
+
assert mon_bin_vlv[MonBinVlv.MON_STAT_ERR] == False
|
|
130
|
+
assert mon_bin_vlv[MonBinVlv.MON_DYN_ERR] == False
|
|
131
|
+
assert mon_bin_vlv[BinVlv.SAFE_POS_ACT] == False
|
|
132
|
+
finally:
|
|
133
|
+
mon_bin_vlv.set_stop_monitor()
|
|
134
|
+
mon_bin_vlv.monitor_static_thread.join()
|
|
135
|
+
mon_bin_vlv.monitor_dynamic_thread.join()
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
test_scenario_control_signals = [
|
|
139
|
+
("op", "int", "set_open_op", "set_close_op"),
|
|
140
|
+
("op", "man", "set_open_op", "set_close_op"),
|
|
141
|
+
("aut", "int", "set_open_aut", "set_close_aut"),
|
|
142
|
+
("aut", "man", "set_open_aut", "set_close_aut"),
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@pytest.mark.parametrize(
|
|
147
|
+
"op_mode, src_mode, open_command, close_command", test_scenario_control_signals
|
|
148
|
+
)
|
|
149
|
+
def test_dynamic_error_open_close(op_mode, src_mode, open_command, close_command):
|
|
150
|
+
mon_bin_vlv = init_mon_bin_vlv(init_op_mode=op_mode, init_src_mode=src_mode)
|
|
151
|
+
try:
|
|
152
|
+
mon_bin_vlv.start_monitor()
|
|
153
|
+
eval(f"mon_bin_vlv.{open_command}(True)")
|
|
154
|
+
print(f"Scenario: mode {op_mode} {src_mode}, {open_command}")
|
|
155
|
+
|
|
156
|
+
# mimic an error situation: OpenFbk does not change to True after control signal has changed to open
|
|
157
|
+
mon_bin_vlv[BinVlv.OPEN_FBK] = False
|
|
158
|
+
time.sleep(mon_bin_vlv[MonBinVlv.MON_DYN_TI] * 2)
|
|
159
|
+
|
|
160
|
+
assert mon_bin_vlv[MonBinVlv.MON_DYN_ERR] == True
|
|
161
|
+
assert mon_bin_vlv[MonBinVlv.MON_STAT_ERR] == False
|
|
162
|
+
assert mon_bin_vlv[BinVlv.SAFE_POS_ACT] == True
|
|
163
|
+
assert mon_bin_vlv[BinVlv.OPEN_FBK] == True # safe position of valve is open
|
|
164
|
+
|
|
165
|
+
eval(f"mon_bin_vlv.{close_command}(True)")
|
|
166
|
+
print(f"Scenario: mode {op_mode} {src_mode}, {close_command}")
|
|
167
|
+
|
|
168
|
+
# mimic an error situation: OpenFbk does not change to False after control signal has changed to close
|
|
169
|
+
mon_bin_vlv[BinVlv.OPEN_FBK] = True
|
|
170
|
+
time.sleep(mon_bin_vlv[MonBinVlv.MON_DYN_TI] * 2)
|
|
171
|
+
|
|
172
|
+
assert mon_bin_vlv["MonDynErr"] == True
|
|
173
|
+
assert mon_bin_vlv["MonStatErr"] == False
|
|
174
|
+
assert mon_bin_vlv["SafePosAct"] == True
|
|
175
|
+
assert mon_bin_vlv["OpenFbk"] == True # safe position of valve is open
|
|
176
|
+
finally:
|
|
177
|
+
mon_bin_vlv.set_stop_monitor()
|
|
178
|
+
mon_bin_vlv.monitor_static_thread.join()
|
|
179
|
+
mon_bin_vlv.monitor_dynamic_thread.join()
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
test_scenario_control_signals_reset = [
|
|
183
|
+
("op", "int", "set_reset_op"),
|
|
184
|
+
("op", "man", "set_reset_op"),
|
|
185
|
+
("aut", "int", "set_reset_aut"),
|
|
186
|
+
("aut", "man", "set_reset_aut"),
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
@pytest.mark.parametrize(
|
|
191
|
+
"op_mode, src_mode, set_command", test_scenario_control_signals_reset
|
|
192
|
+
)
|
|
193
|
+
def test_dynamic_error_reset(op_mode, src_mode, set_command):
|
|
194
|
+
mon_bin_vlv = init_mon_bin_vlv(init_op_mode=op_mode, init_src_mode=src_mode)
|
|
195
|
+
try:
|
|
196
|
+
mon_bin_vlv.start_monitor()
|
|
197
|
+
# set valve to open
|
|
198
|
+
if op_mode == "op":
|
|
199
|
+
mon_bin_vlv.set_open_op(True)
|
|
200
|
+
elif op_mode == "aut":
|
|
201
|
+
mon_bin_vlv.set_open_aut(True)
|
|
202
|
+
time.sleep(mon_bin_vlv[MonBinVlv.MON_DYN_TI] * 1)
|
|
203
|
+
|
|
204
|
+
# reset valve
|
|
205
|
+
eval(f"mon_bin_vlv.{set_command}(True)")
|
|
206
|
+
print(f"Scenario: mode {op_mode} {src_mode}, {set_command}")
|
|
207
|
+
|
|
208
|
+
# mimic an error situation: OpenFbk does not change to False after reset changes to True
|
|
209
|
+
mon_bin_vlv[BinVlv.OPEN_FBK] = True
|
|
210
|
+
time.sleep(mon_bin_vlv[MonBinVlv.MON_DYN_TI] * 3)
|
|
211
|
+
|
|
212
|
+
assert mon_bin_vlv[MonBinVlv.MON_DYN_ERR] == True
|
|
213
|
+
assert mon_bin_vlv[MonBinVlv.MON_STAT_ERR] == False
|
|
214
|
+
assert mon_bin_vlv[BinVlv.SAFE_POS_ACT] == True
|
|
215
|
+
assert mon_bin_vlv[BinVlv.OPEN_FBK] == True # safe position of valve is open
|
|
216
|
+
finally:
|
|
217
|
+
mon_bin_vlv.set_stop_monitor()
|
|
218
|
+
mon_bin_vlv.monitor_static_thread.join()
|
|
219
|
+
mon_bin_vlv.monitor_dynamic_thread.join()
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
if __name__ == "__main__":
|
|
223
|
+
# This allows running the tests directly if needed
|
|
224
|
+
pytest.main([__file__, "-v"])
|