conson-xp 2.0.2__tar.gz → 2.0.4__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-2.0.2 → conson_xp-2.0.4}/PKG-INFO +1 -1
- {conson_xp-2.0.2 → conson_xp-2.0.4}/pyproject.toml +1 -1
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/__init__.py +1 -1
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_raw_commands.py +9 -10
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_raw_service.py +13 -10
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/term/homekit_accessory_driver.py +67 -11
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/term/homekit_service.py +63 -4
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_conbus_raw_integration.py +27 -20
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_conbus_raw_service.py +8 -8
- {conson_xp-2.0.2 → conson_xp-2.0.4}/LICENSE +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/README.md +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/__main__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_actiontable_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_autoreport_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_blink_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_config_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_custom_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_datapoint_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_discover_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_event_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_export_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_lightlevel_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_linknumber_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_modulenumber_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_msactiontable_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_output_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_receive_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_scan_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/file_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/module_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/reverse_proxy_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/server/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/server/server_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram_blink_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram_checksum_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram_discover_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram_linknumber_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram_parse_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram_version_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/term/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/term/term.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/term/term_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/main.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/utils/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/utils/click_tree.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/utils/datapoint_type_choice.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/utils/decorators.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/utils/error_handlers.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/utils/formatters.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/utils/module_type_choice.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/utils/serial_number_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/utils/system_function_choice.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/actiontable/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/actiontable/actiontable.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/actiontable/actiontable_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/actiontable/msactiontable_xp20.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/actiontable/msactiontable_xp24.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/actiontable/msactiontable_xp33.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_autoreport.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_blink.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_client_config.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_connection_status.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_custom.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_datapoint.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_discover.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_event_list.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_event_raw.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_export.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_lightlevel.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_linknumber.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_logger_config.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_output.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_raw.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_receive.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/conbus/conbus_writeconfig.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/config/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/config/conson_module_config.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/homekit/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/homekit/homekit_accessory.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/homekit/homekit_config.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/log_entry.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/protocol/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/protocol/conbus_protocol.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/response.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/action_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/datapoint_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/event_telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/event_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/input_action_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/input_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/module_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/module_type_code.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/output_telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/reply_telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/system_function.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/system_telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/telegram_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/telegram/timeparam_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/term/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/term/accessory_state.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/term/connection_state.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/term/module_state.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/term/protocol_keys_config.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/term/status_message.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/term/telegram_display.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/models/write_config_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/actiontable/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/actiontable/actiontable_serializer.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/actiontable/download_state_machine.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/actiontable/msactiontable_serializer.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/actiontable/msactiontable_xp20_serializer.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/actiontable/msactiontable_xp24_serializer.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/actiontable/msactiontable_xp33_serializer.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/actiontable/serializer_protocol.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/actiontable/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/actiontable/actiontable_download_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/actiontable/actiontable_list_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/actiontable/actiontable_show_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/actiontable/actiontable_upload_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_blink_all_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_blink_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_custom_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_datapoint_queryall_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_datapoint_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_discover_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_event_list_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_event_raw_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_export_actiontable_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_export_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_output_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_receive_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/conbus_scan_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/conbus/write_config_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/log_file_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/module_type_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/protocol/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/protocol/conbus_event_protocol.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/reverse_proxy_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/base_server_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/client_buffer_manager.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/cp20_server_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/device_service_factory.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/server_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/xp130_server_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/xp20_server_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/xp230_server_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/xp24_server_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/server/xp33_server_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/telegram/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/telegram/telegram_blink_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/telegram/telegram_checksum_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/telegram/telegram_datapoint_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/telegram/telegram_discover_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/telegram/telegram_link_number_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/telegram/telegram_output_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/telegram/telegram_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/telegram/telegram_version_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/term/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/term/protocol_monitor_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/services/term/state_monitor_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/homekit.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/homekit.tcss +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/protocol.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/protocol.tcss +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/state.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/state.tcss +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/widgets/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/widgets/help_menu.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/widgets/modules_list.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/widgets/protocol_log.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/widgets/room_list.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/term/widgets/status_footer.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/utils/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/utils/checksum.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/utils/dependencies.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/utils/event_helper.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/utils/logging.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/utils/serialization.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/utils/state_machine.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/utils/time_utils.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/.coverage +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/conftest.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/.coverage +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/telegram_test_data.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_actiontable_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_api/.coverage +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_api/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_blink_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_checksum_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_conbus_blink_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_conbus_datapoint_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_conbus_receive_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_discovery_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_event_telegram_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_link_number_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_module_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_output_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_reverse_proxy_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_system_reply_telegram_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_term_logging_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_version_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_xp20_action_table_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/integration/test_xp24_action_table_integration.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_api/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_click_tree.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_conbus_actiontable_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_conbus_blink_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_conbus_msactiontable_upload_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_datapoint_type_choice.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_decorators.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_error_handlers.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_formatters.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_serial_number_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_system_function_choice.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_cli/test_term_commands.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_encoding/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_encoding/test_latin1_edge_cases.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_conbus.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_conbus_client_send.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_conbus_discover.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_conbus_linknumber.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_event_telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_log_entry.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_logger_config.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_module_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_reply_telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_system_telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_system_telegram_enhancements.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_term/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_term/test_accessory_state.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_version_telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_write_config_type.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_xp20_action_table.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_xp24_action_table.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_xp24_action_table_short_format.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_models/test_xp24_action_telegram.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_actiontable_download_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_actiontable_serializer.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_actiontable_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_actiontable_upload_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_base_server_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_blink_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_checksum_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_client_buffer_manager.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_conbus_blink_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_conbus_event_list_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_conbus_event_protocol.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_conbus_event_raw_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_conbus_output_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_conbus_receive_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_conbus_reverse_proxy_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_conbus_scan_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_device_service_factory.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_discovery_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_homekit_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_log_file_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_module_type_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_protocol_monitor_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_server_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_state_monitor_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_telegram_input_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_telegram_output_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_telegram_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_version_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_xp20_action_table_serializer.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_xp24_action_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_xp24_action_table_serializer.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_xp24_action_table_service.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_xp33_action_table_serializer.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_xp33_short_format.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_services/test_xp_server_services.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_tui/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_tui/test_homekit_app.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_tui/test_protocol_log.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_tui/test_room_list.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_utils/__init__.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_utils/test_checksum.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_utils/test_event_helper.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_utils/test_logging.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_utils/test_serialization.py +0 -0
- {conson_xp-2.0.2 → conson_xp-2.0.4}/tests/unit/test_utils/test_time_utils.py +0 -0
|
@@ -14,25 +14,24 @@ from xp.services.conbus.conbus_raw_service import ConbusRawService
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@conbus.command("raw")
|
|
17
|
-
@click.argument("
|
|
17
|
+
@click.argument("telegrams", nargs=-1, required=True)
|
|
18
18
|
@click.pass_context
|
|
19
19
|
@connection_command()
|
|
20
|
-
def send_raw_telegrams(ctx: Context,
|
|
20
|
+
def send_raw_telegrams(ctx: Context, telegrams: tuple[str, ...]) -> None:
|
|
21
21
|
r"""
|
|
22
22
|
Send raw telegram sequence to Conbus server.
|
|
23
23
|
|
|
24
|
-
Accepts
|
|
25
|
-
Multiple telegrams should be concatenated without separators.
|
|
24
|
+
Accepts one or more telegrams in format S2113010000F02D (without <> nor CHECKSUM) as separate arguments.
|
|
26
25
|
|
|
27
26
|
Args:
|
|
28
27
|
ctx: Click context object.
|
|
29
|
-
|
|
28
|
+
telegrams: Raw telegram string(s).
|
|
30
29
|
|
|
31
30
|
Examples:
|
|
32
31
|
\b
|
|
33
|
-
xp conbus raw '
|
|
34
|
-
xp conbus raw '
|
|
35
|
-
xp conbus raw '
|
|
32
|
+
xp conbus raw 'S2113010000F02D'
|
|
33
|
+
xp conbus raw 'S2113010000F02D' 'S2113010001F02D'
|
|
34
|
+
xp conbus raw 'S0012345003F02D12F' 'S0012345009F02D12'
|
|
36
35
|
"""
|
|
37
36
|
service: ConbusRawService = (
|
|
38
37
|
ctx.obj.get("container").get_container().resolve(ConbusRawService)
|
|
@@ -62,8 +61,8 @@ def send_raw_telegrams(ctx: Context, raw_telegrams: str) -> None:
|
|
|
62
61
|
service.on_progress.connect(on_progress)
|
|
63
62
|
service.on_finish.connect(on_finish)
|
|
64
63
|
# Setup
|
|
65
|
-
service.
|
|
66
|
-
|
|
64
|
+
service.send_raw_telegrams(
|
|
65
|
+
telegrams=list(telegrams),
|
|
67
66
|
timeout_seconds=5.0,
|
|
68
67
|
)
|
|
69
68
|
# Start (blocks until completion)
|
|
@@ -51,7 +51,7 @@ class ConbusRawService:
|
|
|
51
51
|
self.conbus_protocol.on_timeout.connect(self.timeout)
|
|
52
52
|
self.conbus_protocol.on_failed.connect(self.failed)
|
|
53
53
|
|
|
54
|
-
self.
|
|
54
|
+
self.telegrams: list[str] = []
|
|
55
55
|
self.service_response: ConbusRawResponse = ConbusRawResponse(
|
|
56
56
|
success=False,
|
|
57
57
|
)
|
|
@@ -60,8 +60,11 @@ class ConbusRawService:
|
|
|
60
60
|
|
|
61
61
|
def connection_made(self) -> None:
|
|
62
62
|
"""Handle connection established event."""
|
|
63
|
-
self.logger.debug(
|
|
64
|
-
|
|
63
|
+
self.logger.debug(
|
|
64
|
+
f"Connection established, sending {len(self.telegrams)} telegrams"
|
|
65
|
+
)
|
|
66
|
+
for telegram in self.telegrams:
|
|
67
|
+
self.conbus_protocol.send_raw_telegram(telegram)
|
|
65
68
|
|
|
66
69
|
def telegram_sent(self, telegram_sent: str) -> None:
|
|
67
70
|
"""
|
|
@@ -108,22 +111,22 @@ class ConbusRawService:
|
|
|
108
111
|
self.service_response.error = message
|
|
109
112
|
self.on_finish.emit(self.service_response)
|
|
110
113
|
|
|
111
|
-
def
|
|
114
|
+
def send_raw_telegrams(
|
|
112
115
|
self,
|
|
113
|
-
|
|
116
|
+
telegrams: list[str],
|
|
114
117
|
timeout_seconds: Optional[float] = None,
|
|
115
118
|
) -> None:
|
|
116
119
|
"""
|
|
117
|
-
Send
|
|
120
|
+
Send raw telegrams to the Conbus server.
|
|
118
121
|
|
|
119
122
|
Args:
|
|
120
|
-
|
|
123
|
+
telegrams: List of raw telegram strings to send.
|
|
121
124
|
timeout_seconds: Timeout in seconds.
|
|
122
125
|
"""
|
|
123
|
-
self.logger.info("Starting
|
|
126
|
+
self.logger.info(f"Starting send_raw_telegrams with {len(telegrams)} telegrams")
|
|
124
127
|
if timeout_seconds:
|
|
125
128
|
self.conbus_protocol.timeout_seconds = timeout_seconds
|
|
126
|
-
self.
|
|
129
|
+
self.telegrams = telegrams
|
|
127
130
|
|
|
128
131
|
def set_timeout(self, timeout_seconds: float) -> None:
|
|
129
132
|
"""
|
|
@@ -151,7 +154,7 @@ class ConbusRawService:
|
|
|
151
154
|
"""
|
|
152
155
|
# Reset state for singleton reuse
|
|
153
156
|
self.service_response = ConbusRawResponse(success=False)
|
|
154
|
-
self.
|
|
157
|
+
self.telegrams = []
|
|
155
158
|
return self
|
|
156
159
|
|
|
157
160
|
def __exit__(
|
|
@@ -10,9 +10,18 @@ from pyhap.const import CATEGORY_LIGHTBULB, CATEGORY_OUTLET
|
|
|
10
10
|
|
|
11
11
|
from xp.models.homekit.homekit_config import HomekitConfig
|
|
12
12
|
|
|
13
|
+
# Callback type: (accessory_name, is_on, brightness_or_none)
|
|
14
|
+
OnSetCallback = Callable[[str, bool, Optional[int]], None]
|
|
15
|
+
|
|
13
16
|
|
|
14
17
|
class XPAccessory(Accessory):
|
|
15
|
-
"""
|
|
18
|
+
"""
|
|
19
|
+
Single accessory wrapping a Conbus output.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
logger: Logger instance for this accessory.
|
|
23
|
+
current_brightness: Current brightness value 0-100.
|
|
24
|
+
"""
|
|
16
25
|
|
|
17
26
|
def __init__(
|
|
18
27
|
self,
|
|
@@ -35,12 +44,19 @@ class XPAccessory(Accessory):
|
|
|
35
44
|
super().__init__(driver._driver, display_name, aid=aid)
|
|
36
45
|
self._hk_driver = driver
|
|
37
46
|
self._accessory_id = name
|
|
47
|
+
self._is_dimmable = service_type == "dimminglight"
|
|
48
|
+
self._char_brightness: Optional[object] = None
|
|
49
|
+
self._current_brightness: int = 100
|
|
38
50
|
self.logger = logging.getLogger(__name__)
|
|
39
51
|
|
|
40
|
-
if
|
|
52
|
+
if self._is_dimmable:
|
|
41
53
|
self.category = CATEGORY_LIGHTBULB
|
|
42
54
|
serv = self.add_preload_service("Lightbulb", chars=["On", "Brightness"])
|
|
43
|
-
|
|
55
|
+
self._char_brightness = serv.configure_char(
|
|
56
|
+
"Brightness",
|
|
57
|
+
setter_callback=self._set_brightness,
|
|
58
|
+
value=self._current_brightness,
|
|
59
|
+
)
|
|
44
60
|
elif service_type == "outlet":
|
|
45
61
|
self.category = CATEGORY_OUTLET
|
|
46
62
|
serv = self.add_preload_service("Outlet")
|
|
@@ -58,16 +74,36 @@ class XPAccessory(Accessory):
|
|
|
58
74
|
value: True for on, False for off.
|
|
59
75
|
"""
|
|
60
76
|
if self._hk_driver._on_set:
|
|
61
|
-
self._hk_driver._on_set(self._accessory_id, value)
|
|
77
|
+
self._hk_driver._on_set(self._accessory_id, value, None)
|
|
78
|
+
|
|
79
|
+
def _set_brightness(self, value: int) -> None:
|
|
80
|
+
"""
|
|
81
|
+
Handle HomeKit set brightness request.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
value: Brightness value 0-100.
|
|
85
|
+
"""
|
|
86
|
+
if self._hk_driver._on_set:
|
|
87
|
+
self._hk_driver._on_set(self._accessory_id, True, value)
|
|
88
|
+
self._current_brightness = value
|
|
62
89
|
|
|
63
|
-
def update_state(self, is_on: bool) -> None:
|
|
90
|
+
def update_state(self, is_on: bool, brightness: Optional[int] = None) -> None:
|
|
64
91
|
"""
|
|
65
92
|
Update accessory state from Conbus event.
|
|
66
93
|
|
|
67
94
|
Args:
|
|
68
95
|
is_on: True if accessory is on, False otherwise.
|
|
96
|
+
brightness: Optional brightness value 0-100.
|
|
69
97
|
"""
|
|
70
98
|
self._char_on.set_value(is_on)
|
|
99
|
+
if brightness is not None and self._char_brightness:
|
|
100
|
+
self._char_brightness.set_value(brightness) # type: ignore[attr-defined]
|
|
101
|
+
self._current_brightness = brightness
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def current_brightness(self) -> int:
|
|
105
|
+
"""Get current brightness value."""
|
|
106
|
+
return self._current_brightness
|
|
71
107
|
|
|
72
108
|
|
|
73
109
|
class HomekitAccessoryDriver:
|
|
@@ -84,14 +120,15 @@ class HomekitAccessoryDriver:
|
|
|
84
120
|
self._homekit_config = homekit_config
|
|
85
121
|
self._driver: Optional[AccessoryDriver] = None
|
|
86
122
|
self._accessories: Dict[str, XPAccessory] = {}
|
|
87
|
-
self._on_set: Optional[
|
|
123
|
+
self._on_set: Optional[OnSetCallback] = None
|
|
88
124
|
|
|
89
|
-
def set_callback(self, on_set:
|
|
125
|
+
def set_callback(self, on_set: OnSetCallback) -> None:
|
|
90
126
|
"""
|
|
91
127
|
Set callback for HomeKit set events.
|
|
92
128
|
|
|
93
129
|
Args:
|
|
94
|
-
on_set: Callback(accessory_name, is_on) called when HomeKit app
|
|
130
|
+
on_set: Callback(accessory_name, is_on, brightness) called when HomeKit app changes state.
|
|
131
|
+
brightness is None for on/off only, or 0-100 for dimming.
|
|
95
132
|
"""
|
|
96
133
|
self._on_set = on_set
|
|
97
134
|
|
|
@@ -157,15 +194,34 @@ class HomekitAccessoryDriver:
|
|
|
157
194
|
except Exception as e:
|
|
158
195
|
self.logger.error(f"Error stopping AccessoryDriver: {e}", exc_info=True)
|
|
159
196
|
|
|
160
|
-
def update_state(
|
|
197
|
+
def update_state(
|
|
198
|
+
self, accessory_name: str, is_on: bool, brightness: Optional[int] = None
|
|
199
|
+
) -> None:
|
|
161
200
|
"""
|
|
162
201
|
Update accessory state from Conbus event.
|
|
163
202
|
|
|
164
203
|
Args:
|
|
165
204
|
accessory_name: Accessory name to update.
|
|
166
205
|
is_on: True if accessory is on, False otherwise.
|
|
206
|
+
brightness: Optional brightness value 0-100.
|
|
167
207
|
"""
|
|
168
|
-
|
|
169
|
-
|
|
208
|
+
acc = self._accessories.get(accessory_name)
|
|
209
|
+
if acc:
|
|
210
|
+
acc.update_state(is_on, brightness)
|
|
170
211
|
else:
|
|
171
212
|
self.logger.warning(f"Unknown accessory name: {accessory_name}")
|
|
213
|
+
|
|
214
|
+
def get_brightness(self, accessory_name: str) -> int:
|
|
215
|
+
"""
|
|
216
|
+
Get current brightness for an accessory.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
accessory_name: Accessory name.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Current brightness 0-100, defaults to 100 if not found.
|
|
223
|
+
"""
|
|
224
|
+
acc = self._accessories.get(accessory_name)
|
|
225
|
+
if acc:
|
|
226
|
+
return acc.current_brightness
|
|
227
|
+
return 100
|
|
@@ -300,23 +300,82 @@ class HomekitService:
|
|
|
300
300
|
await self._accessory_driver.stop()
|
|
301
301
|
self.cleanup()
|
|
302
302
|
|
|
303
|
-
def _on_homekit_set(
|
|
303
|
+
def _on_homekit_set(
|
|
304
|
+
self, accessory_name: str, is_on: bool, brightness: Optional[int]
|
|
305
|
+
) -> None:
|
|
304
306
|
"""
|
|
305
|
-
Handle HomeKit app
|
|
307
|
+
Handle HomeKit app set request (on/off or brightness).
|
|
306
308
|
|
|
307
309
|
Args:
|
|
308
310
|
accessory_name: Accessory name from HomeKit.
|
|
309
311
|
is_on: True for on, False for off.
|
|
312
|
+
brightness: Brightness value 0-100, or None for on/off only.
|
|
310
313
|
"""
|
|
311
314
|
config = self._find_accessory_config(accessory_name)
|
|
312
|
-
if config:
|
|
315
|
+
if not config:
|
|
316
|
+
self.logger.warning(f"No config found for accessory: {accessory_name}")
|
|
317
|
+
return
|
|
318
|
+
|
|
319
|
+
if brightness is not None:
|
|
320
|
+
# Handle brightness change
|
|
321
|
+
self._handle_brightness_change(accessory_name, config, brightness)
|
|
322
|
+
else:
|
|
323
|
+
# Handle on/off toggle
|
|
313
324
|
action = config.on_action if is_on else config.off_action
|
|
314
325
|
self.send_action(action)
|
|
315
326
|
self.on_status_message.emit(
|
|
316
327
|
f"HomeKit: {accessory_name} {'ON' if is_on else 'OFF'}"
|
|
317
328
|
)
|
|
329
|
+
|
|
330
|
+
def _handle_brightness_change(
|
|
331
|
+
self,
|
|
332
|
+
accessory_name: str,
|
|
333
|
+
config: "HomekitAccessoryConfig",
|
|
334
|
+
target_brightness: int,
|
|
335
|
+
) -> None:
|
|
336
|
+
"""
|
|
337
|
+
Handle brightness change by sending dimup/dimdown actions.
|
|
338
|
+
|
|
339
|
+
Calculates delta from current brightness and sends appropriate
|
|
340
|
+
number of LEVELINC or LEVELDEC commands (step = 10%).
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
accessory_name: Accessory name.
|
|
344
|
+
config: Accessory configuration.
|
|
345
|
+
target_brightness: Target brightness 0-100.
|
|
346
|
+
"""
|
|
347
|
+
current = self._accessory_driver.get_brightness(accessory_name)
|
|
348
|
+
delta = target_brightness - current
|
|
349
|
+
|
|
350
|
+
if delta == 0:
|
|
351
|
+
return
|
|
352
|
+
|
|
353
|
+
# Determine action and steps (10% per step)
|
|
354
|
+
step_size = 10
|
|
355
|
+
steps = abs(delta) // step_size
|
|
356
|
+
|
|
357
|
+
if delta > 0:
|
|
358
|
+
# Increase brightness
|
|
359
|
+
if not config.dimup_action:
|
|
360
|
+
self.logger.warning(f"No dimup_action for {accessory_name}")
|
|
361
|
+
return
|
|
362
|
+
action = config.dimup_action
|
|
363
|
+
direction = "+"
|
|
318
364
|
else:
|
|
319
|
-
|
|
365
|
+
# Decrease brightness
|
|
366
|
+
if not config.dimdown_action:
|
|
367
|
+
self.logger.warning(f"No dimdown_action for {accessory_name}")
|
|
368
|
+
return
|
|
369
|
+
action = config.dimdown_action
|
|
370
|
+
direction = "-"
|
|
371
|
+
|
|
372
|
+
# Send action for each step
|
|
373
|
+
for _ in range(steps):
|
|
374
|
+
self.send_action(action)
|
|
375
|
+
|
|
376
|
+
self.on_status_message.emit(
|
|
377
|
+
f"HomeKit: {accessory_name} {current}% → {target_brightness}% ({direction}{steps * step_size}%)"
|
|
378
|
+
)
|
|
320
379
|
|
|
321
380
|
def send_action(self, action: str) -> None:
|
|
322
381
|
"""
|
|
@@ -59,12 +59,12 @@ class TestConbusRawIntegration:
|
|
|
59
59
|
mock_service.on_progress.connect.side_effect = mock_on_progress_connect
|
|
60
60
|
|
|
61
61
|
# Make the mock service call the callback immediately
|
|
62
|
-
def
|
|
62
|
+
def mock_send_raw_telegrams(telegrams, timeout_seconds=None):
|
|
63
63
|
"""
|
|
64
64
|
Test helper function.
|
|
65
65
|
|
|
66
66
|
Args:
|
|
67
|
-
|
|
67
|
+
telegrams: List of raw telegram inputs.
|
|
68
68
|
timeout_seconds: Timeout in seconds.
|
|
69
69
|
"""
|
|
70
70
|
# Call the on_finish callback that was connected
|
|
@@ -76,7 +76,7 @@ class TestConbusRawIntegration:
|
|
|
76
76
|
# Do nothing in test
|
|
77
77
|
pass
|
|
78
78
|
|
|
79
|
-
mock_service.
|
|
79
|
+
mock_service.send_raw_telegrams.side_effect = mock_send_raw_telegrams
|
|
80
80
|
mock_service.start_reactor.side_effect = mock_start_reactor
|
|
81
81
|
|
|
82
82
|
# Mock the container
|
|
@@ -92,7 +92,7 @@ class TestConbusRawIntegration:
|
|
|
92
92
|
assert result.exit_code == 0
|
|
93
93
|
assert '"success": true' in result.output
|
|
94
94
|
assert '"received_telegrams": [' in result.output
|
|
95
|
-
mock_service.
|
|
95
|
+
mock_service.send_raw_telegrams.assert_called_once()
|
|
96
96
|
|
|
97
97
|
def test_conbus_raw_multiple_telegrams(self):
|
|
98
98
|
"""Test conbus raw command with multiple telegrams."""
|
|
@@ -137,12 +137,12 @@ class TestConbusRawIntegration:
|
|
|
137
137
|
mock_service.on_progress.connect.side_effect = mock_on_progress_connect
|
|
138
138
|
|
|
139
139
|
# Make the mock service call the callback immediately
|
|
140
|
-
def
|
|
140
|
+
def mock_send_raw_telegrams(telegrams, timeout_seconds=None):
|
|
141
141
|
"""
|
|
142
142
|
Test helper function.
|
|
143
143
|
|
|
144
144
|
Args:
|
|
145
|
-
|
|
145
|
+
telegrams: List of raw telegram inputs.
|
|
146
146
|
timeout_seconds: Timeout in seconds.
|
|
147
147
|
"""
|
|
148
148
|
# Simulate progress callbacks for each received telegram
|
|
@@ -159,23 +159,30 @@ class TestConbusRawIntegration:
|
|
|
159
159
|
# Do nothing in test
|
|
160
160
|
pass
|
|
161
161
|
|
|
162
|
-
mock_service.
|
|
162
|
+
mock_service.send_raw_telegrams.side_effect = mock_send_raw_telegrams
|
|
163
163
|
mock_service.start_reactor.side_effect = mock_start_reactor
|
|
164
164
|
|
|
165
165
|
# Mock the container
|
|
166
166
|
mock_container = MagicMock()
|
|
167
167
|
mock_container.get_container().resolve.return_value = mock_service
|
|
168
168
|
|
|
169
|
-
raw_input = "<S2113010000F02D12><S2113010001F02D12><S2113010002F02D12>"
|
|
170
169
|
result = self.runner.invoke(
|
|
171
|
-
cli,
|
|
170
|
+
cli,
|
|
171
|
+
[
|
|
172
|
+
"conbus",
|
|
173
|
+
"raw",
|
|
174
|
+
"<S2113010000F02D12>",
|
|
175
|
+
"<S2113010001F02D12>",
|
|
176
|
+
"<S2113010002F02D12>",
|
|
177
|
+
],
|
|
178
|
+
obj={"container": mock_container},
|
|
172
179
|
)
|
|
173
180
|
|
|
174
181
|
assert result.exit_code == 0
|
|
175
182
|
assert "<R2113010000F02D12>" in result.output
|
|
176
183
|
assert "<R2113010001F02D12>" in result.output
|
|
177
184
|
assert "<S2113010002F02D12>" in result.output
|
|
178
|
-
mock_service.
|
|
185
|
+
mock_service.send_raw_telegrams.assert_called_once()
|
|
179
186
|
|
|
180
187
|
def test_conbus_raw_connection_error(self):
|
|
181
188
|
"""Test conbus raw command with connection error."""
|
|
@@ -212,12 +219,12 @@ class TestConbusRawIntegration:
|
|
|
212
219
|
mock_service.on_progress.connect.side_effect = mock_on_progress_connect
|
|
213
220
|
|
|
214
221
|
# Make the mock service call the callback immediately
|
|
215
|
-
def
|
|
222
|
+
def mock_send_raw_telegrams(telegrams, timeout_seconds=None):
|
|
216
223
|
"""
|
|
217
224
|
Test helper function.
|
|
218
225
|
|
|
219
226
|
Args:
|
|
220
|
-
|
|
227
|
+
telegrams: List of raw telegram inputs.
|
|
221
228
|
timeout_seconds: Timeout in seconds.
|
|
222
229
|
"""
|
|
223
230
|
# Call the on_finish callback that was connected
|
|
@@ -229,7 +236,7 @@ class TestConbusRawIntegration:
|
|
|
229
236
|
# Do nothing in test
|
|
230
237
|
pass
|
|
231
238
|
|
|
232
|
-
mock_service.
|
|
239
|
+
mock_service.send_raw_telegrams.side_effect = mock_send_raw_telegrams
|
|
233
240
|
mock_service.start_reactor.side_effect = mock_start_reactor
|
|
234
241
|
|
|
235
242
|
# Mock the container
|
|
@@ -285,12 +292,12 @@ class TestConbusRawIntegration:
|
|
|
285
292
|
mock_service.on_progress.connect.side_effect = mock_on_progress_connect
|
|
286
293
|
|
|
287
294
|
# Make the mock service call the callback immediately
|
|
288
|
-
def
|
|
295
|
+
def mock_send_raw_telegrams(telegrams, timeout_seconds=None):
|
|
289
296
|
"""
|
|
290
297
|
Test helper function.
|
|
291
298
|
|
|
292
299
|
Args:
|
|
293
|
-
|
|
300
|
+
telegrams: List of raw telegram inputs.
|
|
294
301
|
timeout_seconds: Timeout in seconds.
|
|
295
302
|
"""
|
|
296
303
|
# Call the on_finish callback that was connected
|
|
@@ -302,7 +309,7 @@ class TestConbusRawIntegration:
|
|
|
302
309
|
# Do nothing in test
|
|
303
310
|
pass
|
|
304
311
|
|
|
305
|
-
mock_service.
|
|
312
|
+
mock_service.send_raw_telegrams.side_effect = mock_send_raw_telegrams
|
|
306
313
|
mock_service.start_reactor.side_effect = mock_start_reactor
|
|
307
314
|
|
|
308
315
|
# Mock the container
|
|
@@ -331,14 +338,14 @@ class TestConbusRawIntegration:
|
|
|
331
338
|
output = result.output
|
|
332
339
|
|
|
333
340
|
assert "Send raw telegram sequence to Conbus server" in output
|
|
334
|
-
assert "
|
|
341
|
+
assert "TELEGRAMS" in output
|
|
335
342
|
|
|
336
343
|
def test_conbus_raw_missing_arguments(self):
|
|
337
344
|
"""Test conbus raw command with missing arguments."""
|
|
338
345
|
result = self.runner.invoke(cli, ["conbus", "raw"])
|
|
339
346
|
|
|
340
347
|
assert result.exit_code != 0
|
|
341
|
-
assert "Usage: cli conbus raw [OPTIONS]
|
|
348
|
+
assert "Usage: cli conbus raw [OPTIONS] TELEGRAMS" in result.output
|
|
342
349
|
|
|
343
350
|
def test_conbus_raw_service_exception(self):
|
|
344
351
|
"""Test conbus raw command when service raises exception."""
|
|
@@ -347,8 +354,8 @@ class TestConbusRawIntegration:
|
|
|
347
354
|
mock_service.__enter__.return_value = mock_service
|
|
348
355
|
mock_service.__exit__.return_value = None
|
|
349
356
|
|
|
350
|
-
# Make the service raise an exception when
|
|
351
|
-
mock_service.
|
|
357
|
+
# Make the service raise an exception when send_raw_telegrams is called
|
|
358
|
+
mock_service.send_raw_telegrams.side_effect = Exception("Service error")
|
|
352
359
|
|
|
353
360
|
# Mock the container
|
|
354
361
|
mock_container = MagicMock()
|
|
@@ -37,7 +37,7 @@ class TestConbusRawService:
|
|
|
37
37
|
|
|
38
38
|
def test_service_initialization(self, service, mock_conbus_protocol):
|
|
39
39
|
"""Test service can be initialized with required dependencies."""
|
|
40
|
-
assert service.
|
|
40
|
+
assert service.telegrams == []
|
|
41
41
|
assert service.service_response.success is False
|
|
42
42
|
# Verify signals were connected
|
|
43
43
|
assert mock_conbus_protocol.on_connection_made.connect.called
|
|
@@ -172,7 +172,7 @@ class TestConbusRawService:
|
|
|
172
172
|
def test_context_manager_enter_resets_state(self, service):
|
|
173
173
|
"""Test __enter__ resets state for singleton reuse."""
|
|
174
174
|
# Set some state
|
|
175
|
-
service.
|
|
175
|
+
service.telegrams = ["test"]
|
|
176
176
|
service.service_response.success = True
|
|
177
177
|
|
|
178
178
|
# Enter context
|
|
@@ -180,7 +180,7 @@ class TestConbusRawService:
|
|
|
180
180
|
|
|
181
181
|
# Verify state is reset
|
|
182
182
|
assert result is service
|
|
183
|
-
assert service.
|
|
183
|
+
assert service.telegrams == []
|
|
184
184
|
assert service.service_response.success is False
|
|
185
185
|
|
|
186
186
|
def test_context_manager_exit_disconnects_signals(
|
|
@@ -208,9 +208,9 @@ class TestConbusRawService:
|
|
|
208
208
|
mock_conbus_protocol.stop_reactor.assert_called_once()
|
|
209
209
|
|
|
210
210
|
def test_connection_made(self, service, mock_conbus_protocol):
|
|
211
|
-
"""Test connection_made sends raw
|
|
212
|
-
service.
|
|
211
|
+
"""Test connection_made sends raw telegrams."""
|
|
212
|
+
service.telegrams = ["S2113010000F02D12", "S2113010001F02D12"]
|
|
213
213
|
service.connection_made()
|
|
214
|
-
mock_conbus_protocol.send_raw_telegram.
|
|
215
|
-
|
|
216
|
-
)
|
|
214
|
+
assert mock_conbus_protocol.send_raw_telegram.call_count == 2
|
|
215
|
+
mock_conbus_protocol.send_raw_telegram.assert_any_call("S2113010000F02D12")
|
|
216
|
+
mock_conbus_protocol.send_raw_telegram.assert_any_call("S2113010001F02D12")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_actiontable_commands.py
RENAMED
|
File without changes
|
{conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_autoreport_commands.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_lightlevel_commands.py
RENAMED
|
File without changes
|
{conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_linknumber_commands.py
RENAMED
|
File without changes
|
{conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_modulenumber_commands.py
RENAMED
|
File without changes
|
{conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/conbus/conbus_msactiontable_commands.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram_checksum_commands.py
RENAMED
|
File without changes
|
{conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram_discover_commands.py
RENAMED
|
File without changes
|
{conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram_linknumber_commands.py
RENAMED
|
File without changes
|
|
File without changes
|
{conson_xp-2.0.2 → conson_xp-2.0.4}/src/xp/cli/commands/telegram/telegram_version_commands.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|