conson-xp 1.39.0__tar.gz → 1.41.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 (324) hide show
  1. {conson_xp-1.39.0 → conson_xp-1.41.0}/PKG-INFO +2 -1
  2. {conson_xp-1.39.0 → conson_xp-1.41.0}/README.md +1 -0
  3. {conson_xp-1.39.0 → conson_xp-1.41.0}/pyproject.toml +1 -1
  4. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/__init__.py +1 -1
  5. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_msactiontable_commands.py +134 -15
  6. conson_xp-1.41.0/src/xp/models/actiontable/msactiontable_xp20.py +143 -0
  7. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/actiontable/msactiontable_xp24.py +9 -10
  8. conson_xp-1.41.0/src/xp/models/actiontable/msactiontable_xp33.py +360 -0
  9. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/config/conson_module_config.py +6 -2
  10. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/actiontable/msactiontable_xp20_serializer.py +2 -2
  11. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/actiontable/msactiontable_xp24_serializer.py +1 -1
  12. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/actiontable/msactiontable_xp33_serializer.py +2 -2
  13. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/msactiontable/msactiontable_download_service.py +4 -4
  14. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/msactiontable/msactiontable_list_service.py +9 -1
  15. conson_xp-1.41.0/src/xp/services/conbus/msactiontable/msactiontable_upload_service.py +324 -0
  16. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/utils/dependencies.py +16 -0
  17. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_xp24_action_table_integration.py +2 -2
  18. conson_xp-1.41.0/tests/unit/test_cli/test_conbus_msactiontable_upload_commands.py +376 -0
  19. conson_xp-1.41.0/tests/unit/test_models/test_xp20_action_table.py +515 -0
  20. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_xp24_action_table_short_format.py +19 -21
  21. conson_xp-1.41.0/tests/unit/test_services/test_msactiontable_upload_service.py +503 -0
  22. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_xp20_action_table_serializer.py +35 -0
  23. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_xp24_action_table_service.py +1 -3
  24. conson_xp-1.41.0/tests/unit/test_services/test_xp33_short_format.py +436 -0
  25. conson_xp-1.39.0/src/xp/models/actiontable/msactiontable.py +0 -9
  26. conson_xp-1.39.0/src/xp/models/actiontable/msactiontable_xp20.py +0 -53
  27. conson_xp-1.39.0/src/xp/models/actiontable/msactiontable_xp33.py +0 -93
  28. conson_xp-1.39.0/tests/unit/test_models/test_xp20_action_table.py +0 -229
  29. {conson_xp-1.39.0 → conson_xp-1.41.0}/LICENSE +0 -0
  30. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/__init__.py +0 -0
  31. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/__main__.py +0 -0
  32. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/__init__.py +0 -0
  33. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/__init__.py +0 -0
  34. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus.py +0 -0
  35. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_actiontable_commands.py +0 -0
  36. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_autoreport_commands.py +0 -0
  37. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_blink_commands.py +0 -0
  38. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_config_commands.py +0 -0
  39. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_custom_commands.py +0 -0
  40. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_datapoint_commands.py +0 -0
  41. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_discover_commands.py +0 -0
  42. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_event_commands.py +0 -0
  43. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_export_commands.py +0 -0
  44. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_lightlevel_commands.py +0 -0
  45. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_linknumber_commands.py +0 -0
  46. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_modulenumber_commands.py +0 -0
  47. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_output_commands.py +0 -0
  48. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_raw_commands.py +0 -0
  49. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_receive_commands.py +0 -0
  50. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/conbus/conbus_scan_commands.py +0 -0
  51. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/file_commands.py +0 -0
  52. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/homekit/__init__.py +0 -0
  53. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/homekit/homekit.py +0 -0
  54. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/homekit/homekit_start_commands.py +0 -0
  55. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/module_commands.py +0 -0
  56. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/reverse_proxy_commands.py +0 -0
  57. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/server/__init__.py +0 -0
  58. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/server/server_commands.py +0 -0
  59. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/telegram/__init__.py +0 -0
  60. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/telegram/telegram.py +0 -0
  61. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/telegram/telegram_blink_commands.py +0 -0
  62. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/telegram/telegram_checksum_commands.py +0 -0
  63. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/telegram/telegram_discover_commands.py +0 -0
  64. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/telegram/telegram_linknumber_commands.py +0 -0
  65. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/telegram/telegram_parse_commands.py +0 -0
  66. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/telegram/telegram_version_commands.py +0 -0
  67. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/term/__init__.py +0 -0
  68. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/term/term.py +0 -0
  69. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/commands/term/term_commands.py +0 -0
  70. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/main.py +0 -0
  71. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/utils/__init__.py +0 -0
  72. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/utils/click_tree.py +0 -0
  73. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/utils/datapoint_type_choice.py +0 -0
  74. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/utils/decorators.py +0 -0
  75. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/utils/error_handlers.py +0 -0
  76. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/utils/formatters.py +0 -0
  77. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/utils/module_type_choice.py +0 -0
  78. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/utils/serial_number_type.py +0 -0
  79. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/utils/system_function_choice.py +0 -0
  80. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/cli/utils/xp_module_type.py +0 -0
  81. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/__init__.py +0 -0
  82. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/actiontable/__init__.py +0 -0
  83. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/actiontable/actiontable.py +0 -0
  84. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/__init__.py +0 -0
  85. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus.py +0 -0
  86. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_autoreport.py +0 -0
  87. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_blink.py +0 -0
  88. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_client_config.py +0 -0
  89. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_connection_status.py +0 -0
  90. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_custom.py +0 -0
  91. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_datapoint.py +0 -0
  92. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_discover.py +0 -0
  93. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_event_list.py +0 -0
  94. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_event_raw.py +0 -0
  95. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_export.py +0 -0
  96. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_lightlevel.py +0 -0
  97. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_linknumber.py +0 -0
  98. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_logger_config.py +0 -0
  99. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_output.py +0 -0
  100. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_raw.py +0 -0
  101. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_receive.py +0 -0
  102. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/conbus/conbus_writeconfig.py +0 -0
  103. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/config/__init__.py +0 -0
  104. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/homekit/__init__.py +0 -0
  105. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/homekit/homekit_accessory.py +0 -0
  106. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/homekit/homekit_config.py +0 -0
  107. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/log_entry.py +0 -0
  108. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/protocol/__init__.py +0 -0
  109. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/protocol/conbus_protocol.py +0 -0
  110. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/response.py +0 -0
  111. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/__init__.py +0 -0
  112. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/action_type.py +0 -0
  113. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/datapoint_type.py +0 -0
  114. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/event_telegram.py +0 -0
  115. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/event_type.py +0 -0
  116. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/input_action_type.py +0 -0
  117. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/input_type.py +0 -0
  118. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/module_type.py +0 -0
  119. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/module_type_code.py +0 -0
  120. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/output_telegram.py +0 -0
  121. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/reply_telegram.py +0 -0
  122. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/system_function.py +0 -0
  123. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/system_telegram.py +0 -0
  124. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/telegram.py +0 -0
  125. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/telegram_type.py +0 -0
  126. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/telegram/timeparam_type.py +0 -0
  127. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/term/__init__.py +0 -0
  128. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/term/connection_state.py +0 -0
  129. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/term/module_state.py +0 -0
  130. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/term/protocol_keys_config.py +0 -0
  131. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/term/status_message.py +0 -0
  132. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/term/telegram_display.py +0 -0
  133. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/models/write_config_type.py +0 -0
  134. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/__init__.py +0 -0
  135. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/actiontable/__init__.py +0 -0
  136. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/actiontable/actiontable_serializer.py +0 -0
  137. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/actiontable/msactiontable_serializer.py +0 -0
  138. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/__init__.py +0 -0
  139. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/actiontable/__init__.py +0 -0
  140. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/actiontable/actiontable_download_service.py +0 -0
  141. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/actiontable/actiontable_list_service.py +0 -0
  142. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/actiontable/actiontable_show_service.py +0 -0
  143. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/actiontable/actiontable_upload_service.py +0 -0
  144. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_blink_all_service.py +0 -0
  145. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_blink_service.py +0 -0
  146. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_custom_service.py +0 -0
  147. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_datapoint_queryall_service.py +0 -0
  148. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_datapoint_service.py +0 -0
  149. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_discover_service.py +0 -0
  150. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_event_list_service.py +0 -0
  151. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_event_raw_service.py +0 -0
  152. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_export_service.py +0 -0
  153. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_output_service.py +0 -0
  154. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_raw_service.py +0 -0
  155. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_receive_service.py +0 -0
  156. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/conbus_scan_service.py +0 -0
  157. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/msactiontable/__init__.py +0 -0
  158. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/msactiontable/msactiontable_show_service.py +0 -0
  159. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/conbus/write_config_service.py +0 -0
  160. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/__init__.py +0 -0
  161. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_cache_service.py +0 -0
  162. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_conbus_service.py +0 -0
  163. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_config_validator.py +0 -0
  164. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_conson_validator.py +0 -0
  165. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_dimminglight.py +0 -0
  166. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_dimminglight_service.py +0 -0
  167. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_hap_service.py +0 -0
  168. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_lightbulb.py +0 -0
  169. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_lightbulb_service.py +0 -0
  170. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_module_service.py +0 -0
  171. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_outlet.py +0 -0
  172. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_outlet_service.py +0 -0
  173. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/homekit/homekit_service.py +0 -0
  174. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/log_file_service.py +0 -0
  175. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/module_type_service.py +0 -0
  176. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/protocol/__init__.py +0 -0
  177. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/protocol/conbus_event_protocol.py +0 -0
  178. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/protocol/conbus_protocol.py +0 -0
  179. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/protocol/protocol_factory.py +0 -0
  180. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/protocol/telegram_protocol.py +0 -0
  181. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/reverse_proxy_service.py +0 -0
  182. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/__init__.py +0 -0
  183. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/base_server_service.py +0 -0
  184. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/client_buffer_manager.py +0 -0
  185. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/cp20_server_service.py +0 -0
  186. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/device_service_factory.py +0 -0
  187. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/server_service.py +0 -0
  188. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/xp130_server_service.py +0 -0
  189. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/xp20_server_service.py +0 -0
  190. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/xp230_server_service.py +0 -0
  191. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/xp24_server_service.py +0 -0
  192. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/server/xp33_server_service.py +0 -0
  193. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/telegram/__init__.py +0 -0
  194. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/telegram/telegram_blink_service.py +0 -0
  195. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/telegram/telegram_checksum_service.py +0 -0
  196. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/telegram/telegram_datapoint_service.py +0 -0
  197. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/telegram/telegram_discover_service.py +0 -0
  198. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/telegram/telegram_link_number_service.py +0 -0
  199. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/telegram/telegram_output_service.py +0 -0
  200. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/telegram/telegram_service.py +0 -0
  201. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/telegram/telegram_version_service.py +0 -0
  202. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/term/__init__.py +0 -0
  203. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/term/protocol_monitor_service.py +0 -0
  204. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/services/term/state_monitor_service.py +0 -0
  205. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/term/__init__.py +0 -0
  206. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/term/protocol.py +0 -0
  207. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/term/protocol.tcss +0 -0
  208. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/term/state.py +0 -0
  209. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/term/state.tcss +0 -0
  210. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/term/widgets/__init__.py +0 -0
  211. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/term/widgets/help_menu.py +0 -0
  212. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/term/widgets/modules_list.py +0 -0
  213. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/term/widgets/protocol_log.py +0 -0
  214. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/term/widgets/status_footer.py +0 -0
  215. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/utils/__init__.py +0 -0
  216. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/utils/checksum.py +0 -0
  217. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/utils/event_helper.py +0 -0
  218. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/utils/logging.py +0 -0
  219. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/utils/serialization.py +0 -0
  220. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/utils/state_machine.py +0 -0
  221. {conson_xp-1.39.0 → conson_xp-1.41.0}/src/xp/utils/time_utils.py +0 -0
  222. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/.coverage +0 -0
  223. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/__init__.py +0 -0
  224. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/conftest.py +0 -0
  225. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/.coverage +0 -0
  226. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/__init__.py +0 -0
  227. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/telegram_test_data.py +0 -0
  228. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_actiontable_integration.py +0 -0
  229. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_api/.coverage +0 -0
  230. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_api/__init__.py +0 -0
  231. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_blink_integration.py +0 -0
  232. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_checksum_integration.py +0 -0
  233. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_conbus_blink_integration.py +0 -0
  234. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_conbus_datapoint_integration.py +0 -0
  235. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_conbus_raw_integration.py +0 -0
  236. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_conbus_receive_integration.py +0 -0
  237. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_discovery_integration.py +0 -0
  238. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_event_telegram_integration.py +0 -0
  239. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_homekit_config_integration.py +0 -0
  240. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_link_number_integration.py +0 -0
  241. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_module_integration.py +0 -0
  242. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_output_integration.py +0 -0
  243. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_reverse_proxy_integration.py +0 -0
  244. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_system_reply_telegram_integration.py +0 -0
  245. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_term_logging_integration.py +0 -0
  246. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_version_integration.py +0 -0
  247. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/integration/test_xp20_action_table_integration.py +0 -0
  248. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/__init__.py +0 -0
  249. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_api/__init__.py +0 -0
  250. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/__init__.py +0 -0
  251. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/test_click_tree.py +0 -0
  252. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/test_conbus_actiontable_commands.py +0 -0
  253. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/test_conbus_blink_commands.py +0 -0
  254. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/test_datapoint_type_choice.py +0 -0
  255. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/test_decorators.py +0 -0
  256. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/test_error_handlers.py +0 -0
  257. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/test_formatters.py +0 -0
  258. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/test_serial_number_type.py +0 -0
  259. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/test_system_function_choice.py +0 -0
  260. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_cli/test_term_commands.py +0 -0
  261. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_encoding/__init__.py +0 -0
  262. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_encoding/test_latin1_edge_cases.py +0 -0
  263. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/__init__.py +0 -0
  264. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_conbus.py +0 -0
  265. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_conbus_client_send.py +0 -0
  266. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_conbus_discover.py +0 -0
  267. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_conbus_linknumber.py +0 -0
  268. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_event_telegram.py +0 -0
  269. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_log_entry.py +0 -0
  270. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_logger_config.py +0 -0
  271. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_module_type.py +0 -0
  272. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_reply_telegram.py +0 -0
  273. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_system_telegram.py +0 -0
  274. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_system_telegram_enhancements.py +0 -0
  275. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_version_telegram.py +0 -0
  276. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_write_config_type.py +0 -0
  277. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_xp24_action_table.py +0 -0
  278. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_models/test_xp24_action_telegram.py +0 -0
  279. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/__init__.py +0 -0
  280. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_actiontable_serializer.py +0 -0
  281. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_actiontable_service.py +0 -0
  282. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_actiontable_upload_service.py +0 -0
  283. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_base_server_service.py +0 -0
  284. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_blink_service.py +0 -0
  285. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_checksum_service.py +0 -0
  286. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_client_buffer_manager.py +0 -0
  287. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_conbus_blink_service.py +0 -0
  288. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_conbus_event_list_service.py +0 -0
  289. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_conbus_event_protocol.py +0 -0
  290. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_conbus_event_raw_service.py +0 -0
  291. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_conbus_output_service.py +0 -0
  292. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_conbus_raw_service.py +0 -0
  293. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_conbus_receive_service.py +0 -0
  294. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_conbus_reverse_proxy_service.py +0 -0
  295. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_conbus_scan_service.py +0 -0
  296. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_device_service_factory.py +0 -0
  297. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_discovery_service.py +0 -0
  298. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_homekit_cache_service.py +0 -0
  299. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_homekit_config_validator.py +0 -0
  300. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_homekit_conson_service.py +0 -0
  301. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_homekit_services.py +0 -0
  302. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_log_file_service.py +0 -0
  303. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_module_type_service.py +0 -0
  304. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_protocol.py +0 -0
  305. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_protocol_monitor_service.py +0 -0
  306. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_server_service.py +0 -0
  307. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_state_monitor_service.py +0 -0
  308. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_telegram_input_service.py +0 -0
  309. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_telegram_output_service.py +0 -0
  310. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_telegram_protocol.py +0 -0
  311. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_telegram_service.py +0 -0
  312. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_version_service.py +0 -0
  313. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_xp24_action_service.py +0 -0
  314. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_xp24_action_table_serializer.py +0 -0
  315. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_xp33_action_table_serializer.py +0 -0
  316. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_services/test_xp_server_services.py +0 -0
  317. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_tui/__init__.py +0 -0
  318. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_tui/test_protocol_log.py +0 -0
  319. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_utils/__init__.py +0 -0
  320. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_utils/test_checksum.py +0 -0
  321. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_utils/test_event_helper.py +0 -0
  322. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_utils/test_logging.py +0 -0
  323. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_utils/test_serialization.py +0 -0
  324. {conson_xp-1.39.0 → conson_xp-1.41.0}/tests/unit/test_utils/test_time_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: conson-xp
3
- Version: 1.39.0
3
+ Version: 1.41.0
4
4
  Summary: XP Protocol Communication Tools
5
5
  Author-Email: ldvchosal <ldvchosal@github.com>
6
6
  License: MIT License
@@ -376,6 +376,7 @@ xp conbus msactiontable
376
376
  xp conbus msactiontable download
377
377
  xp conbus msactiontable list
378
378
  xp conbus msactiontable show
379
+ xp conbus msactiontable upload
379
380
 
380
381
 
381
382
  xp conbus output
@@ -323,6 +323,7 @@ xp conbus msactiontable
323
323
  xp conbus msactiontable download
324
324
  xp conbus msactiontable list
325
325
  xp conbus msactiontable show
326
+ xp conbus msactiontable upload
326
327
 
327
328
 
328
329
  xp conbus output
@@ -22,7 +22,7 @@ dependencies = [
22
22
  ]
23
23
  requires-python = ">=3.11"
24
24
  readme = "README.md"
25
- version = "1.39.0"
25
+ version = "1.41.0"
26
26
 
27
27
  [project.license]
28
28
  file = "LICENSE"
@@ -3,7 +3,7 @@
3
3
  conson-xp package.
4
4
  """
5
5
 
6
- __version__ = "1.39.0"
6
+ __version__ = "1.41.0"
7
7
  __manufacturer__ = "salchichon"
8
8
  __model__ = "xp.cli"
9
9
  __serial__ = "2025.09.23.000"
@@ -25,6 +25,9 @@ from xp.services.conbus.msactiontable.msactiontable_list_service import (
25
25
  from xp.services.conbus.msactiontable.msactiontable_show_service import (
26
26
  MsActionTableShowService,
27
27
  )
28
+ from xp.services.conbus.msactiontable.msactiontable_upload_service import (
29
+ MsActionTableUploadService,
30
+ )
28
31
 
29
32
 
30
33
  @conbus_msactiontable.command("download", short_help="Download MSActionTable")
@@ -55,29 +58,30 @@ def conbus_download_msactiontable(
55
58
  click.echo(progress, nl=False)
56
59
 
57
60
  def on_finish(
58
- msaction_table: Union[
59
- Xp20MsActionTable, Xp24MsActionTable, Xp33MsActionTable, None
60
- ],
61
- msaction_table_short: str,
61
+ msaction_table: Union[Xp20MsActionTable, Xp24MsActionTable, Xp33MsActionTable],
62
+ msaction_table_short: list[str],
62
63
  ) -> None:
63
- """Handle successful completion of MS action table download.
64
+ """Handle successful completion of XP24 MS action table download.
64
65
 
65
66
  Args:
66
- msaction_table: Downloaded MS action table object or None if failed.
67
- msaction_table_short: Short version of MS action table object or None if failed.
68
-
69
- Raises:
70
- Abort: If action table download failed.
67
+ msaction_table: Downloaded XP MS action table object.
68
+ msaction_table_short: Short version of XP24 MS action table.
71
69
  """
72
70
  service.stop_reactor()
73
- if msaction_table is None:
74
- click.echo("Error: Failed to download MS action table")
75
- raise click.Abort()
71
+
72
+ # Format short representation based on module type
73
+ short_field_name = f"{xpmoduletype}_msaction_table"
74
+ # XP24 returns single-element list, XP20/XP33 return multi-line lists
75
+ short_value: Union[str, list[str]]
76
+ if len(msaction_table_short) == 1:
77
+ short_value = msaction_table_short[0]
78
+ else:
79
+ short_value = msaction_table_short
76
80
 
77
81
  output = {
78
82
  "serial_number": serial_number,
79
83
  "xpmoduletype": xpmoduletype,
80
- "msaction_table_short": msaction_table_short,
84
+ short_field_name: short_value,
81
85
  "msaction_table": msaction_table.model_dump(),
82
86
  }
83
87
  click.echo(json.dumps(output, indent=2, default=str))
@@ -93,6 +97,8 @@ def conbus_download_msactiontable(
93
97
  with service:
94
98
  service.on_progress.connect(on_progress)
95
99
  service.on_error.connect(on_error)
100
+
101
+ # Connect to the appropriate signal based on module type
96
102
  service.on_finish.connect(on_finish)
97
103
  service.start(
98
104
  serial_number=serial_number,
@@ -155,9 +161,37 @@ def conbus_show_msactiontable(ctx: Context, serial_number: str) -> None:
155
161
  Args:
156
162
  module: Dictionary containing module configuration.
157
163
  """
164
+ click.echo(f"\nModule: {module.name} ({module.serial_number})")
165
+
166
+ # Display short format if action table exists
167
+ if module.xp33_msaction_table:
168
+ click.echo("Short:")
169
+ for line in module.xp33_msaction_table:
170
+ click.echo(f" - {line}")
171
+ elif module.xp24_msaction_table:
172
+ click.echo("Short:")
173
+ for line in module.xp24_msaction_table:
174
+ click.echo(f" - {line}")
175
+ elif module.xp20_msaction_table:
176
+ click.echo("Short:")
177
+ for line in module.xp20_msaction_table:
178
+ click.echo(f" - {line}")
179
+
180
+ # Display full YAML format
181
+ click.echo("Full:")
158
182
  module_data = module.model_dump()
159
183
  module_data.pop("action_table", None)
160
- click.echo(json.dumps(module_data, indent=2, default=str))
184
+
185
+ # Show the action table in YAML format
186
+ if module.xp33_msaction_table:
187
+ yaml_dict = {"xp33_msaction_table": module_data}
188
+ click.echo(_format_yaml(yaml_dict, indent=2))
189
+ elif module.xp24_msaction_table:
190
+ yaml_dict = {"xp24_msaction_table": module_data}
191
+ click.echo(_format_yaml(yaml_dict, indent=2))
192
+ elif module.xp20_msaction_table:
193
+ yaml_dict = {"xp20_msaction_table": module_data}
194
+ click.echo(_format_yaml(yaml_dict, indent=2))
161
195
 
162
196
  def error_callback(error: str) -> None:
163
197
  """Handle errors during action table show.
@@ -173,3 +207,88 @@ def conbus_show_msactiontable(ctx: Context, serial_number: str) -> None:
173
207
  finish_callback=on_finish,
174
208
  error_callback=error_callback,
175
209
  )
210
+
211
+
212
+ @conbus_msactiontable.command("upload", short_help="Upload MSActionTable")
213
+ @click.argument("serial_number", type=SERIAL)
214
+ @click.argument("xpmoduletype", type=XP_MODULE_TYPE)
215
+ @click.pass_context
216
+ @connection_command()
217
+ def conbus_upload_msactiontable(
218
+ ctx: Context, serial_number: str, xpmoduletype: str
219
+ ) -> None:
220
+ """Upload MS action table from conson.yml to XP module.
221
+
222
+ Args:
223
+ ctx: Click context object.
224
+ serial_number: 10-digit module serial number.
225
+ xpmoduletype: XP module type.
226
+ """
227
+ service: MsActionTableUploadService = (
228
+ ctx.obj.get("container").get_container().resolve(MsActionTableUploadService)
229
+ )
230
+
231
+ def on_progress(progress: str) -> None:
232
+ """Handle progress updates during MS action table upload.
233
+
234
+ Args:
235
+ progress: Progress message string.
236
+ """
237
+ click.echo(progress, nl=False)
238
+
239
+ def on_finish(success: bool) -> None:
240
+ """Handle successful completion of MS action table upload.
241
+
242
+ Args:
243
+ success: Whether upload was successful.
244
+ """
245
+ service.stop_reactor()
246
+ if success:
247
+ click.echo("\nMsactiontable uploaded successfully")
248
+
249
+ def on_error(error: str) -> None:
250
+ """Handle errors during MS action table upload.
251
+
252
+ Args:
253
+ error: Error message string.
254
+ """
255
+ service.stop_reactor()
256
+ click.echo(f"\nError: {error}")
257
+
258
+ click.echo(f"Uploading msactiontable to {serial_number}...")
259
+
260
+ with service:
261
+ service.on_progress.connect(on_progress)
262
+ service.on_error.connect(on_error)
263
+ service.on_finish.connect(on_finish)
264
+ service.start(
265
+ serial_number=serial_number,
266
+ xpmoduletype=xpmoduletype,
267
+ )
268
+ service.start_reactor()
269
+
270
+
271
+ def _format_yaml(data: dict, indent: int = 0) -> str:
272
+ """Format a dictionary as YAML-like output.
273
+
274
+ Args:
275
+ data: Dictionary to format.
276
+ indent: Current indentation level.
277
+
278
+ Returns:
279
+ YAML-like formatted string.
280
+ """
281
+ lines: list[str] = []
282
+ for key, value in data.items():
283
+ if isinstance(value, dict):
284
+ lines.extend((f"{' ' * indent}{key}:", _format_yaml(value, indent + 2)))
285
+ elif isinstance(value, list):
286
+ lines.append(f"{' ' * indent}{key}:")
287
+ for item in value:
288
+ if isinstance(item, dict):
289
+ lines.append(_format_yaml(item, indent + 2))
290
+ else:
291
+ lines.append(f"{' ' * (indent + 2)}- {item}")
292
+ else:
293
+ lines.append(f"{' ' * indent}{key}: {value}")
294
+ return "\n".join(lines)
@@ -0,0 +1,143 @@
1
+ """XP20 Action Table models for input actions and settings."""
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+ class InputChannel(BaseModel):
7
+ """Configuration for a single input channel in XP20 action table.
8
+
9
+ Attributes:
10
+ invert: Input inversion flag
11
+ short_long: Short/long press detection flag
12
+ group_on_off: Group on/off function flag
13
+ and_functions: 8-bit AND function configuration array
14
+ sa_function: SA function flag
15
+ ta_function: TA function flag
16
+ """
17
+
18
+ invert: bool = False
19
+ short_long: bool = False
20
+ group_on_off: bool = False
21
+ and_functions: list[bool] = Field(default_factory=lambda: [False] * 8)
22
+ sa_function: bool = False
23
+ ta_function: bool = False
24
+
25
+
26
+ class Xp20MsActionTable(BaseModel):
27
+ """XP20 Action Table for managing 8 input channels.
28
+
29
+ Contains configuration for 8 input channels (input1 through input8),
30
+ each with flags for inversion, short/long press detection, group functions,
31
+ AND functions, SA functions, and TA functions.
32
+
33
+ Attributes:
34
+ input1: Configuration for input channel 1.
35
+ input2: Configuration for input channel 2.
36
+ input3: Configuration for input channel 3.
37
+ input4: Configuration for input channel 4.
38
+ input5: Configuration for input channel 5.
39
+ input6: Configuration for input channel 6.
40
+ input7: Configuration for input channel 7.
41
+ input8: Configuration for input channel 8.
42
+ """
43
+
44
+ input1: InputChannel = Field(default_factory=InputChannel)
45
+ input2: InputChannel = Field(default_factory=InputChannel)
46
+ input3: InputChannel = Field(default_factory=InputChannel)
47
+ input4: InputChannel = Field(default_factory=InputChannel)
48
+ input5: InputChannel = Field(default_factory=InputChannel)
49
+ input6: InputChannel = Field(default_factory=InputChannel)
50
+ input7: InputChannel = Field(default_factory=InputChannel)
51
+ input8: InputChannel = Field(default_factory=InputChannel)
52
+
53
+ def to_short_format(self) -> list[str]:
54
+ """Convert action table to short format string.
55
+
56
+ Returns:
57
+ Short format string with each channel on a separate line.
58
+ Example:
59
+ CH1 I:0 S:0 G:0 AND:00000000 SA:0 TA:0
60
+ CH2 I:0 S:0 G:0 AND:00000000 SA:0 TA:0
61
+ ...
62
+ """
63
+ lines = []
64
+ for i in range(1, 9):
65
+ channel = getattr(self, f"input{i}")
66
+ # Convert and_functions list to binary string
67
+ and_bits = "".join("1" if bit else "0" for bit in channel.and_functions)
68
+ line = (
69
+ f"CH{i} "
70
+ f"I:{1 if channel.invert else 0} "
71
+ f"S:{1 if channel.short_long else 0} "
72
+ f"G:{1 if channel.group_on_off else 0} "
73
+ f"AND:{and_bits} "
74
+ f"SA:{1 if channel.sa_function else 0} "
75
+ f"TA:{1 if channel.ta_function else 0}"
76
+ )
77
+ lines.append(line)
78
+ return lines
79
+
80
+ @classmethod
81
+ def from_short_format(cls, short_str: list[str]) -> "Xp20MsActionTable":
82
+ """Parse short format string into action table.
83
+
84
+ Args:
85
+ short_str: Short format string with 8 channel lines.
86
+
87
+ Returns:
88
+ Xp20MsActionTable instance.
89
+
90
+ Raises:
91
+ ValueError: If format is invalid.
92
+ """
93
+ import re
94
+
95
+ if len(short_str) != 8:
96
+ raise ValueError(f"Expected 8 channel lines, got {len(short_str)}")
97
+
98
+ pattern = re.compile(
99
+ r"^CH([1-8]) I:([01]) S:([01]) G:([01]) AND:([01]{8}) SA:([01]) TA:([01])$"
100
+ )
101
+
102
+ channels = {}
103
+ for line in short_str:
104
+ line = line.strip()
105
+ match = pattern.match(line)
106
+ if not match:
107
+ raise ValueError(f"Invalid channel format: {line}")
108
+
109
+ ch_num = int(match.group(1))
110
+ invert = match.group(2) == "1"
111
+ short_long = match.group(3) == "1"
112
+ group_on_off = match.group(4) == "1"
113
+ and_bits = match.group(5)
114
+ sa_function = match.group(6) == "1"
115
+ ta_function = match.group(7) == "1"
116
+
117
+ # Convert binary string to list of bools
118
+ and_functions = [bit == "1" for bit in and_bits]
119
+
120
+ channels[ch_num] = InputChannel(
121
+ invert=invert,
122
+ short_long=short_long,
123
+ group_on_off=group_on_off,
124
+ and_functions=and_functions,
125
+ sa_function=sa_function,
126
+ ta_function=ta_function,
127
+ )
128
+
129
+ # Verify all channels are present
130
+ for i in range(1, 9):
131
+ if i not in channels:
132
+ raise ValueError(f"Missing channel {i}")
133
+
134
+ return cls(
135
+ input1=channels[1],
136
+ input2=channels[2],
137
+ input3=channels[3],
138
+ input4=channels[4],
139
+ input5=channels[5],
140
+ input6=channels[6],
141
+ input7=channels[7],
142
+ input8=channels[8],
143
+ )
@@ -4,7 +4,6 @@ from typing import Any, ClassVar, Union
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field, field_validator
6
6
 
7
- from xp.models.actiontable.msactiontable import MsActionTable
8
7
  from xp.models.telegram.input_action_type import InputActionType
9
8
  from xp.models.telegram.timeparam_type import TimeParam
10
9
 
@@ -82,7 +81,7 @@ class InputAction(BaseModel):
82
81
  raise ValueError(f"Invalid type for TimeParam: {type(v)}")
83
82
 
84
83
 
85
- class Xp24MsActionTable(MsActionTable):
84
+ class Xp24MsActionTable(BaseModel):
86
85
  """XP24 Action Table for managing input actions and settings.
87
86
 
88
87
  Each input has an action type (TOGGLE, ON, LEVELSET, etc.)
@@ -159,7 +158,7 @@ class Xp24MsActionTable(MsActionTable):
159
158
  curtain34: bool = False # Curtain setting for inputs 3-4
160
159
  mutual_deadtime: int = MS300 # Master timing (MS300=12 or MS500=20)
161
160
 
162
- def to_short_format(self) -> str:
161
+ def to_short_format(self) -> list[str]:
163
162
  """Convert action table to short format string.
164
163
 
165
164
  Returns:
@@ -179,7 +178,7 @@ class Xp24MsActionTable(MsActionTable):
179
178
  param_value = action.param.value
180
179
  action_parts.append(f"{short_code}:{param_value}")
181
180
 
182
- result = f"XP24 {' '.join(action_parts)}"
181
+ result = " ".join(action_parts)
183
182
 
184
183
  # Add settings
185
184
  settings = (
@@ -191,10 +190,10 @@ class Xp24MsActionTable(MsActionTable):
191
190
  )
192
191
  result = f"{result} | {settings}"
193
192
 
194
- return result
193
+ return [result]
195
194
 
196
195
  @classmethod
197
- def from_short_format(cls, short_str: str) -> "Xp24MsActionTable":
196
+ def from_short_format(cls, short_str: list[str]) -> "Xp24MsActionTable":
198
197
  """Parse short format string into action table.
199
198
 
200
199
  Args:
@@ -207,20 +206,20 @@ class Xp24MsActionTable(MsActionTable):
207
206
  ValueError: If format is invalid.
208
207
  """
209
208
  # Split by pipe to separate actions from settings
210
- parts = short_str.split("|")
209
+ parts = short_str[0].split("|")
211
210
  action_part = parts[0].strip()
212
211
  settings_part = parts[1].strip()
213
212
 
214
213
  # Parse action part
215
214
  tokens = action_part.split()
216
- if len(tokens) != 5 or tokens[0] != "XP24":
215
+ if len(tokens) != 4:
217
216
  raise ValueError(
218
- f"Invalid short format: expected 'XP24 <a1> <a2> <a3> <a4>', got '{action_part}'"
217
+ f"Invalid short format: expected '<a1> <a2> <a3> <a4>', got '{action_part}'"
219
218
  )
220
219
 
221
220
  # Parse input actions
222
221
  input_actions = []
223
- for i, token in enumerate(tokens[1:5], 1):
222
+ for i, token in enumerate(tokens[0:4], 1):
224
223
  if ":" not in token:
225
224
  raise ValueError(f"Invalid action format at position {i}: '{token}'")
226
225