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,185 @@
|
|
|
1
|
+
"""Test Suite for Procedure."""
|
|
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.indicator_elements.views.ana_view import AnaView
|
|
9
|
+
from mtppy.part3.data_assembly_set.indicator_elements.views.bin_view import BinView
|
|
10
|
+
from mtppy.part3.data_assembly_set.indicator_elements.views.dint_view import DIntView
|
|
11
|
+
from mtppy.part3.data_assembly_set.indicator_elements.views.string_view import StringView
|
|
12
|
+
from mtppy.part3.data_assembly_set.data_assembly import DataAssembly
|
|
13
|
+
from mtppy.part4.process_values.input_elements.bin_process_value_in import BinProcessValueIn
|
|
14
|
+
from mtppy.part4.process_values.input_elements.string_process_value_in import StringProcessValueIn
|
|
15
|
+
from mtppy.part4.automation_services.procedure import Procedure
|
|
16
|
+
from mtppy.part4.automation_services.service_elements.parameter_elements.ana_serv_param import AnaServParam
|
|
17
|
+
from mtppy.part4.automation_services.service_elements.parameter_elements.bin_serv_param import BinServParam
|
|
18
|
+
from mtppy.part4.automation_services.service_elements.parameter_elements.dint_serv_param import DIntServParam
|
|
19
|
+
from mtppy.part4.automation_services.service_elements.parameter_elements.string_serv_param import StringServParam
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
operation_elements = [
|
|
23
|
+
AnaServParam(
|
|
24
|
+
"serv_param_ana", v_min=0, v_max=50, v_scl_min=0, v_scl_max=10, v_unit=23
|
|
25
|
+
),
|
|
26
|
+
DIntServParam(
|
|
27
|
+
"serv_param_dint", v_min=-10, v_max=10, v_scl_min=0, v_scl_max=-10, v_unit=23
|
|
28
|
+
),
|
|
29
|
+
BinServParam("serv_param_bin", v_state_0="state_0", v_state_1="state_1"),
|
|
30
|
+
StringServParam("serv_param_str"),
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
indicator_elements = [
|
|
34
|
+
AnaView("proc_rv_ana", v_scl_min=0, v_scl_max=10, v_unit=23),
|
|
35
|
+
DIntView("proc_rv_dint", v_scl_min=0, v_scl_max=-10, v_unit=23),
|
|
36
|
+
BinView("proc_rv_bin", v_state_0="state_0", v_state_1="state_1"),
|
|
37
|
+
StringView("proc_rv_str"),
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def create_dummy_procedure():
|
|
42
|
+
return Procedure(1, "DummyProcedure", "procedure for testing", False)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_procedure_initialization():
|
|
46
|
+
procedure = Procedure(7, "TestProcedure", "Test description", True)
|
|
47
|
+
|
|
48
|
+
assert procedure.procedure_id == 7
|
|
49
|
+
assert procedure.name == "TestProcedure"
|
|
50
|
+
assert procedure.is_self_completing is True
|
|
51
|
+
assert procedure.procedure_parameters == {}
|
|
52
|
+
assert procedure.process_value_ins == {}
|
|
53
|
+
assert procedure.process_value_outs == {}
|
|
54
|
+
assert procedure.report_values == {}
|
|
55
|
+
assert procedure.required_equipment == {}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_add_procedure_parameter_list_and_dict():
|
|
59
|
+
procedure = create_dummy_procedure()
|
|
60
|
+
parameters = [
|
|
61
|
+
AnaServParam("Parameter1", v_min=0, v_max=10, v_scl_min=0, v_scl_max=10, v_unit=23),
|
|
62
|
+
DIntServParam("Parameter2", v_min=-10, v_max=10, v_scl_min=-10, v_scl_max=10, v_unit=23),
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
procedure.add_procedure_parameter(parameters)
|
|
66
|
+
procedure.add_procedure_parameter({"parameter": parameters[0]})
|
|
67
|
+
|
|
68
|
+
assert procedure.procedure_parameters == {
|
|
69
|
+
parameter.tag_name: parameter for parameter in parameters
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_add_procedure_parameter():
|
|
74
|
+
valid_parameters = operation_elements
|
|
75
|
+
invalid_parameters = indicator_elements
|
|
76
|
+
|
|
77
|
+
procedure = create_dummy_procedure()
|
|
78
|
+
for valid_parameter in valid_parameters:
|
|
79
|
+
procedure.add_procedure_parameter(valid_parameter)
|
|
80
|
+
assert (
|
|
81
|
+
procedure.procedure_parameters[valid_parameter.tag_name] == valid_parameter
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
procedure = create_dummy_procedure()
|
|
85
|
+
for invalid_parameter in invalid_parameters:
|
|
86
|
+
try:
|
|
87
|
+
procedure.add_procedure_parameter(invalid_parameter)
|
|
88
|
+
assert False
|
|
89
|
+
except TypeError:
|
|
90
|
+
assert True
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_add_report_values():
|
|
94
|
+
valid_parameters = indicator_elements
|
|
95
|
+
invalid_parameters = operation_elements
|
|
96
|
+
|
|
97
|
+
procedure = create_dummy_procedure()
|
|
98
|
+
for valid_parameter in valid_parameters:
|
|
99
|
+
procedure.add_report_value(valid_parameter)
|
|
100
|
+
assert procedure.report_values[valid_parameter.tag_name] == valid_parameter
|
|
101
|
+
|
|
102
|
+
procedure = create_dummy_procedure()
|
|
103
|
+
for invalid_parameter in invalid_parameters:
|
|
104
|
+
try:
|
|
105
|
+
procedure.add_report_value(invalid_parameter)
|
|
106
|
+
assert False
|
|
107
|
+
except TypeError:
|
|
108
|
+
assert True
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_add_value_outs():
|
|
112
|
+
valid_parameters = indicator_elements
|
|
113
|
+
invalid_parameters = operation_elements
|
|
114
|
+
|
|
115
|
+
procedure = create_dummy_procedure()
|
|
116
|
+
for valid_parameter in valid_parameters:
|
|
117
|
+
procedure.add_process_value_out(valid_parameter)
|
|
118
|
+
assert procedure.process_value_outs[valid_parameter.tag_name] == valid_parameter
|
|
119
|
+
|
|
120
|
+
procedure = create_dummy_procedure()
|
|
121
|
+
for invalid_parameter in invalid_parameters:
|
|
122
|
+
try:
|
|
123
|
+
procedure.add_process_value_out(invalid_parameter)
|
|
124
|
+
assert False
|
|
125
|
+
except TypeError:
|
|
126
|
+
assert True
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_add_process_value_ins_single_and_list():
|
|
130
|
+
procedure = create_dummy_procedure()
|
|
131
|
+
process_value_in = BinProcessValueIn("Input1", "Binary input")
|
|
132
|
+
process_value_ins = [
|
|
133
|
+
StringProcessValueIn("Input2", "String input"),
|
|
134
|
+
StringProcessValueIn("Input3", "Another string input"),
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
procedure.add_process_value_in(process_value_in)
|
|
138
|
+
procedure.add_process_value_in(process_value_ins)
|
|
139
|
+
|
|
140
|
+
assert procedure.process_value_ins == {
|
|
141
|
+
"Input1": process_value_in,
|
|
142
|
+
"Input2": process_value_ins[0],
|
|
143
|
+
"Input3": process_value_ins[1],
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_add_process_value_in_rejects_wrong_type():
|
|
148
|
+
procedure = create_dummy_procedure()
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
procedure.add_process_value_in(indicator_elements[0])
|
|
152
|
+
assert False
|
|
153
|
+
except TypeError:
|
|
154
|
+
assert True
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_add_required_equipment_single_list_dict_and_none():
|
|
158
|
+
equipment = [DataAssembly("Equipment1"), DataAssembly("Equipment2")]
|
|
159
|
+
procedure = Procedure(
|
|
160
|
+
1,
|
|
161
|
+
"ProcedureWithEquipment",
|
|
162
|
+
required_equipment={"first": equipment[0], "second": equipment[1]},
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
procedure.add_required_equipment(equipment)
|
|
166
|
+
procedure.add_required_equipment(None)
|
|
167
|
+
|
|
168
|
+
assert procedure.required_equipment == {
|
|
169
|
+
"Equipment1": equipment[0],
|
|
170
|
+
"Equipment2": equipment[1],
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def test_apply_procedure_parameters(monkeypatch):
|
|
175
|
+
procedure = create_dummy_procedure()
|
|
176
|
+
parameter = AnaServParam(
|
|
177
|
+
"Parameter1", v_min=0, v_max=10, v_scl_min=0, v_scl_max=10, v_unit=23
|
|
178
|
+
)
|
|
179
|
+
update_calls = []
|
|
180
|
+
monkeypatch.setattr(parameter, "update_v_out", lambda: update_calls.append(parameter))
|
|
181
|
+
procedure.add_procedure_parameter(parameter)
|
|
182
|
+
|
|
183
|
+
procedure.apply_procedure_parameters()
|
|
184
|
+
|
|
185
|
+
assert update_calls == [parameter]
|
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
"""Service is an abstract class implementing the concepts specified in
|
|
2
|
+
PNO MTP 2.0 Part 4, Sections 8.2.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
__copyright__ = (
|
|
6
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
7
|
+
)
|
|
8
|
+
__license__ = "MIT"
|
|
9
|
+
|
|
10
|
+
from abc import ABC, abstractmethod
|
|
11
|
+
|
|
12
|
+
from mtppy.part3.data_assembly_set.data_assembly import DataAssembly
|
|
13
|
+
from mtppy.part4.automation_services.base_functions.service_operation_mode import (
|
|
14
|
+
ServiceOperationMode,
|
|
15
|
+
)
|
|
16
|
+
from mtppy.part4.automation_services.helpers.state_machine import StateMachine
|
|
17
|
+
from mtppy.part4.automation_services.helpers.thread_control import ThreadControl
|
|
18
|
+
from mtppy.part4.automation_services.procedure import Procedure
|
|
19
|
+
from mtppy.part4.automation_services.service_elements.parameter_elements.parameter_element import (
|
|
20
|
+
ParameterElement,
|
|
21
|
+
)
|
|
22
|
+
from mtppy.part4.automation_services.service_elements.service_control import (
|
|
23
|
+
ServiceControl,
|
|
24
|
+
)
|
|
25
|
+
from mtppy.utils.logging import logger
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _has_zero_id(
|
|
29
|
+
procedure: Procedure | list[Procedure | None] | dict[str, Procedure | None] | None,
|
|
30
|
+
) -> bool:
|
|
31
|
+
"""Check whether a procedure or procedure collection contains ID zero.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
procedure: A procedure, a list of procedures, a mapping of procedures,
|
|
35
|
+
or ``None``.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
``True`` if any supplied procedure has an ID of zero; otherwise,
|
|
39
|
+
``False``.
|
|
40
|
+
"""
|
|
41
|
+
logger.info(f"procedure={procedure}")
|
|
42
|
+
if procedure is None: # No procedure does no harm
|
|
43
|
+
return False
|
|
44
|
+
if isinstance(procedure, dict):
|
|
45
|
+
# Check if any value in the dict has procedure_id == 0, ignoring None values
|
|
46
|
+
return any(p is not None and p.procedure_id == 0 for p in procedure.values())
|
|
47
|
+
if isinstance(procedure, list):
|
|
48
|
+
# Check if any element in the list has procedure_id == 0, ignoring None values
|
|
49
|
+
if all(p is None for p in procedure):
|
|
50
|
+
return False
|
|
51
|
+
return any(p is not None and p.procedure_id == 0 for p in procedure)
|
|
52
|
+
# For a single Procedure object
|
|
53
|
+
return procedure.procedure_id == 0
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class Service(ABC):
|
|
57
|
+
"""Abstract Base class implementing the Service specification.
|
|
58
|
+
|
|
59
|
+
This abstract base class provides the foundational structure for
|
|
60
|
+
implementing services according to PNO MTP 2.0 Part 4 specifications.
|
|
61
|
+
It handles state management, procedure execution, and configuration
|
|
62
|
+
parameter handling through a state machine and thread control system.
|
|
63
|
+
|
|
64
|
+
It provides functions for all the defined states, such as
|
|
65
|
+
`idle`, `starting`, ..., `resetting`, a.s.o, that shall be implemented
|
|
66
|
+
by instantiable derivatives.
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
Attributes:
|
|
70
|
+
thread_ctrl: Thread control manager for service operations.
|
|
71
|
+
configuration_parameters: Dictionary of configuration parameters.
|
|
72
|
+
procedures: Dictionary mapping procedure IDs to Procedure objects.
|
|
73
|
+
service_control: Service control instance managing operation modes.
|
|
74
|
+
state_machine: State machine for service state transitions.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
thread_ctrl: ThreadControl
|
|
78
|
+
configuration_parameters: dict[str, ParameterElement]
|
|
79
|
+
procedures: dict[int, Procedure]
|
|
80
|
+
service_control: ServiceControl
|
|
81
|
+
state_machine: StateMachine
|
|
82
|
+
tag_name: str
|
|
83
|
+
|
|
84
|
+
def __init__(self, tag_name: str, tag_description: str = "") -> None:
|
|
85
|
+
"""Initialize a service instance.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
tag_name: Tag name of the service.
|
|
89
|
+
tag_description: Optional description of the service.
|
|
90
|
+
"""
|
|
91
|
+
super().__init__()
|
|
92
|
+
self.tag_name = tag_name
|
|
93
|
+
self.tag_description = tag_description
|
|
94
|
+
self.thread_ctrl = ThreadControl()
|
|
95
|
+
|
|
96
|
+
self.configuration_parameters = {}
|
|
97
|
+
self.procedures = {}
|
|
98
|
+
|
|
99
|
+
self.service_control = ServiceControl(
|
|
100
|
+
tag_name,
|
|
101
|
+
tag_description,
|
|
102
|
+
execution_procedure=self.command_execution,
|
|
103
|
+
)
|
|
104
|
+
self.state_machine = StateMachine(
|
|
105
|
+
service_control=self.service_control,
|
|
106
|
+
execution_routine=self._state_change_callback,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
self.service_control.service_op_mode.add_enter_offline_callback(
|
|
110
|
+
self.state_machine.command_en_ctrl.disable_all,
|
|
111
|
+
)
|
|
112
|
+
self.service_control.service_op_mode.add_exit_offline_callback(
|
|
113
|
+
self.state_machine.command_en_ctrl.set_default,
|
|
114
|
+
)
|
|
115
|
+
self.service_control.service_op_mode.add_exit_offline_callback(
|
|
116
|
+
self.apply_configuration_parameters,
|
|
117
|
+
)
|
|
118
|
+
self.service_control.service_op_mode.add_exit_offline_callback(
|
|
119
|
+
self._init_idle_state,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
self.state_machine.activate()
|
|
123
|
+
|
|
124
|
+
# Backwards compatibility
|
|
125
|
+
@property
|
|
126
|
+
def name(self) -> str:
|
|
127
|
+
"""Return the service tag name.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
The current service tag name.
|
|
131
|
+
"""
|
|
132
|
+
return self.tag_name
|
|
133
|
+
|
|
134
|
+
@name.setter
|
|
135
|
+
def name(self, value: str) -> None:
|
|
136
|
+
"""Set the service tag name.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
value: New service tag name.
|
|
140
|
+
"""
|
|
141
|
+
self.tag_name = value
|
|
142
|
+
|
|
143
|
+
def command_execution(self, value: int) -> None:
|
|
144
|
+
"""Forward a command to the service state machine.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
value: Command value defined by the service control interface.
|
|
148
|
+
"""
|
|
149
|
+
self.state_machine.command_execution(value)
|
|
150
|
+
|
|
151
|
+
def _init_idle_state(self) -> None:
|
|
152
|
+
"""Initialize the service's idle state."""
|
|
153
|
+
logger.debug(f"Initialize service {self.tag_name}'s idle_state")
|
|
154
|
+
self._state_change_callback()
|
|
155
|
+
|
|
156
|
+
def _state_change_callback(self) -> None:
|
|
157
|
+
"""Handle a service state change requested by the state machine."""
|
|
158
|
+
msg = f"{self.tag_name},som={self.service_control.service_op_mode.items()}"
|
|
159
|
+
logger.info(msg)
|
|
160
|
+
|
|
161
|
+
if self.service_control.service_op_mode[ServiceOperationMode.STATE_OFF_ACT]:
|
|
162
|
+
logger.info(
|
|
163
|
+
f"service {self.tag_name} not initializable, StateOffAct = True",
|
|
164
|
+
)
|
|
165
|
+
return
|
|
166
|
+
|
|
167
|
+
state_str = self.state_machine.get_current_state_str()
|
|
168
|
+
logger.info(f"{self.tag_name} in state={state_str}")
|
|
169
|
+
if state_str != "undefined":
|
|
170
|
+
if state_str == "starting": # PNO MTP 2.0 Part 4, Section 8.2.4.4
|
|
171
|
+
# we assume that service_control did set Procedure_Cur
|
|
172
|
+
self.apply_procedure_parameters()
|
|
173
|
+
|
|
174
|
+
function_to_execute = getattr(self, state_str)
|
|
175
|
+
self.thread_ctrl.request_state(state_str, function_to_execute)
|
|
176
|
+
self.thread_ctrl.reallocate_running_thread()
|
|
177
|
+
|
|
178
|
+
if state_str == "idle":
|
|
179
|
+
self.service_control.service_op_mode.allow_switch_to_offline_mode(
|
|
180
|
+
allow_flag=True,
|
|
181
|
+
)
|
|
182
|
+
else:
|
|
183
|
+
self.service_control.service_op_mode.allow_switch_to_offline_mode(
|
|
184
|
+
allow_flag=False,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def is_state(self, state_str: str) -> bool:
|
|
188
|
+
"""Check whether the service is in a specified state.
|
|
189
|
+
|
|
190
|
+
If the current state differs, the running thread is reallocated.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
state_str: State name to compare with the current state.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
``True`` if the service is in ``state_str``; otherwise, ``False``.
|
|
197
|
+
"""
|
|
198
|
+
if state_str == self.state_machine.get_current_state_str():
|
|
199
|
+
return True
|
|
200
|
+
self.thread_ctrl.reallocate_running_thread()
|
|
201
|
+
return False
|
|
202
|
+
|
|
203
|
+
def state_change(self) -> None:
|
|
204
|
+
"""Request a state change from a cyclic state to the next one."""
|
|
205
|
+
self.state_machine.state_change()
|
|
206
|
+
|
|
207
|
+
def get_param(self, param_name: str) -> DataAssembly | None:
|
|
208
|
+
"""Return a named item from the current procedure.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
param_name: Name of the procedure parameter or value to retrieve.
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
The matching data assembly, or ``None`` if no item has that name.
|
|
215
|
+
|
|
216
|
+
Raises:
|
|
217
|
+
RuntimeError: If the service has no current procedure.
|
|
218
|
+
"""
|
|
219
|
+
proc: Procedure = self.get_current_procedure()
|
|
220
|
+
if param_name in proc.procedure_parameters:
|
|
221
|
+
return proc.procedure_parameters[param_name]
|
|
222
|
+
if param_name in proc.process_value_ins:
|
|
223
|
+
return proc.process_value_ins[param_name]
|
|
224
|
+
if param_name in proc.process_value_outs:
|
|
225
|
+
return proc.process_value_outs[param_name]
|
|
226
|
+
if param_name in proc.report_values:
|
|
227
|
+
return proc.report_values[param_name]
|
|
228
|
+
if param_name in proc.required_equipment:
|
|
229
|
+
return proc.required_equipment[param_name]
|
|
230
|
+
return None
|
|
231
|
+
|
|
232
|
+
def add_configuration_parameter(
|
|
233
|
+
self,
|
|
234
|
+
configuration_parameter: ParameterElement,
|
|
235
|
+
) -> None:
|
|
236
|
+
"""Add a configuration parameter to the service.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
configuration_parameter: Parameter to add, keyed by its tag name.
|
|
240
|
+
"""
|
|
241
|
+
self.configuration_parameters[configuration_parameter.tag_name] = (
|
|
242
|
+
configuration_parameter
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
def apply_configuration_parameters(self) -> None:
|
|
246
|
+
"""Apply all configuration parameters to the service.
|
|
247
|
+
|
|
248
|
+
Each parameter is updated through its ``update_v_out`` method.
|
|
249
|
+
"""
|
|
250
|
+
logger.debug(f"values={self.configuration_parameters.values()}")
|
|
251
|
+
for configuration_parameter in self.configuration_parameters.values():
|
|
252
|
+
configuration_parameter: ParameterElement
|
|
253
|
+
configuration_parameter.update_v_out()
|
|
254
|
+
|
|
255
|
+
def add_procedure(
|
|
256
|
+
self,
|
|
257
|
+
procedure: (
|
|
258
|
+
Procedure | list[Procedure | None] | dict[str, Procedure | None] | None
|
|
259
|
+
),
|
|
260
|
+
) -> None:
|
|
261
|
+
"""Add one or more procedures to the service.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
procedure: A procedure, a list of procedures, a mapping of names to
|
|
265
|
+
procedures, or ``None``.
|
|
266
|
+
|
|
267
|
+
Raises:
|
|
268
|
+
ValueError: If any procedure has an ID of zero.
|
|
269
|
+
"""
|
|
270
|
+
if procedure is None:
|
|
271
|
+
return
|
|
272
|
+
if _has_zero_id(procedure):
|
|
273
|
+
msg = "Bad ProcedureID, shall not be 0"
|
|
274
|
+
raise ValueError(msg)
|
|
275
|
+
if isinstance(procedure, dict):
|
|
276
|
+
for proc in procedure.values():
|
|
277
|
+
if proc is not None:
|
|
278
|
+
self.procedures[proc.procedure_id] = proc
|
|
279
|
+
self.service_control.add_procedure_key(proc.procedure_id)
|
|
280
|
+
elif isinstance(procedure, list):
|
|
281
|
+
for proc in procedure:
|
|
282
|
+
if proc is not None:
|
|
283
|
+
self.procedures[proc.procedure_id] = proc
|
|
284
|
+
self.service_control.add_procedure_key(proc.procedure_id)
|
|
285
|
+
else:
|
|
286
|
+
self.procedures[procedure.procedure_id] = procedure
|
|
287
|
+
self.service_control.add_procedure_key(procedure.procedure_id)
|
|
288
|
+
|
|
289
|
+
def _lookup_procedure_cur_name(self) -> str:
|
|
290
|
+
"""Return the name of the currently selected procedure.
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
The current procedure name, or ``"undefined"`` when no procedure
|
|
294
|
+
is selected.
|
|
295
|
+
"""
|
|
296
|
+
procedure_cur: int = self.service_control.get_procedure_cur()
|
|
297
|
+
if procedure_cur == 0:
|
|
298
|
+
return "undefined"
|
|
299
|
+
procedure_name = self.procedures[procedure_cur].name
|
|
300
|
+
logger.debug(
|
|
301
|
+
f"procedureCur={procedure_cur}, procedure_name={procedure_name}",
|
|
302
|
+
)
|
|
303
|
+
return procedure_name
|
|
304
|
+
|
|
305
|
+
def get_current_procedure(self) -> Procedure:
|
|
306
|
+
"""Return the currently selected procedure.
|
|
307
|
+
|
|
308
|
+
Returns:
|
|
309
|
+
The procedure selected by ``PROCEDURE_CUR``.
|
|
310
|
+
|
|
311
|
+
Raises:
|
|
312
|
+
RuntimeError: If no current procedure is selected.
|
|
313
|
+
"""
|
|
314
|
+
procedure_cur: int = self.service_control.get_procedure_cur()
|
|
315
|
+
if procedure_cur == 0:
|
|
316
|
+
msg = "No current procedure selected"
|
|
317
|
+
raise RuntimeError(msg)
|
|
318
|
+
return self.procedures[procedure_cur]
|
|
319
|
+
|
|
320
|
+
def _get_procedures(self) -> dict[int, Procedure]:
|
|
321
|
+
"""Return the service's procedure mapping.
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
A mapping from procedure IDs to procedure objects.
|
|
325
|
+
"""
|
|
326
|
+
return self.procedures
|
|
327
|
+
|
|
328
|
+
def apply_procedure_parameters(self) -> None:
|
|
329
|
+
"""Apply parameters for the currently selected procedure."""
|
|
330
|
+
msg = f"Applying procedure parameters for service={self.name}"
|
|
331
|
+
logger.debug(msg)
|
|
332
|
+
|
|
333
|
+
current_procedure_id: int = self.service_control.get_procedure_cur()
|
|
334
|
+
if current_procedure_id > 0:
|
|
335
|
+
self.procedures[current_procedure_id].apply_procedure_parameters()
|
|
336
|
+
|
|
337
|
+
@abstractmethod
|
|
338
|
+
def idle(self) -> bool:
|
|
339
|
+
"""Execute idle state logic.
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
343
|
+
"""
|
|
344
|
+
|
|
345
|
+
@abstractmethod
|
|
346
|
+
def starting(self) -> bool:
|
|
347
|
+
"""Execute starting state logic.
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
@abstractmethod
|
|
354
|
+
def execute(self) -> bool:
|
|
355
|
+
"""Execute execution state logic.
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
359
|
+
"""
|
|
360
|
+
|
|
361
|
+
@abstractmethod
|
|
362
|
+
def completing(self) -> bool:
|
|
363
|
+
"""Execute completing state logic.
|
|
364
|
+
|
|
365
|
+
Returns:
|
|
366
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
367
|
+
"""
|
|
368
|
+
|
|
369
|
+
@abstractmethod
|
|
370
|
+
def completed(self) -> bool:
|
|
371
|
+
"""Execute completed state logic.
|
|
372
|
+
|
|
373
|
+
Returns:
|
|
374
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
375
|
+
"""
|
|
376
|
+
|
|
377
|
+
@abstractmethod
|
|
378
|
+
def pausing(self) -> bool:
|
|
379
|
+
"""Execute pausing state logic.
|
|
380
|
+
|
|
381
|
+
Returns:
|
|
382
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
383
|
+
"""
|
|
384
|
+
|
|
385
|
+
@abstractmethod
|
|
386
|
+
def paused(self) -> bool:
|
|
387
|
+
"""Execute paused state logic.
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
391
|
+
"""
|
|
392
|
+
|
|
393
|
+
@abstractmethod
|
|
394
|
+
def resuming(self) -> bool:
|
|
395
|
+
"""Execute resuming state logic.
|
|
396
|
+
|
|
397
|
+
Returns:
|
|
398
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
399
|
+
"""
|
|
400
|
+
|
|
401
|
+
@abstractmethod
|
|
402
|
+
def holding(self) -> bool:
|
|
403
|
+
"""Execute holding state logic.
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
407
|
+
"""
|
|
408
|
+
|
|
409
|
+
@abstractmethod
|
|
410
|
+
def held(self) -> bool:
|
|
411
|
+
"""Execute held state logic.
|
|
412
|
+
|
|
413
|
+
Returns:
|
|
414
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
415
|
+
"""
|
|
416
|
+
|
|
417
|
+
@abstractmethod
|
|
418
|
+
def unholding(self) -> bool:
|
|
419
|
+
"""Execute unholding state logic.
|
|
420
|
+
|
|
421
|
+
Returns:
|
|
422
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
423
|
+
"""
|
|
424
|
+
|
|
425
|
+
@abstractmethod
|
|
426
|
+
def stopping(self) -> bool:
|
|
427
|
+
"""Execute stopping state logic.
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
431
|
+
"""
|
|
432
|
+
|
|
433
|
+
@abstractmethod
|
|
434
|
+
def stopped(self) -> bool:
|
|
435
|
+
"""Execute stopped state logic.
|
|
436
|
+
|
|
437
|
+
Returns:
|
|
438
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
439
|
+
"""
|
|
440
|
+
|
|
441
|
+
@abstractmethod
|
|
442
|
+
def aborting(self) -> bool:
|
|
443
|
+
"""Execute aborting state logic.
|
|
444
|
+
|
|
445
|
+
Returns:
|
|
446
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
447
|
+
"""
|
|
448
|
+
|
|
449
|
+
@abstractmethod
|
|
450
|
+
def aborted(self) -> bool:
|
|
451
|
+
"""Execute aborted state logic.
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
455
|
+
"""
|
|
456
|
+
|
|
457
|
+
@abstractmethod
|
|
458
|
+
def resetting(self) -> bool:
|
|
459
|
+
"""Execute resetting state logic.
|
|
460
|
+
|
|
461
|
+
Returns:
|
|
462
|
+
``True`` if the state transition is successful; otherwise, ``False``.
|
|
463
|
+
"""
|