|
|
# Tango guidelines
|
|
|
|
|
|
Tango development guidelines for the bliss project. |
|
|
\ No newline at end of file |
|
|
Tango development guidelines within the bliss project.
|
|
|
|
|
|
## General
|
|
|
|
|
|
Writing tango (server and/or client) can be done for the following (non exclusive) purposes:
|
|
|
|
|
|
1. provide remote access to the bliss system in spec
|
|
|
2. provide remote access within bliss to some specific functionality
|
|
|
|
|
|
As an example of use-case 1 you have need to access from spec the bliss motion (system). For this purpose, a device server type (``BlissAxisManager``) has been written which exposes the motion functionality to spec. When writing a tango server to be accessed from spec you need to be aware of some constraints:
|
|
|
|
|
|
* spec does not support tango events
|
|
|
* spec does not support tango pipes
|
|
|
* spec has limited support for complex tango attribute types like long-string or double-string arrays
|
|
|
* spec does not support tango encoded data type
|
|
|
* If an attribute uses a special encoding (ex a string attribute being filled with JSON data),
|
|
|
decoding needs to be done with specific macros
|
|
|
|
|
|
As an example of use-case 2 you have the case of the ct2 (P201/C208) PCI card. An instance of bliss might be running on the Industrial PC where the card is installed but the bliss session that *controls* the experiment might run in the
|
|
|
beamline control workstation. The bliss session accesses the card through a tango client object that mimics the API of the local P201 card API used by the tango server that runs on the Industrial PC.
|
|
|
|
|
|
## Guidelines
|
|
|
|
|
|
### tango server executables:
|
|
|
* should be placed in the `tango/` directory
|
|
|
* preferably a python executable without extension (using python shebang: `#!/usr/bin/env python`)
|
|
|
|
|
|
### tango server code
|
|
|
* should be placed in `bliss/tango/servers`
|
|
|
* logic should be implemented in bliss; tango classes should have a minimum of logic
|
|
|
* if tango class is developed to provide access to spec:
|
|
|
* provide minimum attributes & commands to make it happen
|
|
|
* write a macro in `spec/`
|
|
|
* if tango class is developed to provide bliss with *remote* access to
|
|
|
bliss class (ex: PCI card):
|
|
|
* server API (+ optional tango client class) should be developed
|
|
|
in the sense of providing the same API as original bliss class.
|
|
|
|
|
|
### Example
|
|
|
|
|
|
*write a device class Potentiostat exposing bliss biologic potentiostat.
|
|
|
Also provide an executable capable of running a DS with class Potentiostat*
|
|
|
|
|
|
**bliss/controllers/potentiostat/biologic.py**
|
|
|
|
|
|
```python
|
|
|
class Potentiostat:
|
|
|
def is_channel_plugged(self, channel):
|
|
|
...
|
|
|
def start_channel(self, channel):
|
|
|
...
|
|
|
```
|
|
|
|
|
|
**bliss/tango/servers/potentiostat/biologic.py** module
|
|
|
```python
|
|
|
from PyTango.server import Device, DeviceMeta
|
|
|
|
|
|
from bliss.controllers.potentiostat import biologic
|
|
|
|
|
|
class Potentiostat(Device):
|
|
|
__metaclass__ = DeviceMeta
|
|
|
|
|
|
def init_device(self):
|
|
|
Device.init_device(self)
|
|
|
self.__potentiostat = biologic.Potentiostat()
|
|
|
|
|
|
@command(dtype_in=int, dtype_out=bool)
|
|
|
def is_channel_plugged(self, channel):
|
|
|
return self.__potentiostat.is_channel_plugged()
|
|
|
|
|
|
@command(dtype_in=int)
|
|
|
def start_channel(self, channel):
|
|
|
self.__potentiostat.start_channel(channel)
|
|
|
|
|
|
|
|
|
def main():
|
|
|
from PyTango import GreenMode
|
|
|
from PyTango.server import run
|
|
|
run([Potentiostat,], green_mode=GreenMode.Gevent)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
main()
|
|
|
```
|
|
|
|
|
|
**tango/Potentiostat** executable
|
|
|
```python
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
from bliss.tango.servers.biologic.potentiostat import main()
|
|
|
main()
|
|
|
```
|
|
|
|
|
|
With this approach it becomes simple to create a new server with multiple classes. Example:
|
|
|
|
|
|
**my_server**
|
|
|
```python
|
|
|
#!/usr/bin/env python
|
|
|
from bliss.tango.servers.biologic.potentiostat import Potentiostat
|
|
|
from bliss.tango.servers.musst import Musst
|
|
|
|
|
|
from PyTango import GreenMode
|
|
|
from PyTango.server import run
|
|
|
run([Potentiostat, Musst], green_mode=GreenMode.Gevent)
|
|
|
```
|
|
|
|
|
|
We can even invent a **Bliss** server which can expose all known bliss classes :-)
|
|
|
|
|
|
\ No newline at end of file |