egse.command
This module defines a number of classes and helper functions to define and work with commands that operate hardware devices. The goal is to be able to define / create commands transparently from a YAML file without having to write (too much) code.
Definitions¶
command
a string that is sent to a device over an interface like TCP/IP or USB. This string is generated by the get_cmd_string() method of the Command class.
The string contains format like syntax that looks like an f-string, but is interpreted differently. See further: How to format device command strings.
Command
the base class for commands. This class contains the definition of the command and provides methods to parse and check arguments. The Command can be 'called' or 'executed' in which case a number of actions are performed based on the provided arguments.
CommandExecution
this class contains all the information needed to execute a command, without actually executing it. A CommandExecution contains the command definition and the parameters for the execution. It is mainly served as a communication mechanism to the control servers, i.e. the client side (Proxy) defines a command execution and the server then executes the command.
CommandError
a catch-all exception for unrecoverable errors in this module
InvalidArgumentsError
a CommandError raised when the arguments provided are themselve invalid or if the number of arguments is not matching expectations
The basic interface is:
cmd = Command(name = <command name>,
cmd = <command string>,
response = <callable to retreive a response>,
wait = <callable to wait a specific time/delay>)
where:
- name: a name for the command, this is just needed for reporting, not used in commanding
- cmd: the command string to send or execute, see further for details
- response: send a second command to read or get a response on the 'cmd' sent
- wait: a function object that will wait for a specific duration,
e.g.
partial(time.sleep, 10)
.
Formatting device command strings¶
The cmd
argument is a string that contains placeholders (replacement fields)
for future arguments that will be passed when calling the Command. The replacement
fields are marked with curly braces and are mandatory. When a name is provided
in the curly braces, the argument shall be provided as a keyword argument, otherwise
a positional argument is expected. In the current implementation the cmd
can only contain either positional arguments or keyword argument, not a mix of both.
The replacement fields may also have a format specifier to specify a precise format for that field.
Examples
moveAbsolute = Command(
name = "moveAbsolute",
cmd = "&2 Q70=0 Q71={tx:.6f} Q72={ty:.6f} Q73={tz:.6f} "
"Q74={rx:.6f} Q75={ry:.6f} Q76={rz:.6f} Q20=11"
)
response = moveAbsolute(1, 1, 1, 0, 0, 20)
response = moveAbsolute(tx=1, ty=1, tz=1, rx=0, ry=0, rz=20)
Questions¶
Do we need additional hooks into this commanding?
- add a meaning to the check, what is it and what is it used for?
- add a output processor possibility. A callback function that will process the output value before returning it by the call.
- provide an execute method for the CommandExecution that executes the command with the saved parameters
Classes:
Name | Description |
---|---|
ClientServerCommand |
|
Command |
A Command is basically a string that is send to a device and for which the |
CommandError |
A Command Exception as a base class for this module. |
CommandExecution |
This class contains all the information that is needed to execute a command |
InvalidArgumentsError |
The arguments provided are invalid |
InvalidCommandExecution |
A invalid command execution. |
Functions:
Name | Description |
---|---|
dry_run |
This decorator prepares the function to handle a dry run. |
get_function |
Returns a function (unbound method) from a given class. |
get_method |
Returns a bound method from a given class instance. |
load_commands |
Loads the command definitions from the given |
parse_format_string |
Parse and decode the format string. |
ClientServerCommand
¶
ClientServerCommand(
name,
cmd,
response=None,
wait=None,
check=None,
description=None,
device_method=None,
)
Bases: Command
Methods:
Name | Description |
---|---|
client_call |
This method is called at the client side. It is used by the Proxy |
server_call |
This method is called at the server side. It is used by the CommandProtocol class in the |
client_call
¶
client_call(other, *args, **kwargs)
This method is called at the client side. It is used by the Proxy as a generic command to send a command execution to the server.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
other
|
a sub-class of the Proxy class |
required | |
args
|
arguments that will be passed on to this command when executed |
()
|
|
kwargs
|
keyword arguments that will be passed on to this command when executed |
{}
|
Returns:
Type | Description |
---|---|
the response that is returned by calling the command (at the server side). |
server_call
¶
server_call(other, *args, **kwargs)
This method is called at the server side. It is used by the CommandProtocol class in the
execute
method.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
other
|
a sub-class of the CommandProtocol |
required | |
args
|
arguments are passed on to the response method |
()
|
|
kwargs
|
keyword arguments are passed on to the response method |
{}
|
Returns:
Type | Description |
---|---|
0 on success and -1 on failure. |
Command
¶
Command(
name,
cmd,
response=None,
wait=None,
check=None,
description=None,
device_method=None,
)
A Command is basically a string that is send to a device and for which the device returns a response.
The command string can contain placeholders that will be filled when the command is 'called'.
The arguments that are given will be filled into the formatted string. Arguments can be positional or keyword arguments, not both.
CommandExecution
¶
CommandExecution(cmd, *args, **kwargs)
This class contains all the information that is needed to execute a command with a set of parameters/arguments. The command is however not executed automatically. That is the responsibility of the caller to actually execute the command with the given parameters.
Developer info
you can see this as a partial (functools) which defines the command and
its arguments, but doesn't execute until explicitly called. You can execute
the command by calling the cmd
with the given arguments:
ce = CommandExecution(cmd, 20.0)
...
response = ce.run()
InvalidArgumentsError
¶
Bases: CommandError
The arguments provided are invalid
InvalidCommandExecution
¶
InvalidCommandExecution(exc, cmd, *args, **kwargs)
Bases: CommandExecution
A invalid command execution.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
exc
|
the Exception that was raised and describes the problem |
required | |
cmd
|
the Command object |
required | |
*args
|
the positional arguments that were given |
()
|
|
**kwargs
|
the keyword arguments that were given |
{}
|
dry_run
¶
dry_run(func)
This decorator prepares the function to handle a dry run.
A dry run is used to check the logic of an instrument commanding script without actually executing the instrument commands. The commands are instead added to the command sequence in the global state.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func
|
Callable
|
the function that needs to be executed |
required |
Returns:
Type | Description |
---|---|
Callable
|
A wrapper around the given function. |
get_function
¶
get_function(parent_class, method_name)
Returns a function (unbound method) from a given class.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
parent_class
|
the class that provides the method |
required | |
method_name
|
str
|
name of the method that is requested |
required |
Returns:
Type | Description |
---|---|
Callable
|
the method [type: function]. |
Note
The function returned is an unbound class instance method and therefore this function expects as its first argument the class instance, i.e. self, when you call it as a function.
get_method
¶
get_method(parent_obj, method_name)
Returns a bound method from a given class instance.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
parent_obj
|
the class instance that provides the method |
required | |
method_name
|
str
|
name of the method that is requested |
required |
Returns:
Type | Description |
---|---|
Callable
|
the method [type: method]. |
Note
The method returned is an bound class instance method and therefore this method does not expects as its first argument the class instance, i.e. self, when you call this as a function.
load_commands
¶
load_commands(
protocol_class,
command_settings,
command_class,
device_class,
)
Loads the command definitions from the given command_settings
and builds an internal
dictionary containing the command names as keys and the corresponding Command
class objects
as values.
The command_settings
is usually loaded from a YAML configuration file containing the
command definitions for the device.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
protocol_class
|
the CommandProtocol or a sub-class |
required | |
command_settings
|
a dictionary containing the command definitions for this device |
required | |
command_class
|
the type of command to create, a subclass of Command |
required | |
device_class
|
the type of the base device class from which the methods are loaded |
required |