conson-xp 1.5.0__tar.gz → 1.7.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.
- {conson_xp-1.5.0 → conson_xp-1.7.0}/PKG-INFO +1 -1
- {conson_xp-1.5.0 → conson_xp-1.7.0}/pyproject.toml +1 -1
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/__init__.py +1 -1
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_msactiontable_commands.py +11 -2
- conson_xp-1.7.0/src/xp/services/actiontable/__init__.py +1 -0
- conson_xp-1.7.0/src/xp/services/actiontable/msactiontable_serializer.py +7 -0
- {conson_xp-1.5.0/src/xp/services/conbus → conson_xp-1.7.0/src/xp/services}/actiontable/msactiontable_xp20_serializer.py +13 -25
- {conson_xp-1.5.0/src/xp/services/conbus → conson_xp-1.7.0/src/xp/services}/actiontable/msactiontable_xp24_serializer.py +25 -39
- {conson_xp-1.5.0/src/xp/services/conbus → conson_xp-1.7.0/src/xp/services}/actiontable/msactiontable_xp33_serializer.py +4 -21
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/actiontable/actiontable_service.py +1 -1
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/actiontable/msactiontable_service.py +44 -11
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/protocol/conbus_protocol.py +0 -2
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/server/base_server_service.py +83 -5
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/server/cp20_server_service.py +9 -1
- conson_xp-1.7.0/src/xp/services/server/device_service_factory.py +94 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/server/server_service.py +16 -61
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/server/xp130_server_service.py +10 -2
- conson_xp-1.7.0/src/xp/services/server/xp20_server_service.py +92 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/server/xp230_server_service.py +10 -2
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/server/xp24_server_service.py +54 -1
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/server/xp33_server_service.py +42 -1
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/telegram/telegram_service.py +4 -1
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/utils/dependencies.py +27 -6
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_xp20_action_table_integration.py +4 -12
- conson_xp-1.7.0/tests/unit/test_services/test_device_service_factory.py +149 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_server_service.py +108 -65
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_xp20_action_table_serializer.py +83 -20
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_xp24_action_table_serializer.py +13 -15
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_xp24_action_table_service.py +4 -3
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_xp33_action_table_serializer.py +12 -14
- conson_xp-1.5.0/src/xp/services/server/xp20_server_service.py +0 -50
- {conson_xp-1.5.0 → conson_xp-1.7.0}/LICENSE +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/README.md +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/__main__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_actiontable_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_autoreport_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_blink_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_config_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_custom_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_datapoint_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_discover_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_lightlevel_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_linknumber_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_output_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_raw_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_receive_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_scan_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/file_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/homekit/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/homekit/homekit.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/homekit/homekit_start_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/module_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/reverse_proxy_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/server/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/server/server_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/telegram/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/telegram/telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/telegram/telegram_blink_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/telegram/telegram_checksum_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/telegram/telegram_discover_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/telegram/telegram_linknumber_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/telegram/telegram_parse_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/telegram/telegram_version_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/main.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/utils/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/utils/click_tree.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/utils/datapoint_type_choice.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/utils/decorators.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/utils/error_handlers.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/utils/formatters.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/utils/serial_number_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/utils/system_function_choice.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/utils/xp_module_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/connection/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/connection/exceptions.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/actiontable/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/actiontable/actiontable.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/actiontable/msactiontable_xp20.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/actiontable/msactiontable_xp24.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/actiontable/msactiontable_xp33.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_autoreport.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_blink.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_client_config.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_connection_status.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_custom.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_datapoint.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_discover.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_lightlevel.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_linknumber.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_output.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_raw.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_receive.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/conbus/conbus_writeconfig.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/homekit/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/homekit/homekit_accessory.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/homekit/homekit_config.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/homekit/homekit_conson_config.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/log_entry.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/protocol/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/protocol/conbus_protocol.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/response.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/action_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/datapoint_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/event_telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/event_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/input_action_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/input_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/module_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/module_type_code.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/output_telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/reply_telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/system_function.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/system_telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/telegram_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/telegram/timeparam_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/models/write_config_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/__init__.py +0 -0
- {conson_xp-1.5.0/src/xp/services/conbus → conson_xp-1.7.0/src/xp/services}/actiontable/actiontable_serializer.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/actiontable/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/conbus_blink_all_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/conbus_blink_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/conbus_custom_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/conbus_datapoint_queryall_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/conbus_datapoint_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/conbus_discover_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/conbus_output_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/conbus_raw_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/conbus_receive_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/conbus_scan_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/write_config_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_cache_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_conbus_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_config_validator.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_conson_validator.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_dimminglight.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_dimminglight_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_hap_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_lightbulb.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_lightbulb_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_module_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_outlet.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_outlet_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/homekit/homekit_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/log_file_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/module_type_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/protocol/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/protocol/protocol_factory.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/protocol/telegram_protocol.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/reverse_proxy_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/server/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/telegram/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/telegram/telegram_blink_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/telegram/telegram_checksum_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/telegram/telegram_datapoint_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/telegram/telegram_discover_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/telegram/telegram_link_number_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/telegram/telegram_output_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/telegram/telegram_version_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/utils/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/utils/checksum.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/utils/event_helper.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/utils/serialization.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/utils/time_utils.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/.coverage +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/conftest.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/.coverage +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/telegram_test_data.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_actiontable_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_api/.coverage +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_api/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_blink_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_checksum_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_conbus_blink_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_conbus_datapoint_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_conbus_raw_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_conbus_receive_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_discovery_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_event_telegram_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_homekit_config_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_link_number_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_module_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_output_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_reverse_proxy_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_system_reply_telegram_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_version_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/integration/test_xp24_action_table_integration.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_api/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_cli/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_cli/test_click_tree.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_cli/test_conbus_actiontable_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_cli/test_conbus_blink_commands.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_cli/test_datapoint_type_choice.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_cli/test_decorators.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_cli/test_error_handlers.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_cli/test_formatters.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_cli/test_serial_number_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_cli/test_system_function_choice.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_connection/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_connection/test_connection_init.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_connection/test_exceptions.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_encoding/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_encoding/test_latin1_edge_cases.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_conbus.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_conbus_client_send.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_conbus_discover.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_conbus_linknumber.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_event_telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_log_entry.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_module_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_reply_telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_system_telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_system_telegram_enhancements.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_version_telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_write_config_type.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_xp20_action_table.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_xp24_action_table.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_models/test_xp24_action_telegram.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_actiontable_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_base_server_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_blink_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_checksum_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_conbus_blink_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_conbus_raw_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_conbus_reverse_proxy_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_discovery_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_homekit_cache_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_homekit_config_validator.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_homekit_conson_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_homekit_services.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_log_file_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_module_type_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_protocol.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_telegram_input_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_telegram_protocol.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_telegram_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_version_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_xp24_action_service.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_services/test_xp_server_services.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_utils/__init__.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_utils/test_checksum.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_utils/test_event_helper.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_utils/test_serialization.py +0 -0
- {conson_xp-1.5.0 → conson_xp-1.7.0}/tests/unit/test_utils/test_time_utils.py +0 -0
{conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/cli/commands/conbus/conbus_msactiontable_commands.py
RENAMED
|
@@ -49,13 +49,22 @@ def conbus_download_msactiontable(
|
|
|
49
49
|
click.echo(progress, nl=False)
|
|
50
50
|
|
|
51
51
|
def on_finish(
|
|
52
|
-
action_table: Union[
|
|
52
|
+
action_table: Union[
|
|
53
|
+
Xp20MsActionTable, Xp24MsActionTable, Xp33MsActionTable, None
|
|
54
|
+
],
|
|
53
55
|
) -> None:
|
|
54
56
|
"""Handle successful completion of MS action table download.
|
|
55
57
|
|
|
56
58
|
Args:
|
|
57
|
-
action_table: Downloaded MS action table object.
|
|
59
|
+
action_table: Downloaded MS action table object or None if failed.
|
|
60
|
+
|
|
61
|
+
Raises:
|
|
62
|
+
Abort: If action table download failed.
|
|
58
63
|
"""
|
|
64
|
+
if action_table is None:
|
|
65
|
+
click.echo("Error: Failed to download MS action table")
|
|
66
|
+
raise click.Abort()
|
|
67
|
+
|
|
59
68
|
output = {
|
|
60
69
|
"serial_number": serial_number,
|
|
61
70
|
"xpmoduletype": xpmoduletype,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Action table utils."""
|
|
@@ -46,8 +46,9 @@ class Xp20MsActionTableSerializer:
|
|
|
46
46
|
input_channel, input_index, raw_bytes
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
+
encoded_data = nibbles(raw_bytes)
|
|
49
50
|
# Convert raw bytes to hex string with A-P encoding
|
|
50
|
-
return
|
|
51
|
+
return "AAAA" + encoded_data
|
|
51
52
|
|
|
52
53
|
@staticmethod
|
|
53
54
|
def from_data(msactiontable_rawdata: str) -> Xp20MsActionTable:
|
|
@@ -62,13 +63,20 @@ class Xp20MsActionTableSerializer:
|
|
|
62
63
|
Raises:
|
|
63
64
|
ValueError: If input length is not 64 characters
|
|
64
65
|
"""
|
|
65
|
-
|
|
66
|
+
raw_length = len(msactiontable_rawdata)
|
|
67
|
+
if raw_length < 68: # Minimum: 4 char prefix + 64 chars data
|
|
66
68
|
raise ValueError(
|
|
67
|
-
f"XP20 action table data must be
|
|
69
|
+
f"XP20 action table data must be 68 characters long, got {len(msactiontable_rawdata)}"
|
|
68
70
|
)
|
|
69
71
|
|
|
70
|
-
#
|
|
71
|
-
|
|
72
|
+
# Remove action table count prefix (first 4 characters: AAAA, AAAB, etc.)
|
|
73
|
+
data = msactiontable_rawdata[4:]
|
|
74
|
+
|
|
75
|
+
# Take first 64 chars (32 bytes) as per pseudocode
|
|
76
|
+
hex_data = data[:64]
|
|
77
|
+
|
|
78
|
+
# Convert hex string to bytes using deNibble (A-P encoding)
|
|
79
|
+
raw_bytes = de_nibbles(hex_data)
|
|
72
80
|
|
|
73
81
|
# Decode input channels
|
|
74
82
|
input_channels = []
|
|
@@ -159,23 +167,3 @@ class Xp20MsActionTableSerializer:
|
|
|
159
167
|
and_functions_byte |= 1 << bit_index
|
|
160
168
|
|
|
161
169
|
raw_bytes[AND_FUNCTIONS_INDEX + input_index] = and_functions_byte
|
|
162
|
-
|
|
163
|
-
@staticmethod
|
|
164
|
-
def from_telegrams(ms_telegrams: str) -> Xp20MsActionTable:
|
|
165
|
-
"""Legacy method for backward compatibility. Use from_data() instead.
|
|
166
|
-
|
|
167
|
-
Args:
|
|
168
|
-
ms_telegrams: Full telegram string
|
|
169
|
-
|
|
170
|
-
Returns:
|
|
171
|
-
Decoded XP20 action table
|
|
172
|
-
"""
|
|
173
|
-
# Extract data portion from telegram (skip header, take action table data)
|
|
174
|
-
# Based on XP24 pattern: telegram[16:84] gives us the 68-char data portion
|
|
175
|
-
# For XP20, we need 64 chars, so we take the first 64 chars after removing count
|
|
176
|
-
data_parts = ms_telegrams[16:84]
|
|
177
|
-
|
|
178
|
-
# Remove action table count (first 4 chars: AAAA, AAAB, etc.)
|
|
179
|
-
hex_data = data_parts[4:68] # Take 64 chars after count
|
|
180
|
-
|
|
181
|
-
return Xp20MsActionTableSerializer.from_data(hex_data)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from xp.models.actiontable.msactiontable_xp24 import InputAction, Xp24MsActionTable
|
|
4
4
|
from xp.models.telegram.input_action_type import InputActionType
|
|
5
5
|
from xp.models.telegram.timeparam_type import TimeParam
|
|
6
|
-
from xp.utils.serialization import de_nibbles
|
|
6
|
+
from xp.utils.serialization import de_nibbles, nibbles
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Xp24MsActionTableSerializer:
|
|
@@ -17,11 +17,12 @@ class Xp24MsActionTableSerializer:
|
|
|
17
17
|
action_table: XP24 MS action table to serialize.
|
|
18
18
|
|
|
19
19
|
Returns:
|
|
20
|
-
Serialized action table data string.
|
|
20
|
+
Serialized action table data string (68 characters).
|
|
21
21
|
"""
|
|
22
|
-
|
|
22
|
+
# Build byte array for the action table (32 bytes total)
|
|
23
|
+
raw_bytes = bytearray()
|
|
23
24
|
|
|
24
|
-
# Encode all 4 input actions
|
|
25
|
+
# Encode all 4 input actions (2 bytes each = 8 bytes total)
|
|
25
26
|
input_actions = [
|
|
26
27
|
action_table.input1_action,
|
|
27
28
|
action_table.input2_action,
|
|
@@ -30,26 +31,24 @@ class Xp24MsActionTableSerializer:
|
|
|
30
31
|
]
|
|
31
32
|
|
|
32
33
|
for action in input_actions:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
]
|
|
49
|
-
)
|
|
34
|
+
raw_bytes.append(action.type.value)
|
|
35
|
+
raw_bytes.append(action.param.value)
|
|
36
|
+
|
|
37
|
+
# Add settings (5 bytes)
|
|
38
|
+
raw_bytes.append(0x01 if action_table.mutex12 else 0x00)
|
|
39
|
+
raw_bytes.append(0x01 if action_table.mutex34 else 0x00)
|
|
40
|
+
raw_bytes.append(action_table.mutual_deadtime)
|
|
41
|
+
raw_bytes.append(0x01 if action_table.curtain12 else 0x00)
|
|
42
|
+
raw_bytes.append(0x01 if action_table.curtain34 else 0x00)
|
|
43
|
+
|
|
44
|
+
# Add padding to reach 32 bytes (19 more bytes needed)
|
|
45
|
+
raw_bytes.extend([0x00] * 19)
|
|
46
|
+
|
|
47
|
+
# Encode to A-P nibbles (32 bytes -> 64 chars)
|
|
48
|
+
encoded_data = nibbles(bytes(raw_bytes))
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
return
|
|
50
|
+
# Prepend action table count "AAAA" (4 chars) -> total 68 chars
|
|
51
|
+
return "AAAA" + encoded_data
|
|
53
52
|
|
|
54
53
|
@staticmethod
|
|
55
54
|
def from_data(msactiontable_rawdata: str) -> Xp24MsActionTable:
|
|
@@ -66,7 +65,9 @@ class Xp24MsActionTableSerializer:
|
|
|
66
65
|
"""
|
|
67
66
|
raw_length = len(msactiontable_rawdata)
|
|
68
67
|
if raw_length != 68:
|
|
69
|
-
raise ValueError(
|
|
68
|
+
raise ValueError(
|
|
69
|
+
f"Msactiontable is not 68 bytes long ({raw_length}): {msactiontable_rawdata}"
|
|
70
|
+
)
|
|
70
71
|
|
|
71
72
|
# Remove action table count AAAA, AAAB .
|
|
72
73
|
data = msactiontable_rawdata[4:]
|
|
@@ -117,18 +118,3 @@ class Xp24MsActionTableSerializer:
|
|
|
117
118
|
param_type = TimeParam(param_id)
|
|
118
119
|
|
|
119
120
|
return InputAction(action_type, param_type)
|
|
120
|
-
|
|
121
|
-
@staticmethod
|
|
122
|
-
def from_telegrams(ms_telegrams: str) -> Xp24MsActionTable:
|
|
123
|
-
"""Legacy method for backward compatibility. Use from_data() instead.
|
|
124
|
-
|
|
125
|
-
Args:
|
|
126
|
-
ms_telegrams: Telegram data string.
|
|
127
|
-
|
|
128
|
-
Returns:
|
|
129
|
-
Deserialized XP24 MS action table.
|
|
130
|
-
"""
|
|
131
|
-
# For backward compatibility, assume full telegrams and extract data
|
|
132
|
-
data_parts = ms_telegrams[16:84]
|
|
133
|
-
|
|
134
|
-
return Xp24MsActionTableSerializer.from_data(data_parts)
|
|
@@ -6,7 +6,7 @@ from xp.models.actiontable.msactiontable_xp33 import (
|
|
|
6
6
|
Xp33Scene,
|
|
7
7
|
)
|
|
8
8
|
from xp.models.telegram.timeparam_type import TimeParam
|
|
9
|
-
from xp.utils.serialization import bits_to_byte, byte_to_bits, de_nibbles,
|
|
9
|
+
from xp.utils.serialization import bits_to_byte, byte_to_bits, de_nibbles, nibbles
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class Xp33MsActionTableSerializer:
|
|
@@ -96,13 +96,11 @@ class Xp33MsActionTableSerializer:
|
|
|
96
96
|
raw_bytes[24] = bits_to_byte(leading_edge_bits)
|
|
97
97
|
|
|
98
98
|
# Bytes 25-31 are padding (already 0)
|
|
99
|
-
|
|
100
99
|
# Convert to hex string using nibble encoding
|
|
101
|
-
|
|
102
|
-
for byte_val in raw_bytes:
|
|
103
|
-
hex_data += nibble(byte_val)
|
|
100
|
+
encoded_data = nibbles(raw_bytes)
|
|
104
101
|
|
|
105
|
-
|
|
102
|
+
# Convert raw bytes to hex string with A-P encoding
|
|
103
|
+
return "AAAA" + encoded_data
|
|
106
104
|
|
|
107
105
|
@staticmethod
|
|
108
106
|
def from_data(msactiontable_rawdata: str) -> Xp33MsActionTable:
|
|
@@ -239,18 +237,3 @@ class Xp33MsActionTableSerializer:
|
|
|
239
237
|
output3_level=output3_level,
|
|
240
238
|
time=time_param,
|
|
241
239
|
)
|
|
242
|
-
|
|
243
|
-
@staticmethod
|
|
244
|
-
def from_telegrams(ms_telegrams: str) -> Xp33MsActionTable:
|
|
245
|
-
"""Legacy method for backward compatibility. Use from_data() instead.
|
|
246
|
-
|
|
247
|
-
Args:
|
|
248
|
-
ms_telegrams: Telegram data string.
|
|
249
|
-
|
|
250
|
-
Returns:
|
|
251
|
-
Deserialized XP33 MS action table.
|
|
252
|
-
"""
|
|
253
|
-
# For backward compatibility, assume full telegrams and extract data
|
|
254
|
-
data_parts = ms_telegrams[16:152] # Adjusted for XP33 length
|
|
255
|
-
|
|
256
|
-
return Xp33MsActionTableSerializer.from_data(data_parts)
|
{conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/actiontable/actiontable_service.py
RENAMED
|
@@ -10,7 +10,7 @@ from xp.models.actiontable.actiontable import ActionTable
|
|
|
10
10
|
from xp.models.protocol.conbus_protocol import TelegramReceivedEvent
|
|
11
11
|
from xp.models.telegram.system_function import SystemFunction
|
|
12
12
|
from xp.models.telegram.telegram_type import TelegramType
|
|
13
|
-
from xp.services.
|
|
13
|
+
from xp.services.actiontable.actiontable_serializer import ActionTableSerializer
|
|
14
14
|
from xp.services.protocol import ConbusProtocol
|
|
15
15
|
from xp.services.telegram.telegram_service import TelegramService
|
|
16
16
|
|
{conson_xp-1.5.0 → conson_xp-1.7.0}/src/xp/services/conbus/actiontable/msactiontable_service.py
RENAMED
|
@@ -12,13 +12,13 @@ from xp.models.actiontable.msactiontable_xp33 import Xp33MsActionTable
|
|
|
12
12
|
from xp.models.protocol.conbus_protocol import TelegramReceivedEvent
|
|
13
13
|
from xp.models.telegram.system_function import SystemFunction
|
|
14
14
|
from xp.models.telegram.telegram_type import TelegramType
|
|
15
|
-
from xp.services.
|
|
15
|
+
from xp.services.actiontable.msactiontable_xp20_serializer import (
|
|
16
16
|
Xp20MsActionTableSerializer,
|
|
17
17
|
)
|
|
18
|
-
from xp.services.
|
|
18
|
+
from xp.services.actiontable.msactiontable_xp24_serializer import (
|
|
19
19
|
Xp24MsActionTableSerializer,
|
|
20
20
|
)
|
|
21
|
-
from xp.services.
|
|
21
|
+
from xp.services.actiontable.msactiontable_xp33_serializer import (
|
|
22
22
|
Xp33MsActionTableSerializer,
|
|
23
23
|
)
|
|
24
24
|
from xp.services.protocol import ConbusProtocol
|
|
@@ -74,7 +74,8 @@ class MsActionTableService(ConbusProtocol):
|
|
|
74
74
|
self.error_callback: Optional[Callable[[str], None]] = None
|
|
75
75
|
self.finish_callback: Optional[
|
|
76
76
|
Callable[
|
|
77
|
-
[Union[Xp20MsActionTable, Xp24MsActionTable, Xp33MsActionTable]],
|
|
77
|
+
[Union[Xp20MsActionTable, Xp24MsActionTable, Xp33MsActionTable, None]],
|
|
78
|
+
None,
|
|
78
79
|
]
|
|
79
80
|
] = None
|
|
80
81
|
self.msactiontable_data: list[str] = []
|
|
@@ -114,17 +115,32 @@ class MsActionTableService(ConbusProtocol):
|
|
|
114
115
|
self.logger.debug("Not a reply response")
|
|
115
116
|
return
|
|
116
117
|
|
|
117
|
-
reply_telegram = self.telegram_service.parse_reply_telegram(
|
|
118
|
+
reply_telegram = self.telegram_service.parse_reply_telegram(
|
|
119
|
+
telegram_received.frame
|
|
120
|
+
)
|
|
118
121
|
if reply_telegram.system_function not in (
|
|
119
122
|
SystemFunction.MSACTIONTABLE,
|
|
123
|
+
SystemFunction.ACK,
|
|
124
|
+
SystemFunction.NAK,
|
|
120
125
|
SystemFunction.EOF,
|
|
121
126
|
):
|
|
122
127
|
self.logger.debug("Not a msactiontable response")
|
|
123
128
|
return
|
|
124
129
|
|
|
125
|
-
if reply_telegram.system_function == SystemFunction.
|
|
126
|
-
self.logger.debug("
|
|
127
|
-
|
|
130
|
+
if reply_telegram.system_function == SystemFunction.ACK:
|
|
131
|
+
self.logger.debug("Received ACK")
|
|
132
|
+
return
|
|
133
|
+
|
|
134
|
+
if reply_telegram.system_function == SystemFunction.NAK:
|
|
135
|
+
self.logger.debug("Received NAK")
|
|
136
|
+
self.failed("Received NAK")
|
|
137
|
+
return
|
|
138
|
+
|
|
139
|
+
if reply_telegram.system_function == SystemFunction.MSACTIONTABLE:
|
|
140
|
+
self.logger.debug("Received MSACTIONTABLE")
|
|
141
|
+
self.msactiontable_data.extend(
|
|
142
|
+
(reply_telegram.data, reply_telegram.data_value)
|
|
143
|
+
)
|
|
128
144
|
if self.progress_callback:
|
|
129
145
|
self.progress_callback(".")
|
|
130
146
|
|
|
@@ -137,11 +153,14 @@ class MsActionTableService(ConbusProtocol):
|
|
|
137
153
|
return
|
|
138
154
|
|
|
139
155
|
if reply_telegram.system_function == SystemFunction.EOF:
|
|
156
|
+
self.logger.debug("Received EOF")
|
|
140
157
|
all_data = "".join(self.msactiontable_data)
|
|
141
158
|
# Deserialize from received data
|
|
142
159
|
msactiontable = self.serializer.from_data(all_data)
|
|
143
|
-
|
|
144
|
-
|
|
160
|
+
self.succeed(msactiontable)
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
self.logger.debug("Invalid msactiontable response")
|
|
145
164
|
|
|
146
165
|
def failed(self, message: str) -> None:
|
|
147
166
|
"""Handle failed connection event.
|
|
@@ -152,6 +171,20 @@ class MsActionTableService(ConbusProtocol):
|
|
|
152
171
|
self.logger.debug(f"Failed: {message}")
|
|
153
172
|
if self.error_callback:
|
|
154
173
|
self.error_callback(message)
|
|
174
|
+
self._stop_reactor()
|
|
175
|
+
|
|
176
|
+
def succeed(
|
|
177
|
+
self,
|
|
178
|
+
msactiontable: Union[Xp20MsActionTable, Xp24MsActionTable, Xp33MsActionTable],
|
|
179
|
+
) -> None:
|
|
180
|
+
"""Handle succeed connection event.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
msactiontable: result.
|
|
184
|
+
"""
|
|
185
|
+
if self.finish_callback:
|
|
186
|
+
self.finish_callback(msactiontable)
|
|
187
|
+
self._stop_reactor()
|
|
155
188
|
|
|
156
189
|
def start(
|
|
157
190
|
self,
|
|
@@ -160,7 +193,7 @@ class MsActionTableService(ConbusProtocol):
|
|
|
160
193
|
progress_callback: Callable[[str], None],
|
|
161
194
|
error_callback: Callable[[str], None],
|
|
162
195
|
finish_callback: Callable[
|
|
163
|
-
[Union[Xp20MsActionTable, Xp24MsActionTable, Xp33MsActionTable]], None
|
|
196
|
+
[Union[Xp20MsActionTable, Xp24MsActionTable, Xp33MsActionTable, None]], None
|
|
164
197
|
],
|
|
165
198
|
timeout_seconds: Optional[float] = None,
|
|
166
199
|
) -> None:
|
|
@@ -230,13 +230,11 @@ class ConbusProtocol(protocol.Protocol, protocol.ClientFactory):
|
|
|
230
230
|
self.timeout_call = self.reactor.callLater(
|
|
231
231
|
self.timeout_seconds, self._on_timeout
|
|
232
232
|
)
|
|
233
|
-
self.logger.debug(f"Timeout set for {self.timeout_seconds} seconds")
|
|
234
233
|
|
|
235
234
|
def _cancel_timeout(self) -> None:
|
|
236
235
|
"""Cancel the inactivity timeout."""
|
|
237
236
|
if self.timeout_call and self.timeout_call.active():
|
|
238
237
|
self.timeout_call.cancel()
|
|
239
|
-
self.logger.debug("Timeout cancelled")
|
|
240
238
|
|
|
241
239
|
def _on_timeout(self) -> None:
|
|
242
240
|
"""Handle inactivity timeout expiration."""
|
|
@@ -7,7 +7,7 @@ containing common functionality like module type response generation.
|
|
|
7
7
|
import logging
|
|
8
8
|
import threading
|
|
9
9
|
from abc import ABC
|
|
10
|
-
from typing import Optional
|
|
10
|
+
from typing import Any, Optional
|
|
11
11
|
|
|
12
12
|
from xp.models import ModuleTypeCode
|
|
13
13
|
from xp.models.telegram.datapoint_type import DataPointType
|
|
@@ -46,6 +46,9 @@ class BaseServerService(ABC):
|
|
|
46
46
|
self.telegram_buffer: list[str] = []
|
|
47
47
|
self.telegram_buffer_lock = threading.Lock() # Lock for socket set
|
|
48
48
|
|
|
49
|
+
# MsActionTable download state (None, "ack_sent", "data_sent")
|
|
50
|
+
self.msactiontable_download_state: Optional[str] = None
|
|
51
|
+
|
|
49
52
|
def generate_datapoint_type_response(
|
|
50
53
|
self, datapoint_type: DataPointType
|
|
51
54
|
) -> Optional[str]:
|
|
@@ -151,6 +154,76 @@ class BaseServerService(ABC):
|
|
|
151
154
|
|
|
152
155
|
return None
|
|
153
156
|
|
|
157
|
+
def _get_msactiontable_serializer(self) -> Optional[Any]:
|
|
158
|
+
"""Get the MsActionTable serializer for this device.
|
|
159
|
+
|
|
160
|
+
Subclasses should override this to return their specific serializer.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
The serializer instance, or None if not supported.
|
|
164
|
+
"""
|
|
165
|
+
return None
|
|
166
|
+
|
|
167
|
+
def _get_msactiontable(self) -> Optional[Any]:
|
|
168
|
+
"""Get the MsActionTable for this device.
|
|
169
|
+
|
|
170
|
+
Subclasses should override this to return their msactiontable instance.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
The msactiontable instance, or None if not supported.
|
|
174
|
+
"""
|
|
175
|
+
return None
|
|
176
|
+
|
|
177
|
+
def _handle_download_msactiontable_request(
|
|
178
|
+
self, request: SystemTelegram
|
|
179
|
+
) -> Optional[str]:
|
|
180
|
+
"""Handle F13D - DOWNLOAD_MSACTIONTABLE request.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
request: The system telegram request to process.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
ACK telegram if request is valid, NAK otherwise.
|
|
187
|
+
"""
|
|
188
|
+
serializer = self._get_msactiontable_serializer()
|
|
189
|
+
msactiontable = self._get_msactiontable()
|
|
190
|
+
|
|
191
|
+
# Only handle if serializer and msactiontable are available
|
|
192
|
+
if not serializer or msactiontable is None:
|
|
193
|
+
return None
|
|
194
|
+
|
|
195
|
+
# Send ACK and queue data telegram
|
|
196
|
+
ack_data = self._build_response_telegram(f"R{self.serial_number}F18D") # ACK
|
|
197
|
+
|
|
198
|
+
# Send MsActionTable data
|
|
199
|
+
encoded_data = serializer.to_data(msactiontable)
|
|
200
|
+
data_telegram = self._build_response_telegram(
|
|
201
|
+
f"R{self.serial_number}F17D{encoded_data}"
|
|
202
|
+
)
|
|
203
|
+
self.msactiontable_download_state = "data_sent"
|
|
204
|
+
|
|
205
|
+
# Return ACK and TABLE
|
|
206
|
+
return ack_data + data_telegram
|
|
207
|
+
|
|
208
|
+
def _handle_download_msactiontable_ack_request(
|
|
209
|
+
self, _request: SystemTelegram
|
|
210
|
+
) -> Optional[str]:
|
|
211
|
+
"""Handle MsActionTable download ACK protocol.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
_request: The system telegram request (unused, kept for signature consistency).
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
Data telegram, EOF telegram, or NAK if state is invalid.
|
|
218
|
+
"""
|
|
219
|
+
if self.msactiontable_download_state == "data_sent":
|
|
220
|
+
# Send EOF
|
|
221
|
+
eof_telegram = self._build_response_telegram(f"R{self.serial_number}F16D")
|
|
222
|
+
self.msactiontable_download_state = None
|
|
223
|
+
return eof_telegram
|
|
224
|
+
|
|
225
|
+
return self._build_response_telegram(f"R{self.serial_number}F19D") # NAK
|
|
226
|
+
|
|
154
227
|
def process_system_telegram(self, request: SystemTelegram) -> Optional[str]:
|
|
155
228
|
"""Template method for processing system telegrams.
|
|
156
229
|
|
|
@@ -177,6 +250,15 @@ class BaseServerService(ABC):
|
|
|
177
250
|
elif request.system_function == SystemFunction.ACTION:
|
|
178
251
|
return self._handle_action_request(request)
|
|
179
252
|
|
|
253
|
+
elif request.system_function == SystemFunction.DOWNLOAD_MSACTIONTABLE:
|
|
254
|
+
return self._handle_download_msactiontable_request(request)
|
|
255
|
+
|
|
256
|
+
elif (
|
|
257
|
+
request.system_function == SystemFunction.ACK
|
|
258
|
+
and self.msactiontable_download_state
|
|
259
|
+
):
|
|
260
|
+
return self._handle_download_msactiontable_ack_request(request)
|
|
261
|
+
|
|
180
262
|
self.logger.warning(f"Unhandled {self.device_type} request: {request}")
|
|
181
263
|
return None
|
|
182
264
|
|
|
@@ -278,11 +360,7 @@ class BaseServerService(ABC):
|
|
|
278
360
|
Returns:
|
|
279
361
|
List of telegram strings from the buffer. The buffer is cleared after collection.
|
|
280
362
|
"""
|
|
281
|
-
self.logger.debug(
|
|
282
|
-
f"Collecting {self.serial_number} telegrams from buffer: {len(self.telegram_buffer)}"
|
|
283
|
-
)
|
|
284
363
|
with self.telegram_buffer_lock:
|
|
285
364
|
result = self.telegram_buffer.copy()
|
|
286
|
-
self.logger.debug(f"Resetting {self.serial_number} buffer")
|
|
287
365
|
self.telegram_buffer.clear()
|
|
288
366
|
return result
|
|
@@ -8,6 +8,7 @@ from typing import Dict, Optional
|
|
|
8
8
|
|
|
9
9
|
from xp.models import ModuleTypeCode
|
|
10
10
|
from xp.models.telegram.system_telegram import SystemTelegram
|
|
11
|
+
from xp.services.actiontable.msactiontable_serializer import MsActionTableSerializer
|
|
11
12
|
from xp.services.server.base_server_service import BaseServerService
|
|
12
13
|
|
|
13
14
|
|
|
@@ -25,11 +26,18 @@ class CP20ServerService(BaseServerService):
|
|
|
25
26
|
and implements CP20 telegram format.
|
|
26
27
|
"""
|
|
27
28
|
|
|
28
|
-
def __init__(
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
serial_number: str,
|
|
32
|
+
_variant: str = "",
|
|
33
|
+
_msactiontable_serializer: Optional[MsActionTableSerializer] = None,
|
|
34
|
+
):
|
|
29
35
|
"""Initialize CP20 server service.
|
|
30
36
|
|
|
31
37
|
Args:
|
|
32
38
|
serial_number: The device serial number.
|
|
39
|
+
_variant: Reserved parameter for consistency (unused).
|
|
40
|
+
_msactiontable_serializer: Generic MsActionTable serializer (unused).
|
|
33
41
|
"""
|
|
34
42
|
super().__init__(serial_number)
|
|
35
43
|
self.device_type = "CP20"
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""Device Service Factory for creating device instances.
|
|
2
|
+
|
|
3
|
+
This module provides a factory for creating device service instances
|
|
4
|
+
with proper dependency injection of serializers.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from xp.services.actiontable.msactiontable_serializer import MsActionTableSerializer
|
|
8
|
+
from xp.services.actiontable.msactiontable_xp20_serializer import (
|
|
9
|
+
Xp20MsActionTableSerializer,
|
|
10
|
+
)
|
|
11
|
+
from xp.services.actiontable.msactiontable_xp24_serializer import (
|
|
12
|
+
Xp24MsActionTableSerializer,
|
|
13
|
+
)
|
|
14
|
+
from xp.services.actiontable.msactiontable_xp33_serializer import (
|
|
15
|
+
Xp33MsActionTableSerializer,
|
|
16
|
+
)
|
|
17
|
+
from xp.services.server.base_server_service import BaseServerService
|
|
18
|
+
from xp.services.server.cp20_server_service import CP20ServerService
|
|
19
|
+
from xp.services.server.xp20_server_service import XP20ServerService
|
|
20
|
+
from xp.services.server.xp24_server_service import XP24ServerService
|
|
21
|
+
from xp.services.server.xp33_server_service import XP33ServerService
|
|
22
|
+
from xp.services.server.xp130_server_service import XP130ServerService
|
|
23
|
+
from xp.services.server.xp230_server_service import XP230ServerService
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class DeviceServiceFactory:
|
|
27
|
+
"""Factory for creating device service instances.
|
|
28
|
+
|
|
29
|
+
Encapsulates device creation logic and handles serializer injection
|
|
30
|
+
for different device types.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
xp20ms_serializer: Xp20MsActionTableSerializer,
|
|
36
|
+
xp24ms_serializer: Xp24MsActionTableSerializer,
|
|
37
|
+
xp33ms_serializer: Xp33MsActionTableSerializer,
|
|
38
|
+
ms_serializer: MsActionTableSerializer,
|
|
39
|
+
):
|
|
40
|
+
"""Initialize device service factory.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
xp20ms_serializer: XP20 MsActionTable serializer (injected via DI).
|
|
44
|
+
xp24ms_serializer: XP24 MsActionTable serializer (injected via DI).
|
|
45
|
+
xp33ms_serializer: XP33 MsActionTable serializer (injected via DI).
|
|
46
|
+
ms_serializer: Generic MsActionTable serializer (injected via DI).
|
|
47
|
+
"""
|
|
48
|
+
self.xp20ms_serializer = xp20ms_serializer
|
|
49
|
+
self.xp24ms_serializer = xp24ms_serializer
|
|
50
|
+
self.xp33ms_serializer = xp33ms_serializer
|
|
51
|
+
self.ms_serializer = ms_serializer
|
|
52
|
+
|
|
53
|
+
def create_device(self, module_type: str, serial_number: str) -> BaseServerService:
|
|
54
|
+
"""Create device instance for given module type.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
module_type: Module type code (e.g., "XP20", "XP33LR").
|
|
58
|
+
serial_number: Device serial number.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Device service instance configured with appropriate serializer.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
ValueError: If module_type is unknown or unsupported.
|
|
65
|
+
"""
|
|
66
|
+
# Map module types to their constructors and parameters
|
|
67
|
+
if module_type == "CP20":
|
|
68
|
+
return CP20ServerService(serial_number, "CP20", self.ms_serializer)
|
|
69
|
+
|
|
70
|
+
elif module_type == "XP24":
|
|
71
|
+
return XP24ServerService(serial_number, "XP24", self.xp24ms_serializer)
|
|
72
|
+
|
|
73
|
+
elif module_type == "XP33":
|
|
74
|
+
return XP33ServerService(serial_number, "XP33", self.xp33ms_serializer)
|
|
75
|
+
|
|
76
|
+
elif module_type == "XP33LR":
|
|
77
|
+
return XP33ServerService(serial_number, "XP33LR", self.xp33ms_serializer)
|
|
78
|
+
|
|
79
|
+
elif module_type == "XP33LED":
|
|
80
|
+
return XP33ServerService(serial_number, "XP33LED", self.xp33ms_serializer)
|
|
81
|
+
|
|
82
|
+
elif module_type == "XP20":
|
|
83
|
+
return XP20ServerService(serial_number, "XP20", self.xp20ms_serializer)
|
|
84
|
+
|
|
85
|
+
elif module_type == "XP130":
|
|
86
|
+
return XP130ServerService(serial_number, "XP130", self.ms_serializer)
|
|
87
|
+
|
|
88
|
+
elif module_type == "XP230":
|
|
89
|
+
return XP230ServerService(serial_number, "XP230", self.ms_serializer)
|
|
90
|
+
|
|
91
|
+
else:
|
|
92
|
+
raise ValueError(
|
|
93
|
+
f"Unknown device type '{module_type}' for serial {serial_number}"
|
|
94
|
+
)
|