PLESTY devices define their capabilities in two JSON schema files. These schemas are the source of truth for parameter validation, documentation generation, and test automation.
param_schema.json
Defines all readable/writable device parameters.
Flat schema (simple devices)
{
"WAVELENGTH": {
"type": "int",
"command": "SENS:CORR:WAV",
"unit": "nm",
"min": 400,
"max": 1700,
"description": "Measurement wavelength in nm"
},
"POWER": {
"type": "float",
"command": "MEAS:SCAL:POW",
"unit": "watt",
"read_only": true,
"description": "Measured optical power"
},
"AUTO_RANGE": {
"type": "bool",
"command": "SENS:POW:RANG:AUTO",
"default": true,
"description": "Enable auto-range mode"
},
"AVERAGES": {
"type": "int",
"command": "SENS:AVER:COUN",
"min": 1,
"max": 1000,
"default": 100,
"description": "Number of averages per measurement"
}
}
Grouped schema (multi-channel devices)
{
"Channel1": {
"command_prefix": "CH1",
"parameters": {
"POWER": {
"type": "float",
"command": "MEAS:POW",
"unit": "watt",
"read_only": true
},
"WAVELENGTH": {
"type": "int",
"command": "SENS:WAV",
"unit": "nm"
}
}
}
}
Grouped parameters resolve to keys like CH1.POWER and CH1.WAVELENGTH.
Supported fields
| Field | Required | Type | Description |
|---|---|---|---|
type |
yes | string | One of: int, float, str, bool |
command |
yes | string | Protocol command string |
unit |
no | string | Physical unit label |
min |
no | number | Minimum allowed value |
max |
no | number | Maximum allowed value |
options |
no | array | Allowed categorical values |
default |
no | any | Default value |
read_only |
no | bool | If true, write raises an error |
write_only |
no | bool | If true, query raises an error |
description |
no | string | Human-readable description |
op_schema.json
Defines device operations (functions with inputs and outputs beyond simple param read/write).
{
"measure_power_sequence": {
"iparams": {
"count": {
"type": "int",
"description": "Number of measurements to take"
},
"delay_ms": {
"type": "float",
"description": "Delay between measurements in milliseconds"
}
},
"oparams": {
"powers": {
"type": "float",
"description": "Array of measured power values in watts"
},
"timestamps": {
"type": "float",
"description": "Unix timestamps for each measurement"
}
},
"description": "Take a sequence of power measurements with a fixed delay"
}
}
Each operation has iparams (inputs) and oparams (outputs). Gate d1's test_funcs_mock verifies that all registered operations return a dict with the correct output keys.
Loading schemas in the device class
The simplest way is to pass the schema path to the base class constructor:
from plesty.lib.device.base_device_sync import BaseDeviceSyncModel
class MyDevice(BaseDeviceSyncModel):
def __init__(self, address: str):
super().__init__(
id=address,
param_schema="assets/param_schema.json",
op_schema="assets/op_schema.json",
)
Or register parameters in code (useful for dynamic ranges that depend on constructor arguments):
class PowermeterDevice(BaseDeviceSyncModel):
def __init__(self, address: str, sensor_type: str):
super().__init__(id=address)
min_wl, max_wl = SENSOR_RANGES[sensor_type]
self.register_config("WAVELENGTH", dtype=int, unit="nm",
min_value=min_wl, max_value=max_wl,
command="SENS:CORR:WAV")
Tip: Prefer schema-driven registration for devices with many parameters — an LLM can generate
param_schema.jsondirectly from the vendor manual.