Starting/creating/deleting devices#
Multiple device classes (Python and C++) in a server#
Within the same python interpreter, it is possible to mix several Tango classes.
Let’s say two of your colleagues programmed two separate Tango classes in two
separated python files: A PLC
class in a PLC.py
:
1# PLC.py
2
3from tango.server import Device
4
5class PLC(Device):
6
7 # bla, bla my PLC code
8
9if __name__ == "__main__":
10 PLC.run_server()
… and a IRMirror
in a IRMirror.py
:
1# IRMirror.py
2
3from tango.server import Device
4
5class IRMirror(Device):
6
7 # bla, bla my IRMirror code
8
9if __name__ == "__main__":
10 IRMirror.run_server()
You want to create a Tango server called PLCMirror
that is able to contain
devices from both PLC and IRMirror classes. All you have to do is write
a PLCMirror.py
containing the code:
1# PLCMirror.py
2
3from tango.server import run
4from PLC import PLC
5from IRMirror import IRMirror
6
7run([PLC, IRMirror])
- It is also possible to add C++ Tango class in a Python device server as soon as:
The Tango class is in a shared library
It exist a C function to create the Tango class
The C++ Tango class is linked against the same
libtango.so
object as PyTango (i.e., cannot be used with binary wheels from PyPI, but can with conda-forge or a custom build).
For a Tango class called MyTgClass, the shared library has to be called MyTgClass.so and has to be in a directory listed in the LD_LIBRARY_PATH environment variable. The C function creating the Tango class has to be called _create_MyTgClass_class() and has to take one parameter of type “char *” which is the Tango class name. Here is an example of the main function of the same device server than before but with one C++ Tango class called SerialLine:
1import tango
2import sys
3
4if __name__ == '__main__':
5 util = tango.Util(sys.argv)
6 util.add_class('SerialLine', 'SerialLine', language="c++")
7 util.add_class(PLCClass, PLC, 'PLC')
8 util.add_class(IRMirrorClass, IRMirror, 'IRMirror')
9
10 U = tango.Util.instance()
11 U.server_init()
12 U.server_run()
- Line 6:
The C++ class is registered in the device server
- Line 7 and 8:
The two Python classes are registered in the device server
Create/Delete devices dynamically#
This feature is only possible since PyTango 7.1.2
Starting from PyTango 7.1.2 it is possible to create devices in a device server “en caliente”. This means that you can create a command in your “management device” of a device server that creates devices of (possibly) several other tango classes. There are two ways to create a new device which are described below.
Tango imposes a limitation: the tango class(es) of the device(s) that is(are)
to be created must have been registered before the server starts.
If you use the high level API, the tango class(es) must be listed in the call
to run()
. If you use the lower level server API, it must
be done using individual calls to add_class()
.
Dynamic device from a known tango class name#
If you know the tango class name but you don’t have access to the tango.DeviceClass
(or you are too lazy to search how to get it ;-) the way to do it is call
create_device()
/ delete_device()
.
Here is an example of implementing a tango command on one of your devices that
creates a device of some arbitrary class (the example assumes the tango commands
‘CreateDevice’ and ‘DeleteDevice’ receive a parameter of type DevVarStringArray
with two strings. No error processing was done on the code for simplicity sake):
1from tango import Util
2from tango.server import Device, command
3
4class MyDevice(Device):
5
6 @command(dtype_in=[str])
7 def CreateDevice(self, pars):
8 klass_name, dev_name = pars
9 util = Util.instance()
10 util.create_device(klass_name, dev_name, alias=None, cb=None)
11
12 @command(dtype_in=[str])
13 def DeleteDevice(self, pars):
14 klass_name, dev_name = pars
15 util = Util.instance()
16 util.delete_device(klass_name, dev_name)
An optional callback can be registered that will be executed after the device is registed in the tango database but before the actual device object is created and its init_device method is called. It can be used, for example, to initialize some device properties.
Dynamic device from a known tango class#
If you already have access to the DeviceClass
object that
corresponds to the tango class of the device to be created you can call directly
the create_device()
/ delete_device()
.
For example, if you wish to create a clone of your device, you can create a
tango command called Clone:
1class MyDevice(tango.Device):
2
3 def fill_new_device_properties(self, dev_name):
4 prop_names = db.get_device_property_list(self.get_name(), "*")
5 prop_values = db.get_device_property(self.get_name(), prop_names.value_string)
6 db.put_device_property(dev_name, prop_values)
7
8 # do the same for attributes...
9 ...
10
11 def Clone(self, dev_name):
12 klass = self.get_device_class()
13 klass.create_device(dev_name, alias=None, cb=self.fill_new_device_properties)
14
15 def DeleteSibling(self, dev_name):
16 klass = self.get_device_class()
17 klass.delete_device(dev_name)
Note that the cb parameter is optional. In the example it is given for demonstration purposes only.