PyTango Groups API

I have the following in another thread, but I now believe the issue was not my device inheritance, but an API problem.

Assuming a hierarchy, where the parent class is called STATION, and within this station are a multitude of equivalent devices of the class SUBSTATION.

I am using Tango grouping to be able to communicate with all substations from my main station class. Adding/removing SUBSTATION devices to the STATION is not a problem. I now want to run a particular command on all SUBSTATION within my STATION, with something like:

replies = self.station_devices.command_inout(fnName, fnInput)

I am following the API here.

However I get the following error:
PyTango.DevFailed: DevFailed[
DevError[
    desc = ArgumentError: Python argument types in
               __Group.command_inout_asynch(__Group, str, str)
           did not match C++ signature:
               command_inout_asynch(Tango::Group {lvalue} self, std::string cmd_name, std::vector<Tango::DeviceData, std::allocator<Tango::DeviceData> > param, bool forget=False, bool forward=True)
               command_inout_asynch(Tango::Group {lvalue} self, std::string cmd_name, Tango::DeviceData param, bool forget=False, bool forward=True)
               command_inout_asynch(Tango::Group {lvalue} self, std::string cmd_name, bool forget=False, bool forward=True)

It seems Tango is expecting a certain type for "param", however the API doc says this "param" could be of any type.

Upon some investigation, I can see that group.py contains the method:
    def command_inout(self, cmd_name, param=None, forward=True):
        if param is None:
            idx = self.command_inout_asynch(cmd_name, forget=False, forward=forward)
        else:
            idx = self.command_inout_asynch(cmd_name, param, forget=False, forward=forward)
        return self.command_inout_reply(idx)

The command_inout_asynch is called from the __Group class (the actual C++ Tango), where the method signature is as follows:

 def command_inout_asynch(self, cmd_name, forget=False, forward=True, reserved=-1)

It seems to me that calling commands for a group will currently only work in PyTango if no input parameters are required. The equivalent call for calling group commands with input parameters (translated to DeviceData in the C++ layer) is not yet implemented.

Any help appreciated.

Cheers,
Andrea
Dr Andrea DeMarco, BSc (Hons) (Melita), MSc (Melita), DPhil (UEA)
Lecturer | Researcher
Department of Physics
Institute of Space Sciences and Astronomy

Room 220, Maths and Physics Building
University of Malta, Msida MSD2080, MALTA
Bumping this - can anybody give me an example for supplying command arguments to group command calls in PyTango 8.1.6?

The group commands seem to work when no input is required, but any attempt at an input results in the error reported above.

Update:

It seems that converting my input to a DeviceData object makes the group call work e.g.

dd = PyTango.DeviceData()
dd.insert(PyTango.DevString, cmd_args)
group_replies = group_proxy.command_inout(command, dd)

Otherwise, trying:
group_replies = group_proxy.command_inout(command, cmd_args)

Will not automatically convert cmd_args to a DeviceData object. The documentation for PyTango however seems to suggest otherwise:

command_inout(self, cmd_name, forward=True) → sequence<GroupCmdReply>
command_inout (self, cmd_name, param, forward=True) -> sequence<GroupCmdReply>
command_inout (self, cmd_name, param_list, forward=True) -> sequence<GroupCmdReply>

Just a shortcut to do:
self.command_inout_reply(self.command_inout_asynch(…))
Parameters:
cmd_name: (str) Command name
param: (any) parameter value
param_list: (PyTango.DeviceDataList) sequence of parameters. When given, it’s length must match the group size.
forward: (bool) If it is set to true (the default) request is forwarded to subgroups. Otherwise, it is only applied to the local set of devices.

Cheers,
Andrea
Dr Andrea DeMarco, BSc (Hons) (Melita), MSc (Melita), DPhil (UEA)
Lecturer | Researcher
Department of Physics
Institute of Space Sciences and Astronomy

Room 220, Maths and Physics Building
University of Malta, Msida MSD2080, MALTA
Edited 7 years ago
Hi drea,


# example: Devices with a command 'set_data(float)'

import PyTango
g = PyTango.Group("my_group")
g.add("a/b/c")
g.add("b/c/d")

# execute a command with the same parameter value for all devices in the group
data = PyTango.DeviceData()
data.insert(PyTango.DevDouble, 1.234)
g.command_inout("set_data", data)

# execute a command with different parameter values, one for each device in the group
data_list = PyTango.DeviceDataList()
data_list.append(PyTango.DevDouble, 1.234)
data_list.append(PyTango.DevDouble, 4.321)
g.command_inout("set_data", data_list)


I have to admit PyTango is not consistent here. For DeviceProxy.command_inout PyTango is hiding the C++ DeviceData object but for groups it is not.

May I suggest that you file a bug report in: PyTango github issues.
..or a merge request with a patch smile

Hope it helps


Edited 7 years ago
Hi Thaigo,

Thanks for your notes, in fact this solution (with a DeviceData object) works!

Thank you for your help.

Drea
Dr Andrea DeMarco, BSc (Hons) (Melita), MSc (Melita), DPhil (UEA)
Lecturer | Researcher
Department of Physics
Institute of Space Sciences and Astronomy

Room 220, Maths and Physics Building
University of Malta, Msida MSD2080, MALTA
 
Register or login to create to post a reply.