YEP: | 111 |
---|---|
Title: | Properties |
Authors: | Blaise Thompson |
Status: | accepted |
Tags: | standard |
Post-History: | 2020-09-27, 2022-06-30 |
This YEP describes a "properties" system for the yaq ecosystem. Using properties, yaq daemons provide suggestions for how clients might best display the daemon's state to users. Properties are especially useful when automatically building graphical user interfaces.
When interacting with hardware via "rich" graphical clients, users typically expect to be presented with a set of fields. For example, a simple motor might have the field "position" and the field "velocity". Users might expect a graphical client to display the current value of each of these fields and allow setting their value, where possible. We will use the word "properties" to match the conventions of the Python ecosystem.
Using Avro-RPC (see YEP-107), yaq daemons completely specify their client interface. A client knows the exact signature of every message that the daemon supports. In addition, yaq has a traits system which defines preferred message syntax for common behaviors. Client developers may use the traits system to safely build user interfaces. Despite these tools, the relationship between message protocols and logical "properties" of the daemon is often not obvious. Because individual daemons are allowed to specify arbitrary messages beyond those implied by traits, it can be a challenge to automatically discover the relevant properties for an arbitrary daemon.
A typical graphical client needs to know the following:
Here "property" is a single piece of information about a daemon, things like "current position", "integration time", and "averaging method". This YEP allows daemons to help connected clients by specifying relevant properties in a standardized way. While the primary purpose of properties is automatic user-interface generation, fields may also be useful when choosing what (meta)data to record from each daemon in the context of an experiment.
Properties exist on-top-of and do not modify or define the Avro-RPC protocol itself. Clients may ignore properties without penalty.
Properties appear under the properties
key of every protocol provided by yaq daemons.
This key maps to a string: record
mapping where the string key is the field name and the record matches the following:
{
"type": "record",
"name": "property",
"fields": [
{"name": "type", "type": "string"}
{"name": "getter", "type": "string"},
{"name": "setter", "type": ["null", "string"], "default": "null"},
{"name": "units_getter", "type": ["null", "string"], "default": "null"},
{"name": "limits_getter", "type": ["null", "string"], "default": "null"},
{"name": "options_getter", "type": ["null", "string"], "default": "null"},
{"name": "dynamic", "type": "boolean", "default": true},
{"control_kind": "type": {"type": "enum", "name": "kind", "symbols": ["normal", "hinted", "omitted"]},
{"record_kind": "type": {"type": "enum", "name": "kind", "symbols": ["data", "metadata", "omitted"]},
}
type
is a valid Avro type.
It is encouraged to use simple types here, as most graphical clients may not be able to display arbitrarily complex types.
The strings getter
and setter
are the message names used to get and set that field.
The getter
message must accept no required arguments and must return exactly the type specified.
Every field must have a getter
.
The setter
message must accept exactly one required argument of the type specified.
Read-only fields have no setter
.
units_getter
and limits_getter
are optional but encouraged when appropriate.
Sometimes a property can only accept a limited set of options, but these options are only known at runtime.
In such a case, the limits_getter
method will provide those options.
dyanamic
indicates whether a read-only field's value can change while the daemon is running.
Any field with a setter
is assumed to be dynamic.
dynamic
is default true, so any field that does not provide the dynamic key will be assumed to be dynamic.
A client that encounters a field with dynamic
equal to false
may call the getter only once, caching the response.
In cases where a daemon kicks a client and reconnects, the client should refresh all fields.
control_kind
further informs clients of best behavior for presenting daemons to users.
A common design pattern for graphical user interfaces is to have two "levels" of interface for each piece of hardware---one small simplified interface and one complete "advanced menu" or "engineering screen" (examples: yaqc-cmds, typhos).
A control_kind
of normal
tells the client that the field should only be shown on the "advanced menu".
A control_kind
of hinted
tells the client that the field is of principle importance and should be shown on the "simplified interface".
In an effort to increase compatability between ecosystems, yaq has copied these keys directly from ophyd.
Every field must define control_kind
---there is no default value.
record_kind
is similar to control_kind
, except that it informs data recording systems.
Different clients may choose to highlight primary data above metadata in different ways.
record_kind
will likely influence automatic plotting systems which need to make best guesses about which axes users might prefer to see there data plotted against.
Properties may be specified by traits. Individual daemons may overload trait-specified properties, but only in the following cases:
dynamic
from true
to false
limits_getter
Of course, daemons may add additional properties as needed. For demonstration, the properties of three existing traits are shown below:
has-position (YEP-301)
{
"position": {
"getter": "get_position",
"units_getter": "get_units"
"dyanamic": true,
"control_kind": "hinted",
"record_kind": "data"
"type": "double"
}
"destination": {
"getter": "get_destination",
"setter": "set_position",
"units_getter": "get_units"
"dyanamic": true,
"control_kind": "hinted",
"record_kind": "data",
"type": "double"
}
}
is-discrete (YEP-309)
{
"position_identifier": {
"getter": "get_identifier",
"setter": "set_identifier",
"options_getter": "get_position_identifier_options"
"dynamic": true,
"control_kind": "hinted",
"record_kind": "data",
"type": "string"
}
}
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.
built 2023-10-10 23:52:42 CC0: no copyright