Enumerated attribute
Intended audience: developers, Programming language: c++
Since Tango release 9, enumerated attribute is supported using the new data type DevEnum. This data type is not a real C++ enumeration because:
The enumerated value allways start with 0
Values are consecutive
It is transferred on the network as DevShort data type
One enumeration label is associated to each enumeration value. For the Tango kernel, it is this list of enumeration labels which will define the possible enumeration values. For instance if the enumeration has 3 labels, its value must be between 0 and 2. There are two ways to define the enumeration labels:
At attribute creation time. This is the most common case when the list of possible enumeration values and labels are known at compile time. The Tango code generator Pogo generates for you the code needed to pass the enumeration labels to the Tango kernel.
In the user code when the enumeration values and labels are not known at compile time but retrieved during device startup phase. The user gives the possible enumeration values to the Tango kernel using the Attribute class set_properties() method.
A Tango client is able to retrieve the enumeration labels in the attribute configuration returned by instance by a call to the DeviceProxy::get_attribute_config() method. Using the DeviceProxy::set_attribute_config() call, a user may change the enumeration labels but not their number.
Usage in a Tango class
Within a Tango class, you set the attribute value with a C++ enum or a DevShort variable. In case a DevShort variable is used, its value will be checked according to the enumeration labels list given to Tango kernel.
Setting the labels with enumeration compile time knowledge
In such a case, the enumeration labels are given to Tango at the attribute creation time in the attribute_factory method of the XXXClass class. Let us take one example
1 enum class Card: short
2 {
3 NORTH = 0,
4 SOUTH,
5 EAST,
6 WEST
7 };
8
9 struct TheEnumAttrib : Tango::Attr
10 {
11 ...
12
13 // Required for enum attributes
14 virtual bool same_type(const type_info& in_type) override { return typeid(Card) == in_type; }
15 virtual std::string get_enum_type() override { return "Card"; }
16 }
17
18 void XXXClass::attribute_factory(vector<Tango::Attr *> &att_list)
19 {
20 .....
21 TheEnumAttrib *theenum = new TheEnumAttrib();
22 Tango::UserDefaultAttrProp theenum_prop;
23 vector<string> labels = {"North","South","East","West"};
24 theenum_prop.set_enum_labels(labels);
25 theenum->set_default_properties(theenum_prop);
26 att_list.push_back(theenum);
27 .....
28 }
line 1-7 : The definition of the enumeration (C++11 in this example)
line 9-16 : The definition of the enumerated attribute
line 23 : A vector of strings with the enumeration labels is created. Because there is no way to get the labels from the enumeration definition, they are re-defined here.
line 24 : This vector is given to the theenum_prop object which contains the user default properties
Setting the labels without enumeration compile time knowledge
In such a case, the enumeration labels are retrieved by the user in a way specific to the device and passed to Tango using the Attribute class set_properties() method. Let us take one example
1 void MyDev::init_device()
2 {
3 ...
4
5 Attribute &att = get_device_attr()->get_attr_by_name("TheEnumAtt");
6 MultiAttrProp<DevEnum> multi_prop;
7 att.get_properties(multi_prop);
8
9 multi_prop.enum_labels = {....};
10 att.set_properties(multi_prop);
11 ....
12 }
line 5 : Get a reference to the attribute object
line 7 : Retrieve the attribute properties
line 9 : Initialise the attribute labels in the set of attribute properties
line 10 : Set the attribute properties
Setting the attribute value
It is possible to set the attribute value using either a classical DevShort variable or using a variable of the C++ enumeration. The following example is when you have compile time knowledge of the enumeration definition. We assume that the enumeration is the same than the one defined above (Card enumeration)
1 enum Card points;
2
3 void MyDev::read_TheEnum(Attribute &att)
4 {
5 ...
6 points = SOUTH;
7 att.set_value(&points);
8 }
line 1 : One instance of the Card enum is created (named points)
line 6 : The enumeration is initialized
1 DevShort sh;
2
3 void MyDev::read_TheEnum(Attribute &att)
4 {
5 ...
6 sh = 1;
7 att.set_value(&sh);
8 }
line 1 : A DevShort variable is created (named sh)
line 6 : The variable is initialized
line 7 : The value of the attribute object is set using the DevShort variable (by pointer)
Usage in a Tango client
Within a Tango client, you insert/extract enumerated attribute value in/from DeviceAttribute object with a C++ enum or a DevShort variable. The later case is for generic client which do not have compile time knowledge of the enumeration. The code looks like
1 DeviceAttribute da = the_dev.read_attribute("TheEnumAtt");
2 Card ca;
3 da >> ca;
4
5 DeviceAttribute db = the_dev.read_attribute("TheEnumAtt");
6 DevShort sh;
7 da >> sh;
line 2-3 : The attribute value is extracted in a C++ enumeration variable
line 6-7 : The attribute value is extracted in a DevShort variable