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,252 @@
|
|
|
1
|
+
"""Implementation of the Operation Mode Base Function."""
|
|
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, Callable
|
|
9
|
+
|
|
10
|
+
from mtppy.utils.logging import logger
|
|
11
|
+
from mtppy.utils.data_item import DataItem, DataItemCollection
|
|
12
|
+
from mtppy.part3.definitions.mtp_access import MTPAccess
|
|
13
|
+
from mtppy.part5.definitions.w3c_xml_data_types import W3cXmlDataTypes
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class OperationMode(DataItemCollection):
|
|
17
|
+
# DataItem constant definitions
|
|
18
|
+
STATE_CHANNEL = "StateChannel"
|
|
19
|
+
STATE_OFF_AUT = "StateOffAut"
|
|
20
|
+
STATE_OP_AUT = "StateOpAut"
|
|
21
|
+
STATE_AUT_AUT = "StateAutAut"
|
|
22
|
+
STATE_OFF_OP = "StateOffOp"
|
|
23
|
+
STATE_OP_OP = "StateOpOp"
|
|
24
|
+
STATE_AUT_OP = "StateAutOp"
|
|
25
|
+
STATE_OP_ACT = "StateOpAct"
|
|
26
|
+
STATE_AUT_ACT = "StateAutAct"
|
|
27
|
+
STATE_OFF_ACT = "StateOffAct"
|
|
28
|
+
|
|
29
|
+
# Class-level data items dictionary
|
|
30
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
31
|
+
STATE_CHANNEL: DataItem(
|
|
32
|
+
STATE_CHANNEL, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, False
|
|
33
|
+
),
|
|
34
|
+
STATE_OFF_AUT: DataItem(
|
|
35
|
+
STATE_OFF_AUT, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, False
|
|
36
|
+
),
|
|
37
|
+
STATE_OP_AUT: DataItem(
|
|
38
|
+
STATE_OP_AUT, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, False
|
|
39
|
+
),
|
|
40
|
+
STATE_AUT_AUT: DataItem(
|
|
41
|
+
STATE_AUT_AUT, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, False
|
|
42
|
+
),
|
|
43
|
+
STATE_OFF_OP: DataItem(
|
|
44
|
+
STATE_OFF_OP, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadWriteAccess, False
|
|
45
|
+
),
|
|
46
|
+
STATE_OP_OP: DataItem(
|
|
47
|
+
STATE_OP_OP, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadWriteAccess, False
|
|
48
|
+
),
|
|
49
|
+
STATE_AUT_OP: DataItem(
|
|
50
|
+
STATE_AUT_OP, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadWriteAccess, False
|
|
51
|
+
),
|
|
52
|
+
STATE_OP_ACT: DataItem(
|
|
53
|
+
STATE_OP_ACT, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, False
|
|
54
|
+
),
|
|
55
|
+
STATE_AUT_ACT: DataItem(
|
|
56
|
+
STATE_AUT_ACT, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, False
|
|
57
|
+
),
|
|
58
|
+
STATE_OFF_ACT: DataItem(
|
|
59
|
+
STATE_OFF_ACT, W3cXmlDataTypes.BOOLEAN, MTPAccess.ReadAccess, True
|
|
60
|
+
),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
switch_to_offline_mode_allowed: bool
|
|
64
|
+
|
|
65
|
+
enter_offline_callbacks: list[Callable[[], None]]
|
|
66
|
+
exit_offline_callbacks: list[Callable[[], None]]
|
|
67
|
+
enter_operator_callbacks: list[Callable[[], None]]
|
|
68
|
+
exit_operator_callbacks: list[Callable[[], None]]
|
|
69
|
+
enter_automatic_callbacks: list[Callable[[], None]]
|
|
70
|
+
exit_automatic_callbacks: list[Callable[[], None]]
|
|
71
|
+
|
|
72
|
+
def __init__(self) -> None:
|
|
73
|
+
"""
|
|
74
|
+
Represents the operation mode BaseFunction.
|
|
75
|
+
"""
|
|
76
|
+
super().__init__()
|
|
77
|
+
# Initialize data items with dynamic values (using class-defined data items)
|
|
78
|
+
self.get_item(OperationMode.STATE_CHANNEL).init_value = False
|
|
79
|
+
self.get_item(OperationMode.STATE_OFF_AUT).init_value = False
|
|
80
|
+
self.get_item(OperationMode.STATE_OP_AUT).init_value = False
|
|
81
|
+
self.get_item(OperationMode.STATE_AUT_AUT).init_value = False
|
|
82
|
+
self.get_item(OperationMode.STATE_OFF_OP).init_value = False
|
|
83
|
+
self.get_item(OperationMode.STATE_OP_OP).init_value = False
|
|
84
|
+
self.get_item(OperationMode.STATE_AUT_OP).init_value = False
|
|
85
|
+
self.get_item(OperationMode.STATE_OP_ACT).init_value = False
|
|
86
|
+
self.get_item(OperationMode.STATE_AUT_ACT).init_value = False
|
|
87
|
+
self.get_item(OperationMode.STATE_OFF_ACT).init_value = True
|
|
88
|
+
|
|
89
|
+
self.switch_to_offline_mode_allowed = True
|
|
90
|
+
|
|
91
|
+
self.enter_offline_callbacks = []
|
|
92
|
+
self.exit_offline_callbacks = []
|
|
93
|
+
|
|
94
|
+
self.enter_operator_callbacks = []
|
|
95
|
+
self.exit_operator_callbacks = []
|
|
96
|
+
|
|
97
|
+
self.enter_automatic_callbacks = []
|
|
98
|
+
self.exit_automatic_callbacks = []
|
|
99
|
+
|
|
100
|
+
# Set callbacks for writable items (using the correct pattern for callbacks)
|
|
101
|
+
self.get_item(OperationMode.STATE_OFF_OP).ext_wrt_cb = self.set_state_off_op
|
|
102
|
+
self.get_item(OperationMode.STATE_OP_OP).ext_wrt_cb = self.set_state_op_op
|
|
103
|
+
self.get_item(OperationMode.STATE_AUT_OP).ext_wrt_cb = self.set_state_aut_op
|
|
104
|
+
|
|
105
|
+
self.get_item(OperationMode.STATE_OP_AUT).int_wrt_cb = self.set_state_op_aut
|
|
106
|
+
self.get_item(OperationMode.STATE_OFF_AUT).int_wrt_cb = self.set_state_off_aut
|
|
107
|
+
self.get_item(OperationMode.STATE_AUT_AUT).int_wrt_cb = self.set_state_aut_aut
|
|
108
|
+
|
|
109
|
+
def allow_switch_to_offline_mode(self, allow_flag: bool) -> None:
|
|
110
|
+
self.switch_to_offline_mode_allowed = allow_flag
|
|
111
|
+
|
|
112
|
+
def add_enter_offline_callback(self, callback: Callable[[], None]) -> None:
|
|
113
|
+
self.enter_offline_callbacks.append(callback)
|
|
114
|
+
|
|
115
|
+
def add_exit_offline_callback(self, callback: Callable[[], None]) -> None:
|
|
116
|
+
self.exit_offline_callbacks.append(callback)
|
|
117
|
+
|
|
118
|
+
def add_enter_operator_callback(self, callback: Callable[[], None]) -> None:
|
|
119
|
+
self.enter_operator_callbacks.append(callback)
|
|
120
|
+
|
|
121
|
+
def add_exit_operator_callback(self, callback: Callable[[], None]) -> None:
|
|
122
|
+
self.exit_operator_callbacks.append(callback)
|
|
123
|
+
|
|
124
|
+
def add_enter_automatic_callback(self, callback: Callable[[], None]) -> None:
|
|
125
|
+
self.enter_automatic_callbacks.append(callback)
|
|
126
|
+
|
|
127
|
+
def add_exit_automatic_callback(self, callback: Callable[[], None]) -> None:
|
|
128
|
+
self.exit_automatic_callbacks.append(callback)
|
|
129
|
+
|
|
130
|
+
def _enter_off(self) -> None:
|
|
131
|
+
if len(self.enter_offline_callbacks):
|
|
132
|
+
logger.debug("Applying enter offline mode callbacks")
|
|
133
|
+
[cb() for cb in self.enter_offline_callbacks]
|
|
134
|
+
|
|
135
|
+
def _exit_off(self) -> None:
|
|
136
|
+
if len(self.exit_offline_callbacks):
|
|
137
|
+
logger.debug("Applying exit offline mode callbacks")
|
|
138
|
+
[cb() for cb in self.exit_offline_callbacks]
|
|
139
|
+
|
|
140
|
+
def _enter_op(self) -> None:
|
|
141
|
+
if len(self.enter_operator_callbacks):
|
|
142
|
+
logger.debug("Applying enter operator mode callbacks")
|
|
143
|
+
[cb() for cb in self.enter_operator_callbacks]
|
|
144
|
+
|
|
145
|
+
def _exit_op(self) -> None:
|
|
146
|
+
if len(self.exit_operator_callbacks):
|
|
147
|
+
logger.debug("Applying exit operator mode callbacks")
|
|
148
|
+
[cb() for cb in self.exit_operator_callbacks]
|
|
149
|
+
|
|
150
|
+
def _enter_aut(self) -> None:
|
|
151
|
+
if len(self.enter_automatic_callbacks):
|
|
152
|
+
logger.debug("Applying enter automatic mode callbacks")
|
|
153
|
+
[cb() for cb in self.enter_automatic_callbacks]
|
|
154
|
+
|
|
155
|
+
def _exit_aut(self) -> None:
|
|
156
|
+
if len(self.exit_automatic_callbacks):
|
|
157
|
+
logger.debug("Applying exit automatic mode callbacks")
|
|
158
|
+
[cb() for cb in self.exit_automatic_callbacks]
|
|
159
|
+
|
|
160
|
+
def _opmode_to_off(self) -> None:
|
|
161
|
+
current_mode_is_op = self[OperationMode.STATE_OP_ACT]
|
|
162
|
+
|
|
163
|
+
# Mode change callbacks
|
|
164
|
+
if current_mode_is_op:
|
|
165
|
+
self[OperationMode.STATE_OFF_ACT] = True
|
|
166
|
+
self[OperationMode.STATE_OP_ACT] = False
|
|
167
|
+
self[OperationMode.STATE_AUT_ACT] = False
|
|
168
|
+
self._exit_op()
|
|
169
|
+
self._enter_off()
|
|
170
|
+
logger.debug("Operation mode is now off")
|
|
171
|
+
|
|
172
|
+
def _opmode_to_aut(self) -> None:
|
|
173
|
+
current_mode_is_op = self[OperationMode.STATE_OP_ACT]
|
|
174
|
+
|
|
175
|
+
# Mode change callbacks
|
|
176
|
+
if current_mode_is_op:
|
|
177
|
+
self[OperationMode.STATE_OFF_ACT] = False
|
|
178
|
+
self[OperationMode.STATE_OP_ACT] = False
|
|
179
|
+
self[OperationMode.STATE_AUT_ACT] = True
|
|
180
|
+
self._exit_op()
|
|
181
|
+
self._enter_aut()
|
|
182
|
+
logger.debug("Operation mode is now aut")
|
|
183
|
+
|
|
184
|
+
def _opmode_to_op(self) -> None:
|
|
185
|
+
current_mode_is_off = self[OperationMode.STATE_OFF_ACT]
|
|
186
|
+
current_mode_is_aut = self[OperationMode.STATE_AUT_ACT]
|
|
187
|
+
|
|
188
|
+
# Mode change callbacks
|
|
189
|
+
if current_mode_is_off or current_mode_is_aut:
|
|
190
|
+
if current_mode_is_off:
|
|
191
|
+
self._exit_off()
|
|
192
|
+
elif current_mode_is_aut:
|
|
193
|
+
self._exit_aut()
|
|
194
|
+
self[OperationMode.STATE_OFF_ACT] = False
|
|
195
|
+
self[OperationMode.STATE_OP_ACT] = True
|
|
196
|
+
self[OperationMode.STATE_AUT_ACT] = False
|
|
197
|
+
self._enter_op()
|
|
198
|
+
logger.debug("Operation mode is now op")
|
|
199
|
+
|
|
200
|
+
def set_state_channel(self, value: bool) -> None:
|
|
201
|
+
logger.debug(f"OperationMode StateChannel is now {value}")
|
|
202
|
+
self[OperationMode.STATE_CHANNEL] = value
|
|
203
|
+
|
|
204
|
+
def set_state_aut_aut(self, value: bool) -> None:
|
|
205
|
+
logger.debug(f"StateAutAut set to {value}")
|
|
206
|
+
if self[OperationMode.STATE_CHANNEL] and value:
|
|
207
|
+
if self[OperationMode.STATE_OP_ACT]:
|
|
208
|
+
self._opmode_to_aut()
|
|
209
|
+
|
|
210
|
+
def set_state_aut_op(self, value: bool) -> None:
|
|
211
|
+
logger.debug(f"StateAutOp set to {value}")
|
|
212
|
+
if not self[OperationMode.STATE_CHANNEL] and value:
|
|
213
|
+
if self[OperationMode.STATE_OP_ACT]:
|
|
214
|
+
self._opmode_to_aut()
|
|
215
|
+
# handshake
|
|
216
|
+
self[OperationMode.STATE_AUT_OP] = False
|
|
217
|
+
|
|
218
|
+
def set_state_off_aut(self, value: bool) -> None:
|
|
219
|
+
logger.debug(f"StateOffAut set to {value}")
|
|
220
|
+
if (
|
|
221
|
+
self[OperationMode.STATE_CHANNEL]
|
|
222
|
+
and value
|
|
223
|
+
and self.switch_to_offline_mode_allowed
|
|
224
|
+
):
|
|
225
|
+
if self[OperationMode.STATE_OP_ACT]:
|
|
226
|
+
self._opmode_to_off()
|
|
227
|
+
|
|
228
|
+
def set_state_off_op(self, value: bool) -> None:
|
|
229
|
+
logger.debug(f"StateOffOp set to {value}")
|
|
230
|
+
if (
|
|
231
|
+
not self[OperationMode.STATE_CHANNEL]
|
|
232
|
+
and value
|
|
233
|
+
and self.switch_to_offline_mode_allowed
|
|
234
|
+
):
|
|
235
|
+
if self[OperationMode.STATE_OP_ACT]:
|
|
236
|
+
self._opmode_to_off()
|
|
237
|
+
# handshake
|
|
238
|
+
self[OperationMode.STATE_OFF_OP] = False
|
|
239
|
+
|
|
240
|
+
def set_state_op_aut(self, value: bool) -> None:
|
|
241
|
+
logger.debug(f"StateOpAut set to {value}")
|
|
242
|
+
if self[OperationMode.STATE_CHANNEL] and value:
|
|
243
|
+
if self[OperationMode.STATE_OFF_ACT] or self[OperationMode.STATE_AUT_ACT]:
|
|
244
|
+
self._opmode_to_op()
|
|
245
|
+
|
|
246
|
+
def set_state_op_op(self, value: bool) -> None:
|
|
247
|
+
logger.debug(f"StateOpOp set to {value}")
|
|
248
|
+
if not self[OperationMode.STATE_CHANNEL] and value:
|
|
249
|
+
if self[OperationMode.STATE_OFF_ACT] or self[OperationMode.STATE_AUT_ACT]:
|
|
250
|
+
self._opmode_to_op()
|
|
251
|
+
# handshake
|
|
252
|
+
self[OperationMode.STATE_OP_OP] = False
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"""Test Suite for OperationMode."""
|
|
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.operation_mode import OperationMode
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def init_op_mode(
|
|
14
|
+
init_mode: str = "off",
|
|
15
|
+
state_channel: bool = False,
|
|
16
|
+
allow_switch_to_offline: bool = True,
|
|
17
|
+
):
|
|
18
|
+
|
|
19
|
+
op_mode = OperationMode()
|
|
20
|
+
op_mode.allow_switch_to_offline_mode(allow_switch_to_offline)
|
|
21
|
+
op_mode.set_state_channel(state_channel)
|
|
22
|
+
|
|
23
|
+
if init_mode == "off":
|
|
24
|
+
op_mode[OperationMode.STATE_AUT_ACT] = False
|
|
25
|
+
op_mode[OperationMode.STATE_OFF_ACT] = True
|
|
26
|
+
op_mode[OperationMode.STATE_OP_ACT] = False
|
|
27
|
+
elif init_mode == "op":
|
|
28
|
+
op_mode[OperationMode.STATE_AUT_ACT] = False
|
|
29
|
+
op_mode[OperationMode.STATE_OFF_ACT] = False
|
|
30
|
+
op_mode[OperationMode.STATE_OP_ACT] = True
|
|
31
|
+
elif init_mode == "aut":
|
|
32
|
+
op_mode[OperationMode.STATE_AUT_ACT] = True
|
|
33
|
+
op_mode[OperationMode.STATE_OFF_ACT] = False
|
|
34
|
+
op_mode[OperationMode.STATE_OP_ACT] = False
|
|
35
|
+
else:
|
|
36
|
+
raise ValueError(f"Operation mode {init_mode} is unknown")
|
|
37
|
+
|
|
38
|
+
return op_mode
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def operation_mode_is_in_specific_mode(
|
|
42
|
+
op_mode: OperationMode, state_channel_assertion: bool, mode_assertion: str
|
|
43
|
+
):
|
|
44
|
+
return all(
|
|
45
|
+
[
|
|
46
|
+
op_mode[OperationMode.STATE_CHANNEL] == state_channel_assertion,
|
|
47
|
+
op_mode[OperationMode.STATE_OFF_AUT] == False,
|
|
48
|
+
op_mode[OperationMode.STATE_OP_AUT] == False,
|
|
49
|
+
op_mode[OperationMode.STATE_AUT_AUT] == False,
|
|
50
|
+
op_mode[OperationMode.STATE_OFF_OP] == False,
|
|
51
|
+
op_mode[OperationMode.STATE_OP_OP] == False,
|
|
52
|
+
op_mode[OperationMode.STATE_AUT_OP] == False,
|
|
53
|
+
op_mode[OperationMode.STATE_OP_ACT] == (mode_assertion == "op"),
|
|
54
|
+
op_mode[OperationMode.STATE_AUT_ACT] == (mode_assertion == "aut"),
|
|
55
|
+
op_mode[OperationMode.STATE_OFF_ACT] == (mode_assertion == "off"),
|
|
56
|
+
]
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_initial_state():
|
|
61
|
+
op_mode = init_op_mode(init_mode="off", state_channel=False)
|
|
62
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "off") == True
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_state_channel_change():
|
|
66
|
+
op_mode = init_op_mode()
|
|
67
|
+
op_mode.StateChannel = True
|
|
68
|
+
assert op_mode["StateChannel"] == True
|
|
69
|
+
op_mode.StateChannel = False
|
|
70
|
+
assert op_mode["StateChannel"] == False
|
|
71
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "off") == True
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_off_to_op_state_channel_false():
|
|
75
|
+
# Initial mode
|
|
76
|
+
op_mode = init_op_mode(init_mode="off", state_channel=False)
|
|
77
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "off") == True
|
|
78
|
+
# Emulate mode transition by external writer
|
|
79
|
+
op_mode.get_item(OperationMode.STATE_OP_OP).ext_wrt_cb(True)
|
|
80
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "op") == True
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_off_to_op_state_channel_true():
|
|
84
|
+
# Initial mode
|
|
85
|
+
op_mode = init_op_mode(init_mode="off", state_channel=True)
|
|
86
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "off") == True
|
|
87
|
+
# Trigger mode transition
|
|
88
|
+
op_mode.StateOpAut = True
|
|
89
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "op") == True
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_op_to_off_state_channel_false():
|
|
93
|
+
# Initial mode
|
|
94
|
+
op_mode = init_op_mode(init_mode="op", state_channel=False)
|
|
95
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "op") == True
|
|
96
|
+
# Trigger mode transition
|
|
97
|
+
op_mode.get_item(OperationMode.STATE_OFF_OP).ext_wrt_cb(True)
|
|
98
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "off") == True
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_op_to_off_state_channel_true():
|
|
102
|
+
# Initial mode
|
|
103
|
+
op_mode = init_op_mode(init_mode="op", state_channel=True)
|
|
104
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "op") == True
|
|
105
|
+
# Trigger mode transition
|
|
106
|
+
op_mode.StateOffAut = True
|
|
107
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "off") == True
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_off_to_aut_state_channel_false():
|
|
111
|
+
# Initial mode
|
|
112
|
+
op_mode = init_op_mode(init_mode="off", state_channel=False)
|
|
113
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "off") == True
|
|
114
|
+
# Trigger invalid mode transition --> no change expected
|
|
115
|
+
op_mode.get_item(OperationMode.STATE_AUT_OP).ext_wrt_cb(True)
|
|
116
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "off") == True
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_off_to_aut_state_channel_true():
|
|
120
|
+
# Initial mode
|
|
121
|
+
op_mode = init_op_mode(init_mode="off", state_channel=True)
|
|
122
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "off") == True
|
|
123
|
+
# Trigger invalid mode transition --> no change expected
|
|
124
|
+
op_mode.StateAutAut = True
|
|
125
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "off") == True
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_aut_to_off_state_channel_false():
|
|
129
|
+
# Initial mode
|
|
130
|
+
op_mode = init_op_mode(init_mode="aut", state_channel=False)
|
|
131
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "aut") == True
|
|
132
|
+
# Trigger invalid mode transition --> no change expected
|
|
133
|
+
op_mode.get_item(OperationMode.STATE_OFF_OP).ext_wrt_cb(True)
|
|
134
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "aut") == True
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def test_aut_to_off_state_channel_true():
|
|
138
|
+
# Initial mode
|
|
139
|
+
op_mode = init_op_mode(init_mode="aut", state_channel=True)
|
|
140
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "aut") == True
|
|
141
|
+
# Trigger invalid mode transition --> no change expected
|
|
142
|
+
op_mode.StateOffAut = True
|
|
143
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "aut") == True
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def test_aut_to_op_state_channel_false():
|
|
147
|
+
# Initial mode
|
|
148
|
+
op_mode = init_op_mode(init_mode="aut", state_channel=False)
|
|
149
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "aut") == True
|
|
150
|
+
# Trigger mode transition
|
|
151
|
+
op_mode.get_item(OperationMode.STATE_OP_OP).ext_wrt_cb(True)
|
|
152
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "op") == True
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def test_aut_to_op_state_channel_true():
|
|
156
|
+
# Initial mode
|
|
157
|
+
op_mode = init_op_mode(init_mode="aut", state_channel=True)
|
|
158
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "aut") == True
|
|
159
|
+
# Trigger mode transition
|
|
160
|
+
op_mode.StateOpAut = True
|
|
161
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "op") == True
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def test_op_to_aut_state_channel_false():
|
|
165
|
+
# Initial mode
|
|
166
|
+
op_mode = init_op_mode(init_mode="op", state_channel=False)
|
|
167
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "op") == True
|
|
168
|
+
# Trigger mode transition
|
|
169
|
+
op_mode.get_item(OperationMode.STATE_AUT_OP).ext_wrt_cb(True)
|
|
170
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "aut") == True
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def test_op_to_aut_state_channel_true():
|
|
174
|
+
# Initial mode
|
|
175
|
+
op_mode = init_op_mode(init_mode="op", state_channel=True)
|
|
176
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "op") == True
|
|
177
|
+
# Trigger mode transition
|
|
178
|
+
op_mode.StateAutAut = True
|
|
179
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "aut") == True
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def test_allowance_change_op_to_off_state_channel_false():
|
|
183
|
+
# Initial mode
|
|
184
|
+
op_mode = init_op_mode(
|
|
185
|
+
init_mode="op", state_channel=False, allow_switch_to_offline=False
|
|
186
|
+
)
|
|
187
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "op") == True
|
|
188
|
+
# Trigger mode transition
|
|
189
|
+
op_mode.get_item(OperationMode.STATE_OFF_OP).ext_wrt_cb(True)
|
|
190
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "op") == True
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def test_blocked_change_op_to_off_state_channel_true():
|
|
194
|
+
# Initial mode with offline switch blocked
|
|
195
|
+
op_mode = init_op_mode(
|
|
196
|
+
init_mode="op", state_channel=True, allow_switch_to_offline=False
|
|
197
|
+
)
|
|
198
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "op") == True
|
|
199
|
+
# Trigger valid mode transition
|
|
200
|
+
op_mode.get_item(OperationMode.STATE_OFF_AUT).int_wrt_cb(True)
|
|
201
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "op") == True
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def test_forbidden_change_aut_to_off_state_channel_true():
|
|
205
|
+
# Initial mode
|
|
206
|
+
op_mode = init_op_mode(
|
|
207
|
+
init_mode="aut", state_channel=True, allow_switch_to_offline=True
|
|
208
|
+
)
|
|
209
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "aut") == True
|
|
210
|
+
# Trigger invalid mode transition
|
|
211
|
+
op_mode.get_item(OperationMode.STATE_OFF_AUT).int_wrt_cb(True)
|
|
212
|
+
assert operation_mode_is_in_specific_mode(op_mode, True, "aut") == True
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_exit_offline_callback_off_to_op():
|
|
216
|
+
test_value = {"value": 0}
|
|
217
|
+
|
|
218
|
+
def callback_function():
|
|
219
|
+
test_value["value"] = 10
|
|
220
|
+
|
|
221
|
+
# Initial mode
|
|
222
|
+
op_mode = init_op_mode()
|
|
223
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "off") == True
|
|
224
|
+
|
|
225
|
+
# Simulate external write on StateOpOp
|
|
226
|
+
op_mode.get_item(OperationMode.STATE_OP_OP).ext_wrt_cb(True)
|
|
227
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "op") == True
|
|
228
|
+
assert test_value["value"] == 0
|
|
229
|
+
|
|
230
|
+
# Initial mode
|
|
231
|
+
op_mode = init_op_mode()
|
|
232
|
+
op_mode.add_exit_offline_callback(callback_function)
|
|
233
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "off") == True
|
|
234
|
+
# Trigger mode transition with registered callback
|
|
235
|
+
op_mode.get_item(OperationMode.STATE_OP_OP).ext_wrt_cb(True)
|
|
236
|
+
assert operation_mode_is_in_specific_mode(op_mode, False, "op") == True
|
|
237
|
+
assert test_value["value"] == 10
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@pytest.mark.parametrize(
|
|
241
|
+
"state_request",
|
|
242
|
+
[
|
|
243
|
+
OperationMode.STATE_OFF_OP,
|
|
244
|
+
OperationMode.STATE_OP_OP,
|
|
245
|
+
OperationMode.STATE_AUT_OP,
|
|
246
|
+
],
|
|
247
|
+
)
|
|
248
|
+
def test_external_state_request_handshake(state_request: str) -> None:
|
|
249
|
+
op_mode = init_op_mode()
|
|
250
|
+
|
|
251
|
+
callback = op_mode.get_item(state_request).ext_wrt_cb
|
|
252
|
+
assert callback is not None
|
|
253
|
+
callback(True)
|
|
254
|
+
|
|
255
|
+
assert op_mode[state_request] is False
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
if __name__ == "__main__":
|
|
259
|
+
# This allows running the tests directly if needed
|
|
260
|
+
pytest.main([__file__, "-v"])
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Implementation of the OS Level Base Function."""
|
|
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 OSLevelBaseFunction(DataItemCollection):
|
|
16
|
+
OS_LEVEL = "OSLevel"
|
|
17
|
+
|
|
18
|
+
CLASS_DATA_ITEMS: ClassVar = {
|
|
19
|
+
OS_LEVEL: DataItem(
|
|
20
|
+
OS_LEVEL,
|
|
21
|
+
W3cXmlDataTypes.UNSIGNED_SHORT,
|
|
22
|
+
MTPAccess.ReadWriteAccess,
|
|
23
|
+
init_value=0,
|
|
24
|
+
),
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
def __init__(self) -> None:
|
|
28
|
+
"""
|
|
29
|
+
Initialize the OSLevel BaseFunction.
|
|
30
|
+
"""
|
|
31
|
+
super().__init__()
|
|
32
|
+
self.get_item(self.OS_LEVEL).ext_wrt_cb = self.set_os_level
|
|
33
|
+
|
|
34
|
+
def set_os_level(self, value) -> None:
|
|
35
|
+
self[OSLevelBaseFunction.OS_LEVEL] = value
|