MTPPy2.0 0.1.5__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 (250) hide show
  1. {mtppy2_0-0.1.5/src/MTPPy2.0.egg-info → mtppy2_0-0.2.0}/PKG-INFO +7 -5
  2. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/README.md +4 -4
  3. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/pyproject.toml +14 -3
  4. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0/src/MTPPy2.0.egg-info}/PKG-INFO +7 -5
  5. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/SOURCES.txt +25 -4
  6. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/entry_points.txt +2 -0
  7. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/requires.txt +2 -0
  8. mtppy2_0-0.2.0/src/examples/modbus/m15_logic.py +108 -0
  9. mtppy2_0-0.2.0/src/examples/modbus/m15_pea.py +225 -0
  10. mtppy2_0-0.2.0/src/examples/modbus/m15_pea_test.py +117 -0
  11. mtppy2_0-0.2.0/src/examples/modbus/m15_simulator.py +42 -0
  12. mtppy2_0-0.2.0/src/examples/rmtp/__init__.py +0 -0
  13. mtppy2_0-0.2.0/src/examples/rmtp/minimal+pid.py +81 -0
  14. {mtppy2_0-0.1.5/src/examples → mtppy2_0-0.2.0/src/examples/rmtp}/minimal.py +1 -1
  15. mtppy2_0-0.2.0/src/examples/scratch/__init__.py +0 -0
  16. {mtppy2_0-0.1.5/src/examples → mtppy2_0-0.2.0/src/examples/scratch}/pea_minimal.py +50 -56
  17. mtppy2_0-0.2.0/src/mtppy/feas/__init__.py +6 -0
  18. mtppy2_0-0.2.0/src/mtppy/feas/modbus/__init__.py +37 -0
  19. mtppy2_0-0.2.0/src/mtppy/feas/modbus/config_loader.py +161 -0
  20. mtppy2_0-0.2.0/src/mtppy/feas/modbus/config_loader_test.py +160 -0
  21. mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_action.py +243 -0
  22. mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_action_test.py +296 -0
  23. mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_logic.py +164 -0
  24. mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_logic_test.py +383 -0
  25. mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_procedure.py +49 -0
  26. mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_procedure_test.py +46 -0
  27. mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_service.py +115 -0
  28. mtppy2_0-0.2.0/src/mtppy/feas/modbus/io_service_test.py +62 -0
  29. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/mon_ana_drv.py +212 -89
  30. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/mon_ana_drv_test.py +0 -28
  31. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/mon_bin_drv.py +172 -64
  32. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/mon_bin_drv_test.py +37 -45
  33. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/pid/pid_ctrl.py +4 -0
  34. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/mon_ana_vlv.py +177 -77
  35. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/mon_ana_vlv_test.py +60 -55
  36. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/mon_bin_vlv.py +158 -64
  37. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/mon_bin_vlv_test.py +49 -57
  38. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/operation_mode.py +3 -2
  39. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/operation_mode_test.py +4 -4
  40. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/state_machine.py +24 -9
  41. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/state_machine_test.py +94 -0
  42. mtppy2_0-0.2.0/src/mtppy/part4/automation_services/helpers/thread_control.py +184 -0
  43. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service.py +176 -137
  44. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/service_control.py +10 -8
  45. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/service_control_test.py +8 -4
  46. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_test.py +44 -73
  47. mtppy2_0-0.2.0/src/mtppy/part5/communication_object.py +199 -0
  48. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/data_assembly_factory.py +27 -0
  49. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/mtp_generator/mtp_generator_test.py +21 -20
  50. mtppy2_0-0.2.0/src/mtppy/pea/pea.py +247 -0
  51. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/marshalling.py +12 -0
  52. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/rmtp_pea_test.py +2 -2
  53. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_registry.py +1 -1
  54. mtppy2_0-0.2.0/src/mtppy/pea/user_logic/user_logic_service.py +326 -0
  55. mtppy2_0-0.2.0/src/mtppy/pea/user_logic/user_logic_service_scenario_test.py +360 -0
  56. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_service_test.py +47 -26
  57. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/data_item.py +43 -5
  58. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_reader.py +3 -2
  59. mtppy2_0-0.2.0/src/tools/__init__.py +0 -0
  60. mtppy2_0-0.2.0/src/tools/inspect_mtp.py +172 -0
  61. mtppy2_0-0.2.0/src/tools/minimal_recipe.py +289 -0
  62. mtppy2_0-0.2.0/src/tools/scan_pea.py +224 -0
  63. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/logging.py +1 -1
  64. mtppy2_0-0.2.0/tests/test_examples.py +325 -0
  65. mtppy2_0-0.1.5/src/examples/minimal+pid.py +0 -82
  66. mtppy2_0-0.1.5/src/examples/minimal_recipe.py +0 -117
  67. mtppy2_0-0.1.5/src/mtppy/part4/automation_services/helpers/thread_control.py +0 -39
  68. mtppy2_0-0.1.5/src/mtppy/part5/communication_object.py +0 -99
  69. mtppy2_0-0.1.5/src/mtppy/pea/pea.py +0 -139
  70. mtppy2_0-0.1.5/src/mtppy/pea/user_logic/user_logic_service.py +0 -228
  71. mtppy2_0-0.1.5/src/tools/inspect_mtp.py +0 -110
  72. mtppy2_0-0.1.5/tests/test_examples.py +0 -161
  73. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/LICENSE +0 -0
  74. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/setup.cfg +0 -0
  75. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/dependency_links.txt +0 -0
  76. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/MTPPy2.0.egg-info/top_level.txt +0 -0
  77. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/examples/__init__.py +0 -0
  78. {mtppy2_0-0.1.5/src/tools → mtppy2_0-0.2.0/src/examples/modbus}/__init__.py +0 -0
  79. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/examples/pea_alarm_base.py +0 -0
  80. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/__init__.py +0 -0
  81. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part1/__init__.py +0 -0
  82. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part1/empty_folder_test.py +0 -0
  83. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/__init__.py +0 -0
  84. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/__init__.py +0 -0
  85. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/__init__.py +0 -0
  86. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/active_element.py +0 -0
  87. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/__init__.py +0 -0
  88. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/ana_drv.py +0 -0
  89. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/ana_drv_test.py +0 -0
  90. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/bin_drv.py +0 -0
  91. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/drives/bin_drv_test.py +0 -0
  92. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/pid/__init__.py +0 -0
  93. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/pid/pid_ctrl_test.py +0 -0
  94. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/__init__.py +0 -0
  95. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/ana_vlv.py +0 -0
  96. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/ana_vlv_test.py +0 -0
  97. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/bin_vlv.py +0 -0
  98. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/active_elements/valves/bin_vlv_test.py +0 -0
  99. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/__init__.py +0 -0
  100. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/oslevel.py +0 -0
  101. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/source_mode.py +0 -0
  102. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/source_mode_test.py +0 -0
  103. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/wqc.py +0 -0
  104. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/base_functions/wqc_test.py +0 -0
  105. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/data_assembly.py +0 -0
  106. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/diagnostic_elements/__init__.py +0 -0
  107. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/diagnostic_elements/diagnostic_element.py +0 -0
  108. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/__init__.py +0 -0
  109. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/indicator_element.py +0 -0
  110. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/__init__.py +0 -0
  111. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/ana_view.py +0 -0
  112. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/bin_view.py +0 -0
  113. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/dint_view.py +0 -0
  114. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/indicator_elements/views/string_view.py +0 -0
  115. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/operation_elements/__init__.py +0 -0
  116. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/operation_elements/operation_element.py +0 -0
  117. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/__init__.py +0 -0
  118. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/pea_element.py +0 -0
  119. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/pea_information_label/__init__.py +0 -0
  120. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/pea_information_label/pea_information_label.py +0 -0
  121. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/web_server_url_info/__init__.py +0 -0
  122. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/data_assembly_set/pea_elements/web_server_url_info/web_server_url_info.py +0 -0
  123. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/definitions/__init__.py +0 -0
  124. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part3/definitions/mtp_access.py +0 -0
  125. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/__init__.py +0 -0
  126. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/__init__.py +0 -0
  127. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/__init__.py +0 -0
  128. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_operation_mode.py +0 -0
  129. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_operation_mode_test.py +0 -0
  130. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_operator_interaction.py +0 -0
  131. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_source_mode.py +0 -0
  132. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/base_functions/service_source_mode_test.py +0 -0
  133. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/__init__.py +0 -0
  134. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/command_en_control.py +0 -0
  135. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/command_en_control_test.py +0 -0
  136. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/helpers/thread_control_test.py +0 -0
  137. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/procedure.py +0 -0
  138. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/procedure_test.py +0 -0
  139. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/__init__.py +0 -0
  140. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/__init__.py +0 -0
  141. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/ana_serv_param.py +0 -0
  142. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/ana_serv_param_test.py +0 -0
  143. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/bin_serv_param.py +0 -0
  144. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/bin_serv_param_test.py +0 -0
  145. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/common_serv_param.py +0 -0
  146. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/dint_serv_param.py +0 -0
  147. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/dint_serv_param_test.py +0 -0
  148. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/parameter_element.py +0 -0
  149. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/parameter_element_test.py +0 -0
  150. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/string_serv_param.py +0 -0
  151. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/parameter_elements/string_serv_param_test.py +0 -0
  152. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/procedure_health_view.py +0 -0
  153. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/automation_services/service_elements/service_element.py +0 -0
  154. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/__init__.py +0 -0
  155. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/command_codes.py +0 -0
  156. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/command_codes_test.py +0 -0
  157. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/state_codes.py +0 -0
  158. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/definitions/state_codes_test.py +0 -0
  159. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/__init__.py +0 -0
  160. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/base_functions/__init__.py +0 -0
  161. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/base_functions/vqc.py +0 -0
  162. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/__init__.py +0 -0
  163. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/ana_process_value_in.py +0 -0
  164. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/bin_process_value_in.py +0 -0
  165. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/dint_process_value_in.py +0 -0
  166. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/input_element.py +0 -0
  167. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part4/process_values/input_elements/string_process_value_in.py +0 -0
  168. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part5/__init__.py +0 -0
  169. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part5/communication_object_test.py +0 -0
  170. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/__init__.py +0 -0
  171. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/iec61131_data_types.py +0 -0
  172. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/iec61131_data_types_test.py +0 -0
  173. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/opcua_data_types.py +0 -0
  174. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/opcua_data_types_test.py +0 -0
  175. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/w3c_xml_data_types.py +0 -0
  176. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part5/definitions/w3c_xml_data_types_test.py +0 -0
  177. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part5/server_assembly_set/__init__.py +0 -0
  178. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part6/__init__.py +0 -0
  179. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part6/alarm_set/__init__.py +0 -0
  180. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part6/alarm_set/alarm.py +0 -0
  181. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/part6/alarm_set/alarm_test.py +0 -0
  182. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/__init__.py +0 -0
  183. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/data_assembly_factory_test.py +0 -0
  184. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/mtp_generator/__init__.py +0 -0
  185. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/mtp_generator/mtp_generator.py +0 -0
  186. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/__init__.py +0 -0
  187. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/opcua_options_provider/__init__.py +0 -0
  188. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/opcua_options_provider/instances/basic_opcua_options_provider.py +0 -0
  189. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/opcua_options_provider/opcua_options_provider.py +0 -0
  190. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/pea_opcua_server.py +0 -0
  191. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_opcua_server/subscription_list.py +0 -0
  192. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/pea_test.py +0 -0
  193. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/rmtp_pea.py +0 -0
  194. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/service_factory.py +0 -0
  195. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/service_factory_test.py +0 -0
  196. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/__init__.py +0 -0
  197. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_pea.py +0 -0
  198. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/pea/user_logic/user_logic_registry_test.py +0 -0
  199. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/__init__.py +0 -0
  200. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/data_assembly_dict.py +0 -0
  201. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/data_assembly_dict_test.py +0 -0
  202. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/data_item_com_test.py +0 -0
  203. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/data_item_test.py +0 -0
  204. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/logging.py +0 -0
  205. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/logging_test.py +0 -0
  206. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/__init__.py +0 -0
  207. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/extract_manifest_from_mtp_file.py +0 -0
  208. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/extract_mtp_file.py +0 -0
  209. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_mtp.py +0 -0
  210. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_path_for_manifest.py +0 -0
  211. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_path_to_manifest.py +0 -0
  212. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/is_valid_path_to_mtp.py +0 -0
  213. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/load_manifest_file.py +0 -0
  214. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/__init__.py +0 -0
  215. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_reader_test.py +0 -0
  216. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_xml.py +0 -0
  217. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_reader/mtp_xml_test.py +0 -0
  218. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/__init__.py +0 -0
  219. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/mtp_writer.py +0 -0
  220. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/ressources/get_content_types.py +0 -0
  221. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/ressources/get_rels.py +0 -0
  222. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/mtp_writer/test_mtp_writer.py +0 -0
  223. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_manifest_file.py +0 -0
  224. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_manifest_file_test.py +0 -0
  225. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_mtp_file.py +0 -0
  226. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/mtp_file_handling/write_mtp_file_test.py +0 -0
  227. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/mtppy/utils/testing.py +0 -0
  228. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/tools/create_bugreport.py +0 -0
  229. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/__init__.py +0 -0
  230. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/__init__.py +0 -0
  231. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/cleanup_folder.py +0 -0
  232. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/get_utc_foldername_with_ms.py +0 -0
  233. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/get_work_dir.py +0 -0
  234. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/is_valid_path_for_json.py +0 -0
  235. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/is_valid_path_to_json.py +0 -0
  236. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/load_json_file.py +0 -0
  237. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/read_file_from_file_archive.py +0 -0
  238. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/read_file_string.py +0 -0
  239. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/validate_json_data.py +0 -0
  240. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/file_handling/write_json_file.py +0 -0
  241. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/get_uuid.py +0 -0
  242. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/get_uuid_test.py +0 -0
  243. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/logging_test.py +0 -0
  244. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/opcua/check_node.py +0 -0
  245. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/resolve_unit/resolve_unit.py +0 -0
  246. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/resolve_unit/unit_lib.py +0 -0
  247. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/resolve_unit/unit_lib_test.py +0 -0
  248. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/type_conversion.py +0 -0
  249. {mtppy2_0-0.1.5 → mtppy2_0-0.2.0}/src/utils/type_conversion_test.py +0 -0
  250. {mtppy2_0-0.1.5 → 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.5
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>
@@ -21,6 +21,8 @@ License-File: LICENSE
21
21
  Requires-Dist: opcua~=0.98.13
22
22
  Requires-Dist: jsonschema>=4.26.0
23
23
  Requires-Dist: chardet>=7.6.0
24
+ Requires-Dist: aiohttp>=3.12.0
25
+ Requires-Dist: pymodbus>=3.15.0
24
26
  Requires-Dist: simple-pid>=2.0.1
25
27
  Requires-Dist: pymodbus>=3.15.0
26
28
  Dynamic: license-file
@@ -56,19 +58,19 @@ uv add MTPPy2.0
56
58
 
57
59
  ### Developers
58
60
  - Check out ``main`` from the [gitlab repository](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0)
59
- - Run `uv sync --all-groups` to setup the virtual environment `mtppy2-0` and install
61
+ - Run `uv sync --all-groups` to set up the virtual environment `mtppy2-0` and install
60
62
  all the required packages for running and development
61
63
  - You might want to inspect the examples in ``./examples`` and perhaps the jupyter-notebook snippets in
62
64
  ``./snippets``
63
65
 
64
66
  ### Contributors
65
- - Check out ``next_release`` from the [gitlab repository](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0)
66
- - Run `uv sync --all-groups` to to setup the virtual environment `mtppy2-0` and install
67
+ - Check out ``develop`` from the [gitlab repository](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0)
68
+ - Run `uv sync --all-groups` to set up the virtual environment `mtppy2-0` and install
67
69
  all the required packages for running and development
68
70
  - Study the [developer handbook](https://aas-demo.p2o-lab.ifa.et.tu-dresden.de/mtppy2.0/developer/developer/)
69
71
  - Feel invited to contribute by
70
72
  - joining the development on a certain [branch](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0/-/branches), or by
71
- - selecting an [open issue](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0/-/boards?milestone_title=Started&types=ISSUE) an creating a branch
73
+ - selecting an [open issue](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0/-/boards?milestone_title=Started&types=ISSUE), create your branch and provide a solution
72
74
 
73
75
 
74
76
 
@@ -29,19 +29,19 @@ uv add MTPPy2.0
29
29
 
30
30
  ### Developers
31
31
  - Check out ``main`` from the [gitlab repository](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0)
32
- - Run `uv sync --all-groups` to setup the virtual environment `mtppy2-0` and install
32
+ - Run `uv sync --all-groups` to set up the virtual environment `mtppy2-0` and install
33
33
  all the required packages for running and development
34
34
  - You might want to inspect the examples in ``./examples`` and perhaps the jupyter-notebook snippets in
35
35
  ``./snippets``
36
36
 
37
37
  ### Contributors
38
- - Check out ``next_release`` from the [gitlab repository](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0)
39
- - Run `uv sync --all-groups` to to setup the virtual environment `mtppy2-0` and install
38
+ - Check out ``develop`` from the [gitlab repository](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0)
39
+ - Run `uv sync --all-groups` to set up the virtual environment `mtppy2-0` and install
40
40
  all the required packages for running and development
41
41
  - Study the [developer handbook](https://aas-demo.p2o-lab.ifa.et.tu-dresden.de/mtppy2.0/developer/developer/)
42
42
  - Feel invited to contribute by
43
43
  - joining the development on a certain [branch](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0/-/branches), or by
44
- - selecting an [open issue](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0/-/boards?milestone_title=Started&types=ISSUE) an creating a branch
44
+ - selecting an [open issue](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0/-/boards?milestone_title=Started&types=ISSUE), create your branch and provide a solution
45
45
 
46
46
 
47
47
 
@@ -1,10 +1,10 @@
1
1
  [project]
2
2
  name = "MTPPy2.0"
3
- version = "0.1.5"
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"
7
- license-files = ["LICENSE" ]
7
+ license-files = ["LICENSE"]
8
8
  requires-python = ">=3.13"
9
9
  authors = [
10
10
  { name = "Dresden University of Technology, Process-to-Order Group" },
@@ -25,6 +25,8 @@ dependencies = [
25
25
  "opcua~=0.98.13",
26
26
  "jsonschema>=4.26.0",
27
27
  "chardet>=7.6.0",
28
+ "aiohttp>=3.12.0",
29
+ "pymodbus>=3.15.0",
28
30
  "simple-pid>=2.0.1",
29
31
  "pymodbus>=3.15.0",
30
32
  ]
@@ -40,9 +42,10 @@ build-backend = "setuptools.build_meta"
40
42
 
41
43
  [project.scripts]
42
44
  inspect_mtp = "tools.inspect_mtp:main"
45
+ minimal_recipe = "tools.minimal_recipe:main"
46
+ scan_pea = "tools.scan_pea:main"
43
47
  rmtp_pea = "mtppy.pea.rmtp_pea:main"
44
48
 
45
-
46
49
  [dependency-groups]
47
50
  dev = [
48
51
  "black>=26.5.1",
@@ -100,7 +103,12 @@ filterwarnings = [
100
103
  ]
101
104
 
102
105
  [tool.ruff]
106
+ line-length = 88
107
+ target-version = "py310"
108
+ inline-quotes = "double"
109
+
103
110
  lint.select = ["ALL"]
111
+
104
112
  # ANN001 - Missing type annotation for function argument
105
113
  # `incorrect-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible. Ignoring `incorrect-blank-line-before-class`.
106
114
  # `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible. Ignoring `multi-line-summary-second-line`.
@@ -110,3 +118,6 @@ lint.select = ["ALL"]
110
118
  # `Missing blank line after last section` (D413)
111
119
  # `Too many arguments in function definition` (PLR0913)
112
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.5
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>
@@ -21,6 +21,8 @@ License-File: LICENSE
21
21
  Requires-Dist: opcua~=0.98.13
22
22
  Requires-Dist: jsonschema>=4.26.0
23
23
  Requires-Dist: chardet>=7.6.0
24
+ Requires-Dist: aiohttp>=3.12.0
25
+ Requires-Dist: pymodbus>=3.15.0
24
26
  Requires-Dist: simple-pid>=2.0.1
25
27
  Requires-Dist: pymodbus>=3.15.0
26
28
  Dynamic: license-file
@@ -56,19 +58,19 @@ uv add MTPPy2.0
56
58
 
57
59
  ### Developers
58
60
  - Check out ``main`` from the [gitlab repository](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0)
59
- - Run `uv sync --all-groups` to setup the virtual environment `mtppy2-0` and install
61
+ - Run `uv sync --all-groups` to set up the virtual environment `mtppy2-0` and install
60
62
  all the required packages for running and development
61
63
  - You might want to inspect the examples in ``./examples`` and perhaps the jupyter-notebook snippets in
62
64
  ``./snippets``
63
65
 
64
66
  ### Contributors
65
- - Check out ``next_release`` from the [gitlab repository](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0)
66
- - Run `uv sync --all-groups` to to setup the virtual environment `mtppy2-0` and install
67
+ - Check out ``develop`` from the [gitlab repository](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0)
68
+ - Run `uv sync --all-groups` to set up the virtual environment `mtppy2-0` and install
67
69
  all the required packages for running and development
68
70
  - Study the [developer handbook](https://aas-demo.p2o-lab.ifa.et.tu-dresden.de/mtppy2.0/developer/developer/)
69
71
  - Feel invited to contribute by
70
72
  - joining the development on a certain [branch](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0/-/branches), or by
71
- - selecting an [open issue](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0/-/boards?milestone_title=Started&types=ISSUE) an creating a branch
73
+ - selecting an [open issue](https://gitlab.hrz.tu-chemnitz.de/process-to-order-group/mtppy2.0/-/boards?milestone_title=Started&types=ISSUE), create your branch and provide a solution
72
74
 
73
75
 
74
76
 
@@ -8,12 +8,30 @@ src/MTPPy2.0.egg-info/entry_points.txt
8
8
  src/MTPPy2.0.egg-info/requires.txt
9
9
  src/MTPPy2.0.egg-info/top_level.txt
10
10
  src/examples/__init__.py
11
- src/examples/minimal+pid.py
12
- src/examples/minimal.py
13
- src/examples/minimal_recipe.py
14
11
  src/examples/pea_alarm_base.py
15
- src/examples/pea_minimal.py
12
+ src/examples/modbus/__init__.py
13
+ src/examples/modbus/m15_logic.py
14
+ src/examples/modbus/m15_pea.py
15
+ src/examples/modbus/m15_pea_test.py
16
+ src/examples/modbus/m15_simulator.py
17
+ src/examples/rmtp/__init__.py
18
+ src/examples/rmtp/minimal+pid.py
19
+ src/examples/rmtp/minimal.py
20
+ src/examples/scratch/__init__.py
21
+ src/examples/scratch/pea_minimal.py
16
22
  src/mtppy/__init__.py
23
+ src/mtppy/feas/__init__.py
24
+ src/mtppy/feas/modbus/__init__.py
25
+ src/mtppy/feas/modbus/config_loader.py
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
29
+ src/mtppy/feas/modbus/io_logic.py
30
+ src/mtppy/feas/modbus/io_logic_test.py
31
+ src/mtppy/feas/modbus/io_procedure.py
32
+ src/mtppy/feas/modbus/io_procedure_test.py
33
+ src/mtppy/feas/modbus/io_service.py
34
+ src/mtppy/feas/modbus/io_service_test.py
17
35
  src/mtppy/part1/__init__.py
18
36
  src/mtppy/part1/empty_folder_test.py
19
37
  src/mtppy/part3/__init__.py
@@ -158,6 +176,7 @@ src/mtppy/pea/user_logic/user_logic_pea.py
158
176
  src/mtppy/pea/user_logic/user_logic_registry.py
159
177
  src/mtppy/pea/user_logic/user_logic_registry_test.py
160
178
  src/mtppy/pea/user_logic/user_logic_service.py
179
+ src/mtppy/pea/user_logic/user_logic_service_scenario_test.py
161
180
  src/mtppy/pea/user_logic/user_logic_service_test.py
162
181
  src/mtppy/utils/__init__.py
163
182
  src/mtppy/utils/data_assembly_dict.py
@@ -193,6 +212,8 @@ src/mtppy/utils/mtp_file_handling/mtp_writer/ressources/get_rels.py
193
212
  src/tools/__init__.py
194
213
  src/tools/create_bugreport.py
195
214
  src/tools/inspect_mtp.py
215
+ src/tools/minimal_recipe.py
216
+ src/tools/scan_pea.py
196
217
  src/utils/__init__.py
197
218
  src/utils/get_uuid.py
198
219
  src/utils/get_uuid_test.py
@@ -1,3 +1,5 @@
1
1
  [console_scripts]
2
2
  inspect_mtp = tools.inspect_mtp:main
3
+ minimal_recipe = tools.minimal_recipe:main
3
4
  rmtp_pea = mtppy.pea.rmtp_pea:main
5
+ scan_pea = tools.scan_pea:main
@@ -1,5 +1,7 @@
1
1
  opcua~=0.98.13
2
2
  jsonschema>=4.26.0
3
3
  chardet>=7.6.0
4
+ aiohttp>=3.12.0
5
+ pymodbus>=3.15.0
4
6
  simple-pid>=2.0.1
5
7
  pymodbus>=3.15.0
@@ -0,0 +1,108 @@
1
+ """Application logic for the M15 PEM electrolysis module service ``produce``."""
2
+
3
+ __copyright__ = (
4
+ "Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
5
+ )
6
+ __license__ = "MIT"
7
+
8
+ from mtppy.part3.data_assembly_set.active_elements.pid.pid_ctrl import PIDCtrl
9
+ from mtppy.utils.logging import logger
10
+ from mtppy.part4.automation_services.service import Service
11
+ from mtppy.pea.user_logic.user_logic_registry import register
12
+
13
+ __requirements_mtp__ = "M15.mtp"
14
+
15
+ DA_PRESSURE_UNITS = "p_eng_units"
16
+ DA_TEMP_UNITS = "t_eng_units"
17
+ DA_VOLUME_UNITS = "v_eng_units"
18
+ DA_START_STOP = "start_stop"
19
+ DA_VALVE = "V010"
20
+
21
+
22
+ """
23
+ Spezifikation für produce.auto.starting.entry:
24
+ Setze die Anzeigeeinheiten des Generators (Druck, Temperatur,
25
+ Volumen) auf den Standardwert 0.
26
+ """
27
+
28
+
29
+ @register("produce.auto.starting.entry")
30
+ def reset_units(context: Service) -> bool:
31
+ context.get_param(DA_PRESSURE_UNITS).V = 0
32
+ context.get_param(DA_TEMP_UNITS).V = 0
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
+
44
+ return True
45
+
46
+
47
+ """
48
+ Spezifikation für produce.auto.starting.do:
49
+ Starte den Generator und öffne das Auslassventil.
50
+ """
51
+
52
+
53
+ @register("produce.auto.starting.do")
54
+ def start_generator(context: Service) -> bool:
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
+
64
+ return True
65
+
66
+
67
+ """
68
+ Spezifikation für produce.auto.holding.do:
69
+ Schließe das Auslassventil.
70
+ """
71
+
72
+
73
+ @register("produce.auto.holding.do")
74
+ def hold_generator(context: Service) -> bool:
75
+ context.get_param(DA_VALVE).CloseAut = 1
76
+ return True
77
+
78
+
79
+ """
80
+ Spezifikation für produce.auto.unholding.do:
81
+ Öffne das Auslassventil.
82
+ """
83
+
84
+
85
+ @register("produce.auto.unholding.do")
86
+ def unhold_generator(context: Service) -> bool:
87
+ context.get_param(DA_VALVE).OpenAut = 1
88
+ return True
89
+
90
+
91
+ """
92
+ Spezifikation für produce.auto.completing.do sowie stopping und aborting:
93
+ Stoppe den Generator (DA_START_STOP.V = 1) und schließe das
94
+ Auslassventil (DA_VALVE.V = 0).
95
+ """
96
+
97
+
98
+ @register(
99
+ "produce.auto.completing.do", "produce.auto.stopping.do", "produce.auto.aborting.do"
100
+ )
101
+ def stop_generator(context: Service) -> bool:
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
+
108
+ return True
@@ -0,0 +1,225 @@
1
+ """Access the M15 Modbus server through an MTPPy PEA background service."""
2
+
3
+ __copyright__ = (
4
+ "Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
5
+ )
6
+ __license__ = "MIT"
7
+ import argparse
8
+ import asyncio
9
+ from pathlib import Path
10
+
11
+ from pymodbus.client import ModbusTcpClient
12
+
13
+ from mtppy.feas.modbus import (
14
+ IOLogic,
15
+ IOProcedure,
16
+ IOService,
17
+ load_register_mappings,
18
+ )
19
+ from mtppy.part3.data_assembly_set.data_assembly import DataAssembly
20
+ from mtppy.pea.user_logic.user_logic_pea import UserLogicPEA
21
+ from mtppy.utils.logging import CHOICES, logger, setLogLevel
22
+
23
+ DEFAULT_HOST = "localhost"
24
+ DEFAULT_MODBUS_PORT = 5020
25
+ DEFAULT_OPCUA_ENDPOINT = "opc.tcp://localhost:4044"
26
+ DEFAULT_CYCLE_TIME = 0.5
27
+ CONFIG_PATH = Path(__file__).with_name("m15_modbus.json")
28
+
29
+
30
+ class M15Pea(UserLogicPEA):
31
+ """PEA that exposes M15 registers as internal DataAssemblies."""
32
+
33
+ def __init__(
34
+ self,
35
+ endpoint: str = DEFAULT_OPCUA_ENDPOINT,
36
+ host: str = DEFAULT_HOST,
37
+ modbus_port: int = DEFAULT_MODBUS_PORT,
38
+ config_path: str | Path = CONFIG_PATH,
39
+ cycle_time: float = DEFAULT_CYCLE_TIME,
40
+ mtp: str = "",
41
+ ssd: str = "",
42
+ code: str = "",
43
+ ) -> None:
44
+ super().__init__(endpoint=endpoint, mtp=mtp, ssd=ssd, code=code)
45
+ self.modbus_client = ModbusTcpClient(host, port=modbus_port)
46
+
47
+ internal_data_assemblies, mappings, assignments = load_register_mappings(
48
+ config_path, dict(self.data_assemblies)
49
+ )
50
+ if mtp:
51
+ matching_data_assemblies = self._matching_requirement_data_assemblies(
52
+ internal_data_assemblies
53
+ )
54
+ for mapping in mappings:
55
+ matching_data_assembly = matching_data_assemblies.get(
56
+ mapping.data_assembly.tag_name
57
+ )
58
+ if matching_data_assembly is not None:
59
+ mapping.data_assembly = matching_data_assembly
60
+ else:
61
+ self.add_data_assembly(internal_data_assemblies)
62
+
63
+ self.io_logic = IOLogic(self.modbus_client, mappings)
64
+ self.io_procedure = IOProcedure(
65
+ self.io_logic,
66
+ required_equipment=list(internal_data_assemblies.values()),
67
+ )
68
+ self.io_service = IOService(self.io_procedure, cycle_time=cycle_time)
69
+ self.add_service(self.io_service)
70
+
71
+ self._assign_data_assemblies(assignments, internal_data_assemblies)
72
+
73
+ def _matching_requirement_data_assemblies(
74
+ self, modbus_data_assemblies: dict[str, DataAssembly]
75
+ ) -> dict[str, DataAssembly]:
76
+ """Validate and return rMTP assemblies matching Modbus configuration.
77
+
78
+ Args:
79
+ modbus_data_assemblies: Assemblies declared by the Modbus
80
+ ``internal_equipment`` configuration.
81
+
82
+ Returns:
83
+ rMTP-loaded assemblies keyed by the configured Modbus tag name.
84
+ Tags missing from the requirements MTP or with a mismatching
85
+ DataAssembly class are skipped (and logged) rather than raised.
86
+ """
87
+ matching_data_assemblies: dict[str, DataAssembly] = {}
88
+ for tag_name, modbus_data_assembly in modbus_data_assemblies.items():
89
+ requirement_data_assembly = self.data_assemblies.get(tag_name)
90
+ if requirement_data_assembly is None:
91
+ logger.warning(
92
+ f"Modbus DataAssembly {tag_name!r} is missing from requirements MTP"
93
+ )
94
+ continue
95
+ if type(requirement_data_assembly) is not type(modbus_data_assembly):
96
+ logger.warning(
97
+ f"Modbus DataAssembly {tag_name!r} has class "
98
+ f"{type(modbus_data_assembly).__name__}, but requirements MTP "
99
+ f"defines {type(requirement_data_assembly).__name__}"
100
+ )
101
+ continue
102
+ matching_data_assemblies[tag_name] = requirement_data_assembly
103
+ return matching_data_assemblies
104
+
105
+ def _assign_data_assemblies(
106
+ self,
107
+ assignments: dict[str, list[str]],
108
+ data_assemblies: dict[str, DataAssembly],
109
+ ) -> None:
110
+ """Add DataAssemblies as required equipment to named procedures.
111
+
112
+ Args:
113
+ assignments: Mapping of procedure name to list of tag names.
114
+ data_assemblies: Pool of DataAssembly instances to look up by tag name.
115
+ """
116
+ for procedure_name, tag_names in assignments.items():
117
+ procedure = self._find_procedure(procedure_name)
118
+ if procedure is None:
119
+ logger.critical(
120
+ f"procedure {procedure_name!r} not found for assignment"
121
+ )
122
+ continue
123
+ for tag_name in tag_names:
124
+ if tag_name not in data_assemblies:
125
+ logger.critical(
126
+ f"DataAssembly {tag_name!r} not found for assignment "
127
+ f"to procedure {procedure_name!r}"
128
+ )
129
+ continue
130
+ procedure.add_required_equipment(data_assemblies[tag_name])
131
+
132
+ def _find_procedure(self, name: str):
133
+ """Find a procedure by name among all registered services.
134
+
135
+ Args:
136
+ name: Procedure name to search for.
137
+
138
+ Returns:
139
+ The matching procedure, or None if not found.
140
+ """
141
+ for service in self.service_set.values():
142
+ for procedure in service.procedures.values():
143
+ if procedure.name == name:
144
+ return procedure
145
+ return None
146
+
147
+ def start(self) -> None:
148
+ """Start the OPC UA server and the cyclic Modbus I/O service."""
149
+ if not self.modbus_client.connect():
150
+ raise ConnectionError("unable to connect to the M15 Modbus server")
151
+ super().start()
152
+ self.io_service.activate_and_run()
153
+
154
+ def stop(self) -> None:
155
+ """Stop the cyclic I/O service, OPC UA server, and Modbus client."""
156
+ self.io_service.stop()
157
+ super().stop()
158
+ self.modbus_client.close()
159
+
160
+
161
+ def parse_args(args: list[str] | None = None) -> argparse.Namespace:
162
+ """Parse command-line options for the M15 PEA."""
163
+ parser = argparse.ArgumentParser(description=__doc__)
164
+ parser.add_argument("--host", default=DEFAULT_HOST)
165
+ parser.add_argument("-p", "--modbus-port", type=int, default=DEFAULT_MODBUS_PORT)
166
+ parser.add_argument("--endpoint", default=DEFAULT_OPCUA_ENDPOINT)
167
+ parser.add_argument(
168
+ "-r",
169
+ "--rmtp",
170
+ default="",
171
+ help="basename of the requirements MTP files (without .mtp or .json)",
172
+ )
173
+ parser.add_argument(
174
+ "-u",
175
+ "--user-logic",
176
+ dest="user_logic",
177
+ default="",
178
+ help="Python module containing the user logic",
179
+ )
180
+ parser.add_argument(
181
+ "-m",
182
+ "--modbus-config",
183
+ type=Path,
184
+ default=CONFIG_PATH,
185
+ help="path to the Modbus register-mapping JSON configuration file",
186
+ )
187
+ parser.add_argument("-t", "--duration", type=float, default=10.0)
188
+ parser.add_argument("-c", "--cycle-time", type=float, default=DEFAULT_CYCLE_TIME)
189
+ parser.add_argument("-d", "--daemon", action="store_true")
190
+ parser.add_argument(
191
+ "-l",
192
+ "--log-level",
193
+ default="MTP",
194
+ choices=["DEBUG", "INFO", *CHOICES, "WARNING", "ERROR", "CRITICAL"],
195
+ help="logging level (default: MTP)",
196
+ )
197
+ return parser.parse_args(args)
198
+
199
+
200
+ async def main(args: list[str] | None = None) -> None:
201
+ """Start the M15 PEA and keep it alive for the requested duration."""
202
+ parsed_args = parse_args(args)
203
+ setLogLevel(parsed_args.log_level)
204
+ pea = M15Pea(
205
+ endpoint=parsed_args.endpoint,
206
+ host=parsed_args.host,
207
+ modbus_port=parsed_args.modbus_port,
208
+ config_path=parsed_args.modbus_config,
209
+ cycle_time=parsed_args.cycle_time,
210
+ mtp=f"{parsed_args.rmtp}.mtp" if parsed_args.rmtp else "",
211
+ ssd=f"{parsed_args.rmtp}.json" if parsed_args.rmtp else "",
212
+ code=parsed_args.user_logic,
213
+ )
214
+ try:
215
+ pea.start()
216
+ if parsed_args.daemon:
217
+ await asyncio.Event().wait()
218
+ else:
219
+ await asyncio.sleep(parsed_args.duration)
220
+ finally:
221
+ pea.stop()
222
+
223
+
224
+ if __name__ == "__main__":
225
+ asyncio.run(main())
@@ -0,0 +1,117 @@
1
+ """Tests for M15 PEA."""
2
+
3
+ __copyright__ = (
4
+ "Copyright (c) 2026 Dresden University of Technology, Process-to-Order Group"
5
+ )
6
+ __license__ = "MIT"
7
+
8
+ import json
9
+ from pathlib import Path
10
+ from unittest.mock import patch, MagicMock
11
+
12
+ from examples.modbus.m15_pea import M15Pea
13
+ from mtppy.part3.data_assembly_set.indicator_elements.views.dint_view import DIntView
14
+
15
+
16
+ def test_loads_internal_data_assemblies_from_config(tmp_path):
17
+ config = {
18
+ "internal_equipment": {
19
+ "start_stop": {
20
+ "class": "mtppy.part3.data_assembly_set.indicator_elements.views.dint_view.DIntView",
21
+ "V": {"register": 401, "access": "write"},
22
+ },
23
+ "p_out": {
24
+ "class": "mtppy.part3.data_assembly_set.indicator_elements.views.dint_view.DIntView",
25
+ "V": {"register": 400, "access": "write"},
26
+ },
27
+ }
28
+ }
29
+ config_path = tmp_path / "config.json"
30
+ config_path.write_text(json.dumps(config))
31
+
32
+ with patch("pymodbus.client.ModbusTcpClient") as mock_client_cls:
33
+ mock_client_cls.return_value.connect.return_value = True
34
+ pea = M15Pea(config_path=config_path)
35
+
36
+ assert "start_stop" in pea.data_assemblies
37
+ assert "p_out" in pea.data_assemblies
38
+ assert isinstance(pea.data_assemblies["start_stop"], DIntView)
39
+
40
+
41
+ def test_write_access_configures_communication_object(tmp_path):
42
+ config = {
43
+ "internal_equipment": {
44
+ "start_stop": {
45
+ "class": "mtppy.part3.data_assembly_set.indicator_elements.views.dint_view.DIntView",
46
+ "V": {"register": 401, "access": "write"},
47
+ },
48
+ }
49
+ }
50
+ config_path = tmp_path / "config.json"
51
+ config_path.write_text(json.dumps(config))
52
+
53
+ with patch("pymodbus.client.ModbusTcpClient") as mock_client_cls:
54
+ mock_client_cls.return_value.connect.return_value = True
55
+ pea = M15Pea(config_path=config_path)
56
+
57
+ mapping = pea.io_logic.mappings[0]
58
+ assert mapping.access == "write"
59
+ assert mapping.register == 401
60
+
61
+
62
+ def test_assign_adds_data_assembly_to_named_procedure(tmp_path):
63
+ config = {
64
+ "internal_equipment": {
65
+ "start_stop": {
66
+ "class": "mtppy.part3.data_assembly_set.indicator_elements.views.dint_view.DIntView",
67
+ "assign": ["auto"],
68
+ "V": {"register": 401, "access": "write"},
69
+ },
70
+ }
71
+ }
72
+ config_path = tmp_path / "config.json"
73
+ config_path.write_text(json.dumps(config))
74
+
75
+ mock_procedure = MagicMock()
76
+ mock_procedure.name = "auto"
77
+ mock_service = MagicMock()
78
+ mock_service.procedures = {"auto": mock_procedure}
79
+
80
+ with patch("pymodbus.client.ModbusTcpClient") as mock_client_cls:
81
+ mock_client_cls.return_value.connect.return_value = True
82
+ pea = M15Pea(config_path=config_path)
83
+ pea.service_set["produce"] = mock_service
84
+
85
+ pea._assign_data_assemblies(
86
+ {"auto": ["start_stop"]},
87
+ {"start_stop": pea.data_assemblies["start_stop"]},
88
+ )
89
+
90
+ mock_procedure.add_required_equipment.assert_called_once_with(
91
+ pea.data_assemblies["start_stop"]
92
+ )
93
+
94
+
95
+ def test_assign_logs_warning_for_missing_procedure(tmp_path, caplog):
96
+ config = {
97
+ "internal_equipment": {
98
+ "start_stop": {
99
+ "class": "mtppy.part3.data_assembly_set.indicator_elements.views.dint_view.DIntView",
100
+ "assign": ["nonexistent"],
101
+ "V": {"register": 401, "access": "write"},
102
+ },
103
+ }
104
+ }
105
+ config_path = tmp_path / "config.json"
106
+ config_path.write_text(json.dumps(config))
107
+
108
+ with patch("pymodbus.client.ModbusTcpClient") as mock_client_cls:
109
+ mock_client_cls.return_value.connect.return_value = True
110
+ pea = M15Pea(config_path=config_path)
111
+
112
+ pea._assign_data_assemblies(
113
+ {"nonexistent": ["start_stop"]},
114
+ {"start_stop": pea.data_assemblies["start_stop"]},
115
+ )
116
+
117
+ assert "procedure 'nonexistent' not found for assignment" in caplog.text