plesty.lib.device.base_device_sync
Base synchronous device model for Plesty.
Classes
Abstract base class for synchronous device models in Plesty. |
Module Contents
- class plesty.lib.device.base_device_sync.BaseDeviceSyncModel(id: str, op_schema=None, param_schema=None, op_solver=None, cmd_solver=None, data_path: str | os.PathLike[str] | None = None, allowed_data_roots: collections.abc.Iterable[str | os.PathLike[str]] | None = None, **kwargs)
Bases:
abc.ABC,plesty.lib.device.params.ConfigSystem,plesty.lib.device.funcs.FunctionSystem,plesty.lib.device.telemetry.TelemetrySystemAbstract base class for synchronous device models in Plesty.
Initialize the device model with optional schemas and solvers.
- Parameters:
id (str) – Device identifier, combined with the host IP into the resource key.
op_schema – Optional operation schema for the function system.
param_schema – Optional parameter schema for the configuration system.
op_solver – Optional operation solver bound to the function system.
cmd_solver – Optional command solver bound to the configuration system.
data_path (str | os.PathLike[str] | None) – Default directory for acquired data, used until a client calls
set_data_path(). Device modules read it from their own configuration source (YAML,.env) and pass it in — the library does not prescribe a format.allowed_data_roots (collections.abc.Iterable[str | os.PathLike[str]] | None) – Directories that client-supplied paths must resolve under. Defaults to
[data_path], so a device can only be redirected inside its own data directory unless wider roots are declared explicitly.**kwargs – Extra keyword arguments, accepted and ignored so subclasses can pass their own construction options up the chain.
- Raises:
ValueError – If
data_pathdoes not resolve underallowed_data_roots.
- id
- _resources: list[Any] = []
- _resource_manager: plesty.lib.service.resource_manager.ResourceManager | None = None
- _allowed_data_roots: list[pathlib.Path]
- _root_spellings: list[tuple[pathlib.Path, pathlib.Path]]
- _default_data_path: pathlib.Path | None = None
- _data_path: pathlib.Path | None = None
- _data_path_display: pathlib.Path | None
- register_resources(resources: list[Any]) None
Declare the physical resources this device owns.
Extends the device’s resource inventory and registers the same set with the embedded
ResourceManagerso that direct (non-TCP) clients can request exclusive access viaallocate_resource().- Parameters:
resources (list[Any]) – Resource identifiers in any format accepted by
ResourceManager(flat list, set, or nested dict tree).- Return type:
None
- allocate_resource(resources: Any, client_id: str) bool
Request exclusive access to one or more device resources.
Delegates to the embedded
ResourceManager. ReturnsTrueif the allocation succeeded,Falseif any requested resource is already held by another client. When no resources have been registered, all requests are granted.- Parameters:
resources (Any) – Resource identifiers (str, list, or dict tree).
client_id (str) – Stable identifier for the requesting client.
- Return type:
bool
- release_resource(client_id: str) None
Release all resources previously allocated to client_id.
- Parameters:
client_id (str) – Identifier of the client whose allocation should be freed.
- Return type:
None
- client_resources(client_id: str) list[str]
Return the canonical resource paths currently allocated to client_id.
- Parameters:
client_id (str) – Identifier of the client to query.
- Return type:
list[str]
- _is_allowed_data_path(path: pathlib.Path) bool
Return whether path resolves under one of the allowed data roots.
- Parameters:
path (pathlib.Path)
- Return type:
bool
- _display_path(resolved: pathlib.Path) pathlib.Path
Re-base resolved onto the configured spelling of its data root.
Path.resolve()rewrites a mapped Windows drive to its UNC form, which the operator never configured and some vendor software rejects. A path under a known root is expressed under that root’s configured spelling; anything else is returned as it came.- Parameters:
resolved (pathlib.Path)
- Return type:
pathlib.Path
- _resolve_data_path(path: str | os.PathLike[str]) pathlib.Path
Resolve path to an absolute directory, expanding
~and following links.A relative path is taken relative to the configured default data path (or, when only roots are configured, the first allowed root), so a client can route a run with
set_data_path("session-42")without knowing the server’s filesystem layout.- Parameters:
path (str | os.PathLike[str]) – Absolute or relative directory supplied by the caller.
- Raises:
ValueError – If path is relative and no data root is configured.
- Return type:
pathlib.Path
- set_data_path(path: str | os.PathLike[str], **kwargs) str
Set the directory where this device stores acquired data.
The path is resolved (
~expanded,..collapsed, symlinks followed) and must lie under one of the device’s allowed data roots; it is created if missing. All clients of a device server share one data path — the last call wins, matching the single-operator resource-lock model.- Parameters:
path (str | os.PathLike[str]) – Target directory, absolute or relative to the device’s default data path.
**kwargs – Optional extras such as
resources, ignored here.
- Returns:
The directory now in effect, in the configured spelling of its data root — a mapped drive stays a mapped drive; resolution is used for the containment checks only.
- Raises:
ValueError – If the resolved path is outside the allowed roots, or the device has no data path configured at all.
- Return type:
str
- get_data_path(**kwargs) str
Return the directory currently used for acquired data.
Device code that writes acquisition files should read the directory from here rather than from its own configuration, so client-set paths take effect.
- Parameters:
**kwargs – Optional extras such as
resources, ignored here.- Returns:
the last one set by a client, or the device’s configured default. The directory is created if missing — the configured default is otherwise never created anywhere (construction is side-effect-free), and vendor software validating the directory rejects one that does not exist (plesty-lib#31).
- Return type:
The directory in effect, in its configured spelling
- Raises:
RuntimeError – If the device has no data path configured.
- abstractmethod init(main=None) None
Initialize the device. This should be called before any other operations.
- Return type:
None
- property is_operatable: bool
Check if the device is currently operatable (connected and responsive).
- Return type:
bool
- property state: dict
Return a dictionary representing the current device state with all parameters.
- Return type:
dict
- get_state() dict[str, Any]
Return a dictionary of all configuration parameters and their current values.
- Return type:
dict[str, Any]
- synchronize_param_from_device(keys: list[str] | None = None, sync_constraints: bool = False) None
Synchronizing the model’s configuration with the actual device.
- Parameters:
keys (list[str] | None)
sync_constraints (bool)
- Return type:
None
- doc_model() plesty.lib.device.doc.DeviceDocModel
Return this device’s structured, render-agnostic documentation model.
The model bundles the configuration parameters (grouped) and every callable operation (schema-registered plus
@expose_to_apicustom methods, unified). Documentation renderers consume it instead of re-deriving the metadata.- Returns:
The
DeviceDocModelfor this device.- Return type:
- summary(style: str = 'short', filename=None) str
Summarize both configuration parameters and registered functions.
- Parameters:
style (str) – One of
short,md, orgoogle.filename – Optional file path to save the rendered summary.
- Returns:
A rendered summary string combining parameter and function sections.
- Return type:
str
- get_query_command(key: str) str | None
Return the command that would be sent to query key, sending nothing.
An accessor, not an action — which is the whole difference from
query().query(key)performs the exchange, consumes the reply and returns the value; this returns the command, touches no I/O and leaves the session exactly as it found it. The naming follows the split already in this class:get_*reads what the device declares, a bare verb talks to it.It exists so a caller can transmit a query without reading its answer — the orphaned reply the buffer-drain gate needs. That takes the command and the transport’s
orphan(), and the command is the half only the device knows.- Parameters:
key (str) – Configuration key.
- Returns:
The command, or
Nonewhen this device cannot produce one — the base implementation, since a solver is bound by the subclass. The drain gate then skips and says so.- Return type:
str | None
- query_param_range(key: str) tuple[float | int | None, float | int | None]
Query the device for the valid range of a numeric parameter.
- Parameters:
key (str)
- Return type:
tuple[float | int | None, float | int | None]
- query_param_options(key: str) list[Any] | None
Query the device for the valid options of a categorical parameter.
- Parameters:
key (str)
- Return type:
list[Any] | None
- abstractmethod connect() Any
Placeholder method for connecting to the device.
- Return type:
Any
- abstractmethod disconnect() Any
Placeholder method for disconnecting from the device.
- Return type:
Any
- abstractmethod identity() str
Query the device for its identity string.
- Return type:
str
- abstractmethod check_errors() list[str]
Query the device for any error messages.
- Return type:
list[str]
- abstractmethod check_operatability() bool
Check if the device is currently operatable (connected and responsive).
- Return type:
bool
- __enter__()
Enter the device context: acquire the resource lock, init and connect.
- __exit__(exc_type, exc_value, tb)
Exit the device context, disconnecting and releasing resources.
The resource lock is released even when
disconnect()fails. A transport that throws on the way out — a clear refused by a wedged session, a close on an already-dead handle — must not leave the device marked as in use: every later attempt then fails with “Resource already in use” against an instrument nothing is holding, and the process has to be restarted to clear it.
- response_to_target_type(key, response) Any
Parse a raw device response into the target type for the given parameter key.
- Return type:
Any
- _user_permission_check(user_resources: list[Any], key: str) bool
Check if the client is permitted to access key given its allocated resources.
The default implementation is permissive (returns
True). Subclasses should override this method with device-specific logic, and may callclient_resources()or inspect_resource_managerto query current allocations.- Parameters:
user_resources (list[Any]) – Resources reported by the client for this request.
key (str) – The configuration parameter or function key being accessed.
- Return type:
bool
- write(key: str, value: str | float | int | bool, **kwargs) bool
Write a configuration parameter value to the device after validation.
- Parameters:
key (str) – Name of the parameter to write (as listed on the Parameters page).
value (str | float | int | bool) – New value; validated against the parameter’s type and range before being sent to the device.
**kwargs – Optional extras such as
resourcesfor per-client access control.
- Returns:
Trueif the write succeeded,Falseotherwise (e.g. a permission check failed).- Return type:
bool
- query(key: str, **kwargs) Any
Query a configuration parameter value from the device.
- Parameters:
key (str) – Name of the parameter to read (as listed on the Parameters page).
**kwargs – Optional extras such as
resourcesfor per-client access control.
- Returns:
The parameter’s current value, converted to its declared type.
- Return type:
Any
- abstractmethod _write_(key: str, value: str | float | int | bool) bool
Placeholder method for writing a command to the device.
- Parameters:
key (str)
value (str | float | int | bool)
- Return type:
bool
- abstractmethod _query_(key: str) str
Placeholder method for querying the device.
- Parameters:
key (str)
- Return type:
str
- reset() None
Reset the device to a known state.
- Return type:
None
- clear() None
Clear the device state.
- Return type:
None