Usage of pipes on server side

Dear all,

what is the correct way of retrieving and setting pipes on the server side?
I'm doing the following to set pipe (actually performed inside a Tango callback class)


(device->m_mutex)->lock();
Tango::Pipe& pipe= device->get_device_class()->get_pipe_by_name("myPipe");

pipe.set_name(pipe_name);
pipe.set_root_blob_name("myPipe");
std::vector<std::string> de_names {"x","y"};
pipe.set_data_elt_names(de_names);

double x= 4.5;
double y= 6.7;
pipe << x << y;
(device->m_mutex)->unlock();

Then on the device server class I would like to set the pipe read to the value set above:


void MyDevice::read_myPipe(Tango::Pipe &pipe)
{
  Tango::Pipe& dev_pipe= this->get_device_class()->get_pipe_by_name("myPipe");

  //set pipe to dev_pipe
  //pipe= dev_pipe;               //forbidden ??
  //pipe<< dev_pipe.get_blob();   //throwing error 
}

but I'm missing how to correctly do this latest step.
I'm sure that I do not fully understand how to correctly use the new Pipe feature.

Many thanks for your help,

Simone


PS: Using Tango v9 C++
****************************************************************
Simone Riggi
INAF, Osservatorio Astrofisico di Catania
Via S. Sofia 78
95123, Catania - Italy
phone: +39 095 7332 extension 282
e-mail: simone.riggi@gmail.com,
sriggi@oact.inaf.it
skype: simone.riggi
****************************************************************
Edited 8 years ago
Hi Simone,

I do not really understand what you plan to do especially in your read_myPipe() method.
This method is called when a client is doing a read_pipe() call on a DeviceProxy instance and the object it received
(pipe) is already the pipe object that the client has tried to read. You do not need to call get_pipe_by_name() in this method.

As far as I understand, if what you want to do when the client reads the pipe is to retrieve the value you have inserted
in your callback, I would simply leave the read_myPipe() method empty but be sure that the callback has
been executed first. Note that I give you this advice but I have never tried something like this.

But please note that using Tango 9.1, pipe works if you have only one device in your class! Obviously this is fixed for 9.2

Good luck

Emmanuel
Dear Manu,

thanks for your reply. Yes, you understood correctly what I'm trying to do. I want to set the device pipe using data received in the callback class (the response of an async command). Pipe is read only. Then I want clients to get the pipe I set in the callback when they invoke the read_pipe method.

I did like you suggested:

MyCallBack.cpp

void MyCallBack::cmd_ended(Tango::CmdDoneEvent* event) {
   //… Omitting try and catch blocks…
   Tango::Pipe& pipe= device->get_device_class()->get_pipe_by_name("myPipe");
   pipe.set_root_blob_name("myPipe");
   std::vector<std::string> de_names {"x","y"};
   pipe.set_data_elt_names(de_names);

   double x= 4.5;
   double y= 6.7;
   pipe << x << y;
   
   //…
}

Device class

void MyDevice::read_FinalResponse(Tango::Pipe &pipe){
  //empty…
}

After receiving the event in the callback and setting the pipe, I tried with Jive to execute read_myPipe but I get this exception:

Value for myPipe has not been updated.
Reason - API_PipeValueNotSet

Usually I get this error when I call read_myPipe without prior setting the pipe value, so it seems that I'm not setting the pipe correctly in the callback or that I'm not getting the reference to the pipe object returned by the read method. Infact when I move the callback code (apart frm the first line) inside the read method, I can read the pipe values in the Jive prompt. That's why I was trying to access class pipe from the read method in my previous post.

Any hints?

Simone

****************************************************************
Simone Riggi
INAF, Osservatorio Astrofisico di Catania
Via S. Sofia 78
95123, Catania - Italy
phone: +39 095 7332 extension 282
e-mail: simone.riggi@gmail.com,
sriggi@oact.inaf.it
skype: simone.riggi
****************************************************************
Edited 8 years ago
Hello,

You get this error because there is no data insertion in the pipe in the read_myPipe() method. My previous advice was incorrect.
In fact, it is the same for attribute. You need to set the attribute value in its read() method.

Then, I see two solutions:
- You create your variables x,y in your device, init them in the callback and you move your code which insert the data within the
pipe in the read_myPipe() method.
- In the callback, you prepare the pipe for 3 data elements and you insert the third one in the read_myPipe() method.

Note that the second way is theoretical. I have never tried things like this.

Good luck

Emmanuel
Dear Manu,

many thanks. I tried the first solution and it is working.
Now I tried to insert a nested blob within the pipe following the same approach, but I don't fully understand something. Here is my code:

Device class (define myPipeBlob, x, y as class attributes)

void MyDeviceClass::read_myPipe(Tango::Pipe &pipe)
{
  //Without the first three lines I get segmentation fault (both invalid read and write in valgrind)
  //Without the last line I get an empty blob
  //===============================
  myPipeBlob.set_name("myPipeBlob");
  std::vector<std::string> de_names {"x","y"};
  myPipeBlob.set_data_elt_names(de_names);
  myPipeBlob << x << y;
  //================================
  
  pipe.set_root_blob_name("myPipe");
  std::vector<std::string> blob_names {"myPipeBlob"};
  pipe.set_data_elt_names(blob_names);
  pipe<<myPipeBlob;
}

CallBack class

void MyCallBack::cmd_ended(Tango::CmdDoneEvent* event)
{
  (device->m_mutex)->lock();
  Tango::Pipe& pipe= device->get_device_class()->get_pipe_by_name("myPipe");
 
  //Set blob
  (device->myPipeBlob).set_name("myPipeBlob");
  std::vector<std::string> de_names {"x","y"};
  (device->myPipeBlob).set_data_elt_names(de_names);

  device->x= 4.5;
  device->y= 6.7;
  (device->myPipeBlob) << device->x << device->y;

  //Set pipe
  pipe.set_root_blob_name("myPipe");
  std::vector<std::string> blob_names {"myPipeBlob"};
  pipe.set_data_elt_names(blob_names);
  pipe << device->myPipeBlob;

  (device->m_mutex)->unlock();

My doubt is: if I init and fill the DevicePipeBlob in the callback why do I need to do that again in the read_pipe?
Is the blob reset after the callback?

Many thanks again for your help,

Simone
****************************************************************
Simone Riggi
INAF, Osservatorio Astrofisico di Catania
Via S. Sofia 78
95123, Catania - Italy
phone: +39 095 7332 extension 282
e-mail: simone.riggi@gmail.com,
sriggi@oact.inaf.it
skype: simone.riggi
****************************************************************
Hi Simone,

I guess your device data member myPipeBlob is of type DevicePipeBlob.
You insert some value inside this blob in your call back. Great.
But I won't insert the blob into the pipe in the callback.
I would do this in the read_myPipe() method.

Therefore, my advice is that you remove the second line of the callback plus the last four (keep the mutex unlock)
In your read_myPipe() method, remove the four first lines (because the blob is already initialized) but be sure that the
callback is executed before the pipe is read by the client

Hoping this help

Emmanuel
Thanks Manu,

it worked. So at the end in the callback I fill the pipe blob and also emit pipe events. In the device I fill the pipe using the already filled pipe blob in the read_XXX method.

Thanks again for your help,

Simone
****************************************************************
Simone Riggi
INAF, Osservatorio Astrofisico di Catania
Via S. Sofia 78
95123, Catania - Italy
phone: +39 095 7332 extension 282
e-mail: simone.riggi@gmail.com,
sriggi@oact.inaf.it
skype: simone.riggi
****************************************************************
 
Register or login to create to post a reply.