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