conson-xp 1.7.0__tar.gz → 1.9.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 (259) hide show
  1. {conson_xp-1.7.0 → conson_xp-1.9.0}/PKG-INFO +1 -1
  2. {conson_xp-1.7.0 → conson_xp-1.9.0}/pyproject.toml +1 -1
  3. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/__init__.py +1 -1
  4. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_actiontable_commands.py +11 -4
  5. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/homekit/homekit_conson_config.py +18 -0
  6. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/input_action_type.py +2 -2
  7. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/system_function.py +49 -19
  8. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/actiontable/actiontable_serializer.py +15 -6
  9. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/actiontable/actiontable_service.py +16 -6
  10. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/actiontable/msactiontable_service.py +3 -1
  11. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_actiontable_integration.py +9 -5
  12. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_xp24_action_table_integration.py +2 -2
  13. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_cli/test_conbus_actiontable_commands.py +159 -1
  14. conson_xp-1.9.0/tests/unit/test_services/test_actiontable_serializer.py +280 -0
  15. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_actiontable_service.py +12 -2
  16. {conson_xp-1.7.0 → conson_xp-1.9.0}/LICENSE +0 -0
  17. {conson_xp-1.7.0 → conson_xp-1.9.0}/README.md +0 -0
  18. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/__init__.py +0 -0
  19. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/__main__.py +0 -0
  20. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/__init__.py +0 -0
  21. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/__init__.py +0 -0
  22. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus.py +0 -0
  23. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_autoreport_commands.py +0 -0
  24. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_blink_commands.py +0 -0
  25. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_config_commands.py +0 -0
  26. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_custom_commands.py +0 -0
  27. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_datapoint_commands.py +0 -0
  28. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_discover_commands.py +0 -0
  29. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_lightlevel_commands.py +0 -0
  30. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_linknumber_commands.py +0 -0
  31. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_msactiontable_commands.py +0 -0
  32. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_output_commands.py +0 -0
  33. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_raw_commands.py +0 -0
  34. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_receive_commands.py +0 -0
  35. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/conbus/conbus_scan_commands.py +0 -0
  36. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/file_commands.py +0 -0
  37. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/homekit/__init__.py +0 -0
  38. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/homekit/homekit.py +0 -0
  39. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/homekit/homekit_start_commands.py +0 -0
  40. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/module_commands.py +0 -0
  41. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/reverse_proxy_commands.py +0 -0
  42. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/server/__init__.py +0 -0
  43. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/server/server_commands.py +0 -0
  44. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/telegram/__init__.py +0 -0
  45. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/telegram/telegram.py +0 -0
  46. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/telegram/telegram_blink_commands.py +0 -0
  47. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/telegram/telegram_checksum_commands.py +0 -0
  48. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/telegram/telegram_discover_commands.py +0 -0
  49. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/telegram/telegram_linknumber_commands.py +0 -0
  50. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/telegram/telegram_parse_commands.py +0 -0
  51. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/commands/telegram/telegram_version_commands.py +0 -0
  52. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/main.py +0 -0
  53. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/utils/__init__.py +0 -0
  54. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/utils/click_tree.py +0 -0
  55. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/utils/datapoint_type_choice.py +0 -0
  56. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/utils/decorators.py +0 -0
  57. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/utils/error_handlers.py +0 -0
  58. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/utils/formatters.py +0 -0
  59. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/utils/serial_number_type.py +0 -0
  60. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/utils/system_function_choice.py +0 -0
  61. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/cli/utils/xp_module_type.py +0 -0
  62. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/connection/__init__.py +0 -0
  63. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/connection/exceptions.py +0 -0
  64. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/__init__.py +0 -0
  65. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/actiontable/__init__.py +0 -0
  66. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/actiontable/actiontable.py +0 -0
  67. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/actiontable/msactiontable_xp20.py +0 -0
  68. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/actiontable/msactiontable_xp24.py +0 -0
  69. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/actiontable/msactiontable_xp33.py +0 -0
  70. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/__init__.py +0 -0
  71. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus.py +0 -0
  72. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_autoreport.py +0 -0
  73. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_blink.py +0 -0
  74. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_client_config.py +0 -0
  75. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_connection_status.py +0 -0
  76. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_custom.py +0 -0
  77. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_datapoint.py +0 -0
  78. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_discover.py +0 -0
  79. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_lightlevel.py +0 -0
  80. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_linknumber.py +0 -0
  81. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_output.py +0 -0
  82. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_raw.py +0 -0
  83. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_receive.py +0 -0
  84. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/conbus/conbus_writeconfig.py +0 -0
  85. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/homekit/__init__.py +0 -0
  86. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/homekit/homekit_accessory.py +0 -0
  87. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/homekit/homekit_config.py +0 -0
  88. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/log_entry.py +0 -0
  89. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/protocol/__init__.py +0 -0
  90. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/protocol/conbus_protocol.py +0 -0
  91. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/response.py +0 -0
  92. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/__init__.py +0 -0
  93. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/action_type.py +0 -0
  94. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/datapoint_type.py +0 -0
  95. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/event_telegram.py +0 -0
  96. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/event_type.py +0 -0
  97. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/input_type.py +0 -0
  98. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/module_type.py +0 -0
  99. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/module_type_code.py +0 -0
  100. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/output_telegram.py +0 -0
  101. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/reply_telegram.py +0 -0
  102. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/system_telegram.py +0 -0
  103. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/telegram.py +0 -0
  104. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/telegram_type.py +0 -0
  105. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/telegram/timeparam_type.py +0 -0
  106. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/models/write_config_type.py +0 -0
  107. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/__init__.py +0 -0
  108. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/actiontable/__init__.py +0 -0
  109. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/actiontable/msactiontable_serializer.py +0 -0
  110. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/actiontable/msactiontable_xp20_serializer.py +0 -0
  111. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/actiontable/msactiontable_xp24_serializer.py +0 -0
  112. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/actiontable/msactiontable_xp33_serializer.py +0 -0
  113. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/__init__.py +0 -0
  114. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/actiontable/__init__.py +0 -0
  115. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/conbus_blink_all_service.py +0 -0
  116. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/conbus_blink_service.py +0 -0
  117. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/conbus_custom_service.py +0 -0
  118. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/conbus_datapoint_queryall_service.py +0 -0
  119. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/conbus_datapoint_service.py +0 -0
  120. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/conbus_discover_service.py +0 -0
  121. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/conbus_output_service.py +0 -0
  122. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/conbus_raw_service.py +0 -0
  123. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/conbus_receive_service.py +0 -0
  124. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/conbus_scan_service.py +0 -0
  125. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/conbus/write_config_service.py +0 -0
  126. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/__init__.py +0 -0
  127. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_cache_service.py +0 -0
  128. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_conbus_service.py +0 -0
  129. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_config_validator.py +0 -0
  130. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_conson_validator.py +0 -0
  131. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_dimminglight.py +0 -0
  132. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_dimminglight_service.py +0 -0
  133. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_hap_service.py +0 -0
  134. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_lightbulb.py +0 -0
  135. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_lightbulb_service.py +0 -0
  136. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_module_service.py +0 -0
  137. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_outlet.py +0 -0
  138. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_outlet_service.py +0 -0
  139. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/homekit/homekit_service.py +0 -0
  140. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/log_file_service.py +0 -0
  141. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/module_type_service.py +0 -0
  142. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/protocol/__init__.py +0 -0
  143. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/protocol/conbus_protocol.py +0 -0
  144. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/protocol/protocol_factory.py +0 -0
  145. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/protocol/telegram_protocol.py +0 -0
  146. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/reverse_proxy_service.py +0 -0
  147. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/server/__init__.py +0 -0
  148. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/server/base_server_service.py +0 -0
  149. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/server/cp20_server_service.py +0 -0
  150. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/server/device_service_factory.py +0 -0
  151. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/server/server_service.py +0 -0
  152. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/server/xp130_server_service.py +0 -0
  153. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/server/xp20_server_service.py +0 -0
  154. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/server/xp230_server_service.py +0 -0
  155. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/server/xp24_server_service.py +0 -0
  156. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/server/xp33_server_service.py +0 -0
  157. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/telegram/__init__.py +0 -0
  158. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/telegram/telegram_blink_service.py +0 -0
  159. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/telegram/telegram_checksum_service.py +0 -0
  160. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/telegram/telegram_datapoint_service.py +0 -0
  161. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/telegram/telegram_discover_service.py +0 -0
  162. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/telegram/telegram_link_number_service.py +0 -0
  163. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/telegram/telegram_output_service.py +0 -0
  164. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/telegram/telegram_service.py +0 -0
  165. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/services/telegram/telegram_version_service.py +0 -0
  166. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/utils/__init__.py +0 -0
  167. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/utils/checksum.py +0 -0
  168. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/utils/dependencies.py +0 -0
  169. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/utils/event_helper.py +0 -0
  170. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/utils/serialization.py +0 -0
  171. {conson_xp-1.7.0 → conson_xp-1.9.0}/src/xp/utils/time_utils.py +0 -0
  172. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/.coverage +0 -0
  173. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/__init__.py +0 -0
  174. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/conftest.py +0 -0
  175. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/.coverage +0 -0
  176. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/__init__.py +0 -0
  177. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/telegram_test_data.py +0 -0
  178. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_api/.coverage +0 -0
  179. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_api/__init__.py +0 -0
  180. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_blink_integration.py +0 -0
  181. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_checksum_integration.py +0 -0
  182. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_conbus_blink_integration.py +0 -0
  183. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_conbus_datapoint_integration.py +0 -0
  184. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_conbus_raw_integration.py +0 -0
  185. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_conbus_receive_integration.py +0 -0
  186. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_discovery_integration.py +0 -0
  187. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_event_telegram_integration.py +0 -0
  188. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_homekit_config_integration.py +0 -0
  189. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_link_number_integration.py +0 -0
  190. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_module_integration.py +0 -0
  191. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_output_integration.py +0 -0
  192. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_reverse_proxy_integration.py +0 -0
  193. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_system_reply_telegram_integration.py +0 -0
  194. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_version_integration.py +0 -0
  195. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/integration/test_xp20_action_table_integration.py +0 -0
  196. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/__init__.py +0 -0
  197. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_api/__init__.py +0 -0
  198. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_cli/__init__.py +0 -0
  199. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_cli/test_click_tree.py +0 -0
  200. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_cli/test_conbus_blink_commands.py +0 -0
  201. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_cli/test_datapoint_type_choice.py +0 -0
  202. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_cli/test_decorators.py +0 -0
  203. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_cli/test_error_handlers.py +0 -0
  204. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_cli/test_formatters.py +0 -0
  205. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_cli/test_serial_number_type.py +0 -0
  206. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_cli/test_system_function_choice.py +0 -0
  207. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_connection/__init__.py +0 -0
  208. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_connection/test_connection_init.py +0 -0
  209. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_connection/test_exceptions.py +0 -0
  210. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_encoding/__init__.py +0 -0
  211. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_encoding/test_latin1_edge_cases.py +0 -0
  212. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/__init__.py +0 -0
  213. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_conbus.py +0 -0
  214. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_conbus_client_send.py +0 -0
  215. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_conbus_discover.py +0 -0
  216. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_conbus_linknumber.py +0 -0
  217. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_event_telegram.py +0 -0
  218. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_log_entry.py +0 -0
  219. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_module_type.py +0 -0
  220. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_reply_telegram.py +0 -0
  221. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_system_telegram.py +0 -0
  222. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_system_telegram_enhancements.py +0 -0
  223. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_version_telegram.py +0 -0
  224. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_write_config_type.py +0 -0
  225. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_xp20_action_table.py +0 -0
  226. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_xp24_action_table.py +0 -0
  227. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_models/test_xp24_action_telegram.py +0 -0
  228. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/__init__.py +0 -0
  229. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_base_server_service.py +0 -0
  230. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_blink_service.py +0 -0
  231. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_checksum_service.py +0 -0
  232. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_conbus_blink_service.py +0 -0
  233. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_conbus_raw_service.py +0 -0
  234. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_conbus_reverse_proxy_service.py +0 -0
  235. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_device_service_factory.py +0 -0
  236. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_discovery_service.py +0 -0
  237. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_homekit_cache_service.py +0 -0
  238. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_homekit_config_validator.py +0 -0
  239. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_homekit_conson_service.py +0 -0
  240. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_homekit_services.py +0 -0
  241. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_log_file_service.py +0 -0
  242. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_module_type_service.py +0 -0
  243. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_protocol.py +0 -0
  244. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_server_service.py +0 -0
  245. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_telegram_input_service.py +0 -0
  246. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_telegram_protocol.py +0 -0
  247. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_telegram_service.py +0 -0
  248. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_version_service.py +0 -0
  249. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_xp20_action_table_serializer.py +0 -0
  250. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_xp24_action_service.py +0 -0
  251. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_xp24_action_table_serializer.py +0 -0
  252. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_xp24_action_table_service.py +0 -0
  253. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_xp33_action_table_serializer.py +0 -0
  254. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_services/test_xp_server_services.py +0 -0
  255. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_utils/__init__.py +0 -0
  256. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_utils/test_checksum.py +0 -0
  257. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_utils/test_event_helper.py +0 -0
  258. {conson_xp-1.7.0 → conson_xp-1.9.0}/tests/unit/test_utils/test_serialization.py +0 -0
  259. {conson_xp-1.7.0 → conson_xp-1.9.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.7.0
3
+ Version: 1.9.0
4
4
  Summary: XP Protocol Communication Tools
5
5
  Author-Email: ldvchosal <ldvchosal@github.com>
6
6
  License: MIT License
@@ -20,7 +20,7 @@ dependencies = [
20
20
  ]
21
21
  requires-python = ">=3.11"
22
22
  readme = "README.md"
23
- version = "1.7.0"
23
+ version = "1.9.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.7.0"
6
+ __version__ = "1.9.0"
7
7
  __manufacturer__ = "salchichon"
8
8
  __model__ = "xp.cli"
9
9
  __serial__ = "2025.09.23.000"
@@ -1,7 +1,7 @@
1
1
  """ActionTable CLI commands."""
2
2
 
3
3
  import json
4
- from dataclasses import asdict
4
+ from typing import Any
5
5
 
6
6
  import click
7
7
  from click import Context
@@ -40,15 +40,22 @@ def conbus_download_actiontable(ctx: Context, serial_number: str) -> None:
40
40
  """
41
41
  click.echo(progress)
42
42
 
43
- def on_finish(actiontable: ActionTable) -> None:
43
+ def on_finish(
44
+ _actiontable: ActionTable,
45
+ actiontable_dict: dict[str, Any],
46
+ actiontable_short: list[str],
47
+ ) -> None:
44
48
  """Handle successful completion of action table download.
45
49
 
46
50
  Args:
47
- actiontable: Downloaded action table object.
51
+ _actiontable: Downloaded action table object.
52
+ actiontable_dict: Dictionary representation of action table.
53
+ actiontable_short: List of textual format strings.
48
54
  """
49
55
  output = {
50
56
  "serial_number": serial_number,
51
- "actiontable": asdict(actiontable),
57
+ "actiontable_short": actiontable_short,
58
+ "actiontable": actiontable_dict,
52
59
  }
53
60
  click.echo(json.dumps(output, indent=2, default=str))
54
61
 
@@ -22,6 +22,8 @@ class ConsonModuleConfig(BaseModel):
22
22
  conbus_port: Optional Conbus port number.
23
23
  sw_version: Optional software version.
24
24
  hw_version: Optional hardware version.
25
+ action_table: Optional action table configuration.
26
+ auto_report_status: Optional auto report status.
25
27
  """
26
28
 
27
29
  name: str
@@ -35,6 +37,8 @@ class ConsonModuleConfig(BaseModel):
35
37
  conbus_port: Optional[int] = None
36
38
  sw_version: Optional[str] = None
37
39
  hw_version: Optional[str] = None
40
+ action_table: Optional[List[str]] = None
41
+ auto_report_status: Optional[str] = None
38
42
 
39
43
 
40
44
  class ConsonModuleListConfig(BaseModel):
@@ -66,3 +70,17 @@ class ConsonModuleListConfig(BaseModel):
66
70
  with Path(file_path).open("r") as file:
67
71
  data = yaml.safe_load(file)
68
72
  return cls(root=data)
73
+
74
+ def find_module(self, serial_number: str) -> Optional[ConsonModuleConfig]:
75
+ """Find a module by serial number.
76
+
77
+ Args:
78
+ serial_number: Module serial number to search for.
79
+
80
+ Returns:
81
+ ConsonModuleConfig if found, None otherwise.
82
+ """
83
+ for module in self.root:
84
+ if module.serial_number == serial_number:
85
+ return module
86
+ return None
@@ -1,9 +1,9 @@
1
1
  """Input action types for XP24 module based on Feature-Action-Table.md."""
2
2
 
3
- from enum import IntEnum
3
+ from enum import Enum
4
4
 
5
5
 
6
- class InputActionType(IntEnum):
6
+ class InputActionType(Enum):
7
7
  """Input action types for XP24 module (based on Feature-Action-Table.md).
8
8
 
9
9
  Attributes:
@@ -15,35 +15,65 @@ class SystemFunction(str, Enum):
15
15
  WRITE_CONFIG: Write configuration.
16
16
  BLINK: Blink LED function.
17
17
  UNBLINK: Unblink LED function.
18
- DOWNLOAD_MSACTIONTABLE: Download module specific action table.
18
+ UPLOAD_FIRMWARE_START: Start upload firmware.
19
+ UPLOAD_FIRMWARE_STOP: Stop upload firmware.
20
+ UPLOAD_FIRMWARE: Upload firmware.
21
+ UPLOAD_ACTIONTABLE: Upload ActionTable to module.
19
22
  DOWNLOAD_ACTIONTABLE: Download ActionTable.
23
+ UPLOAD_MSACTIONTABLE: Upload module specific action table to module.
24
+ DOWNLOAD_MSACTIONTABLE: Download module specific action table.
25
+ TELEGRAM_WRITE_START: Start writing telegram.
26
+ TELEGRAM_READ_START: Start reading telegram.
20
27
  EOF: End of msactiontable response.
28
+ TELEGRAM: Module specific telegram response.
21
29
  MSACTIONTABLE: Module specific action table response.
22
30
  ACTIONTABLE: Module specific action table response.
23
31
  ACK: Acknowledge response.
24
32
  NAK: Not acknowledge response.
33
+ UPLOAD_TOP_FIRMWARE_START: Start upload firmware (TOP).
34
+ UPLOAD_TOP_FIRMWARE_STOP: Stop upload firmware (TOP).
35
+ UPLOAD_TOP_FIRMWARE: Upload firmware (TOP).
36
+ ROTATE_ENABLE: Enable rotate.
37
+ ROTATE_DISABLE: Disable rotate.
25
38
  UNKNOWN_26: Used after discover, unknown purpose.
26
39
  ACTION: Action function.
27
40
  """
28
41
 
29
- NONE = "00" # Undefined
30
- DISCOVERY = "01" # Discover function
31
- READ_DATAPOINT = "02" # Read datapoint
32
- READ_CONFIG = "03" # Read configuration
33
- WRITE_CONFIG = "04" # Write configuration
34
- BLINK = "05" # Blink LED function
35
- UNBLINK = "06" # Unblink LED function
36
- DOWNLOAD_MSACTIONTABLE = (
37
- "13" # Download the module specific action table (MsActionTable)
38
- )
39
- DOWNLOAD_ACTIONTABLE = "11D" # Download ActionTable
40
- EOF = "16" # End of msactiontable response
41
- MSACTIONTABLE = "17" # module specific action table (MsActionTable) response
42
- ACTIONTABLE = "17" # module specific action table (MsActionTable) response
43
- ACK = "18" # Acknowledge response
44
- NAK = "19" # Not acknowledge response
45
- UNKNOWN_26 = "26" # Used after discover, but don't know what it is
46
- ACTION = "27" # Action function
42
+ NONE = "00" # F00D Undefined
43
+ DISCOVERY = "01" # F01D Discover function
44
+ READ_DATAPOINT = "02" # F02D Read datapoint
45
+ READ_CONFIG = "03" # F03D Read configuration
46
+ WRITE_CONFIG = "04" # F04D Write configuration
47
+ BLINK = "05" # F05D Blink LED function
48
+ UNBLINK = "06" # F06D Unblink LED function
49
+
50
+ UPLOAD_FIRMWARE_START = "07" # F07D Start Upload firmware
51
+ UPLOAD_FIRMWARE_STOP = "08" # F08D Stop Upload firmware
52
+ UPLOAD_FIRMWARE = "09" # F09D Upload firmware
53
+
54
+ UPLOAD_ACTIONTABLE = "10" # F10D Upload ActionTable
55
+ DOWNLOAD_ACTIONTABLE = "11" # F11D Download ActionTable
56
+ UPLOAD_MSACTIONTABLE = "12" # F12D Upload MsActionTable to module
57
+ DOWNLOAD_MSACTIONTABLE = "13" # F13D Download MsActionTable
58
+
59
+ TELEGRAM_WRITE_START = "14" # F14D Start writing telegram
60
+ TELEGRAM_READ_START = "15" # F15D Start reading telegram
61
+ EOF = "16" # F16D End of msactiontable response
62
+ TELEGRAM = "17" # F17D module specific Telegram response
63
+ MSACTIONTABLE = "17" # F17D module specific ms action table (Telegram) response
64
+ ACTIONTABLE = "17" # F17D module specific action table (Telegram) response
65
+ ACK = "18" # F18D Acknowledge / continue response
66
+ NAK = "19" # F19D Not acknowledge response
67
+
68
+ UPLOAD_TOP_FIRMWARE_START = "20" # F20D Start Upload firmware (TOP)
69
+ UPLOAD_TOP_FIRMWARE_STOP = "21" # F21D Stop Upload firmware (TOP)
70
+ UPLOAD_TOP_FIRMWARE = "22" # F22D Upload firmware (TOP)
71
+
72
+ ROTATE_ENABLE = "23" # F23D Enable rotate
73
+ ROTATE_DISABLE = "24" # F24D Disable rotate
74
+
75
+ UNKNOWN_26 = "26" # F26D Used after discover, but don't know what it is
76
+ ACTION = "27" # F27D Action function
47
77
 
48
78
  def get_description(self) -> str:
49
79
  """Get the description of the SystemFunction.
@@ -141,29 +141,38 @@ class ActionTableSerializer:
141
141
  return ActionTableSerializer.from_data(data)
142
142
 
143
143
  @staticmethod
144
- def format_decoded_output(action_table: ActionTable) -> str:
144
+ def format_decoded_output(action_table: ActionTable) -> list[str]:
145
145
  """Format ActionTable as human-readable decoded output.
146
146
 
147
147
  Args:
148
148
  action_table: ActionTable to format
149
149
 
150
150
  Returns:
151
- Human-readable string representation
151
+ List of human-readable string representations
152
152
  """
153
153
  lines = []
154
154
  for entry in action_table.entries:
155
- # Format: CP20 0 0 > 1 OFF;
155
+ # Format: CP20 0 0 > 1 OFF [param];
156
156
  module_type = entry.module_type.name
157
157
  link = entry.link_number
158
158
  input_num = entry.module_input
159
159
  output = entry.module_output
160
160
  command = entry.command.name
161
161
 
162
- # Add prefix for special commands
162
+ # Add prefix for inverted commands
163
163
  if entry.inverted:
164
164
  command = f"~{command}"
165
165
 
166
- line = f"{module_type} {link} {input_num} > {output} {command};"
166
+ # Build base line
167
+ line = f"{module_type} {link} {input_num} > {output} {command}"
168
+
169
+ # Add parameter if present and non-zero
170
+ if entry.parameter is not None and entry.parameter.value != 0:
171
+ line += f" {entry.parameter.value}"
172
+
173
+ # Add semicolon terminator
174
+ line += ";"
175
+
167
176
  lines.append(line)
168
177
 
169
- return "\n".join(lines)
178
+ return lines
@@ -1,7 +1,8 @@
1
1
  """Service for downloading ActionTable via Conbus protocol."""
2
2
 
3
3
  import logging
4
- from typing import Callable, Optional
4
+ from dataclasses import asdict
5
+ from typing import Any, Callable, Dict, Optional
5
6
 
6
7
  from twisted.internet.posixbase import PosixReactorBase
7
8
 
@@ -44,14 +45,19 @@ class ActionTableService(ConbusProtocol):
44
45
  self.serial_number: str = ""
45
46
  self.progress_callback: Optional[Callable[[str], None]] = None
46
47
  self.error_callback: Optional[Callable[[str], None]] = None
47
- self.finish_callback: Optional[Callable[[ActionTable], None]] = None
48
+ self.finish_callback: Optional[
49
+ Callable[[ActionTable, Dict[str, Any], list[str]], None]
50
+ ] = None
51
+
48
52
  self.actiontable_data: list[str] = []
49
53
  # Set up logging
50
54
  self.logger = logging.getLogger(__name__)
51
55
 
52
56
  def connection_established(self) -> None:
53
57
  """Handle connection established event."""
54
- self.logger.debug("Connection established, sending discover telegram")
58
+ self.logger.debug(
59
+ "Connection established, sending download actiontable telegram"
60
+ )
55
61
  self.send_telegram(
56
62
  telegram_type=TelegramType.SYSTEM,
57
63
  serial_number=self.serial_number,
@@ -82,7 +88,9 @@ class ActionTableService(ConbusProtocol):
82
88
  self.logger.debug("Not a reply response")
83
89
  return
84
90
 
85
- reply_telegram = self.telegram_service.parse_reply_telegram(telegram_received)
91
+ reply_telegram = self.telegram_service.parse_reply_telegram(
92
+ telegram_received.frame
93
+ )
86
94
  if reply_telegram.system_function not in (
87
95
  SystemFunction.ACTIONTABLE,
88
96
  SystemFunction.EOF,
@@ -109,8 +117,10 @@ class ActionTableService(ConbusProtocol):
109
117
  all_data = "".join(self.actiontable_data)
110
118
  # Deserialize from received data
111
119
  actiontable = self.serializer.from_encoded_string(all_data)
120
+ actiontable_dict = asdict(actiontable)
121
+ actiontable_short = self.serializer.format_decoded_output(actiontable)
112
122
  if self.finish_callback:
113
- self.finish_callback(actiontable)
123
+ self.finish_callback(actiontable, actiontable_dict, actiontable_short)
114
124
 
115
125
  def failed(self, message: str) -> None:
116
126
  """Handle failed connection event.
@@ -127,7 +137,7 @@ class ActionTableService(ConbusProtocol):
127
137
  serial_number: str,
128
138
  progress_callback: Callable[[str], None],
129
139
  error_callback: Callable[[str], None],
130
- finish_callback: Callable[[ActionTable], None],
140
+ finish_callback: Callable[[ActionTable, Dict[str, Any], list[str]], None],
131
141
  timeout_seconds: Optional[float] = None,
132
142
  ) -> None:
133
143
  """Run reactor in dedicated thread with its own event loop.
@@ -84,7 +84,9 @@ class MsActionTableService(ConbusProtocol):
84
84
 
85
85
  def connection_established(self) -> None:
86
86
  """Handle connection established event."""
87
- self.logger.debug("Connection established, sending discover telegram")
87
+ self.logger.debug(
88
+ "Connection established, sending download msactiontable telegram"
89
+ )
88
90
  self.send_telegram(
89
91
  telegram_type=TelegramType.SYSTEM,
90
92
  serial_number=self.serial_number,
@@ -1,5 +1,6 @@
1
1
  """Integration tests for ActionTable functionality."""
2
2
 
3
+ from dataclasses import asdict
3
4
  from unittest.mock import Mock
4
5
 
5
6
  import pytest
@@ -12,9 +13,7 @@ from xp.models import ModuleTypeCode
12
13
  from xp.models.actiontable.actiontable import ActionTable, ActionTableEntry
13
14
  from xp.models.telegram.input_action_type import InputActionType
14
15
  from xp.models.telegram.timeparam_type import TimeParam
15
- from xp.services.conbus.actiontable.actiontable_service import (
16
- ActionTableSerializer,
17
- )
16
+ from xp.services.actiontable.actiontable_serializer import ActionTableSerializer
18
17
 
19
18
 
20
19
  class TestActionTableIntegration:
@@ -89,7 +88,7 @@ class TestActionTableIntegration:
89
88
  # Test decoded output format
90
89
  decoded = serializer.format_decoded_output(sample_actiontable)
91
90
  expected_lines = ["CP20 0 0 > 1 TURNOFF;", "CP20 0 1 > 2 ~TURNON;"]
92
- assert decoded == "\n".join(expected_lines)
91
+ assert decoded == expected_lines
93
92
 
94
93
  # Test encoded output format
95
94
  encoded = serializer.to_encoded_string(sample_actiontable)
@@ -115,7 +114,12 @@ class TestActionTableIntegration:
115
114
  finish_callback: Callback when finished.
116
115
  error_callback: Callback for errors.
117
116
  """
118
- finish_callback(sample_actiontable)
117
+ # Generate dict and short format like the service does
118
+ actiontable_dict = asdict(sample_actiontable)
119
+ actiontable_short = ActionTableSerializer.format_decoded_output(
120
+ sample_actiontable
121
+ )
122
+ finish_callback(sample_actiontable, actiontable_dict, actiontable_short)
119
123
 
120
124
  mock_service.start.side_effect = mock_start
121
125
 
@@ -92,9 +92,9 @@ class TestXp24ActionTableIntegration:
92
92
 
93
93
  # Verify action table structure
94
94
  action_table = output["action_table"]
95
- assert action_table["input1_action"]["type"] == InputActionType.TOGGLE.value
95
+ assert action_table["input1_action"]["type"] == str(InputActionType.TOGGLE)
96
96
  assert action_table["input1_action"]["param"] == TimeParam.NONE.value
97
- assert action_table["input2_action"]["type"] == InputActionType.TURNON.value
97
+ assert action_table["input2_action"]["type"] == str(InputActionType.TURNON)
98
98
  assert action_table["input2_action"]["param"] == TimeParam.T5SEC.value
99
99
  assert action_table["mutex34"] is True
100
100
  assert action_table["curtain34"] is True
@@ -1,5 +1,6 @@
1
1
  """Unit tests for conbus actiontable CLI commands."""
2
2
 
3
+ from dataclasses import asdict
3
4
  from unittest.mock import Mock
4
5
 
5
6
  import pytest
@@ -12,6 +13,7 @@ from xp.models import ModuleTypeCode
12
13
  from xp.models.actiontable.actiontable import ActionTable, ActionTableEntry
13
14
  from xp.models.telegram.input_action_type import InputActionType
14
15
  from xp.models.telegram.timeparam_type import TimeParam
16
+ from xp.services.actiontable.actiontable_serializer import ActionTableSerializer
15
17
 
16
18
 
17
19
  class TestConbusActionTableCommands:
@@ -67,7 +69,12 @@ class TestConbusActionTableCommands:
67
69
  error_callback(error)
68
70
  else:
69
71
  if actiontable:
70
- finish_callback(actiontable)
72
+ # Generate dict and short format like the service does
73
+ actiontable_dict = asdict(actiontable)
74
+ actiontable_short = ActionTableSerializer.format_decoded_output(
75
+ actiontable
76
+ )
77
+ finish_callback(actiontable, actiontable_dict, actiontable_short)
71
78
 
72
79
  mock_service.start.side_effect = mock_start
73
80
  return mock_service
@@ -227,3 +234,154 @@ class TestConbusActionTableCommands:
227
234
  assert "0000012345" in result.output
228
235
  assert "actiontable" in result.output
229
236
  assert "entries" in result.output
237
+
238
+ def test_download_actiontable_includes_short_format(
239
+ self, runner, sample_actiontable
240
+ ):
241
+ """Test that actiontable download includes actiontable_short field."""
242
+ # Setup mock service
243
+ mock_service = self._create_mock_service(actiontable=sample_actiontable)
244
+
245
+ # Setup mock container to resolve ActionTableService
246
+ mock_container = Mock()
247
+ mock_container.resolve.return_value = mock_service
248
+ mock_service_container = Mock()
249
+ mock_service_container.get_container.return_value = mock_container
250
+
251
+ # Execute command
252
+ result = runner.invoke(
253
+ conbus_download_actiontable,
254
+ ["012345"],
255
+ obj={"container": mock_service_container},
256
+ )
257
+
258
+ # Verify success
259
+ assert result.exit_code == 0
260
+
261
+ # Verify actiontable_short field exists
262
+ assert "actiontable_short" in result.output
263
+
264
+ def test_download_actiontable_short_format_correct(
265
+ self, runner, sample_actiontable
266
+ ):
267
+ """Test that actiontable_short field contains correctly formatted entries."""
268
+ # Setup mock service
269
+ mock_service = self._create_mock_service(actiontable=sample_actiontable)
270
+
271
+ # Setup mock container to resolve ActionTableService
272
+ mock_container = Mock()
273
+ mock_container.resolve.return_value = mock_service
274
+ mock_service_container = Mock()
275
+ mock_service_container.get_container.return_value = mock_container
276
+
277
+ # Execute command
278
+ result = runner.invoke(
279
+ conbus_download_actiontable,
280
+ ["012345"],
281
+ obj={"container": mock_service_container},
282
+ )
283
+
284
+ # Verify success
285
+ assert result.exit_code == 0
286
+
287
+ # Verify short format is present with semicolons
288
+ assert "CP20 0 0 > 1 TURNOFF;" in result.output
289
+
290
+ def test_download_actiontable_backward_compatible(self, runner, sample_actiontable):
291
+ """Test that JSON actiontable field is still present for backward compatibility."""
292
+ # Setup mock service
293
+ mock_service = self._create_mock_service(actiontable=sample_actiontable)
294
+
295
+ # Setup mock container to resolve ActionTableService
296
+ mock_container = Mock()
297
+ mock_container.resolve.return_value = mock_service
298
+ mock_service_container = Mock()
299
+ mock_service_container.get_container.return_value = mock_container
300
+
301
+ # Execute command
302
+ result = runner.invoke(
303
+ conbus_download_actiontable,
304
+ ["012345"],
305
+ obj={"container": mock_service_container},
306
+ )
307
+
308
+ # Verify success
309
+ assert result.exit_code == 0
310
+
311
+ # Verify both formats are present
312
+ assert "actiontable_short" in result.output
313
+ assert "actiontable" in result.output
314
+ assert "entries" in result.output
315
+
316
+ def test_download_actiontable_short_with_parameter(self, runner):
317
+ """Test actiontable_short displays parameter when non-zero."""
318
+ # Create actiontable with parameter
319
+ entry = ActionTableEntry(
320
+ module_type=ModuleTypeCode.CP20,
321
+ link_number=0,
322
+ module_input=2,
323
+ module_output=1,
324
+ inverted=False,
325
+ command=InputActionType.TURNON,
326
+ parameter=TimeParam.T1SEC, # value = 2
327
+ )
328
+ actiontable = ActionTable(entries=[entry])
329
+
330
+ # Setup mock service
331
+ mock_service = self._create_mock_service(actiontable=actiontable)
332
+
333
+ # Setup mock container to resolve ActionTableService
334
+ mock_container = Mock()
335
+ mock_container.resolve.return_value = mock_service
336
+ mock_service_container = Mock()
337
+ mock_service_container.get_container.return_value = mock_container
338
+
339
+ # Execute command
340
+ result = runner.invoke(
341
+ conbus_download_actiontable,
342
+ ["012345"],
343
+ obj={"container": mock_service_container},
344
+ )
345
+
346
+ # Verify success
347
+ assert result.exit_code == 0
348
+
349
+ # Verify parameter is included in output
350
+ assert "CP20 0 2 > 1 TURNON 2;" in result.output
351
+
352
+ def test_download_actiontable_short_inverted(self, runner):
353
+ """Test actiontable_short displays inverted commands with ~ prefix."""
354
+ # Create actiontable with inverted command
355
+ entry = ActionTableEntry(
356
+ module_type=ModuleTypeCode.CP20,
357
+ link_number=0,
358
+ module_input=1,
359
+ module_output=1,
360
+ inverted=True,
361
+ command=InputActionType.TURNON,
362
+ parameter=TimeParam.NONE,
363
+ )
364
+ actiontable = ActionTable(entries=[entry])
365
+
366
+ # Setup mock service
367
+ mock_service = self._create_mock_service(actiontable=actiontable)
368
+
369
+ # Setup mock container to resolve ActionTableService
370
+ mock_container = Mock()
371
+ mock_container.resolve.return_value = mock_service
372
+ mock_service_container = Mock()
373
+ mock_service_container.get_container.return_value = mock_container
374
+
375
+ # Execute command
376
+ result = runner.invoke(
377
+ conbus_download_actiontable,
378
+ ["012345"],
379
+ obj={"container": mock_service_container},
380
+ )
381
+
382
+ # Verify success
383
+ assert result.exit_code == 0
384
+
385
+ # Verify inverted prefix is present
386
+ assert "~TURNON" in result.output
387
+ assert "CP20 0 1 > 1 ~TURNON;" in result.output