20 #include <itkMutexLockHolder.h>
21 #include <itksys/SystemTools.hxx>
24 #include <igtlTransformMessage.h>
27 #include <igtl_status.h>
30 #include <igtlTrackingDataMessage.h>
39 m_Name(
"Unspecified Device"),
40 m_StopCommunication(false),
41 m_Hostname(
"127.0.0.1"),
43 m_MultiThreader(nullptr), m_SendThreadID(0), m_ReceiveThreadID(0), m_ConnectThreadID(0)
45 m_ReadFully = ReadFully;
67 if (GetState() == Running)
69 this->StopCommunication();
70 this->CloseConnection();
72 else if (GetState() == Ready)
74 this->CloseConnection();
77 if (m_MultiThreader.IsNotNull())
79 if ((m_SendThreadID != 0))
81 m_MultiThreader->TerminateThread(m_SendThreadID);
83 if ((m_ReceiveThreadID != 0))
85 m_MultiThreader->TerminateThread(m_ReceiveThreadID);
87 if ((m_ConnectThreadID != 0))
89 m_MultiThreader->TerminateThread(m_ConnectThreadID);
92 m_MultiThreader =
nullptr;
103 itkDebugMacro(
"setting m_State to " << state);
105 m_StateMutex->Lock();
108 if (m_State == state)
110 m_StateMutex->Unlock();
114 m_StateMutex->Unlock();
130 headerMsg->InitPack();
134 socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(), 0);
144 return IGTL_STATUS_NOT_PRESENT;
149 return IGTL_STATUS_TIME_OUT;
151 else if (r == headerMsg->GetPackSize())
155 int crcCheck = headerMsg->Unpack(1);
157 if (crcCheck & igtl::MessageHeader::UNPACK_HEADER)
167 headerMsg->GetTimeStamp(ts);
168 ts->GetTimeStamp(&sec, &nanosec);
182 const char* curDevType = headerMsg->GetDeviceType();
183 if (std::strstr(curDevType,
"GET_") !=
nullptr ||
184 std::strstr(curDevType,
"STP_") !=
nullptr ||
185 std::strstr(curDevType,
"RTS_") !=
nullptr)
187 this->m_MessageQueue->PushCommandMessage(headerMsg);
188 this->InvokeEvent(CommandReceivedEvent());
189 return IGTL_STATUS_OK;
194 curMessage = m_MessageFactory->CreateInstance(headerMsg);
198 if (curMessage.IsNull())
200 socket->Skip(headerMsg->GetBodySizeToRead(), 0);
203 return IGTL_STATUS_NOT_FOUND;
207 curMessage->SetMessageHeader(headerMsg);
208 curMessage->AllocatePack();
211 int receiveCheck = 0;
212 receiveCheck = socket->Receive(curMessage->GetPackBodyPointer(),
213 curMessage->GetPackBodySize(), m_ReadFully);
215 if (receiveCheck > 0)
217 int c = curMessage->Unpack(1);
218 if (!(c & igtl::MessageHeader::UNPACK_BODY))
220 return IGTL_STATUS_CHECKSUM_ERROR;
228 if (std::strstr(curDevType,
"STT_") !=
nullptr)
230 this->m_MessageQueue->PushCommandMessage(curMessage);
231 this->InvokeEvent(CommandReceivedEvent());
235 this->m_MessageQueue->PushMessage(curMessage);
236 this->InvokeEvent(MessageReceivedEvent());
238 return IGTL_STATUS_OK;
242 MITK_ERROR(
"IGTLDevice") <<
"Received a valid header but could not "
243 <<
"read the whole message.";
244 return IGTL_STATUS_UNKNOWN_ERROR;
251 return IGTL_STATUS_CHECKSUM_ERROR;
259 return IGTL_STATUS_UNKNOWN_ERROR;
271 m_MessageQueue->PushSendMessage(msg);
280 MITK_ERROR(
"IGTLDevice") <<
"Could not send message because message is not "
281 "valid. Please check.";
286 msg->SetDeviceName(this->
GetName().c_str());
291 int sendSuccess = socket->Send(msg->GetPackPointer(), msg->GetPackSize());
295 this->InvokeEvent(MessageSentEvent());
296 return IGTL_STATUS_OK;
300 return IGTL_STATUS_UNKNOWN_ERROR;
306 if (this->GetState() != Running)
316 bool localStopCommunication;
319 this->m_StopCommunicationMutex->Lock();
320 localStopCommunication = this->m_StopCommunication;
321 this->m_StopCommunicationMutex->Unlock();
322 while ((this->GetState() == Running) && (localStopCommunication ==
false))
324 (this->*ComFunction)();
327 this->m_StopCommunicationMutex->Lock();
328 localStopCommunication = m_StopCommunication;
329 this->m_StopCommunicationMutex->Unlock();
332 itksys::SystemTools::Delay(1);
338 this->StopCommunication();
339 MITK_ERROR(
"IGTLDevice::RunCommunication") <<
"Error while communicating. Thread stopped.";
345 MITK_DEBUG(
"IGTLDevice::RunCommunication") <<
"Reached end of communication.";
353 if (this->GetState() != Ready)
357 this->SetState(Running);
363 this->m_StopCommunicationMutex->Lock();
364 this->m_StopCommunication =
false;
365 this->m_StopCommunicationMutex->Unlock();
368 m_SendingFinishedMutex->Unlock();
369 m_ReceivingFinishedMutex->Unlock();
370 m_ConnectingFinishedMutex->Unlock();
374 m_MultiThreader->SpawnThread(this->ThreadStartSending,
this);
376 m_MultiThreader->SpawnThread(this->ThreadStartReceiving,
this);
378 m_MultiThreader->SpawnThread(this->ThreadStartConnecting,
this);
385 if (this->GetState() == Running)
389 m_StopCommunicationMutex->Lock();
390 m_StopCommunication =
true;
391 m_StopCommunicationMutex->Unlock();
394 m_SendingFinishedMutex->Lock();
395 m_ReceivingFinishedMutex->Lock();
396 m_ConnectingFinishedMutex->Lock();
400 this->SetState(Ready);
407 if (this->GetState() ==
Setup)
411 else if (this->GetState() == Running)
413 this->StopCommunication();
416 m_Socket->CloseSocket();
419 this->SetState(
Setup);
430 std::string returnType(
"RTS_");
431 returnType.append(type);
434 this->m_MessageFactory->CreateInstance(returnType);
437 if (rtsMsg.IsNotNull())
439 this->SendMessage(rtsMsg);
455 return this->m_MessageQueue->PullImage2dMessage();
460 return this->m_MessageQueue->PullImage3dMessage();
465 return this->m_MessageQueue->PullTransformMessage();
476 return this->m_MessageQueue->PullStringMessage();
481 return this->m_MessageQueue->PullMiscMessage();
486 return m_MessageQueue->PullCommandMessage();
493 queue->EnableInfiniteBuffering(enable);
499 struct itk::MultiThreader::ThreadInfoStruct * pInfo =
500 (
struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
501 if (pInfo ==
nullptr)
503 return ITK_THREAD_RETURN_VALUE;
505 if (pInfo->UserData ==
nullptr)
507 return ITK_THREAD_RETURN_VALUE;
510 if (igtlDevice !=
nullptr)
514 igtlDevice->m_SendThreadID = 0;
515 return ITK_THREAD_RETURN_VALUE;
521 struct itk::MultiThreader::ThreadInfoStruct * pInfo =
522 (
struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
523 if (pInfo ==
nullptr)
525 return ITK_THREAD_RETURN_VALUE;
527 if (pInfo->UserData ==
nullptr)
529 return ITK_THREAD_RETURN_VALUE;
532 if (igtlDevice !=
nullptr)
537 igtlDevice->m_ReceiveThreadID = 0;
538 return ITK_THREAD_RETURN_VALUE;
544 struct itk::MultiThreader::ThreadInfoStruct * pInfo =
545 (
struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
546 if (pInfo ==
nullptr)
548 return ITK_THREAD_RETURN_VALUE;
550 if (pInfo->UserData ==
nullptr)
552 return ITK_THREAD_RETURN_VALUE;
555 if (igtlDevice !=
nullptr)
560 igtlDevice->m_ConnectThreadID = 0;
561 return ITK_THREAD_RETURN_VALUE;
itk::FastMutexLock::Pointer m_ReceivingFinishedMutex
itk::FastMutexLock::Pointer m_StopCommunicationMutex
virtual igtl::MessageBase::Pointer GetMessage() const
returns the OpenIGTLink message
mitk::IGTLMessageFactory::Pointer m_MessageFactory
itk::SmartPointer< Self > Pointer
void SetState(IGTLDeviceState state)
change object state
static ITK_THREAD_RETURN_TYPE ThreadStartConnecting(void *data)
static start method for the connection thread.
bool StartCommunication()
Starts the communication between the two devices.
IGTLDeviceState GetState() const
Returns current object state (Setup, Ready or Running)
igtl::MessageBase::Pointer GetNextMiscMessage()
itk::FastMutexLock::Pointer m_StateMutex
unsigned int SendMessagePrivate(igtl::MessageBase::Pointer msg, igtl::Socket::Pointer socket)
Sends a message.
static const int SOCKET_SEND_RECEIVE_TIMEOUT_MSEC
itk::FastMutexLock::Pointer m_ConnectingFinishedMutex
void EnableInfiniteBufferingMode(mitk::IGTLMessageQueue::Pointer queue, bool enable=true)
Sets the buffering mode of the given queue.
DataCollection - Class to facilitate loading/accessing structured data.
igtl::MessageBase::Pointer GetNextCommand()
Returns the oldest message in the command queue.
igtl::ImageMessage::Pointer GetNextImage2dMessage()
Returns the oldest message in the receive queue.
igtl::TransformMessage::Pointer GetNextTransformMessage()
igtl::ImageMessage::Pointer GetNextImage3dMessage()
virtual void Connect()
Call this method to check for other devices that want to connect to this one.
virtual void Send()=0
Call this method to send a message. The message will be read from the queue.
bool SendRTSMessage(const char *type)
Send RTS message of given type.
unsigned int ReceivePrivate(igtl::Socket *device)
Call this method to receive a message from the given device.
A wrapper for the OpenIGTLink message type.
virtual bool TestConnection()
TestConnection() tries to connect to a IGTL device on the current ip and port.
virtual void Receive()=0
Call this method to receive a message.
virtual bool CloseConnection()
Closes the connection to the device.
itk::MutexLockHolder< itk::FastMutexLock > MutexLockHolder
IGTLDeviceState
Type for state variable. The IGTLDevice is always in one of these states.
mitk::IGTLMessageQueue::Pointer m_MessageQueue
itk::FastMutexLock::Pointer m_SendingFinishedMutex
Interface for all OpenIGTLink Devices.
igtl::TrackingDataMessage::Pointer GetNextTrackingDataMessage()
virtual bool StopCommunication()
Stops the communication between the two devices.
static ITK_THREAD_RETURN_TYPE ThreadStartReceiving(void *data)
static start method for the receiving thread.
static ITK_THREAD_RETURN_TYPE ThreadStartSending(void *data)
static start method for the sending thread.
void SendMessage(igtl::MessageBase::Pointer msg)
Adds the given message to the sending queue.
static std::string GetName(std::string fileName, std::string suffix)
igtl::StringMessage::Pointer GetNextStringMessage()
void RunCommunication(void(IGTLDevice::*ComFunction)(void), itk::FastMutexLock *mutex)
Continuously calls the given function.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.