CustusX  18.04-rc6
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 "igtlioCommandDevice.h"
20 #include "igtlioStatusDevice.h"
21 #include "igtlioStringDevice.h"
22 
23 #include "igtlioConnector.h"
24 
25 #include "igtlioImageConverter.h"
26 #include "igtlioTransformConverter.h"
27 #include "igtlioCommandConverter.h"
28 #include "igtlioStatusConverter.h"
29 #include "igtlioStringConverter.h"
30 
31 #include "cxLogger.h"
32 
33 namespace cx
34 {
35 
36 NetworkHandler::NetworkHandler(igtlio::LogicPointer 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 igtlio::SessionPointer 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()!=igtlio::Connector::STATE_OFF)
66  {
67  CX_LOG_DEBUG() << "NetworkHandler: Disconnecting from server" << mSession->GetConnector()->GetName();
68  igtlio::ConnectorPointer connector = mSession->GetConnector();
69  if(connector->GetState() != igtlio::Connector::STATE_WAIT_CONNECTION) //Don't try to stop connection while in STATE_WAIT_CONNECTION.
70  {
71  connector->Stop();//This takes to long if connect isn't finished (because mutex is blocking)
72  }
73  else
74  {
75  connector->SetServerStopFlag(true); //Just setting stop flag should also stop the server
76  }
77  mLogic->RemoveConnector(connector);
78  }
79  mProbeDefinitionFromStringMessages->reset();
80 }
81 
82 void NetworkHandler::onDeviceReceived(vtkObject* caller_device, void* unknown, unsigned long event , void*)
83 {
84  Q_UNUSED(unknown);
85  Q_UNUSED(event);
86  vtkSmartPointer<igtlio::Device> receivedDevice(reinterpret_cast<igtlio::Device*>(caller_device));
87 
88  igtlio::BaseConverter::HeaderData header = receivedDevice->GetHeader();
89  std::string device_type = receivedDevice->GetDeviceType();
90 
91 // CX_LOG_DEBUG() << "Device is modified, device type: " << device_type << " on device: " << receivedDevice->GetDeviceName() << " equipmentId: " << header.equipmentId;
92 
93  // Currently the only id available is the Device name defined in PLUS xml. Looking like this: Probe_sToReference_s
94  // Use this for all message types for now, instead of equipmentId.
95  // Anser integration may send equipmentId, so this is checked for when we get a transform.
96  QString deviceName(receivedDevice->GetDeviceName().c_str());
97 
98  if(device_type == igtlio::ImageConverter::GetIGTLTypeName())
99  {
100  igtlio::ImageDevicePointer imageDevice = igtlio::ImageDevice::SafeDownCast(receivedDevice);
101 
102  igtlio::ImageConverter::ContentData content = imageDevice->GetContent();
103 
104 // QString deviceName(header.deviceName.c_str());
105 // QString deviceName(header.equipmentId.c_str());//Use equipmentId
106  ImagePtr cximage = ImagePtr(new Image(deviceName, content.image));
107  // get timestamp from igtl second-format:;
108  double timestampMS = header.timestamp * 1000;
109  cximage->setAcquisitionTime( QDateTime::fromMSecsSinceEpoch(qint64(timestampMS)));
110  //this->decode_rMd(msg, retval);
111 
112  mProbeDefinitionFromStringMessages->setImage(cximage);
113 
114  if (mProbeDefinitionFromStringMessages->haveValidValues() && mProbeDefinitionFromStringMessages->haveChanged())
115  {
116 // QString deviceName(header.deviceName.c_str());
117 // QString deviceName(header.equipmentId.c_str());//Use equipmentId instead?
118 
119  emit probedefinition(deviceName, mProbeDefinitionFromStringMessages->createProbeDefintion(deviceName));
120  }
121 
122 
123  emit image(cximage);
124  }
125  else if(device_type == igtlio::TransformConverter::GetIGTLTypeName())
126  {
127  igtlio::TransformDevicePointer transformDevice = igtlio::TransformDevice::SafeDownCast(receivedDevice);
128  igtlio::TransformConverter::ContentData content = transformDevice->GetContent();
129 
130 // QString deviceName(content.deviceName.c_str());
131 // QString deviceName(header.equipmentId.c_str());//Use equipmentId
132  //QString streamIdTo(content.streamIdTo.c_str());
133  //QString streamIdFrom(content.streamIdFrom.c_str());
134  Transform3D cxtransform = Transform3D::fromVtkMatrix(content.transform);
135 
136 // CX_LOG_DEBUG() << "TRANSFORM: " << " equipmentId: " << header.equipmentId
137 // << " streamIdTo: " << content.streamIdTo
138 // << " streamIdFrom: " << content.streamIdFrom
139 // << " deviceName: " << deviceName
140 // << " transform: " << cxtransform;
141 
142  double timestamp = header.timestamp;
143 // emit transform(deviceName, header.equipmentType, cxtransform, timestamp);
144  //test: Set all messages as type TRACKED_US_PROBE for now
145 // emit transform(deviceName, igtlio::BaseConverter::TRACKED_US_PROBE, cxtransform, timestamp);
146 
147  // Try to use equipmentId from OpenIGTLink meta data. If not presnet use deviceName.
148  // Having equipmentId in OpenIGTLink meta data is something we would like to have a part of the OpenIGTLinkIO standard,
149  // and added to the messages from PLUS.
150  std::string openigtlinktransformid;
151  bool gotTransformId = receivedDevice->GetMetaDataElement("equipmentId", openigtlinktransformid);
152 
153  if (gotTransformId)
154  emit transform(qstring_cast(openigtlinktransformid), cxtransform, timestamp);
155  else
156  emit transform(deviceName, cxtransform, timestamp);
157  }
158  else if(device_type == igtlio::CommandConverter::GetIGTLTypeName())
159  {
160  CX_LOG_DEBUG() << "Received command message.";
161  igtlio::CommandDevicePointer command = igtlio::CommandDevice::SafeDownCast(receivedDevice);
162 
163  igtlio::CommandConverter::ContentData content = command->GetContent();
164  CX_LOG_DEBUG() << "COMMAND: " << " id: " << content.id
165  << " name: " << content.name
166  << " content: " << content.content;
167  QString deviceName(content.name.c_str());
168  QString xml(content.content.c_str());
169  emit commandRespons(deviceName, xml);
170 
171  }
172  else if(device_type == igtlio::StatusConverter::GetIGTLTypeName())
173  {
174  igtlio::StatusDevicePointer status = igtlio::StatusDevice::SafeDownCast(receivedDevice);
175 
176  igtlio::StatusConverter::ContentData content = status->GetContent();
177 
178  CX_LOG_DEBUG() << "STATUS: " << " code: " << content.code
179  << " subcode: " << content.subcode
180  << " errorname: " << content.errorname
181  << " statusstring: " << content.statusstring;
182 
183  }
184  else if(device_type == igtlio::StringConverter::GetIGTLTypeName())
185  {
186  igtlio::StringDevicePointer string = igtlio::StringDevice::SafeDownCast(receivedDevice);
187 
188  igtlio::StringConverter::ContentData content = string->GetContent();
189 
190 // CX_LOG_DEBUG() << "STRING: " << " equipmentId: " << header.equipmentId
191 // << " encoding: " << content.encoding
192 // << " string: " << content.string_msg;
193 
194  QString message(content.string_msg.c_str());
195  mProbeDefinitionFromStringMessages->parseStringMessage(header, message);
196  emit string_message(message);
197  }
198  else
199  {
200  CX_LOG_WARNING() << "Found unhandled devicetype: " << device_type;
201  }
202 
203 }
204 
205 void NetworkHandler::onConnectionEvent(vtkObject* caller, void* connector, unsigned long event , void*)
206 {
207  Q_UNUSED(caller);
208  Q_UNUSED(connector);
209  if (event==igtlio::Logic::ConnectionAddedEvent)
210  {
211  emit connected();
212  }
213  if (event==igtlio::Logic::ConnectionAboutToBeRemovedEvent)
214  {
215  emit disconnected();
216  }
217 }
218 
219 void NetworkHandler::onDeviceAddedOrRemoved(vtkObject* caller, void* void_device, unsigned long event, void* callData)
220 {
221  Q_UNUSED(caller);
222  Q_UNUSED(callData);
223  if (event==igtlio::Logic::NewDeviceEvent)
224  {
225  igtlio::DevicePointer device(reinterpret_cast<igtlio::Device*>(void_device));
226  if(device)
227  {
228  CX_LOG_DEBUG() << " NetworkHandler is listening to " << device->GetDeviceName();
229  qvtkReconnect(NULL, device, igtlio::Device::ReceiveEvent, this, SLOT(onDeviceReceived(vtkObject*, void*, unsigned long, void*)));
230  }
231  }
232  if (event==igtlio::Logic::RemovedDeviceEvent)
233  {
234  CX_LOG_WARNING() << "TODO: on remove device event, not implemented";
235  }
236 }
237 
238 void NetworkHandler::periodicProcess()
239 {
240  mLogic->PeriodicProcess();
241 }
242 
243 void NetworkHandler::connectToConnectionEvents()
244 {
245  foreach(int eventId, QList<int>()
246  << igtlio::Logic::ConnectionAddedEvent
247  << igtlio::Logic::ConnectionAboutToBeRemovedEvent
248  )
249  {
250  qvtkReconnect(NULL, mLogic, eventId,
251  this, SLOT(onConnectionEvent(vtkObject*, void*, unsigned long, void*)));
252  }
253 }
254 
255 void NetworkHandler::connectToDeviceEvents()
256 {
257  foreach(int eventId, QList<int>()
258  << igtlio::Logic::NewDeviceEvent
259  << igtlio::Logic::RemovedDeviceEvent
260  )
261  {
262  qvtkReconnect(NULL, mLogic, eventId,
263  this, SLOT(onDeviceAddedOrRemoved(vtkObject*, void*, unsigned long, void*)));
264  }
265 }
266 
267 } // namespace cx
QString qstring_cast(const T &val)
void commandRespons(QString devicename, QString xml)
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
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(igtlio::LogicPointer logic)
igtlio::SessionPointer requestConnectToServer(std::string serverHost, int serverPort=-1, igtlio::SYNCHRONIZATION_TYPE sync=igtlio::BLOCKING, double timeout_s=5)
void image(ImagePtr image)
Namespace for all CustusX production code.