conson-xp 1.9.0__tar.gz → 1.10.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 (264) hide show
  1. {conson_xp-1.9.0 → conson_xp-1.10.0}/PKG-INFO +4 -1
  2. {conson_xp-1.9.0 → conson_xp-1.10.0}/README.md +3 -0
  3. {conson_xp-1.9.0 → conson_xp-1.10.0}/pyproject.toml +1 -1
  4. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/__init__.py +1 -1
  5. conson_xp-1.10.0/src/xp/cli/commands/conbus/conbus_actiontable_commands.py +233 -0
  6. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/actiontable/actiontable.py +1 -1
  7. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/actiontable/msactiontable_xp24.py +1 -1
  8. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/input_action_type.py +4 -4
  9. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/actiontable/actiontable_serializer.py +99 -4
  10. conson_xp-1.9.0/src/xp/services/conbus/actiontable/actiontable_service.py → conson_xp-1.10.0/src/xp/services/conbus/actiontable/actiontable_download_service.py +3 -4
  11. conson_xp-1.10.0/src/xp/services/conbus/actiontable/actiontable_list_service.py +91 -0
  12. conson_xp-1.10.0/src/xp/services/conbus/actiontable/actiontable_show_service.py +89 -0
  13. conson_xp-1.10.0/src/xp/services/conbus/actiontable/actiontable_upload_service.py +211 -0
  14. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/utils/dependencies.py +36 -1
  15. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_actiontable_integration.py +9 -8
  16. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_xp24_action_table_integration.py +2 -2
  17. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_cli/test_conbus_actiontable_commands.py +264 -8
  18. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_xp24_action_table.py +7 -7
  19. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_actiontable_serializer.py +160 -29
  20. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_actiontable_service.py +8 -6
  21. conson_xp-1.10.0/tests/unit/test_services/test_actiontable_upload_service.py +591 -0
  22. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_xp24_action_table_serializer.py +2 -2
  23. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_xp24_action_table_service.py +1 -1
  24. conson_xp-1.9.0/src/xp/cli/commands/conbus/conbus_actiontable_commands.py +0 -76
  25. {conson_xp-1.9.0 → conson_xp-1.10.0}/LICENSE +0 -0
  26. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/__init__.py +0 -0
  27. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/__main__.py +0 -0
  28. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/__init__.py +0 -0
  29. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/__init__.py +0 -0
  30. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus.py +0 -0
  31. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_autoreport_commands.py +0 -0
  32. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_blink_commands.py +0 -0
  33. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_config_commands.py +0 -0
  34. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_custom_commands.py +0 -0
  35. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_datapoint_commands.py +0 -0
  36. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_discover_commands.py +0 -0
  37. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_lightlevel_commands.py +0 -0
  38. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_linknumber_commands.py +0 -0
  39. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_msactiontable_commands.py +0 -0
  40. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_output_commands.py +0 -0
  41. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_raw_commands.py +0 -0
  42. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_receive_commands.py +0 -0
  43. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/conbus/conbus_scan_commands.py +0 -0
  44. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/file_commands.py +0 -0
  45. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/homekit/__init__.py +0 -0
  46. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/homekit/homekit.py +0 -0
  47. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/homekit/homekit_start_commands.py +0 -0
  48. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/module_commands.py +0 -0
  49. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/reverse_proxy_commands.py +0 -0
  50. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/server/__init__.py +0 -0
  51. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/server/server_commands.py +0 -0
  52. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/telegram/__init__.py +0 -0
  53. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/telegram/telegram.py +0 -0
  54. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/telegram/telegram_blink_commands.py +0 -0
  55. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/telegram/telegram_checksum_commands.py +0 -0
  56. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/telegram/telegram_discover_commands.py +0 -0
  57. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/telegram/telegram_linknumber_commands.py +0 -0
  58. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/telegram/telegram_parse_commands.py +0 -0
  59. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/commands/telegram/telegram_version_commands.py +0 -0
  60. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/main.py +0 -0
  61. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/utils/__init__.py +0 -0
  62. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/utils/click_tree.py +0 -0
  63. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/utils/datapoint_type_choice.py +0 -0
  64. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/utils/decorators.py +0 -0
  65. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/utils/error_handlers.py +0 -0
  66. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/utils/formatters.py +0 -0
  67. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/utils/serial_number_type.py +0 -0
  68. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/utils/system_function_choice.py +0 -0
  69. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/cli/utils/xp_module_type.py +0 -0
  70. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/connection/__init__.py +0 -0
  71. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/connection/exceptions.py +0 -0
  72. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/__init__.py +0 -0
  73. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/actiontable/__init__.py +0 -0
  74. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/actiontable/msactiontable_xp20.py +0 -0
  75. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/actiontable/msactiontable_xp33.py +0 -0
  76. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/__init__.py +0 -0
  77. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus.py +0 -0
  78. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_autoreport.py +0 -0
  79. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_blink.py +0 -0
  80. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_client_config.py +0 -0
  81. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_connection_status.py +0 -0
  82. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_custom.py +0 -0
  83. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_datapoint.py +0 -0
  84. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_discover.py +0 -0
  85. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_lightlevel.py +0 -0
  86. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_linknumber.py +0 -0
  87. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_output.py +0 -0
  88. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_raw.py +0 -0
  89. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_receive.py +0 -0
  90. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/conbus/conbus_writeconfig.py +0 -0
  91. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/homekit/__init__.py +0 -0
  92. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/homekit/homekit_accessory.py +0 -0
  93. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/homekit/homekit_config.py +0 -0
  94. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/homekit/homekit_conson_config.py +0 -0
  95. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/log_entry.py +0 -0
  96. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/protocol/__init__.py +0 -0
  97. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/protocol/conbus_protocol.py +0 -0
  98. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/response.py +0 -0
  99. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/__init__.py +0 -0
  100. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/action_type.py +0 -0
  101. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/datapoint_type.py +0 -0
  102. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/event_telegram.py +0 -0
  103. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/event_type.py +0 -0
  104. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/input_type.py +0 -0
  105. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/module_type.py +0 -0
  106. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/module_type_code.py +0 -0
  107. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/output_telegram.py +0 -0
  108. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/reply_telegram.py +0 -0
  109. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/system_function.py +0 -0
  110. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/system_telegram.py +0 -0
  111. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/telegram.py +0 -0
  112. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/telegram_type.py +0 -0
  113. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/telegram/timeparam_type.py +0 -0
  114. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/models/write_config_type.py +0 -0
  115. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/__init__.py +0 -0
  116. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/actiontable/__init__.py +0 -0
  117. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/actiontable/msactiontable_serializer.py +0 -0
  118. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/actiontable/msactiontable_xp20_serializer.py +0 -0
  119. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/actiontable/msactiontable_xp24_serializer.py +0 -0
  120. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/actiontable/msactiontable_xp33_serializer.py +0 -0
  121. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/__init__.py +0 -0
  122. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/actiontable/__init__.py +0 -0
  123. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/actiontable/msactiontable_service.py +0 -0
  124. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/conbus_blink_all_service.py +0 -0
  125. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/conbus_blink_service.py +0 -0
  126. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/conbus_custom_service.py +0 -0
  127. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/conbus_datapoint_queryall_service.py +0 -0
  128. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/conbus_datapoint_service.py +0 -0
  129. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/conbus_discover_service.py +0 -0
  130. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/conbus_output_service.py +0 -0
  131. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/conbus_raw_service.py +0 -0
  132. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/conbus_receive_service.py +0 -0
  133. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/conbus_scan_service.py +0 -0
  134. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/conbus/write_config_service.py +0 -0
  135. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/__init__.py +0 -0
  136. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_cache_service.py +0 -0
  137. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_conbus_service.py +0 -0
  138. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_config_validator.py +0 -0
  139. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_conson_validator.py +0 -0
  140. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_dimminglight.py +0 -0
  141. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_dimminglight_service.py +0 -0
  142. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_hap_service.py +0 -0
  143. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_lightbulb.py +0 -0
  144. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_lightbulb_service.py +0 -0
  145. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_module_service.py +0 -0
  146. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_outlet.py +0 -0
  147. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_outlet_service.py +0 -0
  148. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/homekit/homekit_service.py +0 -0
  149. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/log_file_service.py +0 -0
  150. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/module_type_service.py +0 -0
  151. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/protocol/__init__.py +0 -0
  152. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/protocol/conbus_protocol.py +0 -0
  153. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/protocol/protocol_factory.py +0 -0
  154. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/protocol/telegram_protocol.py +0 -0
  155. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/reverse_proxy_service.py +0 -0
  156. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/server/__init__.py +0 -0
  157. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/server/base_server_service.py +0 -0
  158. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/server/cp20_server_service.py +0 -0
  159. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/server/device_service_factory.py +0 -0
  160. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/server/server_service.py +0 -0
  161. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/server/xp130_server_service.py +0 -0
  162. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/server/xp20_server_service.py +0 -0
  163. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/server/xp230_server_service.py +0 -0
  164. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/server/xp24_server_service.py +0 -0
  165. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/server/xp33_server_service.py +0 -0
  166. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/telegram/__init__.py +0 -0
  167. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/telegram/telegram_blink_service.py +0 -0
  168. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/telegram/telegram_checksum_service.py +0 -0
  169. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/telegram/telegram_datapoint_service.py +0 -0
  170. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/telegram/telegram_discover_service.py +0 -0
  171. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/telegram/telegram_link_number_service.py +0 -0
  172. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/telegram/telegram_output_service.py +0 -0
  173. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/telegram/telegram_service.py +0 -0
  174. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/services/telegram/telegram_version_service.py +0 -0
  175. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/utils/__init__.py +0 -0
  176. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/utils/checksum.py +0 -0
  177. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/utils/event_helper.py +0 -0
  178. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/utils/serialization.py +0 -0
  179. {conson_xp-1.9.0 → conson_xp-1.10.0}/src/xp/utils/time_utils.py +0 -0
  180. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/.coverage +0 -0
  181. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/__init__.py +0 -0
  182. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/conftest.py +0 -0
  183. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/.coverage +0 -0
  184. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/__init__.py +0 -0
  185. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/telegram_test_data.py +0 -0
  186. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_api/.coverage +0 -0
  187. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_api/__init__.py +0 -0
  188. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_blink_integration.py +0 -0
  189. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_checksum_integration.py +0 -0
  190. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_conbus_blink_integration.py +0 -0
  191. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_conbus_datapoint_integration.py +0 -0
  192. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_conbus_raw_integration.py +0 -0
  193. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_conbus_receive_integration.py +0 -0
  194. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_discovery_integration.py +0 -0
  195. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_event_telegram_integration.py +0 -0
  196. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_homekit_config_integration.py +0 -0
  197. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_link_number_integration.py +0 -0
  198. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_module_integration.py +0 -0
  199. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_output_integration.py +0 -0
  200. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_reverse_proxy_integration.py +0 -0
  201. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_system_reply_telegram_integration.py +0 -0
  202. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_version_integration.py +0 -0
  203. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/integration/test_xp20_action_table_integration.py +0 -0
  204. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/__init__.py +0 -0
  205. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_api/__init__.py +0 -0
  206. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_cli/__init__.py +0 -0
  207. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_cli/test_click_tree.py +0 -0
  208. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_cli/test_conbus_blink_commands.py +0 -0
  209. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_cli/test_datapoint_type_choice.py +0 -0
  210. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_cli/test_decorators.py +0 -0
  211. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_cli/test_error_handlers.py +0 -0
  212. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_cli/test_formatters.py +0 -0
  213. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_cli/test_serial_number_type.py +0 -0
  214. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_cli/test_system_function_choice.py +0 -0
  215. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_connection/__init__.py +0 -0
  216. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_connection/test_connection_init.py +0 -0
  217. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_connection/test_exceptions.py +0 -0
  218. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_encoding/__init__.py +0 -0
  219. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_encoding/test_latin1_edge_cases.py +0 -0
  220. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/__init__.py +0 -0
  221. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_conbus.py +0 -0
  222. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_conbus_client_send.py +0 -0
  223. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_conbus_discover.py +0 -0
  224. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_conbus_linknumber.py +0 -0
  225. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_event_telegram.py +0 -0
  226. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_log_entry.py +0 -0
  227. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_module_type.py +0 -0
  228. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_reply_telegram.py +0 -0
  229. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_system_telegram.py +0 -0
  230. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_system_telegram_enhancements.py +0 -0
  231. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_version_telegram.py +0 -0
  232. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_write_config_type.py +0 -0
  233. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_xp20_action_table.py +0 -0
  234. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_models/test_xp24_action_telegram.py +0 -0
  235. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/__init__.py +0 -0
  236. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_base_server_service.py +0 -0
  237. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_blink_service.py +0 -0
  238. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_checksum_service.py +0 -0
  239. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_conbus_blink_service.py +0 -0
  240. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_conbus_raw_service.py +0 -0
  241. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_conbus_reverse_proxy_service.py +0 -0
  242. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_device_service_factory.py +0 -0
  243. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_discovery_service.py +0 -0
  244. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_homekit_cache_service.py +0 -0
  245. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_homekit_config_validator.py +0 -0
  246. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_homekit_conson_service.py +0 -0
  247. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_homekit_services.py +0 -0
  248. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_log_file_service.py +0 -0
  249. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_module_type_service.py +0 -0
  250. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_protocol.py +0 -0
  251. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_server_service.py +0 -0
  252. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_telegram_input_service.py +0 -0
  253. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_telegram_protocol.py +0 -0
  254. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_telegram_service.py +0 -0
  255. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_version_service.py +0 -0
  256. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_xp20_action_table_serializer.py +0 -0
  257. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_xp24_action_service.py +0 -0
  258. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_xp33_action_table_serializer.py +0 -0
  259. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_services/test_xp_server_services.py +0 -0
  260. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_utils/__init__.py +0 -0
  261. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_utils/test_checksum.py +0 -0
  262. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_utils/test_event_helper.py +0 -0
  263. {conson_xp-1.9.0 → conson_xp-1.10.0}/tests/unit/test_utils/test_serialization.py +0 -0
  264. {conson_xp-1.9.0 → conson_xp-1.10.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.9.0
3
+ Version: 1.10.0
4
4
  Summary: XP Protocol Communication Tools
5
5
  Author-Email: ldvchosal <ldvchosal@github.com>
6
6
  License: MIT License
@@ -276,6 +276,9 @@ xp conbus
276
276
 
277
277
  xp conbus actiontable
278
278
  xp conbus actiontable download
279
+ xp conbus actiontable list
280
+ xp conbus actiontable show
281
+ xp conbus actiontable upload
279
282
 
280
283
 
281
284
  xp conbus autoreport
@@ -225,6 +225,9 @@ xp conbus
225
225
 
226
226
  xp conbus actiontable
227
227
  xp conbus actiontable download
228
+ xp conbus actiontable list
229
+ xp conbus actiontable show
230
+ xp conbus actiontable upload
228
231
 
229
232
 
230
233
  xp conbus autoreport
@@ -20,7 +20,7 @@ dependencies = [
20
20
  ]
21
21
  requires-python = ">=3.11"
22
22
  readme = "README.md"
23
- version = "1.9.0"
23
+ version = "1.10.0"
24
24
 
25
25
  [project.license]
26
26
  file = "LICENSE"
@@ -3,7 +3,7 @@
3
3
  conson-xp package.
4
4
  """
5
5
 
6
- __version__ = "1.9.0"
6
+ __version__ = "1.10.0"
7
7
  __manufacturer__ = "salchichon"
8
8
  __model__ = "xp.cli"
9
9
  __serial__ = "2025.09.23.000"
@@ -0,0 +1,233 @@
1
+ """ActionTable CLI commands."""
2
+
3
+ import json
4
+ from contextlib import suppress
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import click
9
+ from click import Context
10
+
11
+ from xp.cli.commands.conbus.conbus import conbus_actiontable
12
+ from xp.cli.utils.decorators import (
13
+ connection_command,
14
+ )
15
+ from xp.cli.utils.serial_number_type import SERIAL
16
+ from xp.models.actiontable.actiontable import ActionTable
17
+ from xp.models.homekit.homekit_conson_config import (
18
+ ConsonModuleConfig,
19
+ ConsonModuleListConfig,
20
+ )
21
+ from xp.services.conbus.actiontable.actiontable_download_service import (
22
+ ActionTableService,
23
+ )
24
+ from xp.services.conbus.actiontable.actiontable_list_service import (
25
+ ActionTableListService,
26
+ )
27
+ from xp.services.conbus.actiontable.actiontable_show_service import (
28
+ ActionTableShowService,
29
+ )
30
+ from xp.services.conbus.actiontable.actiontable_upload_service import (
31
+ ActionTableUploadService,
32
+ )
33
+
34
+
35
+ class ActionTableError(Exception):
36
+ """Raised when ActionTable operations fail."""
37
+
38
+ pass
39
+
40
+
41
+ @conbus_actiontable.command("download", short_help="Download ActionTable")
42
+ @click.argument("serial_number", type=SERIAL)
43
+ @click.pass_context
44
+ @connection_command()
45
+ def conbus_download_actiontable(ctx: Context, serial_number: str) -> None:
46
+ """Download action table from XP module.
47
+
48
+ Args:
49
+ ctx: Click context object.
50
+ serial_number: 10-digit module serial number.
51
+ """
52
+ service: ActionTableService = (
53
+ ctx.obj.get("container").get_container().resolve(ActionTableService)
54
+ )
55
+
56
+ def progress_callback(progress: str) -> None:
57
+ """Handle progress updates during action table download.
58
+
59
+ Args:
60
+ progress: Progress message string.
61
+ """
62
+ click.echo(progress)
63
+
64
+ def on_finish(
65
+ _actiontable: ActionTable,
66
+ actiontable_dict: dict[str, Any],
67
+ actiontable_short: list[str],
68
+ ) -> None:
69
+ """Handle successful completion of action table download.
70
+
71
+ Args:
72
+ _actiontable: Downloaded action table object.
73
+ actiontable_dict: Dictionary representation of action table.
74
+ actiontable_short: List of textual format strings.
75
+ """
76
+ output = {
77
+ "serial_number": serial_number,
78
+ "actiontable_short": actiontable_short,
79
+ "actiontable": actiontable_dict,
80
+ }
81
+ click.echo(json.dumps(output, indent=2, default=str))
82
+
83
+ def error_callback(error: str) -> None:
84
+ """Handle errors during action table download.
85
+
86
+ Args:
87
+ error: Error message string.
88
+ """
89
+ click.echo(error)
90
+
91
+ with service:
92
+ service.start(
93
+ serial_number=serial_number,
94
+ progress_callback=progress_callback,
95
+ finish_callback=on_finish,
96
+ error_callback=error_callback,
97
+ )
98
+
99
+
100
+ @conbus_actiontable.command("upload", short_help="Upload ActionTable")
101
+ @click.argument("serial_number", type=SERIAL)
102
+ @click.pass_context
103
+ @connection_command()
104
+ def conbus_upload_actiontable(ctx: Context, serial_number: str) -> None:
105
+ """Upload action table from conson.yml to XP module.
106
+
107
+ Args:
108
+ ctx: Click context object.
109
+ serial_number: 10-digit module serial number.
110
+ """
111
+ service: ActionTableUploadService = (
112
+ ctx.obj.get("container").get_container().resolve(ActionTableUploadService)
113
+ )
114
+
115
+ click.echo(f"Uploading action table to {serial_number}...")
116
+
117
+ # Track number of entries for success message
118
+ entries_count = 0
119
+
120
+ def progress_callback(progress: str) -> None:
121
+ """Handle progress updates during action table upload.
122
+
123
+ Args:
124
+ progress: Progress message string.
125
+ """
126
+ click.echo(progress, nl=False)
127
+
128
+ def success_callback() -> None:
129
+ """Handle successful completion of action table upload."""
130
+ click.echo("\nAction table uploaded successfully")
131
+ if entries_count > 0:
132
+ click.echo(f"{entries_count} entries written")
133
+
134
+ def error_callback(error: str) -> None:
135
+ """Handle errors during action table upload.
136
+
137
+ Args:
138
+ error: Error message string.
139
+
140
+ Raises:
141
+ ActionTableError: Always raised with upload failure message.
142
+ """
143
+ raise ActionTableError(f"Upload failed: {error}")
144
+
145
+ with service:
146
+ # Load config to get entry count for success message
147
+ config_path = Path.cwd() / "conson.yml"
148
+ if config_path.exists():
149
+ with suppress(Exception):
150
+ config = ConsonModuleListConfig.from_yaml(str(config_path))
151
+ module = config.find_module(serial_number)
152
+ if module and module.action_table:
153
+ entries_count = len(module.action_table)
154
+
155
+ service.start(
156
+ serial_number=serial_number,
157
+ progress_callback=progress_callback,
158
+ success_callback=success_callback,
159
+ error_callback=error_callback,
160
+ )
161
+
162
+
163
+ @conbus_actiontable.command("list", short_help="List modules with ActionTable")
164
+ @click.pass_context
165
+ def conbus_list_actiontable(ctx: Context) -> None:
166
+ """List all modules with action table configurations from conson.yml.
167
+
168
+ Args:
169
+ ctx: Click context object.
170
+ """
171
+ service: ActionTableListService = (
172
+ ctx.obj.get("container").get_container().resolve(ActionTableListService)
173
+ )
174
+
175
+ def on_finish(module_list: dict) -> None:
176
+ """Handle successful completion of action table list.
177
+
178
+ Args:
179
+ module_list: Dictionary containing modules and total count.
180
+ """
181
+ click.echo(json.dumps(module_list, indent=2, default=str))
182
+
183
+ def error_callback(error: str) -> None:
184
+ """Handle errors during action table list.
185
+
186
+ Args:
187
+ error: Error message string.
188
+ """
189
+ click.echo(error)
190
+
191
+ with service:
192
+ service.start(
193
+ finish_callback=on_finish,
194
+ error_callback=error_callback,
195
+ )
196
+
197
+
198
+ @conbus_actiontable.command("show", short_help="Show ActionTable configuration")
199
+ @click.argument("serial_number", type=SERIAL)
200
+ @click.pass_context
201
+ def conbus_show_actiontable(ctx: Context, serial_number: str) -> None:
202
+ """Show action table configuration for a specific module from conson.yml.
203
+
204
+ Args:
205
+ ctx: Click context object.
206
+ serial_number: 10-digit module serial number.
207
+ """
208
+ service: ActionTableShowService = (
209
+ ctx.obj.get("container").get_container().resolve(ActionTableShowService)
210
+ )
211
+
212
+ def on_finish(module: ConsonModuleConfig) -> None:
213
+ """Handle successful completion of action table show.
214
+
215
+ Args:
216
+ module: Dictionary containing module configuration.
217
+ """
218
+ click.echo(json.dumps(module.model_dump(), indent=2, default=str))
219
+
220
+ def error_callback(error: str) -> None:
221
+ """Handle errors during action table show.
222
+
223
+ Args:
224
+ error: Error message string.
225
+ """
226
+ click.echo(error)
227
+
228
+ with service:
229
+ service.start(
230
+ serial_number=serial_number,
231
+ finish_callback=on_finish,
232
+ error_callback=error_callback,
233
+ )
@@ -27,7 +27,7 @@ class ActionTableEntry:
27
27
  link_number: int = 0
28
28
  module_input: int = 0
29
29
  module_output: int = 1
30
- command: InputActionType = InputActionType.TURNOFF
30
+ command: InputActionType = InputActionType.OFF
31
31
  parameter: TimeParam = TimeParam.NONE
32
32
  inverted: bool = False
33
33
 
@@ -23,7 +23,7 @@ class InputAction:
23
23
  class Xp24MsActionTable:
24
24
  """XP24 Action Table for managing input actions and settings.
25
25
 
26
- Each input has an action type (TOGGLE, TURNON, LEVELSET, etc.)
26
+ Each input has an action type (TOGGLE, ON, LEVELSET, etc.)
27
27
  with an optional parameter string.
28
28
 
29
29
  Attributes:
@@ -8,8 +8,8 @@ class InputActionType(Enum):
8
8
 
9
9
  Attributes:
10
10
  VOID: No action.
11
- TURNON: Turn on action.
12
- TURNOFF: Turn off action.
11
+ ON: Turn on action.
12
+ OFF: Turn off action.
13
13
  TOGGLE: Toggle action.
14
14
  BLOCK: Block action.
15
15
  AUXRELAY: Auxiliary relay action.
@@ -39,8 +39,8 @@ class InputActionType(Enum):
39
39
  """
40
40
 
41
41
  VOID = 0
42
- TURNON = 1
43
- TURNOFF = 2
42
+ ON = 1
43
+ OFF = 2
44
44
  TOGGLE = 3
45
45
  BLOCK = 4
46
46
  AUXRELAY = 5
@@ -1,5 +1,7 @@
1
1
  """Serializer for ActionTable telegram encoding/decoding."""
2
2
 
3
+ import re
4
+
3
5
  from xp.models import ModuleTypeCode
4
6
  from xp.models.actiontable.actiontable import ActionTable, ActionTableEntry
5
7
  from xp.models.telegram.input_action_type import InputActionType
@@ -18,7 +20,13 @@ from xp.utils.serialization import (
18
20
 
19
21
 
20
22
  class ActionTableSerializer:
21
- """Handles serialization/deserialization of ActionTable to/from telegrams."""
23
+ """Handles serialization/deserialization of ActionTable to/from telegrams.
24
+
25
+ Attributes:
26
+ MAX_ENTRIES: Maximum number of entries in an ActionTable (96).
27
+ """
28
+
29
+ MAX_ENTRIES = 96 # ActionTable must always contain exactly 96 entries
22
30
 
23
31
  @staticmethod
24
32
  def from_data(data: bytes) -> ActionTable:
@@ -57,12 +65,12 @@ class ActionTableSerializer:
57
65
  try:
58
66
  module_type = ModuleTypeCode(module_type_raw)
59
67
  except ValueError:
60
- module_type = ModuleTypeCode.CP20 # Default fallback
68
+ module_type = ModuleTypeCode.NOMOD # Default fallback
61
69
 
62
70
  try:
63
71
  command = InputActionType(command_raw)
64
72
  except ValueError:
65
- command = InputActionType.TURNOFF # Default fallback
73
+ command = InputActionType.OFF # Default fallback
66
74
 
67
75
  try:
68
76
  parameter = TimeParam(parameter_raw)
@@ -91,7 +99,7 @@ class ActionTableSerializer:
91
99
  action_table: ActionTable to serialize
92
100
 
93
101
  Returns:
94
- Raw byte data for telegram
102
+ Raw byte data for telegram (always 480 bytes for 96 entries)
95
103
  """
96
104
  data = bytearray()
97
105
 
@@ -112,6 +120,14 @@ class ActionTableSerializer:
112
120
  [type_byte, link_byte, input_byte, output_command_byte, parameter_byte]
113
121
  )
114
122
 
123
+ # Pad to 96 entries with default NOMOD entries (00 00 00 00 00)
124
+ current_entries = len(action_table.entries)
125
+ if current_entries < ActionTableSerializer.MAX_ENTRIES:
126
+ # Default entry: NOMOD 0 0 > 0 OFF (all zeros)
127
+ padding_bytes = [0x00, 0x00, 0x00, 0x00, 0x00]
128
+ for _ in range(ActionTableSerializer.MAX_ENTRIES - current_entries):
129
+ data.extend(padding_bytes)
130
+
115
131
  return bytes(data)
116
132
 
117
133
  @staticmethod
@@ -176,3 +192,82 @@ class ActionTableSerializer:
176
192
  lines.append(line)
177
193
 
178
194
  return lines
195
+
196
+ @staticmethod
197
+ def parse_action_string(action_str: str) -> ActionTableEntry:
198
+ """Parse action table entry from string format.
199
+
200
+ Args:
201
+ action_str: String in format "CP20 0 0 > 1 OFF" or "CP20 0 1 > 1 ~ON"
202
+
203
+ Returns:
204
+ Parsed ActionTableEntry
205
+
206
+ Raises:
207
+ ValueError: If string format is invalid
208
+ """
209
+ # Remove trailing semicolon if present
210
+ action_str = action_str.strip().rstrip(";")
211
+
212
+ # Pattern: <Type> <Link> <Input> > <Output> <Command> [Parameter]
213
+ pattern = r"^(\w+)\s+(\d+)\s+(\d+)\s+>\s+(\d+)\s+(~?)(\w+)(?:\s+(\d+))?$"
214
+ match = re.match(pattern, action_str)
215
+
216
+ if not match:
217
+ raise ValueError(f"Invalid action table format: {action_str}")
218
+
219
+ (
220
+ module_type_str,
221
+ link_str,
222
+ input_str,
223
+ output_str,
224
+ inverted_str,
225
+ command_str,
226
+ parameter_str,
227
+ ) = match.groups()
228
+
229
+ # Parse module type
230
+ try:
231
+ module_type = ModuleTypeCode[module_type_str]
232
+ except KeyError:
233
+ raise ValueError(f"Invalid module type: {module_type_str}")
234
+
235
+ # Parse command
236
+ try:
237
+ command = InputActionType[command_str]
238
+ except KeyError:
239
+ raise ValueError(f"Invalid command: {command_str}")
240
+
241
+ # Parse parameter (default to NONE)
242
+ parameter = TimeParam.NONE
243
+ if parameter_str:
244
+ try:
245
+ parameter = TimeParam(int(parameter_str))
246
+ except ValueError:
247
+ raise ValueError(f"Invalid parameter: {parameter_str}")
248
+
249
+ return ActionTableEntry(
250
+ module_type=module_type,
251
+ link_number=int(link_str),
252
+ module_input=int(input_str),
253
+ module_output=int(output_str),
254
+ command=command,
255
+ parameter=parameter,
256
+ inverted=bool(inverted_str),
257
+ )
258
+
259
+ @staticmethod
260
+ def parse_action_table(action_strings: list[str]) -> ActionTable:
261
+ """Parse action table from list of string entries.
262
+
263
+ Args:
264
+ action_strings: List of action strings from conson.yml
265
+
266
+ Returns:
267
+ Parsed ActionTable
268
+ """
269
+ entries = [
270
+ ActionTableSerializer.parse_action_string(action_str)
271
+ for action_str in action_strings
272
+ ]
273
+ return ActionTable(entries=entries)
@@ -17,11 +17,10 @@ from xp.services.telegram.telegram_service import TelegramService
17
17
 
18
18
 
19
19
  class ActionTableService(ConbusProtocol):
20
- """
21
- TCP client service for sending telegrams to Conbus servers.
20
+ """TCP client service for downloading action tables from Conbus modules.
22
21
 
23
22
  Manages TCP socket connections, handles telegram generation and transmission,
24
- and processes server responses.
23
+ and processes server responses for action table downloads.
25
24
  """
26
25
 
27
26
  def __init__(
@@ -31,7 +30,7 @@ class ActionTableService(ConbusProtocol):
31
30
  actiontable_serializer: ActionTableSerializer,
32
31
  telegram_service: TelegramService,
33
32
  ) -> None:
34
- """Initialize the Conbus client send service.
33
+ """Initialize the action table download service.
35
34
 
36
35
  Args:
37
36
  cli_config: Conbus client configuration.
@@ -0,0 +1,91 @@
1
+ """Service for listing modules with action table configurations from conson.yml."""
2
+
3
+ import logging
4
+ from pathlib import Path
5
+ from typing import Any, Callable, Optional
6
+
7
+
8
+ class ActionTableListService:
9
+ """Service for listing modules with action table configurations.
10
+
11
+ Reads conson.yml and returns a list of all modules that have action table
12
+ configurations defined.
13
+ """
14
+
15
+ def __init__(self) -> None:
16
+ """Initialize the action table list service."""
17
+ self.logger = logging.getLogger(__name__)
18
+ self.finish_callback: Optional[Callable[[dict[str, Any]], None]] = None
19
+ self.error_callback: Optional[Callable[[str], None]] = None
20
+
21
+ def __enter__(self) -> "ActionTableListService":
22
+ """Context manager entry.
23
+
24
+ Returns:
25
+ Self for context manager use.
26
+ """
27
+ return self
28
+
29
+ def __exit__(self, _exc_type: Any, _exc_val: Any, _exc_tb: Any) -> None:
30
+ """Context manager exit."""
31
+ pass
32
+
33
+ def start(
34
+ self,
35
+ finish_callback: Callable[[dict[str, Any]], None],
36
+ error_callback: Callable[[str], None],
37
+ config_path: Optional[Path] = None,
38
+ ) -> None:
39
+ """List all modules with action table configurations.
40
+
41
+ Args:
42
+ finish_callback: Callback to invoke with the module list.
43
+ error_callback: Callback to invoke on error.
44
+ config_path: Optional path to conson.yml. Defaults to current directory.
45
+ """
46
+ self.finish_callback = finish_callback
47
+ self.error_callback = error_callback
48
+
49
+ # Default to current directory if not specified
50
+ if config_path is None:
51
+ config_path = Path.cwd() / "conson.yml"
52
+
53
+ # Check if config file exists
54
+ if not config_path.exists():
55
+ self._handle_error("Error: conson.yml not found in current directory")
56
+ return
57
+
58
+ # Load configuration
59
+ try:
60
+ from xp.models.homekit.homekit_conson_config import ConsonModuleListConfig
61
+
62
+ config = ConsonModuleListConfig.from_yaml(str(config_path))
63
+ except Exception as e:
64
+ self.logger.error(f"Failed to load conson.yml: {e}")
65
+ self._handle_error(f"Error: Failed to load conson.yml: {e}")
66
+ return
67
+
68
+ # Filter modules that have action_table configured
69
+ modules_with_actiontable = [
70
+ {
71
+ "serial_number": module.serial_number,
72
+ "module_type": module.module_type,
73
+ }
74
+ for module in config.root
75
+ ]
76
+
77
+ # Prepare result
78
+ result = {"modules": modules_with_actiontable}
79
+
80
+ # Invoke callback
81
+ if self.finish_callback is not None:
82
+ self.finish_callback(result)
83
+
84
+ def _handle_error(self, message: str) -> None:
85
+ """Handle error and invoke error callback.
86
+
87
+ Args:
88
+ message: Error message.
89
+ """
90
+ if self.error_callback is not None:
91
+ self.error_callback(message)
@@ -0,0 +1,89 @@
1
+ """Service for showing action table configuration for a specific module."""
2
+
3
+ import logging
4
+ from pathlib import Path
5
+ from typing import Any, Callable, Optional
6
+
7
+ from xp.models.homekit.homekit_conson_config import ConsonModuleConfig
8
+
9
+
10
+ class ActionTableShowService:
11
+ """Service for showing action table configuration for a specific module.
12
+
13
+ Reads conson.yml and returns the action table configuration for the specified
14
+ module serial number.
15
+ """
16
+
17
+ def __init__(self) -> None:
18
+ """Initialize the action table show service."""
19
+ self.logger = logging.getLogger(__name__)
20
+ self.finish_callback: Optional[Callable[[ConsonModuleConfig], None]] = None
21
+ self.error_callback: Optional[Callable[[str], None]] = None
22
+
23
+ def __enter__(self) -> "ActionTableShowService":
24
+ """Context manager entry.
25
+
26
+ Returns:
27
+ Self for context manager use.
28
+ """
29
+ return self
30
+
31
+ def __exit__(self, _exc_type: Any, _exc_val: Any, _exc_tb: Any) -> None:
32
+ """Context manager exit."""
33
+ pass
34
+
35
+ def start(
36
+ self,
37
+ serial_number: str,
38
+ finish_callback: Callable[[ConsonModuleConfig], None],
39
+ error_callback: Callable[[str], None],
40
+ config_path: Optional[Path] = None,
41
+ ) -> None:
42
+ """Show action table configuration for a specific module.
43
+
44
+ Args:
45
+ serial_number: Module serial number.
46
+ finish_callback: Callback to invoke with the module configuration.
47
+ error_callback: Callback to invoke on error.
48
+ config_path: Optional path to conson.yml. Defaults to current directory.
49
+ """
50
+ self.finish_callback = finish_callback
51
+ self.error_callback = error_callback
52
+
53
+ # Default to current directory if not specified
54
+ if config_path is None:
55
+ config_path = Path.cwd() / "conson.yml"
56
+
57
+ # Check if config file exists
58
+ if not config_path.exists():
59
+ self._handle_error("Error: conson.yml not found in current directory")
60
+ return
61
+
62
+ # Load configuration
63
+ try:
64
+ from xp.models.homekit.homekit_conson_config import ConsonModuleListConfig
65
+
66
+ config = ConsonModuleListConfig.from_yaml(str(config_path))
67
+ except Exception as e:
68
+ self.logger.error(f"Failed to load conson.yml: {e}")
69
+ self._handle_error(f"Error: Failed to load conson.yml: {e}")
70
+ return
71
+
72
+ # Find module
73
+ module = config.find_module(serial_number)
74
+ if not module:
75
+ self._handle_error(f"Error: Module {serial_number} not found in conson.yml")
76
+ return
77
+
78
+ # Invoke callback
79
+ if self.finish_callback is not None:
80
+ self.finish_callback(module)
81
+
82
+ def _handle_error(self, message: str) -> None:
83
+ """Handle error and invoke error callback.
84
+
85
+ Args:
86
+ message: Error message.
87
+ """
88
+ if self.error_callback is not None:
89
+ self.error_callback(message)