Controller API reference

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 int is preferred to “int” or “PyTango.DevLong”):

  • for 0D data types:
    • integer: int | DataType.Integer | “int” | “integer” | “long” | long | [ “PyTango.” ] “DevLong”

    • double: float | DataType.Double | “double” | “float” | [ “PyTango.” ] “DevDouble”

    • string: str | DataType.String | “str” | “string” | [ “PyTango.” ] “DevString”

    • boolean: bool | DataType.Boolean | “bool” | “boolean” | [ “PyTango.” ] “DevBoolean”

  • for 1D data types:
    • integer: (int,) | (DataType.Integer,) | (“int”,) | (“integer”,) | (long,) | (“long”,) | [ “PyTango.” ] “DevVarLongArray” | ([ “PyTango.” ] “DevLong”,)

    • double: (float,) | (DataType.Double,) | (“double”,) | (“float”,) | [ “PyTango.” ] “DevVarDoubleArray” | ([ “PyTango.” ] “DevDouble”,)

    • string: (str,) | (DataType.String,) | (“str”,) | (“string”,) | [ “PyTango.” ] “DevVarStringArray” | ([ “PyTango.” ] “DevString”,)

    • boolean: (bool,) | (DataType.Boolean,) | (“bool”,) | (“boolean”,) | [ “PyTango.” ] “DevVarBooleanArray” | ([ “PyTango.” ] “DevBoolean”,)

Deprecated since version 1.0: [ “PyTango.” ] “Dev”<concrete type string> 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) )

Custom command definition

A controller may add Tango commands to its element devices, via axis_commands, and to the controller device itself, via ctrl_commands. Both are a list of 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 None for display_level is equivalent to omitting it.

The method named by fname is looked up on the controller instance. For 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 ctrl_commands no axis is bound, so the signature is (self) or (self, value).

axis_commands applies to every axis of the controller. To give different axes different commands, override 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 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 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 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.

See also

Custom commands for a worked example, and Per-axis custom commands for the per-axis override.