Read Attribute from another

I'm writing a driver device for an UPS.
is it possible call, for example, read_Attribute2((Tango::Attribute &attr) from read_Attribute1()? or read Attribute from always_executed_hook()

The class Tango::Attribute has got attribute value but it's protected, so I may not able to read it.
How can I do?

I could write a generic method to read the physical value end recall it in read_Attribute but but so it is trivial.

Thanks,
Salvo
Hi Salvo.

Salvo
I could write a generic method to read the physical value end recall it in read_Attribute but but so it is trivial.

I think that's the easiest. That's what I would do if I were you.

You cannot really invoke the read_Attribute2(Tango::Attribute &attr) method from read_Attribute1() or from within your device server directly and easily. These methods are usually invoked at some point when a CORBA query to read these attributes is received but many other methods are also invoked on the way.

If you want to read Attribute2 from read_Attribute1(), you can use a DeviceProxy on yourself and do a classical read_attribute client call:
//——————————————————–
/**
* Method : MyDeviceServer::init_device()
* Description : will be called at device initialization.
*/
//——————————————————–
void MyDeviceServer::init_device()
{
DEBUG_STREAM << "MyDeviceServer::init_device() create device " << device_name << endl;
/*—– PROTECTED REGION ID(MyDeviceServer::init_device_before) ENABLED START —–*/

// Initialization before get_device_property() call

/*—– PROTECTED REGION END —–*/ // Youpla::init_device_before

// No device property to be read from database

attr_Attribute1_read = new Tango::DevDouble[1];
attr_Attribute2_read = new Tango::DevDouble[1];
/*—– PROTECTED REGION ID(Youpla::init_device) ENABLED START —–*/

// Initialize device
*attr_Attribute1_read = 1.0;
*attr_Attribute2_read = 2.0;

myself = std::make_unique<Tango::DeviceProxy>(device_name);
// myself = new Tango::DeviceProxy(device_name); // if you are compiling with std < c++14

/*—– PROTECTED REGION END —–*/ // MyDeviceServer::init_device
}

//——————————————————–
/**
* Read attribute Attribute1 related method
* Description:
*
* Data type: Tango::DevDouble
* Attr type: Scalar
*/
//——————————————————–
void MyDeviceServer::read_Attribute1(Tango::Attribute &attr)
{
DEBUG_STREAM << "MyDeviceServer::read_Attribute1(Tango::Attribute &attr) entering… " << endl;
/*—– PROTECTED REGION ID(MyDeviceServer::read_Attribute1) ENABLED START —–*/
try
{
Tango::DeviceAttribute attr2_reply = myself->read_attribute("Attribute2");
Tango::DevDouble attr2_value = 0.0;
attr2_reply >> attr2_value;
*attr_Attribute1_read = attr2_value * 2.0; // Example if we want to have Attribute1 value = double of Attribute2 value
}
catch(Tango::DevFailed &e)
{
Tango::Except::print_exception(e);
Tango::Except::re_throw_exception(e,"Attribute2_Reading_failure","Exception while reading Attribute 2","read_Attribute1()");
}

// Set the attribute value
attr.set_value(attr_Attribute1_read);

/*—– PROTECTED REGION END —–*/ // MyDeviceServer::read_Attribute1
}


And in MyDeviceServer.h:


// Add your own data members
private:
std::unique_ptr<Tango::DeviceProxy> myself;
// Tango::DeviceProxy * myself; // If you are compiling with std < c++14


But you cannot use that method to read Attribute2 from always_executed_hook() nor from read_attr_hardware() method because you would end up with an infinite loop and a crash of the device server because always_executed_hook() would be called as well again when trying to read Attribute2. You would need to use some tricks to detect that always_executed_hook() has already been invoked to avoid to read Attribute 2 again.

So, I think the best way is what you suggested in the end: to write a generic method to read the physical value end recall it in read_Attribute (or always_executed_hook() or read_attr_hardware()).
Another simple way is to store the Attribute1 last read value in a variable.
Usually Pogo gives you one, like attr_Attribute1_read.

If you poll Attribute1 and if you're fine with having an Attribute1 value which can be as old as the polling period, you can simply use that variable to get the latest Attribute1 read value.
Rosenberg's Law: Software is easy to make, except when you want it to do something new.
Corollary: The only software that's worth making is software that does something new.
Please also note that when reading the Attribute2 with the DeviceProxy on yourself method, by default, you will read with DeviceProxy source = Tango::CACHE_DEV, which means that if Attribute1 is polled, you will get by default the last value read during last polling for Attribute1 and read_Attribute1(Tango::Attribute &attr) might not be executed again.

If you want to really force the read_Attribute1(Tango::Attribute &attr) method execution, you would need to use Tango::DEV as source for the DeviceProxy:

myself->set_source(Tango::DEV)
Rosenberg's Law: Software is easy to make, except when you want it to do something new.
Corollary: The only software that's worth making is software that does something new.
Hi Reynald,

it is a general need to be able to read attributes inside the device server class. Is it possible to generalise your suggestion using the high level api proposed by Michal or alternatively by providing a simple api to calling the read_Attribute() methods? We should discuss this in the next kernel developers meeting.

Cheers

Andy
thank Reynald, you were very clear
 
Register or login to create to post a reply.