lager CLI does. You can:
- create and delete saved nets, and edit net and box metadata
- install custom drivers, upload binaries and download files
- assign USB-serial cables to device definitions, and run diagnostics
admin feature, which adds no dependency:
Handle
AsyncLagerBox::admin() returns the same methods for the async client.
Methods
Saved nets
save_net(record: &NetRecord) -> Result<()>
Create a net, or replace the saved record with the same name and role.
NetRecord::new(name, role, instrument) builds a record. Its builder methods set the
rest:
A record that
nets() returns can be changed and saved back. The crate leaves out the
box’s derived live_path, as the CLI does.
The box keys a record by name and role. A record with the same name and another role
stays beside the new one. To change a net’s role, delete the old record first.
rename_net(old_name: &str, record: &NetRecord) -> Result<()>
Save record in place of old_name. The box deletes every record named old_name,
whatever its role, then saves record.
delete_net(name: &str, role: Option<&str>) -> Result<()> and delete_all_nets() -> Result<()>
delete_net with a role deletes only the record with that exact role. Without a role, it
deletes every record with that name. An unknown net is Error::Box with HTTP 404.
Metadata
net_metadata(name: &str) -> Result<NetMetadata>
Read a net’s metadata. This requires box software 0.46.0 or later.
set_net_metadata(name: &str, update: &NetMetadataUpdate) -> Result<NetMetadata>
Change a net’s metadata on every record with that name. A field that the update does not
set keeps its value. clear() removes a field.
Error::Box and HTTP 400.
box_metadata() and set_box_metadata(description, updated_at)
Read and replace the box description. A write replaces the whole record: None for the
description clears it.
Instruments and the bench manifest
instruments() -> Result<Vec<Instrument>>
List the instruments the box sees. Each Instrument has a name for NetRecord::new,
an address, the net_type roles it can serve and its channels. The rest of the
scanner’s report is in extra.
Each call scans the hardware again. To find a robot arm, the scan sends a short handshake
to serial ports that no saved net uses.
bench_manifest() -> Result<BenchManifest>
Read the bench manifest, the whole box configuration as one document. This requires box
software 0.50.0 or later. The schema belongs to the box, so document holds the JSON.
box_id() and schema_version() read two common keys.
Custom drivers
These require box software 0.59.0 or later.install_driver(driver_type: &str, bundle: &[u8]) -> Result<DriverInstall>
Upload a driver’s zip bundle, and replace an installed version. The box installs the
Python packages that the manifest declares. That can take minutes, so the call waits up
to 6 minutes.
status()?.capabilities.custom_driver_deps first. The box refuses an oversized
bundle with HTTP 413, and a pip run past 300 seconds with HTTP 504.
drivers(), driver(type), reinstall_driver_deps(type) and remove_driver(type, force)
drivers() returns a DriverEntry per driver. Each entry has its status, version,
deps and the nets that use it. A driver that does not load has status: "error" and
an error message.
remove_driver() without force fails with HTTP 409 while saved nets use the driver.
The message names the nets. With force, the box removes the driver, and
orphaned_nets lists the nets that lost it.
Binaries and files
add_binary(name: &str, data: &[u8]) -> Result<BinaryAdded>
Upload an executable into the box’s binaries directory, and replace a file with the same
name. restart_required is true when the container needs a restart to see the file.
lager update does that restart.
binaries() lists the directory, and remove_binary(name) deletes a file.
download_file(path: &str) -> Result<Vec<u8>>
Download a file that a script left on the box, as bytes.
/tmp/lager-output, /tmp/lager-results and
/tmp/lager-job-output. Any other path is Error::Box with HTTP 403. download_file()
has no client-side timeout. download_file_with_timeout(path, Some(duration)) sets one.
Custom devices
custom_devices() -> Result<CustomDevices>
List the device definitions the box knows (catalog), the current assignments, and
the USB-serial cables that have no assignment. The box scans the cables, which takes
seconds.
assign_custom_device(instrument: &str, cable: &CableId, baud: Option<u32>) -> Result<DeviceAssigned>
Assign a USB-serial cable to a device definition. CableId names the cable:
CableId::PortPath("1-1.4".into()) for a cable with no serial, or one that shares
its serial with another cable.
remove_custom_device(cable: &CableId) -> Result<DeviceRemoval>
Remove a cable’s assignment and the saved nets that use it. A cable with no assignment
returns removed: false, not an error.
Diagnostics
The checks behindlager diagnose. Each result gives typed fields for the common facts,
and an extra map for the rest of the box’s report. The crate URL-encodes the address.
A failed or skipped VISA probe is data, not an error:
error, error_class and
skipped say what happened.
Older boxes
A route that the box does not serve fails withError::UnsupportedByBox. Where a version
is known, the message names it. A refusal that the route explains, such as an unknown
net, is Error::Box with the box’s message.

