benchlab-pytools 3.2.0__tar.gz → 3.2.1__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.2.0 → benchlab_pytools-3.2.1}/CHANGELOG.md +15 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/PKG-INFO +1 -1
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/__init__.py +1 -1
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/restapi/telemetry_api.py +28 -24
- benchlab_pytools-3.2.1/benchlab/restapi/test_read_recovery.py +235 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/.flake8 +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/.gitignore +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/CONTRIBUTING.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/LICENSE +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/__main__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/bootstrap.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/config_client.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/config_manager.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/config_tool.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/diff.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/examples/complete_config.json +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/examples/rgb_lighting.json +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/examples/simple_fan.json +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/schema.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/test_config_client.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/test_config_manager.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/test_diff.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/config.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/datasource.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/datasource_manager.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/device_registry.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/discovery.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/infrastructure.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/process_manager.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/retry.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/shared_serial.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/core/statistics.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/csv_log/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/csv_log/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/csv_log/csv_logger_enhanced.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/csv_log/message_batcher.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/csv_log/requirements.txt +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/csv_log/smart_retry.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/graph/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/graph/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/graph/app.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/graph/requirements.txt +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/graph/runner.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/graph/test_graph.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/graph/ui.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/hwinfo/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/hwinfo/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/hwinfo/hwinfo_export.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/hwinfo/requirements.txt +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/hwinfo/test_hwinfo_export.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/launcher.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/link/.env.EXAMPLE +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/link/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/link/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/link/link_main.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/link/test_link_main.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/main.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/menu.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/menu_classic.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/mqtt/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/mqtt/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/mqtt/mqtt.config_template +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/mqtt/mqtt_publisher.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/mqtt/requirements.txt +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/mqtt/test_mqtt_publisher.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/prefs.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/requirements.txt +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/restapi/.env.example +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/restapi/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/restapi/favicon.ico +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/restapi/readme.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/restapi/requirements.txt +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/restapi/test_server.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/sources.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/tools.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/tui/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/tui/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/tui/config.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/tui/requirements.txt +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/tui/test_tui_core.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/tui/test_tui_main.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/tui/tui_core.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/tui/tui_main.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/NOTICE.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/Running_from_source_on_linux.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/assets/vu1_hello_world.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/community_applications.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/config.yaml +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/database.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/dial_driver.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/dials/Comms_Hub_Gauge.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/dials/Comms_Hub_Server.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/dials/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/dials/base_logger.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/installer/inc/icon.ico +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/installer/install.nsi +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/make_version.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/pylintrc +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/requirements.txt +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/serial_driver.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/server.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/server_config.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/server_dial_handler.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/vu_notifications.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/android-chrome-192x192.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/android-chrome-512x512.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/apple-touch-icon.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/demo.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/demo.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/demo.rtl.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/demo.rtl.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.rtl.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.rtl.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.rtl.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.rtl.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-social.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-social.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-social.rtl.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-social.rtl.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.rtl.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.rtl.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler.rtl.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/tabler.rtl.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/css/theme.min.css +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/img/header.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/img/logo.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/dark-theme.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/dark-theme.min.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/demo.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/demo.min.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/jquery.min.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/tabler.esm.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/tabler.esm.min.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/tabler.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/tabler.min.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/vu1_api.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_api_key_settings.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_api_keys.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_dial.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_home.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_root.js +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/favicon-16x16.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/favicon-32x32.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/favicon.ico +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/favicon.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/index.html +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/views/api_keys.html +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/views/dial.html +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/views/footer.html +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/views/header.html +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/views/key_settings.html +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/www/views/start.html +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/assets/Barlow-Bold.ttf +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/assets/bl_dial_144x200.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/assets/bl_logo_144x200.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/devices.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/requirements.txt +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/sensors.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/test_devices.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/test_vu_server_config.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/test_vu_server_manager.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/test_vu_tui.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/vu_dial.config_template +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/vu_logo_gen.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/vu_server.config_template +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/vu_server_config.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/vu_server_manager.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/vu_tui.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/vu_updater.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/README.md +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/__init__.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/assets/Inter-Bold.ttf +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/assets/Inter.ttf +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/assets/benchlab.png +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/benchlab_fleet.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/benchlab_graph.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/benchlab_overview.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/benchlab_telemetry.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/benchlab_ui.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/benchlab_utils.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/requirements.txt +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/test_wigidash.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/wigidash_device.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/wigidash_manager.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/wigidash_session.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/wigidash_usb.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/wigidash/wigidash_widget.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab.py +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/pyproject.toml +0 -0
- {benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/pytest.ini +0 -0
|
@@ -4,6 +4,20 @@ 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.2.1] - 2026-10-01
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Collector recovery after incomplete sensor reads
|
|
11
|
+
(`benchlab.restapi.telemetry_api.read_device_loop`): incomplete serial
|
|
12
|
+
responses (`read_sensors()` returning `None`) are now treated as read
|
|
13
|
+
failures instead of being silently ignored, so the collector reconnects
|
|
14
|
+
instead of continuing to publish stale telemetry. The read-error
|
|
15
|
+
backoff counter now survives serial port reopen attempts and resets
|
|
16
|
+
only after a successfully decoded sample, restoring the intended
|
|
17
|
+
retry/backoff policy. A device is marked `connected` only once a
|
|
18
|
+
sample has actually been decoded, and stale telemetry is cleared
|
|
19
|
+
before the collector waits to retry. (#77)
|
|
20
|
+
|
|
7
21
|
## [3.2.0] - 2026-09-29
|
|
8
22
|
|
|
9
23
|
### Added
|
|
@@ -159,6 +173,7 @@ export, MQTT publisher, VU dials, WigiDash, and config import/export tools,
|
|
|
159
173
|
sharing a common data-source layer (direct serial, FastAPI, MQTT, named
|
|
160
174
|
pipe, service HTTP, service WebSocket).
|
|
161
175
|
|
|
176
|
+
[3.2.1]: https://github.com/BenchLab-io/benchlab-pytools/compare/v3.2.0...v3.2.1
|
|
162
177
|
[3.2.0]: https://github.com/BenchLab-io/benchlab-pytools/compare/v3.1.0...v3.2.0
|
|
163
178
|
[3.1.0]: https://github.com/BenchLab-io/benchlab-pytools/compare/v3.0.4...v3.1.0
|
|
164
179
|
[3.0.4]: https://github.com/BenchLab-io/benchlab-pytools/compare/v3.0.3...v3.0.4
|
|
@@ -441,30 +441,25 @@ def read_device_loop(port, uid):
|
|
|
441
441
|
reconnection logic."""
|
|
442
442
|
ser = None
|
|
443
443
|
consecutive_errors = 0
|
|
444
|
-
max_consecutive_errors = 10 #
|
|
444
|
+
max_consecutive_errors = 10 # Back off after repeated read failures
|
|
445
445
|
product_id = None # Will be set once we read device info
|
|
446
|
-
is_connected = False #
|
|
446
|
+
is_connected = False # Only valid telemetry establishes a connection
|
|
447
|
+
with data_lock:
|
|
448
|
+
was_connected = devices_data.get(uid, {}).get("connected", False)
|
|
449
|
+
if uid in devices_data:
|
|
450
|
+
devices_data[uid]["connected"] = False
|
|
451
|
+
devices_data[uid]["latest"] = create_empty_telemetry()
|
|
452
|
+
if was_connected:
|
|
453
|
+
schedule_device_event(uid, "disconnected")
|
|
447
454
|
|
|
448
455
|
while not shutdown_event.is_set():
|
|
449
456
|
# --- (Re)connect ---
|
|
450
457
|
if ser is None:
|
|
451
|
-
# Mark as disconnected
|
|
452
|
-
if is_connected:
|
|
453
|
-
is_connected = False
|
|
454
|
-
with data_lock:
|
|
455
|
-
if uid in devices_data:
|
|
456
|
-
devices_data[uid]["connected"] = False
|
|
457
|
-
devices_data[uid]["latest"] = create_empty_telemetry()
|
|
458
|
-
schedule_device_event(uid, "disconnected")
|
|
459
|
-
logger.info("[%s] Device disconnected", uid)
|
|
460
|
-
|
|
461
458
|
try:
|
|
462
459
|
new_ser = open_serial_connection(port)
|
|
463
460
|
if new_ser is None:
|
|
464
461
|
raise OSError("open_serial_connection returned None")
|
|
465
462
|
ser = new_ser
|
|
466
|
-
# Reset error counter on successful connect
|
|
467
|
-
consecutive_errors = 0
|
|
468
463
|
|
|
469
464
|
# Read device info to get product_id for sensor reading
|
|
470
465
|
try:
|
|
@@ -481,18 +476,12 @@ def read_device_loop(port, uid):
|
|
|
481
476
|
except Exception:
|
|
482
477
|
pass
|
|
483
478
|
|
|
484
|
-
is_connected = True
|
|
485
|
-
with data_lock:
|
|
486
|
-
if uid in devices_data:
|
|
487
|
-
devices_data[uid]["connected"] = True
|
|
488
|
-
schedule_device_event(uid, "connected")
|
|
489
|
-
logger.info("Connected to device %s on %s", uid, port)
|
|
490
479
|
except Exception as exc:
|
|
491
480
|
ser = None # Ensure ser is None on error
|
|
492
481
|
consecutive_errors += 1
|
|
493
482
|
delay = min(
|
|
494
483
|
RECONNECT_DELAY * consecutive_errors,
|
|
495
|
-
30) #
|
|
484
|
+
30) # Linear backoff, capped
|
|
496
485
|
logger.warning(
|
|
497
486
|
"[%s] Failed to open serial port %s: %s (retry in %.1fs)",
|
|
498
487
|
uid,
|
|
@@ -509,6 +498,8 @@ def read_device_loop(port, uid):
|
|
|
509
498
|
shutdown_event.wait(1)
|
|
510
499
|
continue
|
|
511
500
|
sensors = read_sensors(ser, product_id=product_id)
|
|
501
|
+
if sensors is None:
|
|
502
|
+
raise OSError("No complete sensor response received")
|
|
512
503
|
if sensors:
|
|
513
504
|
translated = translate_sensor_struct(sensors)
|
|
514
505
|
translated["timestamp"] = datetime.now().strftime(
|
|
@@ -518,12 +509,15 @@ def read_device_loop(port, uid):
|
|
|
518
509
|
|
|
519
510
|
with data_lock:
|
|
520
511
|
if uid in devices_data:
|
|
512
|
+
devices_data[uid]["connected"] = True
|
|
521
513
|
devices_data[uid]["latest"] = translated
|
|
522
514
|
devices_data[uid]["history"].append(translated)
|
|
523
515
|
|
|
516
|
+
if not is_connected:
|
|
517
|
+
is_connected = True
|
|
518
|
+
schedule_device_event(uid, "connected")
|
|
519
|
+
logger.info("Connected to device %s on %s", uid, port)
|
|
524
520
|
schedule_update(uid, translated)
|
|
525
|
-
else:
|
|
526
|
-
logger.debug("[%s] No sensor data read", uid)
|
|
527
521
|
except Exception as e:
|
|
528
522
|
consecutive_errors += 1
|
|
529
523
|
# Specific debug logging for unsupported commands
|
|
@@ -547,8 +541,18 @@ def read_device_loop(port, uid):
|
|
|
547
541
|
except Exception:
|
|
548
542
|
pass
|
|
549
543
|
ser = None
|
|
544
|
+
was_connected = is_connected
|
|
545
|
+
if is_connected:
|
|
546
|
+
logger.info("[%s] Device disconnected", uid)
|
|
547
|
+
is_connected = False
|
|
548
|
+
with data_lock:
|
|
549
|
+
if uid in devices_data:
|
|
550
|
+
devices_data[uid]["connected"] = False
|
|
551
|
+
devices_data[uid]["latest"] = create_empty_telemetry()
|
|
552
|
+
if was_connected:
|
|
553
|
+
schedule_device_event(uid, "disconnected")
|
|
550
554
|
|
|
551
|
-
#
|
|
555
|
+
# Linear backoff with cap
|
|
552
556
|
if consecutive_errors >= max_consecutive_errors:
|
|
553
557
|
delay = min(RECONNECT_DELAY * consecutive_errors, 30)
|
|
554
558
|
logger.warning(
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""Fault injection for the collector's serial recovery; no hardware needed."""
|
|
2
|
+
from collections import deque
|
|
3
|
+
from unittest.mock import MagicMock, call
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from benchlab.restapi import telemetry_api as api
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class StopEvent:
|
|
11
|
+
def __init__(self):
|
|
12
|
+
self.stopped = False
|
|
13
|
+
self.waits = []
|
|
14
|
+
self.on_wait = lambda _: None
|
|
15
|
+
|
|
16
|
+
def is_set(self):
|
|
17
|
+
return self.stopped
|
|
18
|
+
|
|
19
|
+
def wait(self, delay):
|
|
20
|
+
self.waits.append(delay)
|
|
21
|
+
self.on_wait(delay)
|
|
22
|
+
return self.stopped
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.fixture
|
|
26
|
+
def reader(monkeypatch):
|
|
27
|
+
stop = StopEvent()
|
|
28
|
+
device = {"connected": False, "latest": {}, "history": deque()}
|
|
29
|
+
connections = []
|
|
30
|
+
|
|
31
|
+
def open_port(_):
|
|
32
|
+
ser = MagicMock()
|
|
33
|
+
connections.append(ser)
|
|
34
|
+
if len(connections) > 30:
|
|
35
|
+
stop.stopped = True # Bound regressions that never reach backoff.
|
|
36
|
+
return ser
|
|
37
|
+
|
|
38
|
+
monkeypatch.setattr(api, "shutdown_event", stop)
|
|
39
|
+
monkeypatch.setattr(api, "devices_data", {"test": device})
|
|
40
|
+
monkeypatch.setattr(api, "open_serial_connection", open_port)
|
|
41
|
+
monkeypatch.setattr(api, "read_device", lambda _: {"ProductId": 16})
|
|
42
|
+
monkeypatch.setattr(
|
|
43
|
+
api, "translate_sensor_struct", lambda _: {"TS_2": 24.0})
|
|
44
|
+
trace = []
|
|
45
|
+
snapshots = []
|
|
46
|
+
|
|
47
|
+
def device_event(uid, event):
|
|
48
|
+
# Record rather than assert here: the reader catches exceptions.
|
|
49
|
+
unlocked = api.data_lock.acquire(blocking=False)
|
|
50
|
+
if unlocked:
|
|
51
|
+
api.data_lock.release()
|
|
52
|
+
wire = api._device_to_wire_shape(uid) if unlocked else {}
|
|
53
|
+
snapshots.append((event, device["connected"],
|
|
54
|
+
device["latest"].copy(), unlocked, wire))
|
|
55
|
+
trace.append(event)
|
|
56
|
+
|
|
57
|
+
events = MagicMock(side_effect=device_event)
|
|
58
|
+
publish = MagicMock(side_effect=lambda *_: trace.append("telemetry"))
|
|
59
|
+
monkeypatch.setattr(api, "schedule_update", publish)
|
|
60
|
+
monkeypatch.setattr(api, "schedule_device_event", events)
|
|
61
|
+
yield stop, device, connections, publish, events, trace
|
|
62
|
+
|
|
63
|
+
for event, connected, latest, unlocked, wire in snapshots:
|
|
64
|
+
assert unlocked, "Device event scheduled while holding data_lock"
|
|
65
|
+
assert connected == (event == "connected")
|
|
66
|
+
assert wire["status"] == event.upper()
|
|
67
|
+
if connected:
|
|
68
|
+
assert latest["TS_2"] == 24.0
|
|
69
|
+
else:
|
|
70
|
+
assert latest["connected"] is False
|
|
71
|
+
assert latest["TS_2"] == 0
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@pytest.mark.parametrize("failure", [None, OSError("USB disconnected")])
|
|
75
|
+
def test_failed_read_discards_stale_data_and_reconnects(
|
|
76
|
+
monkeypatch, reader, failure):
|
|
77
|
+
stop, device, connections, publish, events, trace = reader
|
|
78
|
+
reads = 0
|
|
79
|
+
|
|
80
|
+
def read(*args, **kwargs):
|
|
81
|
+
nonlocal reads
|
|
82
|
+
reads += 1
|
|
83
|
+
if reads >= 3:
|
|
84
|
+
stop.stopped = True
|
|
85
|
+
if reads == 2:
|
|
86
|
+
assert device["connected"]
|
|
87
|
+
if isinstance(failure, Exception):
|
|
88
|
+
raise failure
|
|
89
|
+
return failure
|
|
90
|
+
if reads == 3:
|
|
91
|
+
assert not device["connected"]
|
|
92
|
+
assert device["latest"]["connected"] is False
|
|
93
|
+
assert len(connections) == 2
|
|
94
|
+
stop.stopped = True
|
|
95
|
+
return object()
|
|
96
|
+
|
|
97
|
+
monkeypatch.setattr(api, "read_sensors", read)
|
|
98
|
+
api.read_device_loop("/fake", "test")
|
|
99
|
+
assert publish.call_count == 2
|
|
100
|
+
assert trace == ["connected", "telemetry", "disconnected",
|
|
101
|
+
"connected", "telemetry", "disconnected"]
|
|
102
|
+
assert events.call_args_list == [
|
|
103
|
+
call("test", "connected"), call("test", "disconnected"),
|
|
104
|
+
call("test", "connected"), call("test", "disconnected"),
|
|
105
|
+
]
|
|
106
|
+
assert len(device["history"]) == 2
|
|
107
|
+
assert all(s.close.call_count == 1 for s in connections)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@pytest.mark.parametrize("failure", [None, OSError("read failed")])
|
|
111
|
+
def test_repeated_read_failures_back_off_even_when_open_succeeds(
|
|
112
|
+
monkeypatch, reader, failure):
|
|
113
|
+
stop, device, connections, publish, events, trace = reader
|
|
114
|
+
|
|
115
|
+
def read(*args, **kwargs):
|
|
116
|
+
assert not device["connected"]
|
|
117
|
+
if isinstance(failure, Exception):
|
|
118
|
+
raise failure
|
|
119
|
+
return failure
|
|
120
|
+
|
|
121
|
+
def waited(delay):
|
|
122
|
+
assert not device["connected"]
|
|
123
|
+
assert device["latest"]["connected"] is False
|
|
124
|
+
stop.stopped = True
|
|
125
|
+
|
|
126
|
+
stop.on_wait = waited
|
|
127
|
+
monkeypatch.setattr(api, "read_sensors", read)
|
|
128
|
+
api.read_device_loop("/fake", "test")
|
|
129
|
+
assert len(connections) == 10
|
|
130
|
+
assert stop.waits == [min(api.RECONNECT_DELAY * 10, 30)]
|
|
131
|
+
publish.assert_not_called()
|
|
132
|
+
assert not device["history"]
|
|
133
|
+
events.assert_not_called()
|
|
134
|
+
assert all(s.close.call_count == 1 for s in connections)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def test_valid_sample_resets_failure_streak(monkeypatch, reader):
|
|
138
|
+
stop, device, connections, publish, events, trace = reader
|
|
139
|
+
reads = 0
|
|
140
|
+
|
|
141
|
+
def read(*args, **kwargs):
|
|
142
|
+
nonlocal reads
|
|
143
|
+
reads += 1
|
|
144
|
+
if reads > 30:
|
|
145
|
+
stop.stopped = True
|
|
146
|
+
if reads == 10:
|
|
147
|
+
return object()
|
|
148
|
+
return None
|
|
149
|
+
|
|
150
|
+
def waited(delay):
|
|
151
|
+
if delay == api.poll_interval:
|
|
152
|
+
assert device["connected"]
|
|
153
|
+
else:
|
|
154
|
+
assert reads == 20
|
|
155
|
+
stop.stopped = True
|
|
156
|
+
|
|
157
|
+
stop.on_wait = waited
|
|
158
|
+
monkeypatch.setattr(api, "read_sensors", read)
|
|
159
|
+
api.read_device_loop("/fake", "test")
|
|
160
|
+
assert stop.waits == [api.poll_interval, min(api.RECONNECT_DELAY * 10, 30)]
|
|
161
|
+
publish.assert_called_once()
|
|
162
|
+
assert len(device["history"]) == 1
|
|
163
|
+
assert trace == ["connected", "telemetry", "disconnected"]
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@pytest.mark.parametrize("initially_connected", [False, True])
|
|
167
|
+
def test_failed_initial_open_clears_discovery_connected_flag(
|
|
168
|
+
monkeypatch, reader, initially_connected):
|
|
169
|
+
stop, device, connections, publish, events, trace = reader
|
|
170
|
+
device.update(connected=initially_connected, latest={"TS_2": 24.0})
|
|
171
|
+
monkeypatch.setattr(api, "open_serial_connection", lambda _: None)
|
|
172
|
+
|
|
173
|
+
def waited(delay):
|
|
174
|
+
assert not device["connected"]
|
|
175
|
+
assert device["latest"]["connected"] is False
|
|
176
|
+
stop.stopped = True
|
|
177
|
+
|
|
178
|
+
stop.on_wait = waited
|
|
179
|
+
api.read_device_loop("/fake", "test")
|
|
180
|
+
assert stop.waits == [min(api.RECONNECT_DELAY, 30)]
|
|
181
|
+
publish.assert_not_called()
|
|
182
|
+
assert trace == (["disconnected"] if initially_connected else [])
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def test_steady_samples_emit_one_connection_and_shutdown_event(
|
|
186
|
+
monkeypatch, reader):
|
|
187
|
+
stop, device, connections, publish, events, trace = reader
|
|
188
|
+
reads = 0
|
|
189
|
+
|
|
190
|
+
def read(*args, **kwargs):
|
|
191
|
+
nonlocal reads
|
|
192
|
+
reads += 1
|
|
193
|
+
if reads >= 3:
|
|
194
|
+
stop.stopped = True
|
|
195
|
+
return object()
|
|
196
|
+
|
|
197
|
+
monkeypatch.setattr(api, "read_sensors", read)
|
|
198
|
+
api.read_device_loop("/fake", "test")
|
|
199
|
+
assert trace == ["connected", "telemetry", "telemetry", "telemetry",
|
|
200
|
+
"disconnected"]
|
|
201
|
+
assert len(connections) == 1
|
|
202
|
+
assert publish.call_count == 3
|
|
203
|
+
assert not device["connected"]
|
|
204
|
+
assert connections[0].close.call_count == 1
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
@pytest.mark.parametrize("failure", [None, OSError("read failed")])
|
|
208
|
+
def test_disconnect_event_precedes_backoff(monkeypatch, reader, failure):
|
|
209
|
+
stop, device, connections, publish, events, trace = reader
|
|
210
|
+
reads = 0
|
|
211
|
+
backoff_traces = []
|
|
212
|
+
|
|
213
|
+
def read(*args, **kwargs):
|
|
214
|
+
nonlocal reads
|
|
215
|
+
reads += 1
|
|
216
|
+
if reads > 15:
|
|
217
|
+
stop.stopped = True
|
|
218
|
+
if reads == 1:
|
|
219
|
+
return object()
|
|
220
|
+
if isinstance(failure, Exception):
|
|
221
|
+
raise failure
|
|
222
|
+
return failure
|
|
223
|
+
|
|
224
|
+
def waited(delay):
|
|
225
|
+
if delay != api.poll_interval:
|
|
226
|
+
backoff_traces.append(trace.copy())
|
|
227
|
+
stop.stopped = True
|
|
228
|
+
|
|
229
|
+
stop.on_wait = waited
|
|
230
|
+
monkeypatch.setattr(api, "read_sensors", read)
|
|
231
|
+
api.read_device_loop("/fake", "test")
|
|
232
|
+
assert reads == 11
|
|
233
|
+
assert backoff_traces == [["connected", "telemetry", "disconnected"]]
|
|
234
|
+
assert trace == backoff_traces[0]
|
|
235
|
+
assert stop.waits == [api.poll_interval, min(api.RECONNECT_DELAY * 10, 30)]
|
|
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
|
|
File without changes
|
{benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/examples/complete_config.json
RENAMED
|
File without changes
|
{benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/config/examples/rgb_lighting.json
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
{benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/assets/vu1_hello_world.png
RENAMED
|
File without changes
|
{benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/community_applications.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/dials/Comms_Hub_Gauge.py
RENAMED
|
File without changes
|
{benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/dials/Comms_Hub_Server.py
RENAMED
|
File without changes
|
|
File without changes
|
{benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/dials/base_logger.py
RENAMED
|
File without changes
|
{benchlab_pytools-3.2.0 → benchlab_pytools-3.2.1}/benchlab/vu/VU-Server/installer/inc/icon.ico
RENAMED
|
File without changes
|