lager-cli 0.28.2__tar.gz → 0.28.3__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.
- {lager_cli-0.28.2/lager_cli.egg-info → lager_cli-0.28.3}/PKG-INFO +1 -1
- {lager_cli-0.28.2 → lager_cli-0.28.3}/__init__.py +1 -1
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/diagnose.py +202 -9
- {lager_cli-0.28.2 → lager_cli-0.28.3/lager_cli.egg-info}/PKG-INFO +1 -1
- {lager_cli-0.28.2 → lager_cli-0.28.3}/LICENSE +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/MANIFEST.in +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/README.md +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/__main__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/address_utils.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/battery/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/battery/battery_tui.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/battery/websocket_client.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/box_storage.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/_host_ops.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/_mount_prep.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/_pip_validation.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/_shim_verbs.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/_ssh.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/authorize.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/box_group.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/boxes.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/config.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/dut.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/hello.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/instruments.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/labjack_pins.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/lock.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/net_tui.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/nets.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/box/ssh.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/communication/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/communication/ble.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/communication/blufi.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/communication/i2c.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/communication/router.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/communication/spi.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/communication/uart.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/communication/usb.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/communication/websocket_client.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/communication/wifi.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/arm.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/debug/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/debug/commands.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/debug/gdb.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/debug/net_cache.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/debug/service_client.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/debug/service_helper.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/debug/tunnel.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/devenv.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/development/python.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/measurement/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/measurement/adc.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/measurement/dac.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/measurement/energy.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/measurement/gpi.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/measurement/gpo.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/measurement/logic.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/measurement/scope.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/measurement/thermocouple.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/measurement/watt.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/power/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/power/battery.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/power/eload.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/power/solar.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/power/supply.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/utility/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/utility/binaries.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/utility/defaults.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/utility/exec_.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/utility/install.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/utility/install_wheel.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/utility/logs.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/utility/uninstall.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/utility/update.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/commands/utility/webcam.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/config.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/context/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/context/ci_detection.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/context/constants.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/context/core.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/context/error_handlers.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/context/session.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/group_usage.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/matchers.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/net_group.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/net_helpers.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/net_storage.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/param_types.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/ssh_utils.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/utils.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/version_skew.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/core/ws_diagnose.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/deployment/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/deployment/scripts/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/deployment/scripts/convert_to_sparse_checkout.sh +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/deployment/scripts/setup_and_deploy_box.sh +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/deployment/scripts/setup_ssh_key.sh +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/deployment/security/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/deployment/security/secure_box_firewall.sh +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/common/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/common/construct_utils.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/common/exceptions.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/common/py3compat.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/common/utils.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/construct/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/construct/adapters.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/construct/core.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/construct/debug.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/construct/macros.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/abbrevtable.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/aranges.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/callframe.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/compileunit.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/constants.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/descriptions.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/die.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/dwarf_expr.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/dwarfinfo.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/enums.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/lineprogram.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/locationlists.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/namelut.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/ranges.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/dwarf/structs.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/ehabi/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/ehabi/constants.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/ehabi/decoder.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/ehabi/ehabiinfo.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/ehabi/structs.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/constants.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/descriptions.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/dynamic.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/elffile.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/enums.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/gnuversions.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/hash.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/notes.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/relocation.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/sections.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/segments.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/elftools/elf/structs.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/errors.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/exceptions.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/box_config.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/communication/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/communication/ble.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/communication/blufi.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/communication/i2c.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/communication/router.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/communication/spi.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/communication/uart.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/communication/wifi.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/custom_devices.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/device/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/device/arm.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/device/hello.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/device/usb.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/device/webcam.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/measurement/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/measurement/adc.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/measurement/dac.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/measurement/energy.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/measurement/gpio.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/measurement/scope.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/measurement/scope_stream.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/measurement/thermocouple.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/measurement/watt.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/net.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/power/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/power/battery.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/power/eload.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/power/enable_disable.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/power/solar.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/power/supply.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/impl/query_instruments.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/lager_cli.egg-info/SOURCES.txt +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/lager_cli.egg-info/dependency_links.txt +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/lager_cli.egg-info/entry_points.txt +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/lager_cli.egg-info/requires.txt +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/lager_cli.egg-info/top_level.txt +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/main.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/pyproject.toml +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/safe_unpickle.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/setup.cfg +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/setup.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/simple_hdlc.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/sort_utils.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/status.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/supply/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/supply/supply_tui.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/supply/websocket_client.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/terminal/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/terminal/core/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/terminal/core/executor.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/terminal/main.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/terminal/ui/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/terminal/ui/completer.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/terminal/ui/display.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/terminal/ui/logo.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/terminal/ui/repl.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/terminal/ui/themes.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/tests/test_box_lager_imports.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/tests/test_box_storage.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/tests/test_io_imports.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/update_check.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/vendor/PyCRC/CRC16.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/vendor/PyCRC/CRC16DNP.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/vendor/PyCRC/CRC16Kermit.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/vendor/PyCRC/CRC16SICK.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/vendor/PyCRC/CRC32.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/vendor/PyCRC/CRCCCITT.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/vendor/PyCRC/__init__.py +0 -0
- {lager_cli-0.28.2 → lager_cli-0.28.3}/vendor/__init__.py +0 -0
|
@@ -198,6 +198,201 @@ def _classify(usb_info: dict, visa_info: dict, disp_info: dict) -> tuple[str, st
|
|
|
198
198
|
return ('yellow', 'UNCLEAR — review the per-section output above and rerun if needed.')
|
|
199
199
|
|
|
200
200
|
|
|
201
|
+
def _fmt_usb_lines(d: dict):
|
|
202
|
+
"""Render the host-side USB section. Shared by the USB-TMC and debug
|
|
203
|
+
(J-Link) paths — the `/diagnose/usb` endpoint is instrument-agnostic."""
|
|
204
|
+
return [
|
|
205
|
+
f'enumerated: {d.get("enumerated")}',
|
|
206
|
+
f'sysfs: {d.get("sysfs_path") or "—"}',
|
|
207
|
+
f'device: {d.get("device_path") or "—"}',
|
|
208
|
+
f'usb-tmc class:{" yes" if d.get("is_usbtmc") else " no" if "is_usbtmc" in d else " —"}',
|
|
209
|
+
f'usbtmc kmod: {"LOADED (problem)" if d.get("usbtmc_loaded") else "not loaded (good)"}',
|
|
210
|
+
f"lsof: {', '.join(h.get('command', '?') + '(' + h.get('pid', '?') + ')' for h in (d.get('lsof') or [])) or 'no holders'}",
|
|
211
|
+
f'dmesg tail: {d.get("dmesg_tail", "")[:300] or "(empty)"}',
|
|
212
|
+
]
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _holders_str(d: dict) -> str:
|
|
216
|
+
"""Comma-joined `command(pid)` for the probe's USB holders, or 'none'."""
|
|
217
|
+
holders = d.get('holders') or []
|
|
218
|
+
return ', '.join(f"{h.get('command', '?')}({h.get('pid', '?')})" for h in holders) or 'none'
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def _vtref_str(connect: dict) -> str:
|
|
222
|
+
"""Format VTref (stored in mV) as 'X.XXXV', or 'unknown'."""
|
|
223
|
+
vt = (connect or {}).get('vtref_mv')
|
|
224
|
+
return f'{vt / 1000:.3f}V' if isinstance(vt, (int, float)) else 'unknown'
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def _fmt_jlink_lines(d: dict):
|
|
228
|
+
"""Render the J-Link / debug-probe section from `/diagnose/jlink`."""
|
|
229
|
+
if d.get('mode') == 'openocd-basic':
|
|
230
|
+
oo = d.get('openocd_gdbserver') or {}
|
|
231
|
+
return [
|
|
232
|
+
f"backend: {d.get('backend')}",
|
|
233
|
+
f"probe enum: {d.get('probe_enumerated')}",
|
|
234
|
+
f"holders: {_holders_str(d)}",
|
|
235
|
+
f"openocd server: running={oo.get('running')} pid={oo.get('pid')}",
|
|
236
|
+
"note: deep target diagnosis is J-Link-only for now",
|
|
237
|
+
]
|
|
238
|
+
emu = d.get('emu_list') or []
|
|
239
|
+
visible_str = ', '.join(
|
|
240
|
+
f"{p.get('product', '?')}/{p.get('serial') or '?'}" for p in emu
|
|
241
|
+
) or 'none'
|
|
242
|
+
g = d.get('gdbserver') or {}
|
|
243
|
+
lines = [
|
|
244
|
+
f"backend: {d.get('backend')}",
|
|
245
|
+
f"jlink software: {'installed' if d.get('jlink_installed') else 'NOT INSTALLED'}",
|
|
246
|
+
f"probe enum: {d.get('probe_enumerated')}",
|
|
247
|
+
f"probe visible: {d.get('probe_visible')} (emus: {visible_str})",
|
|
248
|
+
f"holders: {_holders_str(d)}",
|
|
249
|
+
f"gdbserver: running={g.get('running')} pid={g.get('pid')} log_ok={g.get('logfile_ok')}",
|
|
250
|
+
]
|
|
251
|
+
if d.get('connect_skipped'):
|
|
252
|
+
lines.append(f"connect: skipped ({d.get('connect_skip_reason')})")
|
|
253
|
+
elif d.get('connect'):
|
|
254
|
+
c = d['connect']
|
|
255
|
+
lines.append(
|
|
256
|
+
f"connect: ok={c.get('connect_ok')} class={c.get('connect_error_class')} "
|
|
257
|
+
f"VTref={_vtref_str(c)} core={c.get('core') or '—'}"
|
|
258
|
+
)
|
|
259
|
+
# When we couldn't classify the connect, show the raw JLinkExe text so
|
|
260
|
+
# an unrecognized failure is debuggable instead of a dead-end.
|
|
261
|
+
if c.get('connect_error_class') == 'other' and d.get('connect_output'):
|
|
262
|
+
raw = ' / '.join(s for s in str(d['connect_output']).splitlines() if s.strip())
|
|
263
|
+
lines.append(f"connect output: {raw[:400]}")
|
|
264
|
+
if d.get('connect_error'):
|
|
265
|
+
lines.append(f"connect error: {str(d.get('connect_error'))[:200]}")
|
|
266
|
+
return lines
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _classify_jlink(usb_info: dict, jlink_info: dict) -> tuple[str, str]:
|
|
270
|
+
"""Return (color, headline) for a debug net from the USB + J-Link payloads.
|
|
271
|
+
|
|
272
|
+
Walks the J-Link stack outside-in (software → USB → probe-visible →
|
|
273
|
+
gdbserver → target connect) so the most specific actionable fault wins."""
|
|
274
|
+
# Endpoint reachability first — an old box won't have /diagnose/jlink.
|
|
275
|
+
if 'unavailable' in jlink_info:
|
|
276
|
+
return ('yellow',
|
|
277
|
+
'J-Link diagnose endpoint not on this box — deploy this build '
|
|
278
|
+
'(`lager update --box <box> --version <branch>`) to enable it.')
|
|
279
|
+
if 'transport_error' in jlink_info:
|
|
280
|
+
return ('red', f'Could not reach the J-Link diagnose endpoint: {jlink_info["transport_error"]}')
|
|
281
|
+
if jlink_info.get('error'):
|
|
282
|
+
return ('red', f'J-Link diagnose error on box: {jlink_info["error"]}')
|
|
283
|
+
|
|
284
|
+
if jlink_info.get('mode') == 'openocd-basic':
|
|
285
|
+
if jlink_info.get('probe_enumerated') is False:
|
|
286
|
+
return ('red',
|
|
287
|
+
'PROBE NOT ON USB: OpenOCD/ST-Link probe not enumerated. '
|
|
288
|
+
'Check cable, probe power, and (behind a hub) the upstream port.')
|
|
289
|
+
oo = jlink_info.get('openocd_gdbserver') or {}
|
|
290
|
+
return ('yellow',
|
|
291
|
+
f'OPENOCD ({jlink_info.get("backend")}): probe enumerated, gdbserver '
|
|
292
|
+
f'{"running" if oo.get("running") else "idle"}. Deep target diagnosis is '
|
|
293
|
+
'J-Link-only for now — use `lager debug <net> status` and the gdbserver log.')
|
|
294
|
+
|
|
295
|
+
if jlink_info.get('jlink_installed') is False:
|
|
296
|
+
return ('red',
|
|
297
|
+
'J-LINK SOFTWARE MISSING on box — install the SEGGER J-Link tools '
|
|
298
|
+
'(`lager update --box <box>` installs them).')
|
|
299
|
+
|
|
300
|
+
if jlink_info.get('probe_enumerated') is False:
|
|
301
|
+
return ('red',
|
|
302
|
+
'PROBE NOT ON USB: J-Link not enumerated. Check the USB cable, probe '
|
|
303
|
+
'power, and (behind an Acroname hub) the upstream port.')
|
|
304
|
+
|
|
305
|
+
if jlink_info.get('probe_visible') is False:
|
|
306
|
+
holders = jlink_info.get('holders') or usb_info.get('lsof') or []
|
|
307
|
+
if holders:
|
|
308
|
+
who = ', '.join(f"{h.get('command')}({h.get('pid')})" for h in holders[:4])
|
|
309
|
+
return ('red',
|
|
310
|
+
f'PROBE CLAIMED: J-Link is on USB but JLinkExe can\'t see it — another '
|
|
311
|
+
f'process holds it ({who}). Usually a stale gdbserver: '
|
|
312
|
+
'`lager debug <net> disconnect`, or restart the debug service.')
|
|
313
|
+
return ('red',
|
|
314
|
+
'PROBE WEDGED: J-Link is on USB but JLinkExe enumeration is empty — the '
|
|
315
|
+
'probe firmware is likely stuck. USB power-cycle the probe (unplug/replug it).')
|
|
316
|
+
|
|
317
|
+
g = jlink_info.get('gdbserver') or {}
|
|
318
|
+
if g.get('running'):
|
|
319
|
+
if g.get('logfile_ok'):
|
|
320
|
+
return ('green',
|
|
321
|
+
f'HEALTHY: J-Link gdbserver running (PID {g.get("pid")}) and listening — '
|
|
322
|
+
'active debug session.')
|
|
323
|
+
return ('red',
|
|
324
|
+
'GDBSERVER WEDGED: server process is up but its log shows a target-connection '
|
|
325
|
+
'failure. `lager debug <net> disconnect` then reconnect; if it persists, '
|
|
326
|
+
'restart the debug service.')
|
|
327
|
+
|
|
328
|
+
if jlink_info.get('connect_skipped'):
|
|
329
|
+
return ('yellow',
|
|
330
|
+
f'INCONCLUSIVE: connect probe skipped ({jlink_info.get("connect_skip_reason")}). '
|
|
331
|
+
'Probe is visible and idle — rerun, or `lager debug <net> gdbserver` to attach.')
|
|
332
|
+
|
|
333
|
+
c = jlink_info.get('connect')
|
|
334
|
+
if c:
|
|
335
|
+
klass = c.get('connect_error_class')
|
|
336
|
+
vt = _vtref_str(c)
|
|
337
|
+
device = jlink_info.get('device') or '<device>'
|
|
338
|
+
if klass == 'ok':
|
|
339
|
+
# JLinkExe doesn't emit a parseable VTref on every firmware/REPL
|
|
340
|
+
# path, so only surface it when we actually got a number.
|
|
341
|
+
vt_part = f', VTref={vt}' if vt != 'unknown' else ''
|
|
342
|
+
return ('green',
|
|
343
|
+
f'HEALTHY: J-Link connected to {device} '
|
|
344
|
+
f'({c.get("core") or "core identified"}{vt_part}).')
|
|
345
|
+
if klass == 'no_target_power':
|
|
346
|
+
vt_part = f'VTref={vt}' if vt != 'unknown' else 'J-Link reports target voltage too low'
|
|
347
|
+
return ('red',
|
|
348
|
+
f'TARGET UNPOWERED: probe is fine but {vt_part} — the target board has no '
|
|
349
|
+
'power on the debug header (or VTref isn\'t wired). Check target power and '
|
|
350
|
+
'the VTref pin.')
|
|
351
|
+
if klass == 'locked':
|
|
352
|
+
return ('red',
|
|
353
|
+
'TARGET LOCKED: debug access is blocked by readout/IDCODE/AP protection. '
|
|
354
|
+
'A mass-erase/unlock is required (e.g. `nrfjprog --recover` for nRF, or the '
|
|
355
|
+
'vendor unlock flow).')
|
|
356
|
+
if klass == 'wrong_device':
|
|
357
|
+
return ('yellow',
|
|
358
|
+
f'DEVICE NAME: J-Link rejected device {device!r}. Fix the net\'s device/MCU '
|
|
359
|
+
'field (e.g. NRF5340_XXAA_APP for an nRF7002-DK).')
|
|
360
|
+
if klass == 'no_target_comms':
|
|
361
|
+
return ('red',
|
|
362
|
+
f'NO TARGET COMMS: probe + target power OK (VTref={vt}) but SWD/JTAG connect '
|
|
363
|
+
'failed. Check SWDIO/SWCLK wiring, nRST pull-up (not held low), SWD-vs-JTAG, '
|
|
364
|
+
'and try a lower speed.')
|
|
365
|
+
return ('yellow',
|
|
366
|
+
f'UNCLEAR: connect returned class={klass}. See the J-Link section and connect '
|
|
367
|
+
'output above.')
|
|
368
|
+
|
|
369
|
+
return ('yellow', 'UNCLEAR — review the J-Link section above and rerun if needed.')
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def _diagnose_debug(box_ip: str, net: str, address: str) -> None:
|
|
373
|
+
"""Debug-net (J-Link) branch of `lager diagnose`.
|
|
374
|
+
|
|
375
|
+
Fetches the instrument-agnostic host-side USB section plus the new
|
|
376
|
+
`/diagnose/jlink` endpoint (both on box_http_server, port 9000) in
|
|
377
|
+
parallel, renders them, and prints the J-Link classification."""
|
|
378
|
+
urls = {
|
|
379
|
+
'usb': f'http://{box_ip}:9000/diagnose/usb?address={address}',
|
|
380
|
+
'jlink': f'http://{box_ip}:9000/diagnose/jlink?net={net}',
|
|
381
|
+
}
|
|
382
|
+
results: dict[str, dict] = {}
|
|
383
|
+
with ThreadPoolExecutor(max_workers=2) as pool:
|
|
384
|
+
futures = {pool.submit(_call, url): name for name, url in urls.items()}
|
|
385
|
+
for fut in as_completed(futures):
|
|
386
|
+
results[futures[fut]] = fut.result()
|
|
387
|
+
|
|
388
|
+
_print_section('USB (host-side)', results['usb'], _fmt_usb_lines)
|
|
389
|
+
_print_section('J-Link / debug probe', results['jlink'], _fmt_jlink_lines)
|
|
390
|
+
|
|
391
|
+
color, headline = _classify_jlink(results['usb'], results['jlink'])
|
|
392
|
+
click.echo()
|
|
393
|
+
click.echo(click.style(f'Classification: {headline}', fg=color, bold=True))
|
|
394
|
+
|
|
395
|
+
|
|
201
396
|
def _print_section(title: str, data: dict, fmt_lines):
|
|
202
397
|
click.echo()
|
|
203
398
|
click.echo(click.style(f'== {title} ==', bold=True))
|
|
@@ -241,6 +436,12 @@ def diagnose(ctx, net, box, net_type):
|
|
|
241
436
|
click.echo(click.style(f'lager diagnose — {display_name} → {net}', bold=True))
|
|
242
437
|
click.echo(f' NetType: {role} address: {address}')
|
|
243
438
|
|
|
439
|
+
# Debug nets (J-Link / OpenOCD) are not USB-TMC — the pyvisa *IDN? probe
|
|
440
|
+
# below can't reach them. Route them to the J-Link-aware path instead.
|
|
441
|
+
if role == 'debug':
|
|
442
|
+
_diagnose_debug(resolved_box, net, address)
|
|
443
|
+
return
|
|
444
|
+
|
|
244
445
|
# Fire the three endpoints in parallel.
|
|
245
446
|
# Port mapping inside the box container:
|
|
246
447
|
# 5000 — lager.python.service (legacy /cli-version, /status, /nets/list)
|
|
@@ -257,15 +458,7 @@ def diagnose(ctx, net, box, net_type):
|
|
|
257
458
|
for fut in as_completed(futures):
|
|
258
459
|
results[futures[fut]] = fut.result()
|
|
259
460
|
|
|
260
|
-
_print_section('USB (host-side)', results['usb'],
|
|
261
|
-
f'enumerated: {d.get("enumerated")}',
|
|
262
|
-
f'sysfs: {d.get("sysfs_path") or "—"}',
|
|
263
|
-
f'device: {d.get("device_path") or "—"}',
|
|
264
|
-
f'usb-tmc class:{" yes" if d.get("is_usbtmc") else " no" if "is_usbtmc" in d else " —"}',
|
|
265
|
-
f'usbtmc kmod: {"LOADED (problem)" if d.get("usbtmc_loaded") else "not loaded (good)"}',
|
|
266
|
-
f"lsof: {', '.join(h.get('command', '?') + '(' + h.get('pid', '?') + ')' for h in (d.get('lsof') or [])) or 'no holders'}",
|
|
267
|
-
f'dmesg tail: {d.get("dmesg_tail", "")[:300] or "(empty)"}',
|
|
268
|
-
])
|
|
461
|
+
_print_section('USB (host-side)', results['usb'], _fmt_usb_lines)
|
|
269
462
|
|
|
270
463
|
_print_section('VISA (instrument-side)', results['visa'], lambda d: [
|
|
271
464
|
f'idn: {d.get("idn") or "—"}',
|
|
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
|
|
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
|
|
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
|