conson-xp 1.18.0__tar.gz → 1.20.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.18.0 → conson_xp-1.20.0}/PKG-INFO +7 -1
- {conson_xp-1.18.0 → conson_xp-1.20.0}/README.md +5 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/pyproject.toml +3 -1
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/__init__.py +1 -1
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/__init__.py +4 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_event_commands.py +25 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_receive_commands.py +2 -1
- conson_xp-1.20.0/src/xp/cli/commands/term/__init__.py +5 -0
- conson_xp-1.20.0/src/xp/cli/commands/term/term.py +12 -0
- conson_xp-1.20.0/src/xp/cli/commands/term/term_commands.py +31 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/main.py +7 -35
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/__init__.py +2 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_client_config.py +1 -0
- conson_xp-1.20.0/src/xp/models/conbus/conbus_event_list.py +34 -0
- conson_xp-1.20.0/src/xp/models/conbus/conbus_logger_config.py +107 -0
- conson_xp-1.20.0/src/xp/services/conbus/conbus_event_list_service.py +91 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_receive_service.py +58 -30
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/protocol/conbus_event_protocol.py +28 -3
- conson_xp-1.20.0/src/xp/tui/__init__.py +1 -0
- conson_xp-1.20.0/src/xp/tui/app.py +72 -0
- conson_xp-1.20.0/src/xp/tui/protocol.tcss +50 -0
- conson_xp-1.20.0/src/xp/tui/widgets/__init__.py +1 -0
- conson_xp-1.20.0/src/xp/tui/widgets/protocol_log.py +312 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/utils/dependencies.py +34 -6
- conson_xp-1.20.0/src/xp/utils/logging.py +91 -0
- conson_xp-1.20.0/tests/integration/test_term_logging_integration.py +10 -0
- conson_xp-1.20.0/tests/unit/test_cli/test_term_commands.py +10 -0
- conson_xp-1.20.0/tests/unit/test_models/test_logger_config.py +188 -0
- conson_xp-1.20.0/tests/unit/test_services/test_conbus_event_list_service.py +272 -0
- conson_xp-1.20.0/tests/unit/test_services/test_conbus_receive_service.py +283 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_telegram_service.py +19 -0
- conson_xp-1.20.0/tests/unit/test_tui/__init__.py +1 -0
- conson_xp-1.20.0/tests/unit/test_tui/test_protocol_log.py +235 -0
- conson_xp-1.20.0/tests/unit/test_utils/test_logging.py +325 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/LICENSE +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/__main__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_actiontable_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_autoreport_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_blink_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_config_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_custom_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_datapoint_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_discover_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_lightlevel_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_linknumber_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_modulenumber_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_msactiontable_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_output_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_raw_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/conbus/conbus_scan_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/file_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/homekit/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/homekit/homekit.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/homekit/homekit_start_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/module_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/reverse_proxy_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/server/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/server/server_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/telegram/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/telegram/telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/telegram/telegram_blink_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/telegram/telegram_checksum_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/telegram/telegram_discover_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/telegram/telegram_linknumber_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/telegram/telegram_parse_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/commands/telegram/telegram_version_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/utils/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/utils/click_tree.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/utils/datapoint_type_choice.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/utils/decorators.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/utils/error_handlers.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/utils/formatters.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/utils/module_type_choice.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/utils/serial_number_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/utils/system_function_choice.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/cli/utils/xp_module_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/connection/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/connection/exceptions.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/actiontable/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/actiontable/actiontable.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/actiontable/msactiontable_xp20.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/actiontable/msactiontable_xp24.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/actiontable/msactiontable_xp33.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_autoreport.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_blink.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_connection_status.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_custom.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_datapoint.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_discover.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_event_raw.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_lightlevel.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_linknumber.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_output.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_raw.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_receive.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/conbus/conbus_writeconfig.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/homekit/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/homekit/homekit_accessory.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/homekit/homekit_config.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/homekit/homekit_conson_config.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/log_entry.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/protocol/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/protocol/conbus_protocol.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/response.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/action_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/datapoint_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/event_telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/event_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/input_action_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/input_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/module_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/module_type_code.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/output_telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/reply_telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/system_function.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/system_telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/telegram_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/telegram/timeparam_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/models/write_config_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/actiontable/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/actiontable/actiontable_serializer.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/actiontable/msactiontable_serializer.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/actiontable/msactiontable_xp20_serializer.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/actiontable/msactiontable_xp24_serializer.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/actiontable/msactiontable_xp33_serializer.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/actiontable/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/actiontable/actiontable_download_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/actiontable/actiontable_list_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/actiontable/actiontable_show_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/actiontable/actiontable_upload_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/actiontable/msactiontable_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_blink_all_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_blink_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_custom_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_datapoint_queryall_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_datapoint_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_discover_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_event_raw_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_output_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_raw_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/conbus_scan_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/conbus/write_config_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_cache_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_conbus_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_config_validator.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_conson_validator.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_dimminglight.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_dimminglight_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_hap_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_lightbulb.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_lightbulb_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_module_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_outlet.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_outlet_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/homekit/homekit_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/log_file_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/module_type_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/protocol/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/protocol/conbus_protocol.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/protocol/protocol_factory.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/protocol/telegram_protocol.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/reverse_proxy_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/server/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/server/base_server_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/server/cp20_server_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/server/device_service_factory.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/server/server_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/server/xp130_server_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/server/xp20_server_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/server/xp230_server_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/server/xp24_server_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/server/xp33_server_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/telegram/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/telegram/telegram_blink_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/telegram/telegram_checksum_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/telegram/telegram_datapoint_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/telegram/telegram_discover_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/telegram/telegram_link_number_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/telegram/telegram_output_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/telegram/telegram_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/services/telegram/telegram_version_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/utils/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/utils/checksum.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/utils/event_helper.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/utils/serialization.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/src/xp/utils/time_utils.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/.coverage +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/conftest.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/.coverage +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/telegram_test_data.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_actiontable_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_api/.coverage +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_api/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_blink_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_checksum_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_conbus_blink_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_conbus_datapoint_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_conbus_raw_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_conbus_receive_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_discovery_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_event_telegram_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_homekit_config_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_link_number_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_module_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_output_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_reverse_proxy_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_system_reply_telegram_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_version_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_xp20_action_table_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/integration/test_xp24_action_table_integration.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_api/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_cli/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_cli/test_click_tree.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_cli/test_conbus_actiontable_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_cli/test_conbus_blink_commands.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_cli/test_datapoint_type_choice.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_cli/test_decorators.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_cli/test_error_handlers.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_cli/test_formatters.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_cli/test_serial_number_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_cli/test_system_function_choice.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_connection/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_connection/test_connection_init.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_connection/test_exceptions.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_encoding/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_encoding/test_latin1_edge_cases.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_conbus.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_conbus_client_send.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_conbus_discover.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_conbus_linknumber.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_event_telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_log_entry.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_module_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_reply_telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_system_telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_system_telegram_enhancements.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_version_telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_write_config_type.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_xp20_action_table.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_xp24_action_table.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_models/test_xp24_action_telegram.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_actiontable_serializer.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_actiontable_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_actiontable_upload_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_base_server_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_blink_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_checksum_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_conbus_blink_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_conbus_event_raw_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_conbus_raw_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_conbus_reverse_proxy_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_device_service_factory.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_discovery_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_homekit_cache_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_homekit_config_validator.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_homekit_conson_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_homekit_services.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_log_file_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_module_type_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_protocol.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_server_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_telegram_input_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_telegram_protocol.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_version_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_xp20_action_table_serializer.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_xp24_action_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_xp24_action_table_serializer.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_xp24_action_table_service.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_xp33_action_table_serializer.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_services/test_xp_server_services.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_utils/__init__.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_utils/test_checksum.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_utils/test_event_helper.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_utils/test_serialization.py +0 -0
- {conson_xp-1.18.0 → conson_xp-1.20.0}/tests/unit/test_utils/test_time_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: conson-xp
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.20.0
|
|
4
4
|
Summary: XP Protocol Communication Tools
|
|
5
5
|
Author-Email: ldvchosal <ldvchosal@github.com>
|
|
6
6
|
License: MIT License
|
|
@@ -48,6 +48,7 @@ Requires-Dist: punq>=0.7.0
|
|
|
48
48
|
Requires-Dist: twisted>=25.5.0
|
|
49
49
|
Requires-Dist: bubus>=1.5.6
|
|
50
50
|
Requires-Dist: psygnal>=0.15.0
|
|
51
|
+
Requires-Dist: textual>=1.0.0
|
|
51
52
|
Description-Content-Type: text/markdown
|
|
52
53
|
|
|
53
54
|
# 🔌 XP Protocol Communication Tool
|
|
@@ -306,6 +307,7 @@ xp conbus datapoint query
|
|
|
306
307
|
xp conbus discover
|
|
307
308
|
|
|
308
309
|
xp conbus event
|
|
310
|
+
xp conbus event list
|
|
309
311
|
xp conbus event raw
|
|
310
312
|
|
|
311
313
|
|
|
@@ -397,6 +399,10 @@ xp telegram parse
|
|
|
397
399
|
xp telegram validate
|
|
398
400
|
xp telegram version
|
|
399
401
|
|
|
402
|
+
|
|
403
|
+
xp term
|
|
404
|
+
xp term protocol
|
|
405
|
+
|
|
400
406
|
<!-- END CLI HELP -->
|
|
401
407
|
```
|
|
402
408
|
</details>
|
|
@@ -254,6 +254,7 @@ xp conbus datapoint query
|
|
|
254
254
|
xp conbus discover
|
|
255
255
|
|
|
256
256
|
xp conbus event
|
|
257
|
+
xp conbus event list
|
|
257
258
|
xp conbus event raw
|
|
258
259
|
|
|
259
260
|
|
|
@@ -345,6 +346,10 @@ xp telegram parse
|
|
|
345
346
|
xp telegram validate
|
|
346
347
|
xp telegram version
|
|
347
348
|
|
|
349
|
+
|
|
350
|
+
xp term
|
|
351
|
+
xp term protocol
|
|
352
|
+
|
|
348
353
|
<!-- END CLI HELP -->
|
|
349
354
|
```
|
|
350
355
|
</details>
|
|
@@ -18,10 +18,11 @@ dependencies = [
|
|
|
18
18
|
"twisted>=25.5.0",
|
|
19
19
|
"bubus>=1.5.6",
|
|
20
20
|
"psygnal>=0.15.0",
|
|
21
|
+
"textual>=1.0.0",
|
|
21
22
|
]
|
|
22
23
|
requires-python = ">=3.11"
|
|
23
24
|
readme = "README.md"
|
|
24
|
-
version = "1.
|
|
25
|
+
version = "1.20.0"
|
|
25
26
|
|
|
26
27
|
[project.license]
|
|
27
28
|
file = "LICENSE"
|
|
@@ -56,6 +57,7 @@ dev = [
|
|
|
56
57
|
"isort>=6.0.1",
|
|
57
58
|
"absolufy-imports>=0.3.1",
|
|
58
59
|
"pytest-asyncio>=1.2.0",
|
|
60
|
+
"types-docutils>=0.22.2.20251006",
|
|
59
61
|
]
|
|
60
62
|
|
|
61
63
|
[tool.pytest.ini_options]
|
|
@@ -86,6 +86,8 @@ from xp.cli.commands.telegram.telegram_parse_commands import (
|
|
|
86
86
|
validate_telegram,
|
|
87
87
|
)
|
|
88
88
|
from xp.cli.commands.telegram.telegram_version_commands import generate_version_request
|
|
89
|
+
from xp.cli.commands.term.term import term
|
|
90
|
+
from xp.cli.commands.term.term_commands import protocol_monitor
|
|
89
91
|
|
|
90
92
|
__all__ = [
|
|
91
93
|
# Main command groups (conbus excluded to avoid module shadowing)
|
|
@@ -109,7 +111,9 @@ __all__ = [
|
|
|
109
111
|
"checksum",
|
|
110
112
|
"homekit",
|
|
111
113
|
"homekit_start",
|
|
114
|
+
"term",
|
|
112
115
|
# Individual command functions
|
|
116
|
+
"protocol_monitor",
|
|
113
117
|
"conbus_download_msactiontable",
|
|
114
118
|
"conbus_download_actiontable",
|
|
115
119
|
"send_blink_on_telegram",
|
|
@@ -8,6 +8,7 @@ from xp.cli.commands.conbus.conbus import conbus
|
|
|
8
8
|
from xp.cli.utils.decorators import connection_command
|
|
9
9
|
from xp.cli.utils.module_type_choice import MODULE_TYPE
|
|
10
10
|
from xp.models import ConbusEventRawResponse
|
|
11
|
+
from xp.services.conbus.conbus_event_list_service import ConbusEventListService
|
|
11
12
|
from xp.services.conbus.conbus_event_raw_service import ConbusEventRawService
|
|
12
13
|
|
|
13
14
|
|
|
@@ -17,6 +18,30 @@ def conbus_event() -> None:
|
|
|
17
18
|
pass
|
|
18
19
|
|
|
19
20
|
|
|
21
|
+
@conbus_event.command("list")
|
|
22
|
+
@click.pass_context
|
|
23
|
+
def list_events(ctx: click.Context) -> None:
|
|
24
|
+
r"""List configured event telegrams from module action tables.
|
|
25
|
+
|
|
26
|
+
Reads conson.yml configuration, parses action tables, and groups
|
|
27
|
+
modules by their event keys to show which modules are assigned to
|
|
28
|
+
each event (button configuration).
|
|
29
|
+
|
|
30
|
+
Output is sorted by module count (most frequently used events first).
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
ctx: Click context object.
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
\b
|
|
37
|
+
xp conbus event list
|
|
38
|
+
"""
|
|
39
|
+
service: ConbusEventListService = (
|
|
40
|
+
ctx.obj.get("container").get_container().resolve(ConbusEventListService)
|
|
41
|
+
)
|
|
42
|
+
click.echo(json.dumps(service.list_events().to_dict(), indent=2))
|
|
43
|
+
|
|
44
|
+
|
|
20
45
|
@conbus_event.command("raw")
|
|
21
46
|
@click.argument("module_type", type=MODULE_TYPE)
|
|
22
47
|
@click.argument("link_number", type=click.IntRange(0, 99))
|
|
@@ -56,4 +56,5 @@ def receive_telegrams(ctx: Context, timeout: float) -> None:
|
|
|
56
56
|
ctx.obj.get("container").get_container().resolve(ConbusReceiveService)
|
|
57
57
|
)
|
|
58
58
|
with service:
|
|
59
|
-
service.
|
|
59
|
+
service.init(progress, on_finish, timeout)
|
|
60
|
+
service.start_reactor()
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Term CLI group definition for TUI commands."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
from click_help_colors import HelpColorsGroup
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@click.group(
|
|
8
|
+
cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
|
|
9
|
+
)
|
|
10
|
+
def term() -> None:
|
|
11
|
+
"""Terminal UI commands for interactive monitoring and control."""
|
|
12
|
+
pass
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Term protocol CLI command for TUI monitoring."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
from click import Context
|
|
5
|
+
|
|
6
|
+
from xp.cli.commands.term.term import term
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@term.command("protocol")
|
|
10
|
+
@click.pass_context
|
|
11
|
+
def protocol_monitor(ctx: Context) -> None:
|
|
12
|
+
r"""Start TUI for real-time protocol monitoring.
|
|
13
|
+
|
|
14
|
+
Displays live RX/TX telegram stream from Conbus server
|
|
15
|
+
in an interactive terminal interface.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
ctx: Click context object.
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
\b
|
|
22
|
+
xp term protocol
|
|
23
|
+
"""
|
|
24
|
+
from xp.tui.app import ProtocolMonitorApp
|
|
25
|
+
|
|
26
|
+
# Resolve ServiceContainer from context
|
|
27
|
+
container = ctx.obj.get("container").get_container()
|
|
28
|
+
|
|
29
|
+
# Initialize and run Textual app
|
|
30
|
+
app = ProtocolMonitorApp(container=container)
|
|
31
|
+
app.run()
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""XP CLI tool entry point with modular command structure."""
|
|
2
2
|
|
|
3
|
-
import logging
|
|
4
|
-
|
|
5
3
|
import click
|
|
6
4
|
from click_help_colors import HelpColorsGroup
|
|
7
5
|
|
|
@@ -16,8 +14,10 @@ from xp.cli.commands.server.server_commands import server
|
|
|
16
14
|
|
|
17
15
|
# Import command groups from modular structure
|
|
18
16
|
from xp.cli.commands.telegram.telegram_parse_commands import telegram
|
|
17
|
+
from xp.cli.commands.term.term import term
|
|
19
18
|
from xp.cli.utils.click_tree import add_tree_command
|
|
20
19
|
from xp.utils.dependencies import ServiceContainer
|
|
20
|
+
from xp.utils.logging import LoggerService
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
@click.group(
|
|
@@ -31,44 +31,15 @@ def cli(ctx: click.Context) -> None:
|
|
|
31
31
|
Args:
|
|
32
32
|
ctx: Click context object for passing state between commands.
|
|
33
33
|
"""
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# Force format on root logger and all handlers
|
|
39
|
-
formatter = logging.Formatter(log_format, datefmt=date_format)
|
|
40
|
-
root_logger = logging.getLogger()
|
|
41
|
-
root_logger.setLevel(logging.DEBUG)
|
|
42
|
-
|
|
43
|
-
# Update all existing handlers or create new one
|
|
44
|
-
if root_logger.handlers:
|
|
45
|
-
for handler in root_logger.handlers:
|
|
46
|
-
handler.setFormatter(formatter)
|
|
47
|
-
else:
|
|
48
|
-
handler = logging.StreamHandler()
|
|
49
|
-
handler.setFormatter(formatter)
|
|
50
|
-
root_logger.addHandler(handler)
|
|
51
|
-
|
|
52
|
-
# Suppress pyhap.hap_protocol logs
|
|
53
|
-
|
|
54
|
-
# bubus
|
|
55
|
-
logging.getLogger("bubus").setLevel(logging.WARNING)
|
|
56
|
-
|
|
57
|
-
# xp
|
|
58
|
-
logging.getLogger("xp").setLevel(logging.DEBUG)
|
|
59
|
-
logging.getLogger("xp.services.homekit").setLevel(logging.DEBUG)
|
|
60
|
-
|
|
61
|
-
# pyhap
|
|
62
|
-
logging.getLogger("pyhap").setLevel(logging.WARNING)
|
|
63
|
-
logging.getLogger("pyhap.hap_handler").setLevel(logging.WARNING)
|
|
64
|
-
logging.getLogger("pyhap.hap_protocol").setLevel(logging.WARNING)
|
|
65
|
-
# logging.getLogger('pyhap.accessory_driver').setLevel(logging.WARNING)
|
|
34
|
+
container = ServiceContainer()
|
|
35
|
+
logger_config = container.get_container().resolve(LoggerService)
|
|
36
|
+
logger_config.setup()
|
|
66
37
|
|
|
67
38
|
# Initialize the service container and store it in the context
|
|
68
39
|
ctx.ensure_object(dict)
|
|
69
40
|
# Only create a new container if one wasn't provided (e.g., for testing)
|
|
70
41
|
if "container" not in ctx.obj:
|
|
71
|
-
ctx.obj["container"] =
|
|
42
|
+
ctx.obj["container"] = container
|
|
72
43
|
|
|
73
44
|
|
|
74
45
|
# Register all command groups
|
|
@@ -79,6 +50,7 @@ cli.add_command(module)
|
|
|
79
50
|
cli.add_command(file)
|
|
80
51
|
cli.add_command(server)
|
|
81
52
|
cli.add_command(reverse_proxy)
|
|
53
|
+
cli.add_command(term)
|
|
82
54
|
|
|
83
55
|
# Add the tree command
|
|
84
56
|
add_tree_command(cli)
|
|
@@ -5,6 +5,7 @@ from xp.models.conbus.conbus_client_config import ConbusClientConfig
|
|
|
5
5
|
from xp.models.conbus.conbus_connection_status import ConbusConnectionStatus
|
|
6
6
|
from xp.models.conbus.conbus_datapoint import ConbusDatapointResponse
|
|
7
7
|
from xp.models.conbus.conbus_discover import ConbusDiscoverResponse
|
|
8
|
+
from xp.models.conbus.conbus_event_list import ConbusEventListResponse
|
|
8
9
|
from xp.models.conbus.conbus_event_raw import ConbusEventRawResponse
|
|
9
10
|
from xp.models.log_entry import LogEntry
|
|
10
11
|
from xp.models.telegram.event_telegram import EventTelegram
|
|
@@ -31,6 +32,7 @@ __all__ = [
|
|
|
31
32
|
"ConbusResponse",
|
|
32
33
|
"ConbusDatapointResponse",
|
|
33
34
|
"ConbusDiscoverResponse",
|
|
35
|
+
"ConbusEventListResponse",
|
|
34
36
|
"ConbusEventRawResponse",
|
|
35
37
|
"ConbusConnectionStatus",
|
|
36
38
|
]
|
|
@@ -49,6 +49,7 @@ class ConbusClientConfig(BaseModel):
|
|
|
49
49
|
except FileNotFoundError:
|
|
50
50
|
logger.error(f"File {file_path} does not exist, loading default")
|
|
51
51
|
return cls()
|
|
52
|
+
|
|
52
53
|
except yaml.YAMLError:
|
|
53
54
|
logger.error(f"File {file_path} is not valid")
|
|
54
55
|
# Return default config if YAML parsing fails
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Conbus event list response model."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict, Optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class ConbusEventListResponse:
|
|
10
|
+
"""Represents a response from Conbus event list operation.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
events: Dict mapping event keys to list of module names.
|
|
14
|
+
timestamp: Timestamp of the response.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
events: Dict[str, list[str]]
|
|
18
|
+
timestamp: Optional[datetime] = None
|
|
19
|
+
|
|
20
|
+
def __post_init__(self) -> None:
|
|
21
|
+
"""Initialize timestamp if not provided."""
|
|
22
|
+
if self.timestamp is None:
|
|
23
|
+
self.timestamp = datetime.now()
|
|
24
|
+
|
|
25
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
26
|
+
"""Convert to dictionary for JSON serialization.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Dictionary representation of the response.
|
|
30
|
+
"""
|
|
31
|
+
return {
|
|
32
|
+
"events": self.events,
|
|
33
|
+
"timestamp": self.timestamp.isoformat() if self.timestamp else None,
|
|
34
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Logger configuration models for XP application."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Dict, Union
|
|
6
|
+
|
|
7
|
+
import yaml
|
|
8
|
+
from pydantic import BaseModel, Field, field_validator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class LoggingConfig(BaseModel):
|
|
12
|
+
"""Logging configuration.
|
|
13
|
+
|
|
14
|
+
Attributes:
|
|
15
|
+
path: log folder.
|
|
16
|
+
default_level: DEBUG, WARNING, INFO, ERROR, CRITICAL.
|
|
17
|
+
levels: Per-module log level overrides.
|
|
18
|
+
max_bytes: Maximum size in bytes before rotating (default: 1MB).
|
|
19
|
+
backup_count: Number of backup files to keep (default: 365).
|
|
20
|
+
log_format: Log message format string.
|
|
21
|
+
date_format: Date format string for timestamps.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
path: str = "log"
|
|
25
|
+
default_level: str = "DEBUG"
|
|
26
|
+
levels: Dict[str, int] = {
|
|
27
|
+
"xp": logging.DEBUG,
|
|
28
|
+
"xp.services.homekit": logging.WARNING,
|
|
29
|
+
"xp.services.server": logging.WARNING,
|
|
30
|
+
}
|
|
31
|
+
max_bytes: int = 1024 * 1024 # 1MB
|
|
32
|
+
backup_count: int = 365
|
|
33
|
+
log_format: str = (
|
|
34
|
+
"%(asctime)s - [%(threadName)s-%(thread)d] - %(levelname)s - %(name)s - %(message)s"
|
|
35
|
+
)
|
|
36
|
+
date_format: str = "%H:%M:%S"
|
|
37
|
+
|
|
38
|
+
@field_validator("levels", mode="before")
|
|
39
|
+
@classmethod
|
|
40
|
+
def convert_level_names(cls, v: Dict[str, Union[str, int]]) -> Dict[str, int]:
|
|
41
|
+
"""Convert string level names to numeric values.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
v: Dictionary with string or int log levels.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Dictionary with numeric log levels.
|
|
48
|
+
|
|
49
|
+
Raises:
|
|
50
|
+
ValueError: If an invalid log level name is provided.
|
|
51
|
+
"""
|
|
52
|
+
level_map = {
|
|
53
|
+
"DEBUG": logging.DEBUG,
|
|
54
|
+
"INFO": logging.INFO,
|
|
55
|
+
"WARNING": logging.WARNING,
|
|
56
|
+
"ERROR": logging.ERROR,
|
|
57
|
+
"CRITICAL": logging.CRITICAL,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
result = {}
|
|
61
|
+
for module, level in v.items():
|
|
62
|
+
if isinstance(level, str):
|
|
63
|
+
level_upper = level.upper()
|
|
64
|
+
if level_upper not in level_map:
|
|
65
|
+
raise ValueError(
|
|
66
|
+
f"Invalid log level '{level}' for module '{module}'. "
|
|
67
|
+
f"Must be one of: {', '.join(level_map.keys())}"
|
|
68
|
+
)
|
|
69
|
+
result[module] = level_map[level_upper]
|
|
70
|
+
else:
|
|
71
|
+
result[module] = level
|
|
72
|
+
return result
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class ConbusLoggerConfig(BaseModel):
|
|
76
|
+
"""Logging configuration.
|
|
77
|
+
|
|
78
|
+
Attributes:
|
|
79
|
+
log: LoggingConfig instance for logging settings.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
log: LoggingConfig = Field(default_factory=LoggingConfig)
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def from_yaml(cls, file_path: str) -> "ConbusLoggerConfig":
|
|
86
|
+
"""Load configuration from YAML file.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
file_path: Path to the YAML configuration file.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
ConbusClientConfig instance loaded from file or default config.
|
|
93
|
+
"""
|
|
94
|
+
logger = logging.getLogger(__name__)
|
|
95
|
+
try:
|
|
96
|
+
with Path(file_path).open("r") as file:
|
|
97
|
+
data = yaml.safe_load(file)
|
|
98
|
+
return cls(**data)
|
|
99
|
+
|
|
100
|
+
except FileNotFoundError:
|
|
101
|
+
logger.error(f"File {file_path} does not exist, loading default")
|
|
102
|
+
return cls()
|
|
103
|
+
|
|
104
|
+
except yaml.YAMLError:
|
|
105
|
+
logger.error(f"File {file_path} is not valid")
|
|
106
|
+
# Return default config if YAML parsing fails
|
|
107
|
+
return cls()
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Conbus Event List Service for listing configured event telegrams.
|
|
2
|
+
|
|
3
|
+
This service parses action tables from conson.yml and groups events
|
|
4
|
+
by button configuration to show which modules are assigned to each event.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from collections import defaultdict
|
|
9
|
+
from typing import Dict, List
|
|
10
|
+
|
|
11
|
+
from xp.models import ConbusEventListResponse
|
|
12
|
+
from xp.models.homekit.homekit_conson_config import ConsonModuleListConfig
|
|
13
|
+
from xp.services.actiontable.actiontable_serializer import ActionTableSerializer
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ConbusEventListService:
|
|
17
|
+
"""Service for listing configured event telegrams from action tables.
|
|
18
|
+
|
|
19
|
+
Parses action tables from conson.yml configuration and groups modules
|
|
20
|
+
by their event keys to identify common button configurations.
|
|
21
|
+
|
|
22
|
+
Attributes:
|
|
23
|
+
conson_config: Configuration containing module action tables.
|
|
24
|
+
logger: Logger instance for the service.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, conson_config: ConsonModuleListConfig) -> None:
|
|
28
|
+
"""Initialize the Conbus event list service.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
conson_config: ConsonModuleListConfig instance with module action tables.
|
|
32
|
+
"""
|
|
33
|
+
self.conson_config = conson_config
|
|
34
|
+
self.logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
def list_events(self) -> ConbusEventListResponse:
|
|
37
|
+
"""List all configured events from module action tables.
|
|
38
|
+
|
|
39
|
+
Parses action tables, extracts event information (module_type, link, input),
|
|
40
|
+
groups modules by event key, and sorts by usage count.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
ConbusEventListResponse with events dict mapping event keys to module names.
|
|
44
|
+
"""
|
|
45
|
+
# Dict to track which modules are assigned to each event
|
|
46
|
+
# event_key -> set of module names (using set for automatic deduplication)
|
|
47
|
+
event_modules: Dict[str, set[str]] = defaultdict(set)
|
|
48
|
+
|
|
49
|
+
# Process each module's action table
|
|
50
|
+
for module in self.conson_config.root:
|
|
51
|
+
# Skip modules without action table
|
|
52
|
+
if not module.action_table:
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
# Process each action in the module's action table
|
|
56
|
+
for action in module.action_table:
|
|
57
|
+
try:
|
|
58
|
+
# Use existing ActionTableSerializer to parse action
|
|
59
|
+
entry = ActionTableSerializer.parse_action_string(action)
|
|
60
|
+
|
|
61
|
+
# Extract event data from parsed entry
|
|
62
|
+
module_type_name = entry.module_type.name
|
|
63
|
+
link = entry.link_number
|
|
64
|
+
input_num = entry.module_input
|
|
65
|
+
|
|
66
|
+
# Create event key (space-separated format)
|
|
67
|
+
event_key = f"{module_type_name} {link:02d} {input_num:02d}"
|
|
68
|
+
|
|
69
|
+
# Add this module to the event (set automatically deduplicates)
|
|
70
|
+
event_modules[event_key].add(
|
|
71
|
+
f"{module.serial_number}:{entry.module_output}"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
except ValueError as e:
|
|
75
|
+
# Invalid action format - log warning and skip
|
|
76
|
+
self.logger.warning(
|
|
77
|
+
f"Invalid action '{action}' in module '{module.serial_number}': {e}"
|
|
78
|
+
)
|
|
79
|
+
continue
|
|
80
|
+
|
|
81
|
+
# Convert sets to sorted lists and sort events by module count (descending)
|
|
82
|
+
events_dict: Dict[str, List[str]] = {
|
|
83
|
+
event_key: sorted(list(modules))
|
|
84
|
+
for event_key, modules in sorted(
|
|
85
|
+
event_modules.items(),
|
|
86
|
+
key=lambda item: len(item[1]),
|
|
87
|
+
reverse=True,
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return ConbusEventListResponse(events=events_dict)
|