Fraxinus  18.10
An IGT application
cxNetworkHandler.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxNetworkHandler.h"
13 
14 #include <QTimer>
15 
16 #include "igtlioLogic.h"
17 #include "igtlioImageDevice.h"
18 #include "igtlioTransformDevice.h"
19 #include "igtlioStatusDevice.h"
20 #include "igtlioStringDevice.h"
21 
22 #include "igtlioConnector.h"
23 
24 #include "igtlioImageConverter.h"
25 #include "igtlioTransformConverter.h"
26 #include "igtlioCommandConverter.h"
27 #include "igtlioStatusConverter.h"
28 #include "igtlioStringConverter.h"
29 #include "igtlioUsSectorDefinitions.h"
30 
31 #include "cxLogger.h"
32 
33 namespace cx
34 {
35 
36 NetworkHandler::NetworkHandler(igtlioLogicPointer logic) :
37  mTimer(new QTimer(this)),
38  mProbeDefinitionFromStringMessages(ProbeDefinitionFromStringMessagesPtr(new ProbeDefinitionFromStringMessages))
39 {
40  qRegisterMetaType<Transform3D>("Transform3D");
41  qRegisterMetaType<ImagePtr>("ImagePtr");
42 
43  mLogic = logic;
44 
45  this->connectToConnectionEvents();
46  this->connectToDeviceEvents();
47 
48  connect(mTimer, SIGNAL(timeout()), this, SLOT(periodicProcess()));
49  mTimer->start(5);
50 }
51 
53 {
54  mTimer->stop();
55 }
56 
57 igtlioSessionPointer NetworkHandler::requestConnectToServer(std::string serverHost, int serverPort, IGTLIO_SYNCHRONIZATION_TYPE sync, double timeout_s)
58 {
59  mSession = mLogic->ConnectToServer(serverHost, serverPort, sync, timeout_s);
60  return mSession;
61 }
62 
64 {
65  if (mSession->GetConnector() && mSession->GetConnector()->GetState()!=igtlioConnector::STATE_OFF)
66  {
67  CX_LOG_DEBUG() << "NetworkHandler: Disconnecting from server" << mSession->GetConnector()->GetName();
68  igtlioConnectorPointer connector = mSession->GetConnector();
69  connector->Stop();
70  mLogic->RemoveConnector(connector);
71  }
72  mProbeDefinitionFromStringMessages->reset();
73 }
74 
75 void NetworkHandler::onDeviceReceived(vtkObject* caller_device, void* unknown, unsigned long event , void*)
76 {
77  Q_UNUSED(unknown);
78  Q_UNUSED(event);
79  vtkSmartPointer<igtlioDevice> receivedDevice(reinterpret_cast<igtlioDevice*>(caller_device));
80 
81  igtlioBaseConverter::HeaderData header = receivedDevice->GetHeader();
82  std::string device_type = receivedDevice->GetDeviceType();
83 
84 // CX_LOG_DEBUG() << "Device is modified, device type: " << device_type << " on device: " << receivedDevice->GetDeviceName() << " equipmentId: " << header.equipmentId;
85 
86  // Currently the only id available is the Device name defined in PLUS xml. Looking like this: Probe_sToReference_s
87  // Use this for all message types for now, instead of equipmentId.
88  // Anser integration may send equipmentId, so this is checked for when we get a transform.
89  QString deviceName(receivedDevice->GetDeviceName().c_str());
90 
91  if(device_type == igtlioImageConverter::GetIGTLTypeName())
92  {
93  igtlioImageDevicePointer imageDevice = igtlioImageDevice::SafeDownCast(receivedDevice);
94 
95  igtlioImageConverter::ContentData content = imageDevice->GetContent();
96 
97 // QString deviceName(header.deviceName.c_str());
98 // QString deviceName(header.equipmentId.c_str());//Use equipmentId
99  ImagePtr cximage = ImagePtr(new Image(deviceName, content.image));
100  // get timestamp from igtl second-format:;
101  double timestampMS = header.timestamp * 1000;
102  cximage->setAcquisitionTime( QDateTime::fromMSecsSinceEpoch(qint64(timestampMS)));
103  //this->decode_rMd(msg, retval);
104 
105 
106  //Use the igtlio meta data from the image message
107  std::string metaLabel;
108  std::string metaDataValue;
109  QStringList igtlioLabels;
110 
111  igtlioLabels << IGTLIO_KEY_PROBE_TYPE;
112  igtlioLabels << IGTLIO_KEY_ORIGIN;
113  igtlioLabels << IGTLIO_KEY_ANGLES;
114  igtlioLabels << IGTLIO_KEY_BOUNDING_BOX;
115  igtlioLabels << IGTLIO_KEY_DEPTHS;
116  igtlioLabels << IGTLIO_KEY_LINEAR_WIDTH;
117  igtlioLabels << IGTLIO_KEY_SPACING_X;
118  igtlioLabels << IGTLIO_KEY_SPACING_Y;
119  //TODO: Use deciveNameLong when this is defined in IGTLIO and sent with PLUS
120 
121 
122  for (int i = 0; i < igtlioLabels.size(); ++i)
123  {
124  metaLabel = igtlioLabels[i].toStdString();
125  bool gotMetaData = receivedDevice->GetMetaDataElement(metaLabel, metaDataValue);
126  if(!gotMetaData)
127  CX_LOG_WARNING() << "Cannot get needed igtlio meta information: " << metaLabel;
128  else
129  mProbeDefinitionFromStringMessages->parseValue(metaLabel.c_str(), metaDataValue.c_str());
130  }
131 
132 
133  mProbeDefinitionFromStringMessages->setImage(cximage);
134 
135  if (mProbeDefinitionFromStringMessages->haveValidValues() && mProbeDefinitionFromStringMessages->haveChanged())
136  {
137  //TODO: Use deciveNameLong
138  emit probedefinition(deviceName, mProbeDefinitionFromStringMessages->createProbeDefintion(deviceName));
139  }
140 
141  emit image(cximage);
142 
143  // CX-366: Currenly we don't use the transform from the image message, because there is no specification of what this transform should be.
144  // Only the transforms from the transform messages are used.
145 // double timestamp = header.timestamp;
146 // Transform3D cxtransform = Transform3D::fromVtkMatrix(content.transform);
147 // emit transform(deviceName, cxtransform, timestamp);
148  }
149  else if(device_type == igtlioTransformConverter::GetIGTLTypeName())
150  {
151  igtlioTransformDevicePointer transformDevice = igtlioTransformDevice::SafeDownCast(receivedDevice);
152  igtlioTransformConverter::ContentData content = transformDevice->GetContent();
153 
154 // QString deviceName(content.deviceName.c_str());
155 // QString deviceName(header.equipmentId.c_str());//Use equipmentId
156  //QString streamIdTo(content.streamIdTo.c_str());
157  //QString streamIdFrom(content.streamIdFrom.c_str());
158  Transform3D cxtransform = Transform3D::fromVtkMatrix(content.transform);
159 
160 // CX_LOG_DEBUG() << "TRANSFORM: " << " equipmentId: " << header.equipmentId
161 // << " streamIdTo: " << content.streamIdTo
162 // << " streamIdFrom: " << content.streamIdFrom
163 // << " deviceName: " << deviceName
164 // << " transform: " << cxtransform;
165 
166  double timestamp = header.timestamp;
167 // emit transform(deviceName, header.equipmentType, cxtransform, timestamp);
168  //test: Set all messages as type TRACKED_US_PROBE for now
169 // emit transform(deviceName, igtlioBaseConverter::TRACKED_US_PROBE, cxtransform, timestamp);
170 
171  // Try to use equipmentId from OpenIGTLink meta data. If not presnet use deviceName.
172  // Having equipmentId in OpenIGTLink meta data is something we would like to have a part of the OpenIGTLinkIO standard,
173  // and added to the messages from PLUS.
174  std::string openigtlinktransformid;
175  bool gotTransformId = receivedDevice->GetMetaDataElement("equipmentId", openigtlinktransformid);
176 
177  if (gotTransformId)
178  emit transform(qstring_cast(openigtlinktransformid), cxtransform, timestamp);
179  else
180  emit transform(deviceName, cxtransform, timestamp);
181  }
182  else if(device_type == igtlioStatusConverter::GetIGTLTypeName())
183  {
184  igtlioStatusDevicePointer status = igtlioStatusDevice::SafeDownCast(receivedDevice);
185 
186  igtlioStatusConverter::ContentData content = status->GetContent();
187 
188  CX_LOG_DEBUG() << "STATUS: " << " code: " << content.code
189  << " subcode: " << content.subcode
190  << " errorname: " << content.errorname
191  << " statusstring: " << content.statusstring;
192 
193  }
194  else if(device_type == igtlioStringConverter::GetIGTLTypeName())
195  {
196  igtlioStringDevicePointer string = igtlioStringDevice::SafeDownCast(receivedDevice);
197 
198  igtlioStringConverter::ContentData content = string->GetContent();
199 
200 // CX_LOG_DEBUG() << "STRING: " << " equipmentId: " << header.equipmentId
201 // << " encoding: " << content.encoding
202 // << " string: " << content.string_msg;
203 
204  QString message(content.string_msg.c_str());
205 // mProbeDefinitionFromStringMessages->parseStringMessage(header, message);//Turning this off because we want to use meta info instead
206  emit string_message(message);
207  }
208  else
209  {
210  CX_LOG_WARNING() << "Found unhandled devicetype: " << device_type;
211  }
212 
213 }
214 
215 void NetworkHandler::onConnectionEvent(vtkObject* caller, void* connector, unsigned long event , void*)
216 {
217  Q_UNUSED(caller);
218  Q_UNUSED(connector);
219  if (event==igtlioLogic::ConnectionAddedEvent)
220  {
221  emit connected();
222  }
223  if (event==igtlioLogic::ConnectionAboutToBeRemovedEvent)
224  {
225  emit disconnected();
226  }
227 }
228 
229 void NetworkHandler::onDeviceAddedOrRemoved(vtkObject* caller, void* void_device, unsigned long event, void* callData)
230 {
231  Q_UNUSED(caller);
232  Q_UNUSED(callData);
233  if (event==igtlioLogic::NewDeviceEvent)
234  {
235  igtlioDevicePointer device(reinterpret_cast<igtlioDevice*>(void_device));
236  if(device)
237  {
238  CX_LOG_DEBUG() << " NetworkHandler is listening to " << device->GetDeviceName();
239  qvtkReconnect(NULL, device, igtlioDevice::ReceiveEvent, this, SLOT(onDeviceReceived(vtkObject*, void*, unsigned long, void*)));
240  }
241  }
242  if (event==igtlioLogic::RemovedDeviceEvent)
243  {
244  CX_LOG_WARNING() << "TODO: on remove device event, not implemented";
245  }
246 }
247 
248 void NetworkHandler::periodicProcess()
249 {
250  mLogic->PeriodicProcess();
251 }
252 
253 void NetworkHandler::connectToConnectionEvents()
254 {
255  foreach(int eventId, QList<int>()
256  << igtlioLogic::ConnectionAddedEvent
257  << igtlioLogic::ConnectionAboutToBeRemovedEvent
258  )
259  {
260  qvtkReconnect(NULL, mLogic, eventId,
261  this, SLOT(onConnectionEvent(vtkObject*, void*, unsigned long, void*)));
262  }
263 }
264 
265 void NetworkHandler::connectToDeviceEvents()
266 {
267  foreach(int eventId, QList<int>()
268  << igtlioLogic::NewDeviceEvent
269  << igtlioLogic::RemovedDeviceEvent
270  )
271  {
272  qvtkReconnect(NULL, mLogic, eventId,
273  this, SLOT(onDeviceAddedOrRemoved(vtkObject*, void*, unsigned long, void*)));
274  }
275 }
276 
277 } // namespace cx
QString qstring_cast(const T &val)
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
igtlioSessionPointer requestConnectToServer(std::string serverHost, int serverPort=-1, IGTLIO_SYNCHRONIZATION_TYPE sync=IGTLIO_BLOCKING, double timeout_s=5)
void string_message(QString message)
A volumetric data set.
Definition: cxImage.h:45
void transform(QString devicename, Transform3D transform, double timestamp)
void probedefinition(QString devicename, ProbeDefinitionPtr definition)
boost::shared_ptr< class ProbeDefinitionFromStringMessages > ProbeDefinitionFromStringMessagesPtr
#define CX_LOG_DEBUG
Definition: cxLogger.h:95
#define CX_LOG_WARNING
Definition: cxLogger.h:98
NetworkHandler(igtlioLogicPointer logic)
void image(ImagePtr image)
Namespace for all CustusX production code.