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.
Files changed (247) hide show
  1. {mtppy2_0-0.1.7/src/MTPPy2.0.egg-info → mtppy2_0-0.2.0}/PKG-INFO +1 -1
  2. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/pyproject.toml +9 -1
  3. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0/src/MTPPy2.0.egg-info}/PKG-INFO +1 -1
  4. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/SOURCES.txt +4 -0
  5. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/modbus/m15_logic.py +35 -11
  6. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/modbus/m15_pea.py +1 -1
  7. mtppy2_0-0.2.0/src/examples/modbus/m15_simulator.py +42 -0
  8. mtppy2_0-0.2.0/src/examples/rmtp/minimal+pid.py +81 -0
  9. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/rmtp/minimal.py +1 -1
  10. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/scratch/pea_minimal.py +50 -56
  11. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/__init__.py +14 -0
  12. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/config_loader.py +21 -24
  13. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/config_loader_test.py +34 -4
  14. mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_action.py +243 -0
  15. mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_action_test.py +296 -0
  16. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_logic.py +44 -79
  17. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_logic_test.py +107 -11
  18. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_service.py +21 -21
  19. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_service_test.py +2 -1
  20. {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
  21. {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
  22. {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
  23. {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
  24. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/pid/pid_ctrl.py +4 -0
  25. {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
  26. {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
  27. {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
  28. {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
  29. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/operation_mode.py +3 -2
  30. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/operation_mode_test.py +4 -4
  31. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/state_machine.py +24 -9
  32. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/state_machine_test.py +94 -0
  33. mtppy2_0-0.2.0/src/mtppy/part4/automation_services/helpers/thread_control.py +184 -0
  34. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service.py +176 -137
  35. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/service_control.py +10 -8
  36. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/service_control_test.py +8 -4
  37. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_test.py +44 -73
  38. mtppy2_0-0.2.0/src/mtppy/part5/communication_object.py +199 -0
  39. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/data_assembly_factory.py +27 -0
  40. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/mtp_generator/mtp_generator_test.py +21 -20
  41. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea.py +101 -2
  42. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/marshalling.py +12 -0
  43. mtppy2_0-0.2.0/src/mtppy/pea/user_logic/user_logic_service.py +326 -0
  44. mtppy2_0-0.2.0/src/mtppy/pea/user_logic/user_logic_service_scenario_test.py +360 -0
  45. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_service_test.py +47 -26
  46. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/data_item.py +25 -0
  47. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/tools/minimal_recipe.py +72 -6
  48. mtppy2_0-0.2.0/tests/test_examples.py +325 -0
  49. mtppy2_0-0.1.7/src/examples/rmtp/minimal+pid.py +0 -82
  50. mtppy2_0-0.1.7/src/mtppy/part4/automation_services/helpers/thread_control.py +0 -39
  51. mtppy2_0-0.1.7/src/mtppy/part5/communication_object.py +0 -100
  52. mtppy2_0-0.1.7/src/mtppy/pea/user_logic/user_logic_service.py +0 -228
  53. mtppy2_0-0.1.7/tests/test_examples.py +0 -171
  54. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/LICENSE +0 -0
  55. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/README.md +0 -0
  56. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/setup.cfg +0 -0
  57. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/dependency_links.txt +0 -0
  58. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/entry_points.txt +0 -0
  59. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/requires.txt +0 -0
  60. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/top_level.txt +0 -0
  61. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/__init__.py +0 -0
  62. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/modbus/__init__.py +0 -0
  63. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/modbus/m15_pea_test.py +0 -0
  64. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/pea_alarm_base.py +0 -0
  65. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/rmtp/__init__.py +0 -0
  66. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/examples/scratch/__init__.py +0 -0
  67. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/__init__.py +0 -0
  68. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/__init__.py +0 -0
  69. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_procedure.py +0 -0
  70. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/feas/modbus/io_procedure_test.py +0 -0
  71. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part1/__init__.py +0 -0
  72. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part1/empty_folder_test.py +0 -0
  73. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/__init__.py +0 -0
  74. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/__init__.py +0 -0
  75. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/__init__.py +0 -0
  76. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/active_element.py +0 -0
  77. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/__init__.py +0 -0
  78. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/ana_drv.py +0 -0
  79. {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
  80. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/bin_drv.py +0 -0
  81. {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
  82. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/pid/__init__.py +0 -0
  83. {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
  84. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/__init__.py +0 -0
  85. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/ana_vlv.py +0 -0
  86. {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
  87. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/bin_vlv.py +0 -0
  88. {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
  89. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/__init__.py +0 -0
  90. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/oslevel.py +0 -0
  91. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/source_mode.py +0 -0
  92. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/source_mode_test.py +0 -0
  93. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/wqc.py +0 -0
  94. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/wqc_test.py +0 -0
  95. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/data_assembly.py +0 -0
  96. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/diagnostic_elements/__init__.py +0 -0
  97. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/diagnostic_elements/diagnostic_element.py +0 -0
  98. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/__init__.py +0 -0
  99. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/indicator_element.py +0 -0
  100. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/__init__.py +0 -0
  101. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/ana_view.py +0 -0
  102. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/bin_view.py +0 -0
  103. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/dint_view.py +0 -0
  104. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/string_view.py +0 -0
  105. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/operation_elements/__init__.py +0 -0
  106. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/operation_elements/operation_element.py +0 -0
  107. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/__init__.py +0 -0
  108. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/pea_element.py +0 -0
  109. {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
  110. {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
  111. {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
  112. {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
  113. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/definitions/__init__.py +0 -0
  114. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part3/definitions/mtp_access.py +0 -0
  115. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/__init__.py +0 -0
  116. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/__init__.py +0 -0
  117. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/__init__.py +0 -0
  118. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_operation_mode.py +0 -0
  119. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_operation_mode_test.py +0 -0
  120. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_operator_interaction.py +0 -0
  121. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_source_mode.py +0 -0
  122. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_source_mode_test.py +0 -0
  123. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/__init__.py +0 -0
  124. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/command_en_control.py +0 -0
  125. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/command_en_control_test.py +0 -0
  126. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/thread_control_test.py +0 -0
  127. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/procedure.py +0 -0
  128. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/procedure_test.py +0 -0
  129. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/__init__.py +0 -0
  130. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/__init__.py +0 -0
  131. {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
  132. {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
  133. {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
  134. {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
  135. {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
  136. {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
  137. {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
  138. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/parameter_element.py +0 -0
  139. {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
  140. {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
  141. {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
  142. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/procedure_health_view.py +0 -0
  143. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/service_element.py +0 -0
  144. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/__init__.py +0 -0
  145. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/command_codes.py +0 -0
  146. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/command_codes_test.py +0 -0
  147. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/state_codes.py +0 -0
  148. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/state_codes_test.py +0 -0
  149. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/__init__.py +0 -0
  150. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/base_functions/__init__.py +0 -0
  151. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/base_functions/vqc.py +0 -0
  152. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/__init__.py +0 -0
  153. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/ana_process_value_in.py +0 -0
  154. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/bin_process_value_in.py +0 -0
  155. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/dint_process_value_in.py +0 -0
  156. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/input_element.py +0 -0
  157. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/string_process_value_in.py +0 -0
  158. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/__init__.py +0 -0
  159. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/communication_object_test.py +0 -0
  160. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/__init__.py +0 -0
  161. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/iec61131_data_types.py +0 -0
  162. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/iec61131_data_types_test.py +0 -0
  163. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/opcua_data_types.py +0 -0
  164. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/opcua_data_types_test.py +0 -0
  165. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/w3c_xml_data_types.py +0 -0
  166. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/w3c_xml_data_types_test.py +0 -0
  167. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part5/server_assembly_set/__init__.py +0 -0
  168. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part6/__init__.py +0 -0
  169. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part6/alarm_set/__init__.py +0 -0
  170. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part6/alarm_set/alarm.py +0 -0
  171. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/part6/alarm_set/alarm_test.py +0 -0
  172. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/__init__.py +0 -0
  173. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/data_assembly_factory_test.py +0 -0
  174. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/mtp_generator/__init__.py +0 -0
  175. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/mtp_generator/mtp_generator.py +0 -0
  176. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/__init__.py +0 -0
  177. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/opcua_options_provider/__init__.py +0 -0
  178. {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
  179. {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
  180. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/pea_opcua_server.py +0 -0
  181. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/subscription_list.py +0 -0
  182. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_test.py +0 -0
  183. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/rmtp_pea.py +0 -0
  184. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/rmtp_pea_test.py +0 -0
  185. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/service_factory.py +0 -0
  186. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/service_factory_test.py +0 -0
  187. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/__init__.py +0 -0
  188. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_pea.py +0 -0
  189. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_registry.py +0 -0
  190. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_registry_test.py +0 -0
  191. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/__init__.py +0 -0
  192. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/data_assembly_dict.py +0 -0
  193. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/data_assembly_dict_test.py +0 -0
  194. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/data_item_com_test.py +0 -0
  195. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/data_item_test.py +0 -0
  196. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/logging.py +0 -0
  197. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/logging_test.py +0 -0
  198. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/__init__.py +0 -0
  199. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/extract_manifest_from_mtp_file.py +0 -0
  200. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/extract_mtp_file.py +0 -0
  201. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_mtp.py +0 -0
  202. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_path_for_manifest.py +0 -0
  203. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_path_to_manifest.py +0 -0
  204. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_path_to_mtp.py +0 -0
  205. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/load_manifest_file.py +0 -0
  206. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/__init__.py +0 -0
  207. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_reader.py +0 -0
  208. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_reader_test.py +0 -0
  209. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_xml.py +0 -0
  210. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_xml_test.py +0 -0
  211. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/__init__.py +0 -0
  212. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/mtp_writer.py +0 -0
  213. {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
  214. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/ressources/get_rels.py +0 -0
  215. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/test_mtp_writer.py +0 -0
  216. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_manifest_file.py +0 -0
  217. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_manifest_file_test.py +0 -0
  218. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_mtp_file.py +0 -0
  219. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_mtp_file_test.py +0 -0
  220. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/mtppy/utils/testing.py +0 -0
  221. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/tools/__init__.py +0 -0
  222. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/tools/create_bugreport.py +0 -0
  223. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/tools/inspect_mtp.py +0 -0
  224. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/tools/scan_pea.py +0 -0
  225. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/__init__.py +0 -0
  226. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/__init__.py +0 -0
  227. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/cleanup_folder.py +0 -0
  228. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/get_utc_foldername_with_ms.py +0 -0
  229. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/get_work_dir.py +0 -0
  230. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/is_valid_path_for_json.py +0 -0
  231. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/is_valid_path_to_json.py +0 -0
  232. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/load_json_file.py +0 -0
  233. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/read_file_from_file_archive.py +0 -0
  234. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/read_file_string.py +0 -0
  235. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/validate_json_data.py +0 -0
  236. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/file_handling/write_json_file.py +0 -0
  237. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/get_uuid.py +0 -0
  238. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/get_uuid_test.py +0 -0
  239. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/logging.py +0 -0
  240. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/logging_test.py +0 -0
  241. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/opcua/check_node.py +0 -0
  242. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/resolve_unit/resolve_unit.py +0 -0
  243. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/resolve_unit/unit_lib.py +0 -0
  244. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/resolve_unit/unit_lib_test.py +0 -0
  245. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/type_conversion.py +0 -0
  246. {mtppy2_0-0.1.7 → mtppy2_0-0.2.0}/src/utils/type_conversion_test.py +0 -0
  247. {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.1.7
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.1.7"
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.1.7
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
- # DataAssembly names, see mapping.txt / m15_modbus.json (register-derived names
12
- # for unmapped items, per the "_M15_<register>" convention).
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 = "valve"
19
+ DA_VALVE = "V010"
20
+
18
21
 
19
22
  """
20
- Spezifikation für produce.auto.idle.entry:
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.idle.entry")
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).V = 0
43
- context.get_param(DA_VALVE).V = 1
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).V = 0
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).V = 1
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).V = 1
83
- context.get_param(DA_VALVE).V = 0
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.thread_ctrl.stop()
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
@@ -2,7 +2,7 @@ __copyright__ = (
2
2
  "Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
3
3
  )
4
4
  __license__ = "MIT"
5
-
5
+ __requirements_mtp__ = "minimal.mtp"
6
6
  import random
7
7
 
8
8
  from mtppy.utils.logging import logger
@@ -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
- time.sleep(0.2)
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 parameters
96
- lower_bound = (
97
- self._get_procedures()[1]
98
- .procedure_parameters["lower_bound"]
99
- .get_v_out()
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={generated_number}, bounds={[lower_bound, upper_bound]}, cycle_time={cycle_time}s"
98
+ f" {cycle}, generated_number={generated_value.V}, bounds={[lower_bound.VOut, upper_bound.VOut]}"
118
99
  )
119
100
 
120
101
  cycle += 1
121
- time.sleep(max(0.2, cycle_time))
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
- ``map``, ``access``, and ``description``. An optional ``assign`` key
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