Instrument Profiles
An instrument profile is a YAML document that tells galois-edge how to talk to a specific instrument: how to identify it, what commands it supports, what each parameter means, what protocol it speaks. The daemon ships with 130+ profiles for common Keysight, Tektronix, Keithley, R&S, and other gear; you can add your own by dropping YAML files into PROFILE_DIR.
Profiles are loaded at daemon startup and on DeployProfile calls. Each one is matched against *IDN? responses; the first profile whose regex matches is the one that’s used.
File layout
Section titled “File layout”instrument: manufacturer: "Keysight" model: "34461A" class: dmm description: "Truevolt Series Digital Multimeter"
identity: query: "*IDN?" patterns: - "(?:Keysight|Agilent).*34[4-7][0-9][0-9]A"
interfaces: - type: gpib default_address: 22 - type: usb - type: ethernet port: 5025
settings: timeout_ms: 5000 terminator: "\n" opc_query: true
commands: measure_voltage: scpi: "MEAS:VOLT:DC?" type: query returns: type: float unit: V description: "Measure DC voltage"
set_range: scpi: "VOLT:DC:RANG {range}" type: write params: range: type: float unit: V options: [0.1, 1, 10, 100, 1000] default: 10The top-level keys — instrument, identity, interfaces, settings, commands, sequences, sdk — are described below.
instrument
Section titled “instrument”| Field | Type | Required | Notes |
|---|---|---|---|
manufacturer | string | yes | Used by the matched-profile API responses. |
model | string | yes | Combined with manufacturer to form profile_key (lowercase, underscores). |
class | string | yes | Free-form bucket: dmm, oscilloscope, sourcemeter, network_analyzer, magnet, temperature_controller, … Used by instrument_class filters in the API. The YAML key instrument_class: is also accepted as an alias. |
description | string | no | Human-friendly description. |
identity
Section titled “identity”How the daemon recognises this instrument.
| Field | Type | Required | Notes |
|---|---|---|---|
query | string | no | Default *IDN?. |
pattern | string | one of pattern/patterns | Single regex (case-insensitive). |
patterns | list[string] | one of pattern/patterns | Multiple regexes; any match wins. Preferred for instruments with a noisy IDN. |
interfaces
Section titled “interfaces”A list of supported physical transports. The daemon uses this to pre-populate addresses (e.g. default GPIB primary address) and to know what serial parameters to apply.
| Field | Type | Notes |
|---|---|---|
type | string | gpib, usb, ethernet, serial, can. |
port | int | TCP port (LXI/raw socket). |
default_address | int | GPIB primary address. |
baud_rate, parity, data_bits, stop_bits | varies | Serial only. |
usb_vid, usb_pid | string (hex) | Auto-discovery for serial-over-USB. |
bus | string | CAN bus name — can0, vcan0, etc. |
bitrate | int | CAN bus bitrate (bits/s). |
can_protocol | string | can20a, can20b, or canfd. |
settings
Section titled “settings”Communication tuning, applied to every command on this instrument.
| Field | Type | Default | Notes |
|---|---|---|---|
timeout_ms | int | 5000 | Per-command timeout. |
terminator | string | "\n" | Line ending. |
opc_query | bool | false | Send *OPC? after writes to wait for completion. |
init_commands | list[string] | empty | Run on first connect (e.g. *RST). |
cleanup_commands | list[string] | empty | Run on disconnect. |
commands
Section titled “commands”A map of named commands. Each entry follows CommandConfig:
| Field | Type | Required | Notes |
|---|---|---|---|
scpi | string | one of scpi/getter/setter | Template with {param} placeholders. |
getter, setter | string | for type: property | Two SCPI templates for a read/write property. |
type | string | yes | query, write, or property. |
description | string | no | Surfaced in capabilities. |
enabled | bool | no (default true) | Set false to hide from clients. |
streamable | bool | no | Eligible for StreamMeasurement. |
is_dangerous | bool | no | UI hint. |
force_query | bool | no | Send the getter as-is, without trailing ?. |
requires_sweep | bool | no | Reject ExecuteCommand; require StartSweep. |
params | map[string, ParameterConfig] | no | See below. |
returns | ReturnConfig | for type: query | See below. |
sweep | SweepConfig | when requires_sweep | See below. |
sdk_call | SDKCallConfig | optional | Bind to a vendor SDK method. |
can | CANCommandConfig | optional | CAN-bus framing. |
ParameterConfig
Section titled “ParameterConfig”| Field | Type | Notes |
|---|---|---|
type | string | float, int, string, enum, bool. |
unit | string | E.g. V, A, Hz. |
min, max | float | Range limits. |
default | any | Used when caller omits the parameter. |
description | string | |
options | list[string] | Required when type: enum. |
map | map[string, any] | Label → wire-value transform applied on writes. |
ReturnConfig
Section titled “ReturnConfig”| Field | Type | Notes |
|---|---|---|
type | string | float, int, string, array, binary, bool, vector. |
unit | string | |
element_type | string | For array. |
separator | string | For array (default ,). |
format | string | ieee_binary or ascii for trace data. |
fields | list[dict] | Named multi-value returns. |
parser | dict | {type: regex, pattern, group} / {type: strip, prefix, suffix} / {type: split, delimiter, index}. |
x_name, x_unit | string | Vector axis labels. |
x_start_query, x_increment_query | string | SCPI to retrieve waveform x-axis metadata. |
SweepConfig
Section titled “SweepConfig”For commands that ramp over time (magnets, temperature controllers).
| Field | Type | Notes |
|---|---|---|
rate_param | string | Name of the parameter that controls rate. Defaults to "sweep_rate". |
command | string | SCPI template with {value} and {sweep_rate}. |
check_command | string | Status query polled at poll_interval_ms. |
check_idle_match | string | Exact string or regex meaning “done”. |
stop_command | string | Emergency abort SCPI. |
poll_interval_ms | int | Default 1000. |
SDKCallConfig
Section titled “SDKCallConfig”Map a profile command to a method on a Python SDK object.
| Field | Type | Notes |
|---|---|---|
method | string | For ordinary calls. |
getter, setter | string | When is_property: true. |
args_map | map[string, string] | Profile param → SDK kwarg. |
result_field | string | Pull a field out of a returned dict/object. |
is_property | bool |
CANCommandConfig
Section titled “CANCommandConfig”For CAN-bus instruments. Includes message_id, direction (rx/tx/tx_rx), signals (named CANSignalConfig map), response_id (required when direction: tx_rx), payload (fixed request bytes for UDS-style queries), dlc (data length code, 0–64, default 8). Each signal carries start_bit (0–63), bit_length (1–64), byte_order (little_endian/big_endian), signed, scale, offset.
sequences
Section titled “sequences”Multi-step measurement recipes that run as a single transaction on the daemon.
sequences: iv_sweep: description: "Voltage sweep, capture current at each point" parameters: start_v: { type: float, unit: V } stop_v: { type: float, unit: V } step_v: { type: float, unit: V } steps: - command: set_voltage args: { value: "{start_v}" } - scpi: "*WAI" - command: measure_current capture: i_first returns: i_first| Field | Type | Notes |
|---|---|---|
description | string | |
parameters | map[string, ParameterConfig] | The YAML key params: is also accepted as an alias. |
steps | list[SequenceStepConfig] | Each step references either command (named) or scpi (raw). args populates {} placeholders, capture saves the result under a name. At least one step is required. |
returns | string | Captured variable name to return. |
enabled | bool | Default true. |
Top-level vendor-SDK driver — used for instruments that don’t speak SCPI. Once present, the daemon importlib-loads the package and treats the resulting object as the instrument.
sdk: package: "MultiPyVu" import_path: "MultiPyVu" class_name: "Client" is_async: false connect: method: "connect" args: host: "host" defaults: { host: "127.0.0.1", port: 5000 } disconnect: method: "close" identity: method: "get_instrument_info" pattern: "PPMS"| Field | Type | Notes |
|---|---|---|
package | string | PyPI / pip name. |
import_path | string | Module path used in importlib. |
class_name | string | Class to instantiate. |
is_async | bool | Use await on calls. |
connect | SDKConnectConfig | method to call on first use; args maps profile params to kwargs; defaults fills in missing kwargs; constructor_args is passed to the class constructor before connect runs. |
disconnect | SDKDisconnectConfig | method to call on shutdown. |
identity | SDKIdentityConfig | Optional: method or property to read for IDN-equivalent matching, plus pattern regex. |
Validation
Section titled “Validation”The daemon validates every loaded profile and refuses to register one that fails. Validation errors include:
identitydefines neitherpatternnorpatterns, or a regex fails to compile.- A command sets none of
scpi,getter,setter,sdk_call, orcan. - A
propertycommand has neithergetternorsetter. - A parameter declares an unknown
type(must be one offloat,int,string,enum,bool). - An enum parameter has no
options. - A return type is unknown (must be one of
float,int,string,array,binary,bool,vector). - A sequence has zero steps, or a step has neither
commandnorscpi. - A CAN frame has out-of-range
message_id(0..0x1FFFFFFF),dlc(0..64), ordirection(must berx/tx/tx_rx). - A CAN signal has out-of-range
start_bit(0..63),bit_length(1..64), unknownbyte_order, orscale == 0. - A
tx_rxCAN frame is missingresponse_id.
Failures are logged at error level with the offending command/sequence name; the rest of the profile is still loaded if subsequent items validate.
Authoring tips
Section titled “Authoring tips”- Start by capturing a real
*IDN?response — yourpatternsregex should match it case-insensitively without being so loose it catches sibling models you don’t support. - Profiles are matched in load order; for vendors with both old and new product lines, write the more specific pattern first.
- Use
force_query: truefor property-style commands where the SCPI getter looks likeMEAS:VOLT?rather thanVOLT?. - For oscilloscope traces, set
returns.type: vectorand providex_start_query/x_increment_queryso client code gets correct time-domain axes. - Mark anything that can damage hardware (
OUTP ONon an SMU at full scale, magnet ramps) withis_dangerous: trueand route ramps throughrequires_sweep: trueso they go through the safety-checked sweep path. - Drop your YAML in
PROFILE_DIR, thengalois-edge configure set PROFILES_ENABLED trueand restart — the daemon will log the loaded profiles and any validation errors.