# Parameter System The parameter system is the metadata and validation layer used by device classes in PlestyLib. It defines what can be queried or written, validates user input, stores cached values, and supports typed parsing of device responses. Core implementation: `ConfigSystem` in `plesty.lib.device.params`. ## What It Does `ConfigSystem` provides: 1. Parameter registration through code (`register_config`) or schema (`register_params_from_schema`). 2. Optional grouping of parameters (`register_config_group`). 3. Validation for type, range, and categorical options. 4. Read/write permission flags (`read_only`, `write_only`). 5. Current value cache per parameter (`value`). 6. Automatic response casting through `AutoResponseParser`. 7. Human-readable summaries (`param_summary`). ## Main Data Structures ### ConfigParameter Represents one parameter, including: 1. `name` 2. `dtype` 3. `default` and current `value` 4. `unit` 5. `read_only`, `write_only` 6. `min_value`, `max_value` 7. `options` 8. `command` (string or `Command` object) 9. `parser` (optional custom response parser) 10. `description` ### ConfigGroup Represents a parameter group with: 1. Group name 2. Group parameter dictionary 3. Optional command prefix 4. Optional list of group-level allowed commands 5. Group description ### Command Command metadata object used in grouped schemas: 1. `name` 2. `command` # some devices may provide command to query or set parameters in this group 3. `required_params` # defines required parameters for the group command 4. `optional_params` # defines optional paramters for the group command 5. `mode` (`write` or `query`) 6. `description` ## Register Parameters in Code ```python from plesty.lib.device.base_visa_scpi_device import BaseVisaScpiDevice class PowermeterDevice(BaseVisaScpiDevice): def __init__(self, address: str): super().__init__(address) self.register_config("POWER", dtype=float, unit="watt", read_only=True, command="MEAS:SCAL:POW") self.register_config("WAVELENGTH", dtype=int, unit="nm", min_value=400, max_value=1100, command="SENS:CORR:WAV") self.register_config("AUTO_RANGE", dtype=bool, default=True, command="SENS:POW:RANG:AUTO") ``` ## Register Parameters from Schema `register_params_from_schema` supports loading from a JSON file in the following shape: ```json { "ROSCillatorFrequency": { "type": "float", "command": "SOUR:ROSC:FREQ", "description": "Set or query the frequency of the internal reference oscillator." }, "SyncClockoutValue": { "type": "integer", "command": "SYNC:VAL", "read_only": true } } ``` Load schema from file path or dictionary: ```python from plesty.lib.device.params import ConfigSystem cfg = ConfigSystem(param_schema="param_schema.json") # or # cfg = ConfigSystem(param_schema=schema_dict) ``` Load schema directly in a base-device constructor (`BaseDeviceSyncModel`): ```python from plesty.lib.device.base_device_sync import BaseDeviceSyncModel class MyDevice(BaseDeviceSyncModel): def __init__(self, id: str, param_schema): super().__init__(id=id, param_schema=param_schema) def connect(self): ... def disconnect(self): ... def check_errors(self) -> list[str]: return [] def check_operatability(self) -> bool: return True def _write_(self, key, value) -> bool: return True def _query_(self, key) -> str: return "0" dev_a = MyDevice(id="dev-1", param_schema="param_schema.json") # or # dev_b = MyDevice(id="dev-2", param_schema=schema_dict) ``` ## Validation Rules Validation happens at registration and at write-time checks. 1. Type checks: values must match `dtype`. 2. Numeric range checks: `min_value <= value <= max_value`. 3. Option checks: categorical values must be in `options`. 4. Permission checks: cannot write `read_only` parameters. Important behavior: 1. Registration errors raise exceptions. 2. `check_write_config` raises on invalid values. 3. `set_config_value` attempts auto-casting before range/options validation. ## Query/Write Flow Integration In synchronized devices, high-level methods in `BaseDeviceSyncModel` use `ConfigSystem` as follows: 1. `write(key, value)` 2. `check_write_config(key, value)` validates the request 3. Device-specific `_write_` sends command to hardware 4. On success, `set_config_value` updates cached value For queries: 1. `query(key)` 2. `check_query_config(key)` validates access 3. Device-specific `_query_` gets raw response 4. `response_to_target_type` parses/casts response 5. `set_config_value` stores parsed value ## Response Parsing By default, `AutoResponseParser` tries to cast response text to the parameter dtype. Examples: 1. `"42" -> int` 2. `"3.14" -> float` 3. `"true"/"1" -> bool` (via basic cast helper) 4. Delimited strings for typed list/tuple annotations If needed, provide a custom parser in parameter metadata via `parser`. ## Useful API Methods 1. `register_config(...)` 2. `register_config_group(...)` 3. `register_params_from_schema(...)` 4. `get_config(key, group="default")` 5. `get_config_list(group="default")` 6. `get_group_list()` 7. `set_config_value(key, value)` 8. `get_config_value(key)` 9. `set_config_min_max(key, min_value, max_value)` 10. `param_summary(constraints=True, description=False)` ## Minimal End-to-End Example ```python from plesty.lib.device.params import ConfigSystem system = ConfigSystem() system.register_config( key="GAIN", dtype=int, min_value=1, max_value=10, default=5, command="CONF:GAIN", ) system.check_write_config("GAIN", 7) system.set_config_value("GAIN", "7") # auto-cast to int print(system.get_config_value("GAIN")) print(system.param_summary()) ``` ## Best Practices 1. Always set `dtype` for robust validation and auto-casting. 2. Prefer explicit `min_value` and `max_value` for numeric parameters. 3. Use `options` for categorical values. 4. Keep command strings in parameter metadata so solver logic stays generic. 5. Use schema-driven registration for larger devices. 6. Include `description` and `unit` fields to improve generated summaries and docs.