benchlab-pytools 3.0.0__tar.gz → 3.0.2__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.
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/CHANGELOG.md +28 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/CONTRIBUTING.md +1 -1
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/PKG-INFO +20 -3
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/README.md +18 -2
- benchlab_pytools-3.0.2/benchlab/__init__.py +5 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2/benchlab}/bootstrap.py +0 -1
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/config_client.py +3 -4
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/config_manager.py +5 -6
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/datasource.py +4 -7
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/datasource_manager.py +6 -7
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/infrastructure.py +6 -8
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/process_manager.py +1 -2
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/statistics.py +3 -4
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/csv_log/csv_logger_enhanced.py +2 -4
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/csv_log/message_batcher.py +2 -5
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/csv_log/smart_retry.py +6 -8
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/graph/app.py +9 -6
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/hwinfo/hwinfo_export.py +4 -6
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/link/link_main.py +3 -5
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/menu.py +1 -1
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/menu_classic.py +1 -1
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2/benchlab}/requirements.txt +4 -1
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/sources.py +1 -6
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/tools.py +1 -1
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/tui/tui_core.py +27 -44
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/tui/tui_main.py +9 -14
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/vu_server_manager.py +2 -4
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/vu_tui.py +25 -32
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/vu_updater.py +3 -3
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/benchlab_fleet.py +2 -2
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/benchlab_graph.py +3 -4
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/wigidash_device.py +2 -2
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/wigidash_manager.py +3 -6
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/wigidash_session.py +16 -22
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/wigidash_usb.py +6 -10
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/wigidash_widget.py +2 -4
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab.py +5 -2
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/pyproject.toml +1 -0
- benchlab_pytools-3.0.0/benchlab/__init__.py +0 -14
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/.flake8 +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/.gitignore +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/LICENSE +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/__main__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/config_tool.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/diff.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/examples/complete_config.json +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/examples/rgb_lighting.json +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/examples/simple_fan.json +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/schema.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/test_config_client.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/test_config_manager.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/config/test_diff.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/config.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/device_registry.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/discovery.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/retry.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/core/shared_serial.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/csv_log/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/csv_log/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/csv_log/requirements.txt +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/graph/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/graph/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/graph/requirements.txt +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/graph/runner.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/graph/test_graph.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/graph/ui.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/hwinfo/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/hwinfo/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/hwinfo/requirements.txt +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/hwinfo/test_hwinfo_export.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/launcher.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/link/.env.EXAMPLE +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/link/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/link/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/link/test_link_main.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/main.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/mqtt/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/mqtt/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/mqtt/mqtt.config_template +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/mqtt/mqtt_publisher.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/mqtt/requirements.txt +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/mqtt/test_mqtt_publisher.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/prefs.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/restapi/.env.example +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/restapi/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/restapi/favicon.ico +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/restapi/readme.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/restapi/requirements.txt +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/restapi/telemetry_api.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/restapi/test_server.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/tui/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/tui/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/tui/config.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/tui/requirements.txt +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/tui/test_tui_core.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/tui/test_tui_main.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/NOTICE.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/Running_from_source_on_linux.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/assets/vu1_hello_world.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/community_applications.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/config.yaml +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/database.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/dial_driver.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/dials/Comms_Hub_Gauge.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/dials/Comms_Hub_Server.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/dials/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/dials/base_logger.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/installer/inc/icon.ico +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/installer/install.nsi +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/make_version.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/pylintrc +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/requirements.txt +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/serial_driver.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/server.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/server_config.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/server_dial_handler.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/vu_notifications.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/android-chrome-192x192.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/android-chrome-512x512.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/apple-touch-icon.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/demo.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/demo.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/demo.rtl.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/demo.rtl.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.rtl.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.rtl.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.rtl.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.rtl.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-social.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-social.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-social.rtl.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-social.rtl.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.rtl.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.rtl.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler.rtl.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/tabler.rtl.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/css/theme.min.css +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/img/header.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/img/logo.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/dark-theme.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/dark-theme.min.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/demo.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/demo.min.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/jquery.min.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/tabler.esm.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/tabler.esm.min.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/tabler.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/tabler.min.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/vu1_api.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_api_key_settings.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_api_keys.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_dial.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_home.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_root.js +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/favicon-16x16.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/favicon-32x32.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/favicon.ico +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/favicon.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/index.html +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/views/api_keys.html +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/views/dial.html +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/views/footer.html +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/views/header.html +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/views/key_settings.html +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/VU-Server/www/views/start.html +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/assets/Barlow-Bold.ttf +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/assets/bl_dial_144x200.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/assets/bl_logo_144x200.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/devices.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/requirements.txt +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/sensors.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/test_devices.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/test_vu_server_config.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/test_vu_server_manager.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/test_vu_tui.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/vu_dial.config_template +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/vu_logo_gen.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/vu_server.config_template +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/vu/vu_server_config.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/README.md +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/__init__.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/assets/Inter-Bold.ttf +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/assets/Inter.ttf +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/assets/benchlab.png +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/benchlab_overview.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/benchlab_telemetry.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/benchlab_ui.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/benchlab_utils.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/requirements.txt +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/benchlab/wigidash/test_wigidash.py +0 -0
- {benchlab_pytools-3.0.0 → benchlab_pytools-3.0.2}/pytest.ini +0 -0
|
@@ -4,6 +4,32 @@ All notable changes to BENCHLAB PyTools are documented here. Format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows
|
|
5
5
|
[SemVer](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [3.0.2] - 2026-08-18
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Several f-strings had their `{...}` expression split across a line
|
|
11
|
+
break, which is [PEP 701](https://peps.python.org/pep-0701/) syntax
|
|
12
|
+
only valid on Python 3.12+. Despite `requires-python = ">=3.10"`, this
|
|
13
|
+
raised `SyntaxError` immediately on 3.10/3.11 (e.g. `benchlab -tui`
|
|
14
|
+
failing with `SyntaxError: unterminated string literal` in
|
|
15
|
+
`benchlab/core/datasource.py`) — invisible in CI since every workflow
|
|
16
|
+
pins Python 3.13. Collapsed all such f-strings back onto single lines
|
|
17
|
+
across 27 files.
|
|
18
|
+
|
|
19
|
+
## [3.0.1] - 2026-08-18
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- PyPI install was broken: `bootstrap.py` and the core `requirements.txt`
|
|
23
|
+
lived at the repo root and were never included in the wheel (only
|
|
24
|
+
`benchlab/` is packaged), so `pip install benchlab-pytools` followed by
|
|
25
|
+
`benchlab ...` failed with `ModuleNotFoundError: No module named
|
|
26
|
+
'bootstrap'`. Both files moved into `benchlab/`, with internal imports
|
|
27
|
+
updated to relative imports.
|
|
28
|
+
- `pywin32` was missing from `pyproject.toml`'s core dependencies, so
|
|
29
|
+
PyPI installs on Windows did not pull it in despite the `named_pipe`
|
|
30
|
+
data source depending on it. Added `pywin32>=306; platform_system ==
|
|
31
|
+
'Windows'` alongside the existing `windows-curses` entry.
|
|
32
|
+
|
|
7
33
|
## [3.0.0] - 2026-08-15
|
|
8
34
|
|
|
9
35
|
### Added
|
|
@@ -41,4 +67,6 @@ export, MQTT publisher, VU dials, WigiDash, and config import/export tools,
|
|
|
41
67
|
sharing a common data-source layer (direct serial, FastAPI, MQTT, named
|
|
42
68
|
pipe, service HTTP).
|
|
43
69
|
|
|
70
|
+
[3.0.2]: https://github.com/BenchLab-io/benchlab-pytools/compare/v3.0.1...v3.0.2
|
|
71
|
+
[3.0.1]: https://github.com/BenchLab-io/benchlab-pytools/compare/v3.0.0...v3.0.1
|
|
44
72
|
[3.0.0]: https://github.com/BenchLab-io/benchlab-pytools/compare/v0.8.2...v3.0.0
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
```bash
|
|
6
6
|
git clone https://github.com/BenchLab-io/benchlab-pytools.git
|
|
7
7
|
cd benchlab-pytools
|
|
8
|
-
pip install -r requirements.txt
|
|
8
|
+
pip install -r benchlab/requirements.txt
|
|
9
9
|
pip install -r benchlab/csv_log/requirements.txt
|
|
10
10
|
pip install -r benchlab/graph/requirements.txt
|
|
11
11
|
pip install -r benchlab/wigidash/requirements.txt
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: benchlab-pytools
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.2
|
|
4
4
|
Summary: Python control suite for BENCHLAB telemetry devices
|
|
5
5
|
Project-URL: Homepage, https://benchlab.io/
|
|
6
6
|
Project-URL: Repository, https://github.com/BenchLab-io/benchlab-pytools
|
|
@@ -25,6 +25,7 @@ Requires-Python: >=3.10
|
|
|
25
25
|
Requires-Dist: benchlab-pycore>=0.5.1
|
|
26
26
|
Requires-Dist: packaging<26.0,>=23.0
|
|
27
27
|
Requires-Dist: python-dotenv<2.0,>=1.0.0
|
|
28
|
+
Requires-Dist: pywin32>=306; platform_system == 'Windows'
|
|
28
29
|
Requires-Dist: textual<9.0,>=0.60
|
|
29
30
|
Requires-Dist: windows-curses>=2.4.1; platform_system == 'Windows'
|
|
30
31
|
Provides-Extra: all
|
|
@@ -111,8 +112,18 @@ All tools share a common data-source layer, so the same telemetry can be read di
|
|
|
111
112
|
|
|
112
113
|
Requires Python 3.10+.
|
|
113
114
|
|
|
115
|
+
### From PyPI
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pip install benchlab-pytools
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
This installs a `benchlab` console command on your PATH (see [Command-Line Flags](#command-line-flags) below). Install with extras for the tools you need, e.g. `pip install "benchlab-pytools[tui]"`.
|
|
122
|
+
|
|
123
|
+
### From source
|
|
124
|
+
|
|
114
125
|
```bash
|
|
115
|
-
pip install -r requirements.txt
|
|
126
|
+
pip install -r benchlab/requirements.txt
|
|
116
127
|
```
|
|
117
128
|
|
|
118
129
|
Each tool has its own `requirements.txt` (e.g. `benchlab/graph/requirements.txt`, `benchlab/vu/requirements.txt`). The launcher installs a tool's requirements automatically the first time it's run — you generally don't need to install them by hand.
|
|
@@ -135,11 +146,17 @@ or equivalently:
|
|
|
135
146
|
python -m benchlab
|
|
136
147
|
```
|
|
137
148
|
|
|
149
|
+
If installed from PyPI, use the `benchlab` command instead:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
benchlab
|
|
153
|
+
```
|
|
154
|
+
|
|
138
155
|
The interactive menu (prompt_toolkit-based, with a plain-input fallback if `prompt_toolkit` isn't installed) lets you pick a data source and one or more tools, then launches them — installing any missing per-tool dependencies along the way.
|
|
139
156
|
|
|
140
157
|
### Command-Line Flags
|
|
141
158
|
|
|
142
|
-
Each tool can also be launched directly with a flag
|
|
159
|
+
Each tool can also be launched directly with a flag. If installed from PyPI, replace `python -m benchlab` with `benchlab` in the examples below (e.g. `benchlab -tui`).
|
|
143
160
|
|
|
144
161
|
```bash
|
|
145
162
|
python -m benchlab -tui # Interactive terminal dashboard
|
|
@@ -21,8 +21,18 @@ All tools share a common data-source layer, so the same telemetry can be read di
|
|
|
21
21
|
|
|
22
22
|
Requires Python 3.10+.
|
|
23
23
|
|
|
24
|
+
### From PyPI
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install benchlab-pytools
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This installs a `benchlab` console command on your PATH (see [Command-Line Flags](#command-line-flags) below). Install with extras for the tools you need, e.g. `pip install "benchlab-pytools[tui]"`.
|
|
31
|
+
|
|
32
|
+
### From source
|
|
33
|
+
|
|
24
34
|
```bash
|
|
25
|
-
pip install -r requirements.txt
|
|
35
|
+
pip install -r benchlab/requirements.txt
|
|
26
36
|
```
|
|
27
37
|
|
|
28
38
|
Each tool has its own `requirements.txt` (e.g. `benchlab/graph/requirements.txt`, `benchlab/vu/requirements.txt`). The launcher installs a tool's requirements automatically the first time it's run — you generally don't need to install them by hand.
|
|
@@ -45,11 +55,17 @@ or equivalently:
|
|
|
45
55
|
python -m benchlab
|
|
46
56
|
```
|
|
47
57
|
|
|
58
|
+
If installed from PyPI, use the `benchlab` command instead:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
benchlab
|
|
62
|
+
```
|
|
63
|
+
|
|
48
64
|
The interactive menu (prompt_toolkit-based, with a plain-input fallback if `prompt_toolkit` isn't installed) lets you pick a data source and one or more tools, then launches them — installing any missing per-tool dependencies along the way.
|
|
49
65
|
|
|
50
66
|
### Command-Line Flags
|
|
51
67
|
|
|
52
|
-
Each tool can also be launched directly with a flag
|
|
68
|
+
Each tool can also be launched directly with a flag. If installed from PyPI, replace `python -m benchlab` with `benchlab` in the examples below (e.g. `benchlab -tui`).
|
|
53
69
|
|
|
54
70
|
```bash
|
|
55
71
|
python -m benchlab -tui # Interactive terminal dashboard
|
|
@@ -177,8 +177,8 @@ class DirectConfigClient(ConfigClient):
|
|
|
177
177
|
|
|
178
178
|
self.product_id = info.get('ProductId')
|
|
179
179
|
logger.info(
|
|
180
|
-
f"Connected to device on {port},
|
|
181
|
-
|
|
180
|
+
f"Connected to device on {port}, "
|
|
181
|
+
f"Product ID: 0x{self.product_id:02X}")
|
|
182
182
|
|
|
183
183
|
def get_device_info(self) -> Optional[Dict[str, Any]]:
|
|
184
184
|
"""Get device information."""
|
|
@@ -465,8 +465,7 @@ class NamedPipeConfigClient(ConfigClient):
|
|
|
465
465
|
win32pipe.WaitNamedPipe(path, 5000)
|
|
466
466
|
except pywintypes.error as e:
|
|
467
467
|
raise ConnectionError(
|
|
468
|
-
f"Pipe '{
|
|
469
|
-
self.pipe_name}' not available: {e}") from e
|
|
468
|
+
f"Pipe '{self.pipe_name}' not available: {e}") from e
|
|
470
469
|
|
|
471
470
|
self.handle = win32file.CreateFile(
|
|
472
471
|
path,
|
|
@@ -55,8 +55,7 @@ class ConfigManager:
|
|
|
55
55
|
from benchlab_pycore.core import get_fleet_info
|
|
56
56
|
devices = get_fleet_info()
|
|
57
57
|
logger.info(
|
|
58
|
-
f"Discovered {
|
|
59
|
-
len(devices)} device(s) via direct serial")
|
|
58
|
+
f"Discovered {len(devices)} device(s) via direct serial")
|
|
60
59
|
return devices
|
|
61
60
|
except Exception as e:
|
|
62
61
|
logger.error(f"Failed to discover direct devices: {e}")
|
|
@@ -357,8 +356,8 @@ class ConfigManager:
|
|
|
357
356
|
device_config.selector.model_dump(), devices)
|
|
358
357
|
if not identifier:
|
|
359
358
|
logger.error(
|
|
360
|
-
|
|
361
|
-
|
|
359
|
+
"Device not found matching selector: "
|
|
360
|
+
f"{device_config.selector}")
|
|
362
361
|
continue
|
|
363
362
|
|
|
364
363
|
logger.info(f"Selected: {identifier}")
|
|
@@ -453,8 +452,8 @@ class ConfigManager:
|
|
|
453
452
|
if not client.write_fan_config(
|
|
454
453
|
profile.profileId, fan_id, fan_dict):
|
|
455
454
|
logger.error(
|
|
456
|
-
|
|
457
|
-
|
|
455
|
+
"Failed to write fan config "
|
|
456
|
+
f"{profile.profileId}/{fan_id}")
|
|
458
457
|
success = False
|
|
459
458
|
|
|
460
459
|
# Apply RGB profiles
|
|
@@ -372,8 +372,7 @@ class FastAPIDataSource(DataSource):
|
|
|
372
372
|
return True
|
|
373
373
|
else:
|
|
374
374
|
logger.error(
|
|
375
|
-
f"FastAPI health check returned {
|
|
376
|
-
response.status_code}")
|
|
375
|
+
f"FastAPI health check returned {response.status_code}")
|
|
377
376
|
except Exception as e:
|
|
378
377
|
logger.error(f"Failed to connect to FastAPI server: {e}")
|
|
379
378
|
|
|
@@ -1025,9 +1024,8 @@ class ServiceHttpDataSource(DataSource):
|
|
|
1025
1024
|
|
|
1026
1025
|
if resp.status_code != 200:
|
|
1027
1026
|
logger.error(
|
|
1028
|
-
f"BenchLab service health check failed
|
|
1029
|
-
|
|
1030
|
-
self.base_url}/health")
|
|
1027
|
+
f"BenchLab service health check failed "
|
|
1028
|
+
f"(HTTP {resp.status_code}) at {self.base_url}/health")
|
|
1031
1029
|
return False
|
|
1032
1030
|
|
|
1033
1031
|
# Fetch initial device list
|
|
@@ -1051,8 +1049,7 @@ class ServiceHttpDataSource(DataSource):
|
|
|
1051
1049
|
target=self._worker_loop, daemon=True)
|
|
1052
1050
|
self._worker_thread.start()
|
|
1053
1051
|
logger.info(
|
|
1054
|
-
f"Connected to BenchLab service HTTP API at {
|
|
1055
|
-
self.base_url}")
|
|
1052
|
+
f"Connected to BenchLab service HTTP API at {self.base_url}")
|
|
1056
1053
|
return True
|
|
1057
1054
|
|
|
1058
1055
|
def disconnect(self) -> None:
|
|
@@ -109,14 +109,14 @@ class DataSourceManager:
|
|
|
109
109
|
self._datasource = create_datasource(self.source_type, **kwargs)
|
|
110
110
|
|
|
111
111
|
if not self._datasource.connect():
|
|
112
|
-
self._last_error =
|
|
113
|
-
self.source_type} datasource"
|
|
112
|
+
self._last_error = (
|
|
113
|
+
f"Failed to connect to {self.source_type} datasource")
|
|
114
114
|
return False
|
|
115
115
|
|
|
116
116
|
devices = self._datasource.list_devices()
|
|
117
117
|
if not devices:
|
|
118
|
-
self._last_error =
|
|
119
|
-
self.source_type}"
|
|
118
|
+
self._last_error = (
|
|
119
|
+
f"No devices available via {self.source_type}")
|
|
120
120
|
return False
|
|
121
121
|
|
|
122
122
|
if uid and any(d.get('uid') == uid for d in devices):
|
|
@@ -153,9 +153,8 @@ class DataSourceManager:
|
|
|
153
153
|
self._worker_thread.start()
|
|
154
154
|
|
|
155
155
|
logger.info(
|
|
156
|
-
f"Connected to {
|
|
157
|
-
|
|
158
|
-
self._selected_uid}")
|
|
156
|
+
f"Connected to {self.source_type} datasource, "
|
|
157
|
+
f"selected device: {self._selected_uid}")
|
|
159
158
|
return True
|
|
160
159
|
|
|
161
160
|
except Exception as e:
|
|
@@ -80,9 +80,8 @@ class InfrastructureManager:
|
|
|
80
80
|
return True
|
|
81
81
|
|
|
82
82
|
logger.info(
|
|
83
|
-
f"Starting FastAPI server on
|
|
84
|
-
|
|
85
|
-
self.fastapi_port}")
|
|
83
|
+
f"Starting FastAPI server on "
|
|
84
|
+
f"{self.fastapi_host}:{self.fastapi_port}")
|
|
86
85
|
|
|
87
86
|
try:
|
|
88
87
|
# Start FastAPI server as subprocess
|
|
@@ -107,8 +106,8 @@ class InfrastructureManager:
|
|
|
107
106
|
if self._wait_for_port(
|
|
108
107
|
self.fastapi_host, self.fastapi_port, timeout):
|
|
109
108
|
logger.info(
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
"FastAPI server started on port "
|
|
110
|
+
f"{self.fastapi_port}")
|
|
112
111
|
return True
|
|
113
112
|
else:
|
|
114
113
|
logger.error("FastAPI server failed to start")
|
|
@@ -171,9 +170,8 @@ class InfrastructureManager:
|
|
|
171
170
|
return True
|
|
172
171
|
|
|
173
172
|
logger.info(
|
|
174
|
-
f"Starting MQTT publisher to
|
|
175
|
-
|
|
176
|
-
self.mqtt_port}")
|
|
173
|
+
f"Starting MQTT publisher to "
|
|
174
|
+
f"{self.mqtt_broker}:{self.mqtt_port}")
|
|
177
175
|
|
|
178
176
|
try:
|
|
179
177
|
self._stop_event.clear()
|
|
@@ -202,10 +202,9 @@ class StatsFormatter:
|
|
|
202
202
|
if min_val is None or max_val is None or avg_val is None:
|
|
203
203
|
return ""
|
|
204
204
|
|
|
205
|
-
return
|
|
206
|
-
min_val:.{decimals}f}-{
|
|
207
|
-
|
|
208
|
-
avg_val:.{decimals}f}{unit}"
|
|
205
|
+
return (
|
|
206
|
+
f"{min_val:.{decimals}f}-{max_val:.{decimals}f} "
|
|
207
|
+
f"~{avg_val:.{decimals}f}{unit}")
|
|
209
208
|
|
|
210
209
|
|
|
211
210
|
# Convenience function for creating a stats callback
|
|
@@ -141,10 +141,8 @@ class EnhancedCSVLogger:
|
|
|
141
141
|
print("\n--- Available Devices ---")
|
|
142
142
|
for i, dev in enumerate(devices, 1):
|
|
143
143
|
print(
|
|
144
|
-
f" {i}: Port: {
|
|
145
|
-
|
|
146
|
-
dev.uid} FW: {
|
|
147
|
-
dev.firmware}")
|
|
144
|
+
f" {i}: Port: {dev.port:<12} UID: {dev.uid} "
|
|
145
|
+
f"FW: {dev.firmware}")
|
|
148
146
|
|
|
149
147
|
selection = input(
|
|
150
148
|
"\nEnter device numbers (comma-separated), 'all', "
|
|
@@ -95,9 +95,7 @@ class MessageBatcher:
|
|
|
95
95
|
(self.metrics.avg_flush_time * (n - 1) + elapsed) / n
|
|
96
96
|
)
|
|
97
97
|
self.logger.debug(
|
|
98
|
-
f"Flushed {
|
|
99
|
-
len(messages_to_flush)} messages in {
|
|
100
|
-
elapsed:.3f}s")
|
|
98
|
+
f"Flushed {len(messages_to_flush)} messages in {elapsed:.3f}s")
|
|
101
99
|
return True
|
|
102
100
|
|
|
103
101
|
except Exception as e:
|
|
@@ -222,8 +220,7 @@ class CSVBatchWriter:
|
|
|
222
220
|
elif self.format == "json":
|
|
223
221
|
self._write_json_batch(file_info, messages_to_write)
|
|
224
222
|
self.logger.debug(
|
|
225
|
-
f"Wrote {
|
|
226
|
-
len(messages_to_write)} rows for {uid}")
|
|
223
|
+
f"Wrote {len(messages_to_write)} rows for {uid}")
|
|
227
224
|
except Exception as e:
|
|
228
225
|
self.logger.error(f"Failed to write batch for {uid}: {e}")
|
|
229
226
|
buf.extend(messages_to_write) # restore on failure
|
|
@@ -104,8 +104,8 @@ class CircuitBreaker:
|
|
|
104
104
|
if (self.config.circuit_breaker_enabled and
|
|
105
105
|
self.failure_count >= self.config.circuit_failure_threshold):
|
|
106
106
|
self.logger.warning(
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
"Circuit breaker: opening after "
|
|
108
|
+
f"{self.failure_count} failures")
|
|
109
109
|
self.state = CircuitState.OPEN
|
|
110
110
|
|
|
111
111
|
|
|
@@ -144,9 +144,8 @@ class SmartRetryManager:
|
|
|
144
144
|
|
|
145
145
|
if attempt == self.config.max_retries:
|
|
146
146
|
self.logger.error(
|
|
147
|
-
f"Max retries ({
|
|
148
|
-
|
|
149
|
-
func.__name__}")
|
|
147
|
+
f"Max retries ({self.config.max_retries}) "
|
|
148
|
+
f"exceeded for {func.__name__}")
|
|
150
149
|
raise e
|
|
151
150
|
|
|
152
151
|
# Calculate delay
|
|
@@ -242,9 +241,8 @@ class AdaptiveRetryManager:
|
|
|
242
241
|
|
|
243
242
|
if attempt == self.config.max_retries:
|
|
244
243
|
self.logger.error(
|
|
245
|
-
f"Max retries ({
|
|
246
|
-
|
|
247
|
-
func.__name__}")
|
|
244
|
+
f"Max retries ({self.config.max_retries}) "
|
|
245
|
+
f"exceeded for {func.__name__}")
|
|
248
246
|
raise e
|
|
249
247
|
|
|
250
248
|
# Calculate adaptive delay
|
|
@@ -263,12 +263,15 @@ class GraphApp:
|
|
|
263
263
|
min_y - margin, max_y + margin)
|
|
264
264
|
|
|
265
265
|
s = self.session_stats
|
|
266
|
-
min_text =
|
|
267
|
-
s['min']:.2f}"
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
266
|
+
min_text = (
|
|
267
|
+
f"Min: {s['min']:.2f}"
|
|
268
|
+
if s["min"] is not None else "Min: --")
|
|
269
|
+
max_text = (
|
|
270
|
+
f"Max: {s['max']:.2f}"
|
|
271
|
+
if s["max"] is not None else "Max: --")
|
|
272
|
+
avg_text = (
|
|
273
|
+
f"Avg: {s['avg']:.2f}"
|
|
274
|
+
if s["avg"] is not None else "Avg: --")
|
|
272
275
|
for tag, text in (
|
|
273
276
|
("graph_min", min_text),
|
|
274
277
|
("graph_min_float", min_text),
|
|
@@ -71,8 +71,7 @@ def write_hwinfo_sensor(device_name, sensor_type, idx, name, value, unit=None):
|
|
|
71
71
|
# Write Value
|
|
72
72
|
if isinstance(value, float):
|
|
73
73
|
winreg.SetValueEx(
|
|
74
|
-
key, "Value", 0, winreg.REG_SZ, f"{
|
|
75
|
-
value:.3f}")
|
|
74
|
+
key, "Value", 0, winreg.REG_SZ, f"{value:.3f}")
|
|
76
75
|
else:
|
|
77
76
|
winreg.SetValueEx(key, "Value", 0, winreg.REG_SZ, str(value))
|
|
78
77
|
|
|
@@ -156,8 +155,7 @@ def _export_grouped(device_name: str, grouped_sensors: dict):
|
|
|
156
155
|
write_hwinfo_sensor(device_name, group, idx, key, value, unit)
|
|
157
156
|
|
|
158
157
|
summary = ", ".join(
|
|
159
|
-
f"{k}: {
|
|
160
|
-
len(v)}" for k,
|
|
158
|
+
f"{k}: {len(v)}" for k,
|
|
161
159
|
v in grouped_sensors.items() if v)
|
|
162
160
|
logger.debug("Device %s export summary: %s", device_name, summary)
|
|
163
161
|
|
|
@@ -308,8 +306,8 @@ def export_all_devices(update_interval=1, datasource=None):
|
|
|
308
306
|
"HWiNFO export is only supported on Windows. "
|
|
309
307
|
"Please run on a Windows system.")
|
|
310
308
|
raise RuntimeError(
|
|
311
|
-
|
|
312
|
-
|
|
309
|
+
"HWiNFO export requires Windows. "
|
|
310
|
+
f"Current platform: {sys.platform}")
|
|
313
311
|
|
|
314
312
|
# Remove only old BenchLab entries, not user-created sensors
|
|
315
313
|
try:
|
|
@@ -217,8 +217,7 @@ class CloudMQTTClient:
|
|
|
217
217
|
time.sleep(0.1)
|
|
218
218
|
if not self._connected:
|
|
219
219
|
logger.error(
|
|
220
|
-
f"Timed out connecting to {host}:{
|
|
221
|
-
self.cfg['port']}")
|
|
220
|
+
f"Timed out connecting to {host}:{self.cfg['port']}")
|
|
222
221
|
return False
|
|
223
222
|
logger.info(f"Connected to cloud broker {host}:{self.cfg['port']}")
|
|
224
223
|
return True
|
|
@@ -229,9 +228,8 @@ class CloudMQTTClient:
|
|
|
229
228
|
def reconnect(self) -> bool:
|
|
230
229
|
"""Attempt to reconnect using a fresh client."""
|
|
231
230
|
logger.info(
|
|
232
|
-
f"Reconnecting to cloud broker
|
|
233
|
-
|
|
234
|
-
self.cfg['port']}...")
|
|
231
|
+
f"Reconnecting to cloud broker "
|
|
232
|
+
f"{self.cfg['host']}:{self.cfg['port']}...")
|
|
235
233
|
try:
|
|
236
234
|
self._client.loop_stop()
|
|
237
235
|
except Exception:
|
|
@@ -22,4 +22,7 @@ paho-mqtt>=2.0,<3.0
|
|
|
22
22
|
amqtt>=0.12.0,<0.13.0
|
|
23
23
|
|
|
24
24
|
# Curses-based TUI
|
|
25
|
-
windows-curses>=2.4.1; platform_system=="Windows"
|
|
25
|
+
windows-curses>=2.4.1; platform_system=="Windows"
|
|
26
|
+
|
|
27
|
+
# Named Pipe Data Source (BL_Service)
|
|
28
|
+
pywin32>=306; platform_system=="Windows"
|
|
@@ -145,12 +145,7 @@ import asyncio
|
|
|
145
145
|
from amqtt.broker import Broker
|
|
146
146
|
|
|
147
147
|
config = {{
|
|
148
|
-
"listeners": {{
|
|
149
|
-
"default": {{
|
|
150
|
-
"type": "tcp",
|
|
151
|
-
"bind": "0.0.0.0:{port}",
|
|
152
|
-
}},
|
|
153
|
-
}},
|
|
148
|
+
"listeners": {{"default": {{"type": "tcp", "bind": "0.0.0.0:{port}"}}}},
|
|
154
149
|
"auth": {{"allow-anonymous": True}},
|
|
155
150
|
"topic-check": {{"enabled": False}},
|
|
156
151
|
}}
|