conson-xp 1.16.0__tar.gz → 1.17.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 (269) hide show
  1. {conson_xp-1.16.0 → conson_xp-1.17.0}/PKG-INFO +5 -1
  2. {conson_xp-1.16.0 → conson_xp-1.17.0}/README.md +4 -0
  3. {conson_xp-1.16.0 → conson_xp-1.17.0}/pyproject.toml +1 -1
  4. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/__init__.py +1 -1
  5. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/__init__.py +3 -0
  6. conson_xp-1.17.0/src/xp/cli/commands/conbus/conbus_event_commands.py +115 -0
  7. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/__init__.py +2 -0
  8. conson_xp-1.17.0/src/xp/models/conbus/conbus_event_raw.py +47 -0
  9. conson_xp-1.17.0/src/xp/services/conbus/conbus_event_raw_service.py +185 -0
  10. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/utils/dependencies.py +9 -0
  11. conson_xp-1.17.0/tests/unit/test_services/test_conbus_event_raw_service.py +169 -0
  12. {conson_xp-1.16.0 → conson_xp-1.17.0}/LICENSE +0 -0
  13. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/__init__.py +0 -0
  14. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/__main__.py +0 -0
  15. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/__init__.py +0 -0
  16. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus.py +0 -0
  17. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_actiontable_commands.py +0 -0
  18. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_autoreport_commands.py +0 -0
  19. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_blink_commands.py +0 -0
  20. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_config_commands.py +0 -0
  21. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_custom_commands.py +0 -0
  22. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_datapoint_commands.py +0 -0
  23. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_discover_commands.py +0 -0
  24. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_lightlevel_commands.py +0 -0
  25. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_linknumber_commands.py +0 -0
  26. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_modulenumber_commands.py +0 -0
  27. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_msactiontable_commands.py +0 -0
  28. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_output_commands.py +0 -0
  29. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_raw_commands.py +0 -0
  30. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_receive_commands.py +0 -0
  31. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/conbus/conbus_scan_commands.py +0 -0
  32. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/file_commands.py +0 -0
  33. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/homekit/__init__.py +0 -0
  34. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/homekit/homekit.py +0 -0
  35. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/homekit/homekit_start_commands.py +0 -0
  36. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/module_commands.py +0 -0
  37. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/reverse_proxy_commands.py +0 -0
  38. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/server/__init__.py +0 -0
  39. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/server/server_commands.py +0 -0
  40. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/telegram/__init__.py +0 -0
  41. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/telegram/telegram.py +0 -0
  42. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/telegram/telegram_blink_commands.py +0 -0
  43. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/telegram/telegram_checksum_commands.py +0 -0
  44. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/telegram/telegram_discover_commands.py +0 -0
  45. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/telegram/telegram_linknumber_commands.py +0 -0
  46. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/telegram/telegram_parse_commands.py +0 -0
  47. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/commands/telegram/telegram_version_commands.py +0 -0
  48. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/main.py +0 -0
  49. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/utils/__init__.py +0 -0
  50. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/utils/click_tree.py +0 -0
  51. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/utils/datapoint_type_choice.py +0 -0
  52. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/utils/decorators.py +0 -0
  53. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/utils/error_handlers.py +0 -0
  54. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/utils/formatters.py +0 -0
  55. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/utils/serial_number_type.py +0 -0
  56. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/utils/system_function_choice.py +0 -0
  57. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/cli/utils/xp_module_type.py +0 -0
  58. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/connection/__init__.py +0 -0
  59. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/connection/exceptions.py +0 -0
  60. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/actiontable/__init__.py +0 -0
  61. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/actiontable/actiontable.py +0 -0
  62. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/actiontable/msactiontable_xp20.py +0 -0
  63. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/actiontable/msactiontable_xp24.py +0 -0
  64. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/actiontable/msactiontable_xp33.py +0 -0
  65. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/__init__.py +0 -0
  66. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus.py +0 -0
  67. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_autoreport.py +0 -0
  68. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_blink.py +0 -0
  69. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_client_config.py +0 -0
  70. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_connection_status.py +0 -0
  71. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_custom.py +0 -0
  72. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_datapoint.py +0 -0
  73. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_discover.py +0 -0
  74. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_lightlevel.py +0 -0
  75. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_linknumber.py +0 -0
  76. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_output.py +0 -0
  77. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_raw.py +0 -0
  78. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_receive.py +0 -0
  79. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/conbus/conbus_writeconfig.py +0 -0
  80. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/homekit/__init__.py +0 -0
  81. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/homekit/homekit_accessory.py +0 -0
  82. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/homekit/homekit_config.py +0 -0
  83. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/homekit/homekit_conson_config.py +0 -0
  84. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/log_entry.py +0 -0
  85. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/protocol/__init__.py +0 -0
  86. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/protocol/conbus_protocol.py +0 -0
  87. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/response.py +0 -0
  88. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/__init__.py +0 -0
  89. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/action_type.py +0 -0
  90. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/datapoint_type.py +0 -0
  91. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/event_telegram.py +0 -0
  92. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/event_type.py +0 -0
  93. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/input_action_type.py +0 -0
  94. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/input_type.py +0 -0
  95. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/module_type.py +0 -0
  96. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/module_type_code.py +0 -0
  97. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/output_telegram.py +0 -0
  98. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/reply_telegram.py +0 -0
  99. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/system_function.py +0 -0
  100. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/system_telegram.py +0 -0
  101. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/telegram.py +0 -0
  102. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/telegram_type.py +0 -0
  103. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/telegram/timeparam_type.py +0 -0
  104. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/models/write_config_type.py +0 -0
  105. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/__init__.py +0 -0
  106. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/actiontable/__init__.py +0 -0
  107. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/actiontable/actiontable_serializer.py +0 -0
  108. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/actiontable/msactiontable_serializer.py +0 -0
  109. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/actiontable/msactiontable_xp20_serializer.py +0 -0
  110. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/actiontable/msactiontable_xp24_serializer.py +0 -0
  111. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/actiontable/msactiontable_xp33_serializer.py +0 -0
  112. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/__init__.py +0 -0
  113. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/actiontable/__init__.py +0 -0
  114. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/actiontable/actiontable_download_service.py +0 -0
  115. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/actiontable/actiontable_list_service.py +0 -0
  116. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/actiontable/actiontable_show_service.py +0 -0
  117. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/actiontable/actiontable_upload_service.py +0 -0
  118. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/actiontable/msactiontable_service.py +0 -0
  119. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/conbus_blink_all_service.py +0 -0
  120. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/conbus_blink_service.py +0 -0
  121. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/conbus_custom_service.py +0 -0
  122. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/conbus_datapoint_queryall_service.py +0 -0
  123. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/conbus_datapoint_service.py +0 -0
  124. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/conbus_discover_service.py +0 -0
  125. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/conbus_output_service.py +0 -0
  126. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/conbus_raw_service.py +0 -0
  127. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/conbus_receive_service.py +0 -0
  128. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/conbus_scan_service.py +0 -0
  129. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/conbus/write_config_service.py +0 -0
  130. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/__init__.py +0 -0
  131. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_cache_service.py +0 -0
  132. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_conbus_service.py +0 -0
  133. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_config_validator.py +0 -0
  134. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_conson_validator.py +0 -0
  135. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_dimminglight.py +0 -0
  136. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_dimminglight_service.py +0 -0
  137. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_hap_service.py +0 -0
  138. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_lightbulb.py +0 -0
  139. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_lightbulb_service.py +0 -0
  140. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_module_service.py +0 -0
  141. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_outlet.py +0 -0
  142. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_outlet_service.py +0 -0
  143. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/homekit/homekit_service.py +0 -0
  144. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/log_file_service.py +0 -0
  145. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/module_type_service.py +0 -0
  146. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/protocol/__init__.py +0 -0
  147. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/protocol/conbus_event_protocol.py +0 -0
  148. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/protocol/conbus_protocol.py +0 -0
  149. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/protocol/protocol_factory.py +0 -0
  150. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/protocol/telegram_protocol.py +0 -0
  151. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/reverse_proxy_service.py +0 -0
  152. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/server/__init__.py +0 -0
  153. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/server/base_server_service.py +0 -0
  154. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/server/cp20_server_service.py +0 -0
  155. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/server/device_service_factory.py +0 -0
  156. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/server/server_service.py +0 -0
  157. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/server/xp130_server_service.py +0 -0
  158. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/server/xp20_server_service.py +0 -0
  159. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/server/xp230_server_service.py +0 -0
  160. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/server/xp24_server_service.py +0 -0
  161. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/server/xp33_server_service.py +0 -0
  162. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/telegram/__init__.py +0 -0
  163. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/telegram/telegram_blink_service.py +0 -0
  164. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/telegram/telegram_checksum_service.py +0 -0
  165. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/telegram/telegram_datapoint_service.py +0 -0
  166. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/telegram/telegram_discover_service.py +0 -0
  167. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/telegram/telegram_link_number_service.py +0 -0
  168. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/telegram/telegram_output_service.py +0 -0
  169. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/telegram/telegram_service.py +0 -0
  170. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/services/telegram/telegram_version_service.py +0 -0
  171. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/utils/__init__.py +0 -0
  172. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/utils/checksum.py +0 -0
  173. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/utils/event_helper.py +0 -0
  174. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/utils/serialization.py +0 -0
  175. {conson_xp-1.16.0 → conson_xp-1.17.0}/src/xp/utils/time_utils.py +0 -0
  176. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/.coverage +0 -0
  177. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/__init__.py +0 -0
  178. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/conftest.py +0 -0
  179. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/.coverage +0 -0
  180. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/__init__.py +0 -0
  181. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/telegram_test_data.py +0 -0
  182. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_actiontable_integration.py +0 -0
  183. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_api/.coverage +0 -0
  184. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_api/__init__.py +0 -0
  185. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_blink_integration.py +0 -0
  186. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_checksum_integration.py +0 -0
  187. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_conbus_blink_integration.py +0 -0
  188. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_conbus_datapoint_integration.py +0 -0
  189. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_conbus_raw_integration.py +0 -0
  190. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_conbus_receive_integration.py +0 -0
  191. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_discovery_integration.py +0 -0
  192. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_event_telegram_integration.py +0 -0
  193. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_homekit_config_integration.py +0 -0
  194. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_link_number_integration.py +0 -0
  195. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_module_integration.py +0 -0
  196. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_output_integration.py +0 -0
  197. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_reverse_proxy_integration.py +0 -0
  198. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_system_reply_telegram_integration.py +0 -0
  199. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_version_integration.py +0 -0
  200. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_xp20_action_table_integration.py +0 -0
  201. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/integration/test_xp24_action_table_integration.py +0 -0
  202. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/__init__.py +0 -0
  203. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_api/__init__.py +0 -0
  204. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_cli/__init__.py +0 -0
  205. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_cli/test_click_tree.py +0 -0
  206. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_cli/test_conbus_actiontable_commands.py +0 -0
  207. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_cli/test_conbus_blink_commands.py +0 -0
  208. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_cli/test_datapoint_type_choice.py +0 -0
  209. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_cli/test_decorators.py +0 -0
  210. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_cli/test_error_handlers.py +0 -0
  211. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_cli/test_formatters.py +0 -0
  212. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_cli/test_serial_number_type.py +0 -0
  213. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_cli/test_system_function_choice.py +0 -0
  214. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_connection/__init__.py +0 -0
  215. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_connection/test_connection_init.py +0 -0
  216. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_connection/test_exceptions.py +0 -0
  217. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_encoding/__init__.py +0 -0
  218. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_encoding/test_latin1_edge_cases.py +0 -0
  219. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/__init__.py +0 -0
  220. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_conbus.py +0 -0
  221. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_conbus_client_send.py +0 -0
  222. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_conbus_discover.py +0 -0
  223. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_conbus_linknumber.py +0 -0
  224. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_event_telegram.py +0 -0
  225. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_log_entry.py +0 -0
  226. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_module_type.py +0 -0
  227. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_reply_telegram.py +0 -0
  228. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_system_telegram.py +0 -0
  229. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_system_telegram_enhancements.py +0 -0
  230. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_version_telegram.py +0 -0
  231. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_write_config_type.py +0 -0
  232. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_xp20_action_table.py +0 -0
  233. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_xp24_action_table.py +0 -0
  234. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_models/test_xp24_action_telegram.py +0 -0
  235. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/__init__.py +0 -0
  236. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_actiontable_serializer.py +0 -0
  237. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_actiontable_service.py +0 -0
  238. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_actiontable_upload_service.py +0 -0
  239. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_base_server_service.py +0 -0
  240. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_blink_service.py +0 -0
  241. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_checksum_service.py +0 -0
  242. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_conbus_blink_service.py +0 -0
  243. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_conbus_raw_service.py +0 -0
  244. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_conbus_reverse_proxy_service.py +0 -0
  245. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_device_service_factory.py +0 -0
  246. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_discovery_service.py +0 -0
  247. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_homekit_cache_service.py +0 -0
  248. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_homekit_config_validator.py +0 -0
  249. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_homekit_conson_service.py +0 -0
  250. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_homekit_services.py +0 -0
  251. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_log_file_service.py +0 -0
  252. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_module_type_service.py +0 -0
  253. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_protocol.py +0 -0
  254. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_server_service.py +0 -0
  255. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_telegram_input_service.py +0 -0
  256. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_telegram_protocol.py +0 -0
  257. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_telegram_service.py +0 -0
  258. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_version_service.py +0 -0
  259. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_xp20_action_table_serializer.py +0 -0
  260. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_xp24_action_service.py +0 -0
  261. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_xp24_action_table_serializer.py +0 -0
  262. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_xp24_action_table_service.py +0 -0
  263. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_xp33_action_table_serializer.py +0 -0
  264. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_services/test_xp_server_services.py +0 -0
  265. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_utils/__init__.py +0 -0
  266. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_utils/test_checksum.py +0 -0
  267. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_utils/test_event_helper.py +0 -0
  268. {conson_xp-1.16.0 → conson_xp-1.17.0}/tests/unit/test_utils/test_serialization.py +0 -0
  269. {conson_xp-1.16.0 → conson_xp-1.17.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.16.0
3
+ Version: 1.17.0
4
4
  Summary: XP Protocol Communication Tools
5
5
  Author-Email: ldvchosal <ldvchosal@github.com>
6
6
  License: MIT License
@@ -305,6 +305,10 @@ xp conbus datapoint query
305
305
 
306
306
  xp conbus discover
307
307
 
308
+ xp conbus event
309
+ xp conbus event raw
310
+
311
+
308
312
  xp conbus lightlevel
309
313
  xp conbus lightlevel get
310
314
  xp conbus lightlevel off
@@ -253,6 +253,10 @@ xp conbus datapoint query
253
253
 
254
254
  xp conbus discover
255
255
 
256
+ xp conbus event
257
+ xp conbus event raw
258
+
259
+
256
260
  xp conbus lightlevel
257
261
  xp conbus lightlevel get
258
262
  xp conbus lightlevel off
@@ -21,7 +21,7 @@ dependencies = [
21
21
  ]
22
22
  requires-python = ">=3.11"
23
23
  readme = "README.md"
24
- version = "1.16.0"
24
+ version = "1.17.0"
25
25
 
26
26
  [project.license]
27
27
  file = "LICENSE"
@@ -3,7 +3,7 @@
3
3
  conson-xp package.
4
4
  """
5
5
 
6
- __version__ = "1.16.0"
6
+ __version__ = "1.17.0"
7
7
  __manufacturer__ = "salchichon"
8
8
  __model__ = "xp.cli"
9
9
  __serial__ = "2025.09.23.000"
@@ -37,6 +37,7 @@ from xp.cli.commands.conbus.conbus_datapoint_commands import (
37
37
  query_datapoint,
38
38
  )
39
39
  from xp.cli.commands.conbus.conbus_discover_commands import send_discover_telegram
40
+ from xp.cli.commands.conbus.conbus_event_commands import conbus_event, send_event_raw
40
41
  from xp.cli.commands.conbus.conbus_lightlevel_commands import (
41
42
  xp_lightlevel_get,
42
43
  xp_lightlevel_off,
@@ -97,6 +98,7 @@ __all__ = [
97
98
  "conbus_lightlevel",
98
99
  "conbus_msactiontable",
99
100
  "conbus_actiontable",
101
+ "conbus_event",
100
102
  "file",
101
103
  "module",
102
104
  "reverse_proxy",
@@ -118,6 +120,7 @@ __all__ = [
118
120
  "show_config",
119
121
  "send_custom_telegram",
120
122
  "send_discover_telegram",
123
+ "send_event_raw",
121
124
  "xp_output_on",
122
125
  "xp_output_off",
123
126
  "xp_output_status",
@@ -0,0 +1,115 @@
1
+ """Conbus event operations CLI commands."""
2
+
3
+ import json
4
+
5
+ import click
6
+
7
+ from xp.cli.commands.conbus.conbus import conbus
8
+ from xp.cli.utils.decorators import connection_command
9
+ from xp.models import ConbusEventRawResponse
10
+ from xp.models.telegram.module_type_code import ModuleTypeCode
11
+ from xp.services.conbus.conbus_event_raw_service import ConbusEventRawService
12
+
13
+
14
+ @click.group(name="event")
15
+ def conbus_event() -> None:
16
+ """Send event telegrams to Conbus modules."""
17
+ pass
18
+
19
+
20
+ @conbus_event.command("raw")
21
+ @click.argument("module_type", type=str)
22
+ @click.argument("link_number", type=int)
23
+ @click.argument("input_number", type=int)
24
+ @click.argument("time_ms", type=int, default=1000)
25
+ @click.pass_context
26
+ @connection_command()
27
+ def send_event_raw(
28
+ ctx: click.Context,
29
+ module_type: str,
30
+ link_number: int,
31
+ input_number: int,
32
+ time_ms: int,
33
+ ) -> None:
34
+ r"""Send raw event telegrams to simulate button presses.
35
+
36
+ Args:
37
+ ctx: Click context object.
38
+ module_type: Module type code (e.g., CP20, XP33).
39
+ link_number: Link number (0-99).
40
+ input_number: Input number (0-9).
41
+ time_ms: Delay between MAKE/BREAK events in milliseconds (default: 1000).
42
+
43
+ Examples:
44
+ \b
45
+ xp conbus event raw CP20 00 00
46
+ xp conbus event raw XP33 00 00 500
47
+ """
48
+ # Validate parameters
49
+ if link_number < 0 or link_number > 99:
50
+ click.echo(
51
+ json.dumps({"error": "Link number must be between 0 and 99"}, indent=2)
52
+ )
53
+ return
54
+
55
+ if input_number < 0 or input_number > 9:
56
+ click.echo(
57
+ json.dumps({"error": "Input number must be between 0 and 9"}, indent=2)
58
+ )
59
+ return
60
+
61
+ if time_ms <= 0:
62
+ click.echo(json.dumps({"error": "Time must be greater than 0"}, indent=2))
63
+ return
64
+
65
+ # Resolve module type to numeric code
66
+ module_type_code: int = 0
67
+ try:
68
+ # Try to get the enum value by name
69
+ module_type_enum = ModuleTypeCode[module_type.upper()]
70
+ module_type_code = module_type_enum.value
71
+ except KeyError:
72
+ # Module type not found
73
+ click.echo(
74
+ json.dumps(
75
+ {
76
+ "error": f"Unknown module type: {module_type}. Use module types like CP20, XP33, XP24, etc."
77
+ },
78
+ indent=2,
79
+ )
80
+ )
81
+ return
82
+
83
+ def on_finish(response: ConbusEventRawResponse) -> None:
84
+ """Handle successful completion of event raw operation.
85
+
86
+ Args:
87
+ response: Event raw response with sent and received telegrams.
88
+ """
89
+ click.echo(json.dumps(response.to_dict(), indent=2))
90
+
91
+ def on_progress(telegram: str) -> None:
92
+ """Handle progress updates during event operation.
93
+
94
+ Args:
95
+ telegram: Received telegram.
96
+ """
97
+ click.echo(json.dumps({"telegram": telegram}))
98
+
99
+ service: ConbusEventRawService = (
100
+ ctx.obj.get("container").get_container().resolve(ConbusEventRawService)
101
+ )
102
+ service.run(
103
+ module_type_code=module_type_code,
104
+ link_number=link_number,
105
+ input_number=input_number,
106
+ time_ms=time_ms,
107
+ progress_callback=on_progress,
108
+ finish_callback=on_finish,
109
+ timeout_seconds=5,
110
+ )
111
+ service.start_reactor()
112
+
113
+
114
+ # Register the event command group with conbus
115
+ conbus.add_command(conbus_event)
@@ -5,6 +5,7 @@ from xp.models.conbus.conbus_client_config import ConbusClientConfig
5
5
  from xp.models.conbus.conbus_connection_status import ConbusConnectionStatus
6
6
  from xp.models.conbus.conbus_datapoint import ConbusDatapointResponse
7
7
  from xp.models.conbus.conbus_discover import ConbusDiscoverResponse
8
+ from xp.models.conbus.conbus_event_raw import ConbusEventRawResponse
8
9
  from xp.models.log_entry import LogEntry
9
10
  from xp.models.telegram.event_telegram import EventTelegram
10
11
  from xp.models.telegram.event_type import EventType
@@ -30,5 +31,6 @@ __all__ = [
30
31
  "ConbusResponse",
31
32
  "ConbusDatapointResponse",
32
33
  "ConbusDiscoverResponse",
34
+ "ConbusEventRawResponse",
33
35
  "ConbusConnectionStatus",
34
36
  ]
@@ -0,0 +1,47 @@
1
+ """Conbus event raw response model."""
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from typing import Any, Dict, Optional
6
+
7
+
8
+ @dataclass
9
+ class ConbusEventRawResponse:
10
+ """Represents a response from Conbus event raw operation.
11
+
12
+ Attributes:
13
+ success: Whether the operation was successful.
14
+ sent_telegrams: List of event telegrams sent (MAKE and BREAK).
15
+ received_telegrams: List of all telegrams received.
16
+ error: Error message if operation failed.
17
+ timestamp: Timestamp of the response.
18
+ """
19
+
20
+ success: bool
21
+ sent_telegrams: Optional[list[str]] = None
22
+ received_telegrams: Optional[list[str]] = None
23
+ error: Optional[str] = None
24
+ timestamp: Optional[datetime] = None
25
+
26
+ def __post_init__(self) -> None:
27
+ """Initialize timestamp and telegram lists if not provided."""
28
+ if self.timestamp is None:
29
+ self.timestamp = datetime.now()
30
+ if self.sent_telegrams is None:
31
+ self.sent_telegrams = []
32
+ if self.received_telegrams is None:
33
+ self.received_telegrams = []
34
+
35
+ def to_dict(self) -> Dict[str, Any]:
36
+ """Convert to dictionary for JSON serialization.
37
+
38
+ Returns:
39
+ Dictionary representation of the response.
40
+ """
41
+ return {
42
+ "success": self.success,
43
+ "sent_telegrams": self.sent_telegrams,
44
+ "received_telegrams": self.received_telegrams,
45
+ "error": self.error,
46
+ "timestamp": self.timestamp.isoformat() if self.timestamp else None,
47
+ }
@@ -0,0 +1,185 @@
1
+ """Conbus Event Raw Service for sending raw event telegrams.
2
+
3
+ This service implements a TCP client that connects to Conbus servers and sends
4
+ raw event telegrams to simulate button presses on Conbus modules.
5
+ """
6
+
7
+ import logging
8
+ from typing import Callable, Optional
9
+
10
+ from twisted.internet.base import DelayedCall
11
+
12
+ from xp.models import ConbusEventRawResponse
13
+ from xp.models.protocol.conbus_protocol import TelegramReceivedEvent
14
+ from xp.services.protocol.conbus_event_protocol import ConbusEventProtocol
15
+
16
+
17
+ class ConbusEventRawService:
18
+ """Service for sending raw event telegrams to Conbus servers.
19
+
20
+ Uses ConbusEventProtocol to send MAKE/BREAK event sequences to
21
+ simulate button presses on Conbus modules.
22
+
23
+ Attributes:
24
+ conbus_protocol: Protocol instance for Conbus communication.
25
+ """
26
+
27
+ conbus_protocol: ConbusEventProtocol
28
+
29
+ def __init__(self, conbus_protocol: ConbusEventProtocol) -> None:
30
+ """Initialize the Conbus event raw service.
31
+
32
+ Args:
33
+ conbus_protocol: ConbusEventProtocol instance.
34
+ """
35
+ self.progress_callback: Optional[Callable[[str], None]] = None
36
+ self.finish_callback: Optional[Callable[[ConbusEventRawResponse], None]] = None
37
+
38
+ self.conbus_protocol: ConbusEventProtocol = conbus_protocol
39
+ self.conbus_protocol.on_connection_made.connect(self.connection_made)
40
+ self.conbus_protocol.on_telegram_sent.connect(self.telegram_sent)
41
+ self.conbus_protocol.on_telegram_received.connect(self.telegram_received)
42
+ self.conbus_protocol.on_timeout.connect(self.timeout)
43
+ self.conbus_protocol.on_failed.connect(self.failed)
44
+
45
+ self.event_result = ConbusEventRawResponse(success=False)
46
+ self.logger = logging.getLogger(__name__)
47
+
48
+ # Event parameters
49
+ self.module_type_code: int = 0
50
+ self.link_number: int = 0
51
+ self.input_number: int = 0
52
+ self.time_ms: int = 1000
53
+ self.break_event_call: Optional[DelayedCall] = None
54
+
55
+ def connection_made(self) -> None:
56
+ """Handle connection established event."""
57
+ self.logger.debug("Connection established")
58
+ self.logger.debug("Sending MAKE event telegram")
59
+ self._send_make_event()
60
+
61
+ def _send_make_event(self) -> None:
62
+ """Send MAKE event telegram."""
63
+ payload = f"E{self.module_type_code:02d}L{self.link_number:02d}I{self.input_number:02d}M"
64
+ self.logger.debug(f"Sending MAKE event: {payload}")
65
+ self.conbus_protocol.telegram_queue.put_nowait(payload.encode())
66
+ self.conbus_protocol._reactor.callLater(
67
+ 0.0, self.conbus_protocol.start_queue_manager
68
+ )
69
+
70
+ # Schedule BREAK event after delay
71
+ delay_seconds = self.time_ms / 1000.0
72
+ self.break_event_call = self.conbus_protocol._reactor.callLater(
73
+ delay_seconds, self._send_break_event
74
+ )
75
+
76
+ def _send_break_event(self) -> None:
77
+ """Send BREAK event telegram."""
78
+ payload = f"E{self.module_type_code:02d}L{self.link_number:02d}I{self.input_number:02d}B"
79
+ self.logger.debug(f"Sending BREAK event: {payload}")
80
+ self.conbus_protocol.telegram_queue.put_nowait(payload.encode())
81
+ self.conbus_protocol._reactor.callLater(
82
+ 0.0, self.conbus_protocol.start_queue_manager
83
+ )
84
+
85
+ def telegram_sent(self, telegram_sent: str) -> None:
86
+ """Handle telegram sent event.
87
+
88
+ Args:
89
+ telegram_sent: The telegram that was sent.
90
+ """
91
+ self.logger.debug(f"Telegram sent: {telegram_sent}")
92
+ if self.event_result.sent_telegrams is None:
93
+ self.event_result.sent_telegrams = []
94
+ self.event_result.sent_telegrams.append(telegram_sent)
95
+
96
+ def telegram_received(self, telegram_received: TelegramReceivedEvent) -> None:
97
+ """Handle telegram received event.
98
+
99
+ Args:
100
+ telegram_received: The telegram received event.
101
+ """
102
+ self.logger.debug(f"Telegram received: {telegram_received.frame}")
103
+ if self.event_result.received_telegrams is None:
104
+ self.event_result.received_telegrams = []
105
+ self.event_result.received_telegrams.append(telegram_received.frame)
106
+
107
+ # Display progress - show ALL received telegrams
108
+ if self.progress_callback:
109
+ self.progress_callback(telegram_received.frame)
110
+
111
+ def timeout(self) -> None:
112
+ """Handle timeout event.
113
+
114
+ Timeout is the normal/expected way to finish this service.
115
+ """
116
+ timeout_seconds = self.conbus_protocol.timeout_seconds
117
+ self.logger.info("Event raw finished after timeout: %ss", timeout_seconds)
118
+ self.event_result.success = True
119
+ self.event_result.error = None
120
+ if self.finish_callback:
121
+ self.finish_callback(self.event_result)
122
+
123
+ self.stop_reactor()
124
+
125
+ def failed(self, message: str) -> None:
126
+ """Handle failed connection event.
127
+
128
+ Args:
129
+ message: Failure message.
130
+ """
131
+ self.logger.debug(f"Failed: {message}")
132
+ self.event_result.success = False
133
+ self.event_result.error = message
134
+ if self.finish_callback:
135
+ self.finish_callback(self.event_result)
136
+
137
+ self.stop_reactor()
138
+
139
+ def stop_reactor(self) -> None:
140
+ """Stop reactor."""
141
+ self.logger.info("Stopping reactor")
142
+ # Cancel break event call if it's still pending
143
+ if self.break_event_call and self.break_event_call.active():
144
+ self.break_event_call.cancel()
145
+ self.conbus_protocol.stop_reactor()
146
+
147
+ def start_reactor(self) -> None:
148
+ """Start reactor."""
149
+ self.logger.info("Starting reactor")
150
+ self.conbus_protocol.start_reactor()
151
+
152
+ def run(
153
+ self,
154
+ module_type_code: int,
155
+ link_number: int,
156
+ input_number: int,
157
+ time_ms: int,
158
+ progress_callback: Optional[Callable[[str], None]],
159
+ finish_callback: Callable[[ConbusEventRawResponse], None],
160
+ timeout_seconds: int = 5,
161
+ ) -> None:
162
+ """Run reactor in dedicated thread with its own event loop.
163
+
164
+ Args:
165
+ module_type_code: Module type code (numeric, e.g., 2 for CP20, 33 for XP33).
166
+ link_number: Link number (0-99).
167
+ input_number: Input number (0-9).
168
+ time_ms: Delay in milliseconds between MAKE and BREAK events.
169
+ progress_callback: Callback for progress updates (received telegrams).
170
+ finish_callback: Callback when operation completes.
171
+ timeout_seconds: Timeout in seconds (default: 5).
172
+ """
173
+ self.logger.info(
174
+ f"Starting event raw: module={module_type_code}, "
175
+ f"link={link_number}, input={input_number}, time={time_ms}ms"
176
+ )
177
+
178
+ self.module_type_code = module_type_code
179
+ self.link_number = link_number
180
+ self.input_number = input_number
181
+ self.time_ms = time_ms
182
+
183
+ self.conbus_protocol.timeout_seconds = timeout_seconds
184
+ self.progress_callback = progress_callback
185
+ self.finish_callback = finish_callback
@@ -43,6 +43,7 @@ from xp.services.conbus.conbus_datapoint_service import (
43
43
  ConbusDatapointService,
44
44
  )
45
45
  from xp.services.conbus.conbus_discover_service import ConbusDiscoverService
46
+ from xp.services.conbus.conbus_event_raw_service import ConbusEventRawService
46
47
  from xp.services.conbus.conbus_output_service import ConbusOutputService
47
48
  from xp.services.conbus.conbus_raw_service import ConbusRawService
48
49
  from xp.services.conbus.conbus_receive_service import ConbusReceiveService
@@ -180,6 +181,14 @@ class ServiceContainer:
180
181
  scope=punq.Scope.singleton,
181
182
  )
182
183
 
184
+ self.container.register(
185
+ ConbusEventRawService,
186
+ factory=lambda: ConbusEventRawService(
187
+ conbus_protocol=self.container.resolve(ConbusEventProtocol)
188
+ ),
189
+ scope=punq.Scope.singleton,
190
+ )
191
+
183
192
  self.container.register(
184
193
  ConbusBlinkService,
185
194
  factory=lambda: ConbusBlinkService(
@@ -0,0 +1,169 @@
1
+ """Unit tests for ConbusEventRawService."""
2
+
3
+ from unittest.mock import Mock
4
+
5
+ import pytest
6
+
7
+ from xp.models.protocol.conbus_protocol import TelegramReceivedEvent
8
+ from xp.services.conbus.conbus_event_raw_service import ConbusEventRawService
9
+ from xp.services.protocol.conbus_event_protocol import ConbusEventProtocol
10
+
11
+
12
+ class TestConbusEventRawService:
13
+ """Unit tests for ConbusEventRawService functionality."""
14
+
15
+ @pytest.fixture
16
+ def mock_protocol(self):
17
+ """Create a mock ConbusEventProtocol."""
18
+ protocol = Mock(spec=ConbusEventProtocol)
19
+ protocol.on_connection_made = Mock()
20
+ protocol.on_telegram_sent = Mock()
21
+ protocol.on_telegram_received = Mock()
22
+ protocol.on_timeout = Mock()
23
+ protocol.on_failed = Mock()
24
+ protocol.on_connection_made.connect = Mock()
25
+ protocol.on_telegram_sent.connect = Mock()
26
+ protocol.on_telegram_received.connect = Mock()
27
+ protocol.on_timeout.connect = Mock()
28
+ protocol.on_failed.connect = Mock()
29
+ protocol._reactor = Mock()
30
+ protocol.telegram_queue = Mock()
31
+ protocol.timeout_seconds = 5
32
+ return protocol
33
+
34
+ @pytest.fixture
35
+ def service(self, mock_protocol):
36
+ """Create service instance with mock protocol."""
37
+ return ConbusEventRawService(conbus_protocol=mock_protocol)
38
+
39
+ def test_service_initialization(self, service):
40
+ """Test service can be initialized with required dependencies."""
41
+ assert service.module_type_code == 0
42
+ assert service.link_number == 0
43
+ assert service.input_number == 0
44
+ assert service.time_ms == 1000
45
+ assert service.finish_callback is None
46
+ assert service.progress_callback is None
47
+ assert service.event_result.success is False
48
+
49
+ def test_connection_made_sends_make_event(self, service, mock_protocol):
50
+ """Test connection_made sends MAKE event telegram."""
51
+ service.module_type_code = 2 # CP20
52
+ service.link_number = 10
53
+ service.input_number = 5
54
+ service.time_ms = 1000
55
+
56
+ service.connection_made()
57
+
58
+ # Verify MAKE event was queued
59
+ mock_protocol.telegram_queue.put_nowait.assert_called()
60
+ call_args = mock_protocol.telegram_queue.put_nowait.call_args[0][0]
61
+ assert call_args == b"E02L10I05M"
62
+
63
+ # Verify BREAK event was scheduled
64
+ mock_protocol._reactor.callLater.assert_called()
65
+
66
+ def test_telegram_sent(self, service):
67
+ """Test telegram_sent callback updates service response."""
68
+ telegram = "<E02L10I05MAK>"
69
+
70
+ service.telegram_sent(telegram)
71
+
72
+ assert service.event_result.sent_telegrams == [telegram]
73
+
74
+ def test_telegram_received(self, service, mock_protocol):
75
+ """Test telegram_received callback updates service response."""
76
+ telegram_event = TelegramReceivedEvent(
77
+ protocol=mock_protocol,
78
+ frame="<E02L10I05MAK>",
79
+ telegram="E02L10I05MAK",
80
+ payload="E02L10I05M",
81
+ telegram_type="E",
82
+ serial_number="",
83
+ checksum="AK",
84
+ checksum_valid=True,
85
+ )
86
+
87
+ service.telegram_received(telegram_event)
88
+
89
+ assert service.event_result.received_telegrams == ["<E02L10I05MAK>"]
90
+
91
+ def test_telegram_received_with_progress_callback(self, service, mock_protocol):
92
+ """Test telegram_received calls progress callback."""
93
+ progress_mock = Mock()
94
+ service.progress_callback = progress_mock
95
+
96
+ telegram_event = TelegramReceivedEvent(
97
+ protocol=mock_protocol,
98
+ frame="<E02L10I05MAK>",
99
+ telegram="E02L10I05MAK",
100
+ payload="E02L10I05M",
101
+ telegram_type="E",
102
+ serial_number="",
103
+ checksum="AK",
104
+ checksum_valid=True,
105
+ )
106
+
107
+ service.telegram_received(telegram_event)
108
+
109
+ progress_mock.assert_called_once_with("<E02L10I05MAK>")
110
+
111
+ def test_timeout(self, service, mock_protocol):
112
+ """Test timeout callback marks operation as successful."""
113
+ finish_mock = Mock()
114
+ service.finish_callback = finish_mock
115
+
116
+ service.timeout()
117
+
118
+ assert service.event_result.success is True
119
+ assert service.event_result.error is None
120
+ finish_mock.assert_called_once_with(service.event_result)
121
+ mock_protocol.stop_reactor.assert_called_once()
122
+
123
+ def test_failed(self, service, mock_protocol):
124
+ """Test failed callback updates service response."""
125
+ finish_mock = Mock()
126
+ service.finish_callback = finish_mock
127
+
128
+ service.failed("Connection timeout")
129
+
130
+ assert service.event_result.success is False
131
+ assert service.event_result.error == "Connection timeout"
132
+ finish_mock.assert_called_once_with(service.event_result)
133
+ mock_protocol.stop_reactor.assert_called_once()
134
+
135
+ def test_run(self, service, mock_protocol):
136
+ """Test run method sets up service parameters."""
137
+ finish_mock = Mock()
138
+ progress_mock = Mock()
139
+
140
+ service.run(
141
+ module_type_code=33, # XP33
142
+ link_number=15,
143
+ input_number=8,
144
+ time_ms=500,
145
+ progress_callback=progress_mock,
146
+ finish_callback=finish_mock,
147
+ timeout_seconds=10,
148
+ )
149
+
150
+ assert service.module_type_code == 33
151
+ assert service.link_number == 15
152
+ assert service.input_number == 8
153
+ assert service.time_ms == 500
154
+ assert service.progress_callback == progress_mock
155
+ assert service.finish_callback == finish_mock
156
+ assert mock_protocol.timeout_seconds == 10
157
+
158
+ def test_send_break_event(self, service, mock_protocol):
159
+ """Test _send_break_event sends BREAK event telegram."""
160
+ service.module_type_code = 2 # CP20
161
+ service.link_number = 10
162
+ service.input_number = 5
163
+
164
+ service._send_break_event()
165
+
166
+ # Verify BREAK event was queued
167
+ mock_protocol.telegram_queue.put_nowait.assert_called()
168
+ call_args = mock_protocol.telegram_queue.put_nowait.call_args[0][0]
169
+ assert call_args == b"E02L10I05B"
File without changes