.. currentmodule:: sardana.pool.controller .. _sardana-controller-api: ======================== Controller API reference ======================== * :class:`Controller` - Base API for all controller types * :class:`MotorController` - Motor controller API * :class:`CounterTimerController` - Counter/Timer controller API * :class:`ZeroDController` - 0D controller API * :class:`PseudoMotorController` - PseudoMotor controller API * :class:`PseudoCounterController` - PseudoCounter controller API * :class:`TriggerGateController` - Trigger/Gate controller API * :class:`IORegisterController` - IORegister controller API .. _sardana-controller-data-type: Data Type definition ---------------------- When writing a new controller you may need to specify extra attributes (per controller or/and per axis) as well as extra properties. This chapter describes how to describe the data type for each of this additional members. Controller data type definition has the following equivalences. This means you can use any of the given possibilities to describe a field data type. The possibilities are ordered by preference (example: usage of :obj:`int` is preferred to "int" or "PyTango.DevLong"): - for 0D data types: - **integer**: :obj:`int` | :data:`DataType.Integer ` | "int" | "integer" | "long" | :obj:`long` | [ "PyTango." ] "DevLong" - **double**: :obj:`float` | :data:`DataType.Double ` | "double" | "float" | [ "PyTango." ] "DevDouble" - **string**: :obj:`str` | :data:`DataType.String ` | "str" | "string" | [ "PyTango." ] "DevString" - **boolean**: :obj:`bool` | :data:`DataType.Boolean ` | "bool" | "boolean" | [ "PyTango." ] "DevBoolean" - for 1D data types: - **integer**: (:obj:`int`,) | (:data:`DataType.Integer `,) | ("int",) | ("integer",) | (:obj:`long`,) | ("long",) | [ "PyTango." ] "DevVarLongArray" | ([ "PyTango." ] "DevLong",) - **double**: (:obj:`float`,) | (:data:`DataType.Double `,) | ("double",) | ("float",) | [ "PyTango." ] "DevVarDoubleArray" | ([ "PyTango." ] "DevDouble",) - **string**: (:obj:`str`,) | (:data:`DataType.String `,) | ("str",) | ("string",) | [ "PyTango." ] "DevVarStringArray" | ([ "PyTango." ] "DevString",) - **boolean**: (:obj:`bool`,) | (:data:`DataType.Boolean `,) | ("bool",) | ("boolean",) | [ "PyTango." ] "DevVarBooleanArray" | ([ "PyTango." ] "DevBoolean",) .. deprecated:: 1.0 [ "PyTango." ] "Dev" types are considered deprecated. .. note:: when string, types are case insensitive. This means "long" is the same as "LONG" Here is an example on how to define extra attributes per axis: 1. EncoderSource: a scalar r/w string 2. ReflectionMatrix: a 2D readable float with customized getter method :: from sardana import State, DataAccess from sardana.pool.controller import MotorController, \ Type, Description, DefaultValue, Access, FGet, FSet class MyMotorCtrl(MotorController): axis_attributes = \ { 'EncoderSource' : { Type : str, Description : 'motor encoder source', }, 'ReflectionMatrix' : { Type : ( (float,), ), Access : DataAccess.ReadOnly, FGet : 'getReflectionMatrix', }, } def getAxisExtraPar(self, axis, name): name = name.lower() if name == 'encodersource': return self._encodersource[axis] def setAxisPar(self, axis, name, value): name = name.lower() if name == 'encodersource': self._encodersource[axis] = value def getReflectionMatrix(self, axis): return ( (1.0, 0.0), (0.0, 1.0) ) .. _sardana-controller-custom-command-definition: Custom command definition ------------------------- A controller may add Tango_ commands to its element devices, via :attr:`~Controller.axis_commands`, and to the controller device itself, via :attr:`~Controller.ctrl_commands`. Both are a :class:`list` of :class:`tuple`, one tuple per command, with the following positional fields: ==== ================== ========= ============================== ====================== pos. field Mandatory Meaning Default ==== ================== ========= ============================== ====================== 1 ``fname`` Yes controller method to call --- 2 ``dtype_in`` No Tango input data type ``DevVoid`` 3 ``dformat_in`` No Tango input data format ``SCALAR`` 4 ``doc_in`` No input documentation ``""`` 5 ``dtype_out`` No Tango output data type ``DevVoid`` 6 ``dformat_out`` No Tango output data format ``SCALAR`` 7 ``doc_out`` No output documentation ``""`` 8 ``display_level`` No Tango display level ``OPERATOR`` 9 ``cmd_green_mode`` No run in the green mode executor ``True`` ==== ================== ========= ============================== ====================== A tuple may be truncated after any field; omitted fields take their default. ``("MyCommand",)`` is therefore a valid declaration of a command taking and returning nothing. Passing :obj:`None` for ``display_level`` is equivalent to omitting it. The method named by ``fname`` is looked up on the controller instance. For :attr:`~Controller.axis_commands` the axis number is bound as the method's first argument, so the signature is ``(self, axis)``, or ``(self, axis, value)`` when ``dtype_in`` is not ``DevVoid``; the Tango command itself takes only the user argument. For :attr:`~Controller.ctrl_commands` no axis is bound, so the signature is ``(self)`` or ``(self, value)``. :attr:`~Controller.axis_commands` applies to **every** axis of the controller. To give different axes different commands, override :meth:`~Controller.GetAxisCommands`: it is called once per axis, with that axis number, and the list it returns is the one used for that axis. Its default implementation returns a copy of :attr:`~Controller.axis_commands`. The command set of a device is built once, when the dynamic Tango_ interface of that device is created. A change in what :meth:`~Controller.GetAxisCommands` returns therefore requires a restart of the Pool server; the Tango_ ``Init`` command and a controller library reload do not rebuild it. .. note:: Custom commands require **PyTango >= 10.0**; below that version no command is created. ``cmd_green_mode`` requires **PyTango >= 10.1**; on PyTango 10.0 it is forced to ``False``. In both cases a :obj:`RuntimeWarning` is issued and the rest of the device is unaffected. Sardana's own requirement is PyTango >= 9.2.5, so this is not guaranteed by installing Sardana. .. seealso:: :ref:`sardana-controller-howto-custom-commands` for a worked example, and :ref:`sardana-controller-howto-per-axis-commands` for the per-axis override. .. _Tango: http://www.tango-controls.org/