v0.31.10: battery model catalog + Logitech webcam expansion#118
Conversation
…/ list_models action)
…rn driver errors as success:false from /battery/command
…e Logitech models
There was a problem hiding this comment.
Code Review
This pull request adds support for 8 additional Logitech webcams using a new sysfs-based detection mechanism to correctly map video nodes, and introduces a new lager battery models command to list saved and built-in battery models on the instrument. It also addresses several bugs, including battery model readback, SCPI loading of built-in models, and error masking. Feedback on the changes points out a bug in _scpi_error_code where VISA transport-level errors (such as timeouts) are returned as integers outside the SCPI range, causing the model catalog probe to continue trying remaining slots and wasting time instead of aborting immediately.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if args and isinstance(args[0], int): | ||
| return args[0] |
There was a problem hiding this comment.
If a transport-level or VISA communication error occurs (such as a timeout), exc.args[0] will contain a VISA status code (e.g., -1073807339). Since this is an integer, _scpi_error_code currently returns it directly. In model_catalog(), this code is not in the range [-199, -100], and it is not None, so the exception is caught and silently ignored via continue. This causes the catalog probe to continue trying the remaining slots, resulting in multiple consecutive timeouts and wasting significant time.
To fix this, we should ensure that _scpi_error_code only returns valid SCPI error codes (typically within the range [-32768, 32767]), so that VISA/transport errors return None and correctly trigger an immediate abort in model_catalog().
| if args and isinstance(args[0], int): | |
| return args[0] | |
| if args and isinstance(args[0], int): | |
| if -32768 <= args[0] <= 32767: | |
| return args[0] |
What
v0.31.10: adds a read-only battery model catalog (
lager battery models) for the Keithley 2281S, expands webcam support with 8 more Logitech models via catalog-driven detection, and fixes three battery bugs uncovered while hardware-verifying the catalog — model readback using the wrong SCPI query, built-in models being unloadable over SCPI, and driver errors being masked as "Resource busy".Why
Battery-simulator users can load a model by slot (
lager battery model 5) but had no way to discover which slots actually hold a model — they had to guess or walk to the instrument's front panel. Building the discovery feature against real hardware then exposed that the "current model" display had never been truthful (it always showed "DISCHARGE") and that recalling firmware built-in models had never worked at all. On the webcam side, a client needs the Logi 4K Pro; the old detection hard-coded three models and mapped/dev/videonodes with an index heuristic that breaks when cameras expose different node counts.Changes
Battery — model catalog (new)
KeithleyBattery.model_catalog(): read-only catalog assembled from query-only:BATT:MOD<n>:VOC:STEPs?slot probes plus the 5 firmware built-ins. The 2281S has no:BATT:MODel:CATalog?(verified against reference manual 077114601 — the word "catalog" appears nowhere in it).list_modelsreturns{"models": [...]}to/battery/commandcallers (same pattern asstate); shared table formatter keeps CLI/TUI/HTTP output identical.lager battery <NET> models, battery TUImodelscommand, HTTP + WebSocket endpoint actions.Battery — bugs found during hardware verification
model,state, TUI header) used:BATT:STAT?, which reports charge/discharge status — not the model — so it always showed "DISCHARGE", andset_model's verification raised a false "slot is empty" after every successful load. Now reads:BATT:MOD:RCL?(current_model()), which also catches the 2281S's silent empty-slot recall failures (no error is queued; readback is the only detection).LI-ION4_2/LEAD-ACID12, but hyphens are SCPI syntax errors (-102). The catalog now uses the underscore spellings the firmware accepts;set_modeltakes either form.[Errno 16] Resource busy. Driver errors now return assuccess: falsewith the driver's own message (HTTP and WebSocket).Webcam
SUPPORTED_USBentry with awebcamnet_type is detected — adding a model is a table entry inusb_scanner.py+query_instruments.py(+ the role map innets.py), no code changes./dev/videoNmapping now walks/sys/class/video4linux/videoN/deviceto the owning USB device, replacing theidx*4heuristic that broke on mixed setups (C920 exposes 2 nodes, BRIO 4).Docs/release: CHANGELOG, release notes, CLI battery reference, supported-instruments; version bump to 0.31.10.
Testing
/dev/video4, metadata nodes and the host's non-catalog integrated webcam correctly skipped) and addable as a webcam net.test/unit/boxandtest/unit/clisuites pass apart from 3 pre-existing failures that reproduce identically on main.Notes
RCL?echoes slot number or built-in name; empty-slot recalls fail silently; hyphens unparseable) was established by probing real hardware and is documented in the driver docstrings.LI_ION4_2) so catalog output, readback, andmodelinputs are consistent; hyphenated input is still accepted.v0.31.10version commit at the branch tip — after rebase-merge, confirm it's at the tip of main before tagging, then publish to PyPI.