MTPPy2.0 0.1.7__tar.gz → 0.2.0__tar.gz
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.
- {mtppy2_0-0.1.7/src/MTPPy2.0.egg-info → mtppy2_0-0.2.0}/PKG-INFO +1 -1
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/pyproject.toml +9 -1
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0/src/MTPPy2.0.egg-info}/PKG-INFO +1 -1
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/SOURCES.txt +4 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/modbus/m15_logic.py +35 -11
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/modbus/m15_pea.py +1 -1
- mtppy2_0-0.2.0/src/examples/modbus/m15_simulator.py +42 -0
- mtppy2_0-0.2.0/src/examples/rmtp/minimal+pid.py +81 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/rmtp/minimal.py +1 -1
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/scratch/pea_minimal.py +50 -56
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/__init__.py +14 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/config_loader.py +21 -24
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/config_loader_test.py +34 -4
- mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_action.py +243 -0
- mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_action_test.py +296 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_logic.py +44 -79
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_logic_test.py +107 -11
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_service.py +21 -21
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_service_test.py +2 -1
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/mon_ana_drv.py +212 -89
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/mon_ana_drv_test.py +0 -28
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/mon_bin_drv.py +172 -64
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/mon_bin_drv_test.py +37 -45
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/pid/pid_ctrl.py +4 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/mon_ana_vlv.py +177 -77
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/mon_ana_vlv_test.py +60 -55
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/mon_bin_vlv.py +158 -64
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/mon_bin_vlv_test.py +49 -57
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/operation_mode.py +3 -2
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/operation_mode_test.py +4 -4
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/state_machine.py +24 -9
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/state_machine_test.py +94 -0
- mtppy2_0-0.2.0/src/mtppy/part4/automation_services/helpers/thread_control.py +184 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service.py +176 -137
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/service_control.py +10 -8
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/service_control_test.py +8 -4
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_test.py +44 -73
- mtppy2_0-0.2.0/src/mtppy/part5/communication_object.py +199 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/data_assembly_factory.py +27 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/mtp_generator/mtp_generator_test.py +21 -20
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea.py +101 -2
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/marshalling.py +12 -0
- mtppy2_0-0.2.0/src/mtppy/pea/user_logic/user_logic_service.py +326 -0
- mtppy2_0-0.2.0/src/mtppy/pea/user_logic/user_logic_service_scenario_test.py +360 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_service_test.py +47 -26
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/data_item.py +25 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/tools/minimal_recipe.py +72 -6
- mtppy2_0-0.2.0/tests/test_examples.py +325 -0
- mtppy2_0-0.1.7/src/examples/rmtp/minimal+pid.py +0 -82
- mtppy2_0-0.1.7/src/mtppy/part4/automation_services/helpers/thread_control.py +0 -39
- mtppy2_0-0.1.7/src/mtppy/part5/communication_object.py +0 -100
- mtppy2_0-0.1.7/src/mtppy/pea/user_logic/user_logic_service.py +0 -228
- mtppy2_0-0.1.7/tests/test_examples.py +0 -171
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/LICENSE +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/README.md +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/setup.cfg +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/dependency_links.txt +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/entry_points.txt +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/requires.txt +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/top_level.txt +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/modbus/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/modbus/m15_pea_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/pea_alarm_base.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/rmtp/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/scratch/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_procedure.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_procedure_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part1/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part1/empty_folder_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/active_element.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/ana_drv.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/ana_drv_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/bin_drv.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/bin_drv_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/pid/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/pid/pid_ctrl_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/ana_vlv.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/ana_vlv_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/bin_vlv.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/bin_vlv_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/oslevel.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/source_mode.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/source_mode_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/wqc.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/wqc_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/data_assembly.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/diagnostic_elements/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/diagnostic_elements/diagnostic_element.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/indicator_element.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/ana_view.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/bin_view.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/dint_view.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/string_view.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/operation_elements/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/operation_elements/operation_element.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/pea_element.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/pea_information_label/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/pea_information_label/pea_information_label.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/web_server_url_info/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/web_server_url_info/web_server_url_info.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/definitions/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/definitions/mtp_access.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_operation_mode.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_operation_mode_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_operator_interaction.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_source_mode.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_source_mode_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/command_en_control.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/command_en_control_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/thread_control_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/procedure.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/procedure_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/ana_serv_param.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/ana_serv_param_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/bin_serv_param.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/bin_serv_param_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/common_serv_param.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/dint_serv_param.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/dint_serv_param_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/parameter_element.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/parameter_element_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/string_serv_param.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/string_serv_param_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/procedure_health_view.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/service_element.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/command_codes.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/command_codes_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/state_codes.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/state_codes_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/base_functions/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/base_functions/vqc.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/ana_process_value_in.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/bin_process_value_in.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/dint_process_value_in.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/input_element.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/string_process_value_in.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/communication_object_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/iec61131_data_types.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/iec61131_data_types_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/opcua_data_types.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/opcua_data_types_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/w3c_xml_data_types.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/w3c_xml_data_types_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/server_assembly_set/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part6/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part6/alarm_set/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part6/alarm_set/alarm.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part6/alarm_set/alarm_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/data_assembly_factory_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/mtp_generator/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/mtp_generator/mtp_generator.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/opcua_options_provider/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/opcua_options_provider/instances/basic_opcua_options_provider.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/opcua_options_provider/opcua_options_provider.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/pea_opcua_server.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/subscription_list.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/rmtp_pea.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/rmtp_pea_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/service_factory.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/service_factory_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_pea.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_registry.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_registry_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/data_assembly_dict.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/data_assembly_dict_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/data_item_com_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/data_item_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/logging.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/logging_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/extract_manifest_from_mtp_file.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/extract_mtp_file.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_mtp.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_path_for_manifest.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_path_to_manifest.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_path_to_mtp.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/load_manifest_file.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_reader.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_reader_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_xml.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_xml_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/mtp_writer.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/ressources/get_content_types.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/ressources/get_rels.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/test_mtp_writer.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_manifest_file.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_manifest_file_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_mtp_file.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_mtp_file_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/testing.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/tools/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/tools/create_bugreport.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/tools/inspect_mtp.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/tools/scan_pea.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/__init__.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/cleanup_folder.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/get_utc_foldername_with_ms.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/get_work_dir.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/is_valid_path_for_json.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/is_valid_path_to_json.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/load_json_file.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/read_file_from_file_archive.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/read_file_string.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/validate_json_data.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/write_json_file.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/get_uuid.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/get_uuid_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/logging.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/logging_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/opcua/check_node.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/resolve_unit/resolve_unit.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/resolve_unit/unit_lib.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/resolve_unit/unit_lib_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/type_conversion.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/type_conversion_test.py +0 -0
- {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/tests/test_data_item_handshake.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MTPPy2.0
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Open-source modular automation with MTP 2.0
|
|
5
5
|
Author: Dresden University of Technology, Process-to-Order Group
|
|
6
6
|
Author-email: Julius Lorenz <julius.lorenz@tu-dresden.de>, Leon Urbas <leon.urbas@tu-dresden.de>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "MTPPy2.0"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
description = "Open-source modular automation with MTP 2.0"
|
|
5
5
|
readme="README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -103,7 +103,12 @@ filterwarnings = [
|
|
|
103
103
|
]
|
|
104
104
|
|
|
105
105
|
[tool.ruff]
|
|
106
|
+
line-length = 88
|
|
107
|
+
target-version = "py310"
|
|
108
|
+
inline-quotes = "double"
|
|
109
|
+
|
|
106
110
|
lint.select = ["ALL"]
|
|
111
|
+
|
|
107
112
|
# ANN001 - Missing type annotation for function argument
|
|
108
113
|
# `incorrect-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible. Ignoring `incorrect-blank-line-before-class`.
|
|
109
114
|
# `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible. Ignoring `multi-line-summary-second-line`.
|
|
@@ -113,3 +118,6 @@ lint.select = ["ALL"]
|
|
|
113
118
|
# `Missing blank line after last section` (D413)
|
|
114
119
|
# `Too many arguments in function definition` (PLR0913)
|
|
115
120
|
lint.ignore = ["ANN002","ANN003","D203","D213","D205","D413","PLR0913"]
|
|
121
|
+
|
|
122
|
+
[tool.ruff.pydocstyle]
|
|
123
|
+
convention = "google" # Enforce Google-style docstrings
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MTPPy2.0
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Open-source modular automation with MTP 2.0
|
|
5
5
|
Author: Dresden University of Technology, Process-to-Order Group
|
|
6
6
|
Author-email: Julius Lorenz <julius.lorenz@tu-dresden.de>, Leon Urbas <leon.urbas@tu-dresden.de>
|
|
@@ -13,6 +13,7 @@ src/examples/modbus/__init__.py
|
|
|
13
13
|
src/examples/modbus/m15_logic.py
|
|
14
14
|
src/examples/modbus/m15_pea.py
|
|
15
15
|
src/examples/modbus/m15_pea_test.py
|
|
16
|
+
src/examples/modbus/m15_simulator.py
|
|
16
17
|
src/examples/rmtp/__init__.py
|
|
17
18
|
src/examples/rmtp/minimal+pid.py
|
|
18
19
|
src/examples/rmtp/minimal.py
|
|
@@ -23,6 +24,8 @@ src/mtppy/feas/__init__.py
|
|
|
23
24
|
src/mtppy/feas/modbus/__init__.py
|
|
24
25
|
src/mtppy/feas/modbus/config_loader.py
|
|
25
26
|
src/mtppy/feas/modbus/config_loader_test.py
|
|
27
|
+
src/mtppy/feas/modbus/io_action.py
|
|
28
|
+
src/mtppy/feas/modbus/io_action_test.py
|
|
26
29
|
src/mtppy/feas/modbus/io_logic.py
|
|
27
30
|
src/mtppy/feas/modbus/io_logic_test.py
|
|
28
31
|
src/mtppy/feas/modbus/io_procedure.py
|
|
@@ -173,6 +176,7 @@ src/mtppy/pea/user_logic/user_logic_pea.py
|
|
|
173
176
|
src/mtppy/pea/user_logic/user_logic_registry.py
|
|
174
177
|
src/mtppy/pea/user_logic/user_logic_registry_test.py
|
|
175
178
|
src/mtppy/pea/user_logic/user_logic_service.py
|
|
179
|
+
src/mtppy/pea/user_logic/user_logic_service_scenario_test.py
|
|
176
180
|
src/mtppy/pea/user_logic/user_logic_service_test.py
|
|
177
181
|
src/mtppy/utils/__init__.py
|
|
178
182
|
src/mtppy/utils/data_assembly_dict.py
|
|
@@ -5,29 +5,42 @@ __copyright__ = (
|
|
|
5
5
|
)
|
|
6
6
|
__license__ = "MIT"
|
|
7
7
|
|
|
8
|
+
from mtppy.part3.data_assembly_set.active_elements.pid.pid_ctrl import PIDCtrl
|
|
9
|
+
from mtppy.utils.logging import logger
|
|
8
10
|
from mtppy.part4.automation_services.service import Service
|
|
9
11
|
from mtppy.pea.user_logic.user_logic_registry import register
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
__requirements_mtp__ = "M15.mtp"
|
|
14
|
+
|
|
13
15
|
DA_PRESSURE_UNITS = "p_eng_units"
|
|
14
16
|
DA_TEMP_UNITS = "t_eng_units"
|
|
15
17
|
DA_VOLUME_UNITS = "v_eng_units"
|
|
16
18
|
DA_START_STOP = "start_stop"
|
|
17
|
-
DA_VALVE = "
|
|
19
|
+
DA_VALVE = "V010"
|
|
20
|
+
|
|
18
21
|
|
|
19
22
|
"""
|
|
20
|
-
Spezifikation für produce.auto.
|
|
23
|
+
Spezifikation für produce.auto.starting.entry:
|
|
21
24
|
Setze die Anzeigeeinheiten des Generators (Druck, Temperatur,
|
|
22
25
|
Volumen) auf den Standardwert 0.
|
|
23
26
|
"""
|
|
24
27
|
|
|
25
28
|
|
|
26
|
-
@register("produce.auto.
|
|
29
|
+
@register("produce.auto.starting.entry")
|
|
27
30
|
def reset_units(context: Service) -> bool:
|
|
28
31
|
context.get_param(DA_PRESSURE_UNITS).V = 0
|
|
29
32
|
context.get_param(DA_TEMP_UNITS).V = 0
|
|
30
33
|
context.get_param(DA_VOLUME_UNITS).V = 0
|
|
34
|
+
|
|
35
|
+
pctl: PIDCtrl = context.get_param("PIC009")
|
|
36
|
+
|
|
37
|
+
pctl.op_mode.set_state_channel(True)
|
|
38
|
+
pctl.op_mode.set_state_aut_aut(True)
|
|
39
|
+
pctl.src_mode.set_src_channel(True)
|
|
40
|
+
pctl.src_mode.set_src_man_aut(True)
|
|
41
|
+
pctl.SPManMin = pctl.SPSclMin = 0
|
|
42
|
+
pctl.SPManMax = pctl.SPSclMax = 100
|
|
43
|
+
|
|
31
44
|
return True
|
|
32
45
|
|
|
33
46
|
|
|
@@ -39,8 +52,15 @@ Spezifikation für produce.auto.starting.do:
|
|
|
39
52
|
|
|
40
53
|
@register("produce.auto.starting.do")
|
|
41
54
|
def start_generator(context: Service) -> bool:
|
|
42
|
-
context.get_param(DA_START_STOP)
|
|
43
|
-
context.get_param(DA_VALVE)
|
|
55
|
+
start_stop = context.get_param(DA_START_STOP)
|
|
56
|
+
valve = context.get_param(DA_VALVE)
|
|
57
|
+
p_out_sp = context.get_param("p_out_sp")
|
|
58
|
+
pctl: PIDCtrl = context.get_param("PIC009")
|
|
59
|
+
|
|
60
|
+
start_stop.V = 0
|
|
61
|
+
valve.OpenAut = 1
|
|
62
|
+
pctl.SPMan = p_out_sp.VOut
|
|
63
|
+
|
|
44
64
|
return True
|
|
45
65
|
|
|
46
66
|
|
|
@@ -52,7 +72,7 @@ Spezifikation für produce.auto.holding.do:
|
|
|
52
72
|
|
|
53
73
|
@register("produce.auto.holding.do")
|
|
54
74
|
def hold_generator(context: Service) -> bool:
|
|
55
|
-
context.get_param(DA_VALVE).
|
|
75
|
+
context.get_param(DA_VALVE).CloseAut = 1
|
|
56
76
|
return True
|
|
57
77
|
|
|
58
78
|
|
|
@@ -64,7 +84,7 @@ Spezifikation für produce.auto.unholding.do:
|
|
|
64
84
|
|
|
65
85
|
@register("produce.auto.unholding.do")
|
|
66
86
|
def unhold_generator(context: Service) -> bool:
|
|
67
|
-
context.get_param(DA_VALVE).
|
|
87
|
+
context.get_param(DA_VALVE).OpenAut = 1
|
|
68
88
|
return True
|
|
69
89
|
|
|
70
90
|
|
|
@@ -79,6 +99,10 @@ Spezifikation für produce.auto.completing.do sowie stopping und aborting:
|
|
|
79
99
|
"produce.auto.completing.do", "produce.auto.stopping.do", "produce.auto.aborting.do"
|
|
80
100
|
)
|
|
81
101
|
def stop_generator(context: Service) -> bool:
|
|
82
|
-
context.get_param(DA_START_STOP)
|
|
83
|
-
context.get_param(DA_VALVE)
|
|
102
|
+
start_stop = context.get_param(DA_START_STOP)
|
|
103
|
+
valve = context.get_param(DA_VALVE)
|
|
104
|
+
|
|
105
|
+
start_stop.V = 1
|
|
106
|
+
valve.CloseAut = 1
|
|
107
|
+
|
|
84
108
|
return True
|
|
@@ -153,7 +153,7 @@ class M15Pea(UserLogicPEA):
|
|
|
153
153
|
|
|
154
154
|
def stop(self) -> None:
|
|
155
155
|
"""Stop the cyclic I/O service, OPC UA server, and Modbus client."""
|
|
156
|
-
self.io_service.
|
|
156
|
+
self.io_service.stop()
|
|
157
157
|
super().stop()
|
|
158
158
|
self.modbus_client.close()
|
|
159
159
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from pymodbus.simulator import SimData, SimDevice, DataType
|
|
4
|
+
from pymodbus.server import StartAsyncTcpServer
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
async def my_action(
|
|
8
|
+
function_code: int, # request function code
|
|
9
|
+
start_address: int, # address of current_registers[0]
|
|
10
|
+
address: int, # request address
|
|
11
|
+
count: int, # request count
|
|
12
|
+
current_registers: list[int], # current registers (modify inline)
|
|
13
|
+
set_values: (
|
|
14
|
+
list[int] | list[bool] | None
|
|
15
|
+
), # request values to be written (None for read requests)
|
|
16
|
+
) -> None:
|
|
17
|
+
if set_values is not None:
|
|
18
|
+
print(f"{address}:{set_values}")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
devices = SimDevice(
|
|
22
|
+
id=1,
|
|
23
|
+
simdata=[
|
|
24
|
+
SimData(address=400, count=3, datatype=DataType.UINT16),
|
|
25
|
+
SimData(address=534, count=1, datatype=DataType.UINT16),
|
|
26
|
+
SimData(address=1001, count=21, datatype=DataType.UINT16),
|
|
27
|
+
SimData(address=1101, count=1, datatype=DataType.UINT16),
|
|
28
|
+
SimData(address=1106, count=20, datatype=DataType.UINT16),
|
|
29
|
+
SimData(address=1200, count=6, datatype=DataType.UINT16),
|
|
30
|
+
SimData(address=1400, count=1, datatype=DataType.UINT16),
|
|
31
|
+
SimData(address=1479, count=1, datatype=DataType.UINT16),
|
|
32
|
+
],
|
|
33
|
+
action=my_action,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def __main__():
|
|
38
|
+
await StartAsyncTcpServer(context=devices, address=("0.0.0.0", 5020))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if __name__ == "__main__":
|
|
42
|
+
asyncio.run(__main__())
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
__copyright__ = (
|
|
2
|
+
"Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
|
|
3
|
+
)
|
|
4
|
+
__license__ = "MIT"
|
|
5
|
+
|
|
6
|
+
import random
|
|
7
|
+
|
|
8
|
+
from mtppy.part4.automation_services.service import Service
|
|
9
|
+
from mtppy.pea.user_logic.user_logic_registry import register
|
|
10
|
+
from mtppy.utils.logging import logger
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
Spezifikation für Service rand_num_gen:
|
|
14
|
+
Funktion: Generiert eine Zufallszahl innerhalb der angegebenen Grenzen.
|
|
15
|
+
Zustände: Die aktuelle Zahl wird nur in execute generiert, in allen anderen Zuständen
|
|
16
|
+
wird kein neuer Wert generiert.
|
|
17
|
+
Prozedur: cont
|
|
18
|
+
Parameter der Prozedur:
|
|
19
|
+
lower_bound: Untere Grenze für die Zufallszahl.
|
|
20
|
+
upper_bound: Obere Grenze für die Zufallszahl.
|
|
21
|
+
generated_value: Reportvariable, in die die generierte Zufallszahl geschrieben wird.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@register("rand_num_gen.cont.idle.entry")
|
|
26
|
+
def setup_cont(self: Service) -> bool:
|
|
27
|
+
self.cycle_time = 1.0
|
|
28
|
+
return True
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@register("rand_num_gen.cont.execute.do")
|
|
32
|
+
def random_number(self: Service) -> bool:
|
|
33
|
+
lb = self.get_param(PROC, "lower_bound")
|
|
34
|
+
ub = self.get_param(PROC, "upper_bound")
|
|
35
|
+
gn = self.get_param(PROC, "generated_value")
|
|
36
|
+
pid = self.get_param("pid_ctrl")
|
|
37
|
+
|
|
38
|
+
pid.SPSclMin = pid.SPIntMin = lb.VOut
|
|
39
|
+
pid.SPSclMax = pid.SPIntMax = ub.VOut
|
|
40
|
+
gn.V = random.randint(lb.VOut, ub.VOut)
|
|
41
|
+
|
|
42
|
+
logger.app(f"--- generated: {gn.V}")
|
|
43
|
+
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
"""Spezifikation für Service control:
|
|
48
|
+
Funktion: Implementiert die Steuerlogik für den PID-Regler.
|
|
49
|
+
Zustände: Die Steuerung erfolgt nur in execute, in allen anderen Zuständen
|
|
50
|
+
wird keine Regelaktion durchgeführt. Eingangsgröße des Reglers ist die
|
|
51
|
+
in der Prozedur "auto" erzeugte Zufallszahl.
|
|
52
|
+
Prozedur: ctrl
|
|
53
|
+
Parameter der Prozedur: -
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@register("control.ctrl.idle.entry")
|
|
58
|
+
def setup_ctrl(self: Service) -> bool:
|
|
59
|
+
self.cycle_time = 0.1
|
|
60
|
+
pid_ctrl = self.get_param("pid_ctrl")
|
|
61
|
+
pid_ctrl.StateChannel = True
|
|
62
|
+
pid_ctrl.SetAutAut = True
|
|
63
|
+
pid_ctrl.SrcChannel = True
|
|
64
|
+
pid_ctrl.SrcIntAut = True
|
|
65
|
+
pid_ctrl.P = 1
|
|
66
|
+
pid_ctrl.Ti = 0
|
|
67
|
+
pid_ctrl.Td = 0
|
|
68
|
+
return True
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@register("control.ctrl.execute.do")
|
|
72
|
+
def set_target_value(self: Service) -> bool:
|
|
73
|
+
sp = self.get_param("generated_value")
|
|
74
|
+
pid_ctrl = self.get_param("pid_ctrl")
|
|
75
|
+
|
|
76
|
+
if pid_ctrl.SP != sp.V:
|
|
77
|
+
pid_ctrl.SPInt = sp.V
|
|
78
|
+
|
|
79
|
+
logger.app(f"--- Setpoint {pid_ctrl.SP}")
|
|
80
|
+
|
|
81
|
+
return True
|
|
@@ -5,13 +5,16 @@ __copyright__ = (
|
|
|
5
5
|
)
|
|
6
6
|
__license__ = "MIT"
|
|
7
7
|
|
|
8
|
+
import asyncio
|
|
8
9
|
import time
|
|
9
10
|
import random
|
|
10
11
|
import argparse
|
|
11
12
|
import sys
|
|
13
|
+
from pathlib import Path
|
|
12
14
|
|
|
13
15
|
from mtppy.utils.logging import logger, CHOICES, setLogLevel
|
|
14
16
|
from mtppy.pea.pea import PEA
|
|
17
|
+
from mtppy.pea.mtp_generator.mtp_generator import MTPGenerator
|
|
15
18
|
from mtppy.part3.data_assembly_set.active_elements.pid.pid_ctrl import PIDCtrl
|
|
16
19
|
from mtppy.part3.data_assembly_set.indicator_elements.views.ana_view import AnaView
|
|
17
20
|
from mtppy.part4.automation_services.service import Service
|
|
@@ -25,6 +28,7 @@ from utils.resolve_unit.unit_lib import Units
|
|
|
25
28
|
class RandomNumberGenerator(Service):
|
|
26
29
|
def __init__(self, tag_name: str, tag_description: str):
|
|
27
30
|
super().__init__(tag_name, tag_description)
|
|
31
|
+
self.set_cycle_time(0.2)
|
|
28
32
|
|
|
29
33
|
# Define a single procedure with two parameters and one reporting value and add it to the service
|
|
30
34
|
proc_1 = Procedure(1, "cont", is_self_completing=False)
|
|
@@ -50,17 +54,6 @@ class RandomNumberGenerator(Service):
|
|
|
50
54
|
v_unit=Units.UNSPECIFIED.code,
|
|
51
55
|
)
|
|
52
56
|
)
|
|
53
|
-
proc_1.add_procedure_parameter(
|
|
54
|
-
DIntServParam(
|
|
55
|
-
"cycle_time",
|
|
56
|
-
v_op=500,
|
|
57
|
-
v_min=0,
|
|
58
|
-
v_max=1000,
|
|
59
|
-
v_scl_min=0,
|
|
60
|
-
v_scl_max=1000,
|
|
61
|
-
v_unit=Units.UNSPECIFIED.code,
|
|
62
|
-
)
|
|
63
|
-
)
|
|
64
57
|
proc_1.add_report_value(
|
|
65
58
|
AnaView(
|
|
66
59
|
"generated_value",
|
|
@@ -70,93 +63,81 @@ class RandomNumberGenerator(Service):
|
|
|
70
63
|
)
|
|
71
64
|
)
|
|
72
65
|
self.add_procedure(proc_1)
|
|
66
|
+
proc_1.add_required_equipment(proc_1.procedure_parameters)
|
|
67
|
+
proc_1.add_required_equipment(proc_1.report_values)
|
|
73
68
|
|
|
74
69
|
# Define the user logic
|
|
75
|
-
def idle(self):
|
|
70
|
+
async def idle(self):
|
|
76
71
|
logger.app("- Idle -")
|
|
77
72
|
cycle = 0
|
|
78
|
-
while self.is_state("idle"):
|
|
73
|
+
while self.is_state("idle") and not self.thread_ctrl.is_stopped():
|
|
79
74
|
logger.app(
|
|
80
75
|
f" Idle cycle={cycle}, sm.act_state={self.state_machine.act_state}"
|
|
81
76
|
)
|
|
82
77
|
cycle += 1
|
|
83
|
-
|
|
78
|
+
await asyncio.sleep(0.2)
|
|
84
79
|
|
|
85
|
-
def starting(self):
|
|
80
|
+
async def starting(self):
|
|
86
81
|
logger.app("- Starting -")
|
|
87
82
|
logger.app(" Applying procedure parameters...")
|
|
88
83
|
self.state_change()
|
|
89
84
|
|
|
90
|
-
def execute(self):
|
|
85
|
+
async def execute(self):
|
|
91
86
|
logger.app("- Execute -")
|
|
92
87
|
cycle = 0
|
|
93
|
-
while self.is_state("execute"):
|
|
88
|
+
while self.is_state("execute") and not self.thread_ctrl.is_stopped():
|
|
94
89
|
logger.debug(f" About to execute cycle {cycle}")
|
|
95
|
-
# Read procedure
|
|
96
|
-
lower_bound = (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
)
|
|
101
|
-
upper_bound = (
|
|
102
|
-
self._get_procedures()[1]
|
|
103
|
-
.procedure_parameters["upper_bound"]
|
|
104
|
-
.get_v_out()
|
|
105
|
-
)
|
|
106
|
-
cycle_time = (
|
|
107
|
-
self._get_procedures()[1].procedure_parameters["cycle_time"].get_v_out()
|
|
108
|
-
) / 1000.0
|
|
109
|
-
|
|
110
|
-
# Create and report random number
|
|
111
|
-
generated_number = random.randint(lower_bound, upper_bound)
|
|
112
|
-
self._get_procedures()[1].report_values["generated_value"].set_v(
|
|
113
|
-
generated_number
|
|
114
|
-
)
|
|
90
|
+
# Read procedure parameter data assemblies
|
|
91
|
+
lower_bound: DIntServParam = self.get_param("lower_bound")
|
|
92
|
+
upper_bound: DIntServParam = self.get_param("upper_bound")
|
|
93
|
+
generated_value: AnaView = self.get_param("generated_value")
|
|
94
|
+
|
|
95
|
+
generated_value.V = random.randint(lower_bound.VOut, upper_bound.VOut)
|
|
115
96
|
|
|
116
97
|
logger.app(
|
|
117
|
-
f" {cycle}, generated_number={
|
|
98
|
+
f" {cycle}, generated_number={generated_value.V}, bounds={[lower_bound.VOut, upper_bound.VOut]}"
|
|
118
99
|
)
|
|
119
100
|
|
|
120
101
|
cycle += 1
|
|
121
|
-
|
|
102
|
+
await asyncio.sleep(self.cycle_time)
|
|
122
103
|
|
|
123
|
-
def completing(self):
|
|
104
|
+
async def completing(self):
|
|
124
105
|
self.state_change()
|
|
125
106
|
|
|
126
|
-
def completed(self):
|
|
107
|
+
async def completed(self):
|
|
127
108
|
pass
|
|
128
109
|
|
|
129
|
-
def pausing(self):
|
|
110
|
+
async def pausing(self):
|
|
130
111
|
pass
|
|
131
112
|
|
|
132
|
-
def paused(self):
|
|
113
|
+
async def paused(self):
|
|
133
114
|
pass
|
|
134
115
|
|
|
135
|
-
def resuming(self):
|
|
116
|
+
async def resuming(self):
|
|
136
117
|
pass
|
|
137
118
|
|
|
138
|
-
def holding(self):
|
|
119
|
+
async def holding(self):
|
|
139
120
|
pass
|
|
140
121
|
|
|
141
|
-
def held(self):
|
|
122
|
+
async def held(self):
|
|
142
123
|
pass
|
|
143
124
|
|
|
144
|
-
def unholding(self):
|
|
125
|
+
async def unholding(self):
|
|
145
126
|
pass
|
|
146
127
|
|
|
147
|
-
def stopping(self):
|
|
128
|
+
async def stopping(self):
|
|
148
129
|
pass
|
|
149
130
|
|
|
150
|
-
def stopped(self):
|
|
131
|
+
async def stopped(self):
|
|
151
132
|
pass
|
|
152
133
|
|
|
153
|
-
def aborting(self):
|
|
134
|
+
async def aborting(self):
|
|
154
135
|
pass
|
|
155
136
|
|
|
156
|
-
def aborted(self):
|
|
137
|
+
async def aborted(self):
|
|
157
138
|
pass
|
|
158
139
|
|
|
159
|
-
def resetting(self):
|
|
140
|
+
async def resetting(self):
|
|
160
141
|
logger.app("- Resetting -")
|
|
161
142
|
self.state_change()
|
|
162
143
|
|
|
@@ -190,6 +171,11 @@ def parse_args():
|
|
|
190
171
|
default=False,
|
|
191
172
|
help="don't stop, continue to run (default: exit ).",
|
|
192
173
|
)
|
|
174
|
+
p.add_argument(
|
|
175
|
+
"--mtp",
|
|
176
|
+
default=None,
|
|
177
|
+
help="Directory to generate the MTP file into (default: no MTP is generated).",
|
|
178
|
+
)
|
|
193
179
|
return p.parse_args()
|
|
194
180
|
|
|
195
181
|
|
|
@@ -227,17 +213,14 @@ if __name__ == "__main__":
|
|
|
227
213
|
logger.pol("--- Set procedure parameters to Operator mode ---")
|
|
228
214
|
opcua_write("lower_bound.StateOpOp", True)
|
|
229
215
|
opcua_write("upper_bound.StateOpOp", True)
|
|
230
|
-
time.sleep(1)
|
|
231
216
|
|
|
232
217
|
logger.pol("--- Set procedure parameter values ---")
|
|
233
218
|
opcua_write("lower_bound.VOp", 40)
|
|
234
219
|
opcua_write("upper_bound.VOp", 60)
|
|
235
|
-
opcua_write("cycle_time.VOp", 500)
|
|
236
|
-
time.sleep(1)
|
|
237
220
|
|
|
238
221
|
logger.pol("--- Set service to Operator mode ---")
|
|
239
222
|
opcua_write("rand_num_gen.StateOpOp", True)
|
|
240
|
-
time.sleep(1)
|
|
223
|
+
time.sleep(0.1)
|
|
241
224
|
|
|
242
225
|
logger.pol("--- Start service ---")
|
|
243
226
|
opcua_write("rand_num_gen.ProcedureOp", 1)
|
|
@@ -250,6 +233,17 @@ if __name__ == "__main__":
|
|
|
250
233
|
|
|
251
234
|
logger.pol("--- Reset service ---")
|
|
252
235
|
opcua_write("rand_num_gen.CommandOp", CC.RESET.code)
|
|
236
|
+
time.sleep(1)
|
|
237
|
+
|
|
238
|
+
# -------------------------- MTP generation --------------------------
|
|
239
|
+
# The MTP file is generated from the same in-memory model that defines the
|
|
240
|
+
# running PEA. MTPGenerator serializes the PEA's data assemblies, services,
|
|
241
|
+
# process values and alarms into a CAEX .mtp archive.
|
|
242
|
+
if args.mtp:
|
|
243
|
+
out_dir = Path(args.mtp)
|
|
244
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
245
|
+
logger.app(f"--- Generate MTP into {out_dir} ---")
|
|
246
|
+
MTPGenerator().generate(pea, out_path=str(out_dir))
|
|
253
247
|
|
|
254
248
|
# -------------------------- PEA shutdown or detach --------------------------
|
|
255
249
|
if not args.daemon:
|
|
@@ -6,6 +6,14 @@ __copyright__ = (
|
|
|
6
6
|
__license__ = "MIT"
|
|
7
7
|
|
|
8
8
|
from mtppy.feas.modbus.io_logic import IOLogic, RegisterMapping
|
|
9
|
+
from mtppy.feas.modbus.io_action import (
|
|
10
|
+
ACTION_CLASSES,
|
|
11
|
+
IOAction,
|
|
12
|
+
MapAction,
|
|
13
|
+
ScaleAction,
|
|
14
|
+
register_action,
|
|
15
|
+
resolve_action,
|
|
16
|
+
)
|
|
9
17
|
from mtppy.feas.modbus.io_procedure import IOProcedure
|
|
10
18
|
from mtppy.feas.modbus.io_service import IOService
|
|
11
19
|
from mtppy.feas.modbus.config_loader import (
|
|
@@ -16,6 +24,12 @@ from mtppy.feas.modbus.config_loader import (
|
|
|
16
24
|
__all__ = [
|
|
17
25
|
"IOLogic",
|
|
18
26
|
"RegisterMapping",
|
|
27
|
+
"IOAction",
|
|
28
|
+
"ScaleAction",
|
|
29
|
+
"MapAction",
|
|
30
|
+
"ACTION_CLASSES",
|
|
31
|
+
"register_action",
|
|
32
|
+
"resolve_action",
|
|
19
33
|
"IOProcedure",
|
|
20
34
|
"IOService",
|
|
21
35
|
"create_internal_data_assemblies",
|
|
@@ -10,6 +10,7 @@ import json
|
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
12
|
from mtppy.part3.data_assembly_set.data_assembly import DataAssembly
|
|
13
|
+
from mtppy.feas.modbus.io_action import ACTION_CLASSES, IOAction, resolve_action
|
|
13
14
|
from mtppy.feas.modbus.io_logic import RegisterMapping
|
|
14
15
|
from mtppy.utils.logging import logger
|
|
15
16
|
|
|
@@ -61,31 +62,10 @@ def create_internal_data_assemblies(
|
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
def _parse_scale(entry: dict[str, object]) -> tuple[float, float, float, float] | None:
|
|
65
|
-
"""Parse the ``map`` field into a raw-to-engineering linear scale.
|
|
66
|
-
|
|
67
|
-
The ``map`` field is expected to be ``[raw_min, raw_max, eng_min, eng_max]``
|
|
68
|
-
(as strings or numbers), describing a linear conversion between the raw
|
|
69
|
-
register value and the engineering value stored on the DataAssembly.
|
|
70
|
-
|
|
71
|
-
Args:
|
|
72
|
-
entry: Element configuration dict.
|
|
73
|
-
|
|
74
|
-
Returns:
|
|
75
|
-
A ``(raw_min, raw_max, eng_min, eng_max)`` tuple of floats, or
|
|
76
|
-
``None`` if no ``map`` is configured.
|
|
77
|
-
"""
|
|
78
|
-
scaling = entry.get("map")
|
|
79
|
-
if scaling is None:
|
|
80
|
-
return None
|
|
81
|
-
|
|
82
|
-
raw_min, raw_max, eng_min, eng_max = (float(value) for value in scaling)
|
|
83
|
-
return raw_min, raw_max, eng_min, eng_max
|
|
84
|
-
|
|
85
|
-
|
|
86
65
|
def load_register_mappings(
|
|
87
66
|
config_path: str | Path,
|
|
88
67
|
data_assemblies: dict[str, DataAssembly],
|
|
68
|
+
actions: dict[str, type[IOAction]] | None = None,
|
|
89
69
|
) -> tuple[
|
|
90
70
|
dict[str, DataAssembly],
|
|
91
71
|
list[RegisterMapping],
|
|
@@ -96,7 +76,7 @@ def load_register_mappings(
|
|
|
96
76
|
Each entry under ``internal_equipment`` declares a DataAssembly (``class``)
|
|
97
77
|
and one or more element bindings. Each element key (e.g. ``"V"`",
|
|
98
78
|
``"VSclMin"``) maps to a dict with at least ``register``, and optionally
|
|
99
|
-
``
|
|
79
|
+
``action``, ``access``, and ``description``. An optional ``assign`` key
|
|
100
80
|
(list of procedure names) on the entry indicates that the DataAssembly
|
|
101
81
|
shall be added as required equipment to those procedures.
|
|
102
82
|
|
|
@@ -104,6 +84,11 @@ def load_register_mappings(
|
|
|
104
84
|
config_path: Path to the JSON mapping file (see modbus example README).
|
|
105
85
|
data_assemblies: Existing application-level DataAssemblies, keyed by
|
|
106
86
|
tag_name, that mapping entries may refer to (R-002.1).
|
|
87
|
+
actions: Optional registry of action key to
|
|
88
|
+
[IOAction][mtppy.feas.modbus.io_action.IOAction] class used to
|
|
89
|
+
validate each element's ``action`` string. Defaults to the built-in
|
|
90
|
+
[ACTION_CLASSES][mtppy.feas.modbus.io_action.ACTION_CLASSES].
|
|
91
|
+
Unregistered or non-matching actions are dropped.
|
|
107
92
|
|
|
108
93
|
Returns:
|
|
109
94
|
A tuple of:
|
|
@@ -114,6 +99,8 @@ def load_register_mappings(
|
|
|
114
99
|
with Path(config_path).open(encoding="utf-8") as handle:
|
|
115
100
|
config: dict[str, dict[str, dict[str, object]]] = json.load(handle)
|
|
116
101
|
|
|
102
|
+
actions_registry = actions if actions is not None else ACTION_CLASSES
|
|
103
|
+
|
|
117
104
|
internal_equipment = config.get(INTERNAL_EQUIPMENT_KEY, {})
|
|
118
105
|
internal_data_assemblies = create_internal_data_assemblies(internal_equipment)
|
|
119
106
|
|
|
@@ -152,13 +139,23 @@ def load_register_mappings(
|
|
|
152
139
|
continue
|
|
153
140
|
|
|
154
141
|
access = element_config.get("access", "read")
|
|
142
|
+
action = element_config.get("action")
|
|
143
|
+
if (
|
|
144
|
+
isinstance(action, str)
|
|
145
|
+
and resolve_action(action, actions_registry) is None
|
|
146
|
+
):
|
|
147
|
+
logger.warning(
|
|
148
|
+
f"unknown or invalid action {action!r} for "
|
|
149
|
+
f"{tag_name!r}.{element_name!r}"
|
|
150
|
+
)
|
|
151
|
+
action = None
|
|
155
152
|
mappings.append(
|
|
156
153
|
RegisterMapping(
|
|
157
154
|
register=int(element_config["register"]),
|
|
158
155
|
data_assembly=data_assembly,
|
|
159
156
|
element=element_name,
|
|
160
|
-
scale=_parse_scale(element_config),
|
|
161
157
|
access=access,
|
|
158
|
+
action=action,
|
|
162
159
|
)
|
|
163
160
|
)
|
|
164
161
|
return internal_data_assemblies, mappings, assignments
|