16#include <itkMultiThreaderBase.h>
17#include <itksys/SystemTools.hxx>
21#include <igtlTransformMessage.h>
27#include <igtlTrackingDataMessage.h>
39static const int SOCKET_SEND_RECEIVE_TIMEOUT_MSEC = 100;
44m_Name(
"Unspecified Device"),
45m_StopCommunication(false),
46m_Hostname(
"127.0.0.1"),
50 m_ReadFully = ReadFully;
65 if (GetState() == Running)
67 this->StopCommunication();
68 this->CloseConnection();
70 else if (GetState() == Ready)
72 this->CloseConnection();
75 if (m_SendThread.joinable())
76 m_SendThread.detach();
78 if (m_ReceiveThread.joinable())
79 m_ReceiveThread.detach();
81 if (m_ConnectThread.joinable())
82 m_ConnectThread.detach();
87 std::lock_guard<std::mutex> lock(m_StateMutex);
93 itkDebugMacro(
"setting m_State to " << state);
100 m_StateMutex.unlock();
104 m_StateMutex.unlock();
116 igtl::MessageHeader::Pointer headerMsg;
117 headerMsg = igtl::MessageHeader::New();
120 headerMsg->InitPack();
123 bool timeout =
false;
124 auto r = socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(), timeout, 0);
141 else if (r == headerMsg->GetPackSize())
145 int crcCheck = headerMsg->Unpack(1);
147 if (crcCheck & igtl::MessageHeader::UNPACK_HEADER)
150 igtl::TimeStamp::Pointer ts;
151 ts = igtl::TimeStamp::New();
157 headerMsg->GetTimeStamp(ts);
158 ts->GetTimeStamp(&sec, &nanosec);
172 const char* curDevType = headerMsg->GetDeviceType();
173 if (std::strstr(curDevType,
"GET_") !=
nullptr ||
174 std::strstr(curDevType,
"STP_") !=
nullptr ||
175 std::strstr(curDevType,
"RTS_") !=
nullptr)
177 this->m_MessageQueue->PushCommandMessage(headerMsg);
178 this->InvokeEvent(CommandReceivedEvent());
183 igtl::MessageBase::Pointer curMessage;
184 curMessage = m_MessageFactory->CreateInstance(headerMsg);
188 if (curMessage.IsNull())
190 socket->Skip(headerMsg->GetBodySizeToRead(), 0);
197 curMessage->SetMessageHeader(headerMsg);
198 curMessage->AllocatePack();
201 int receiveCheck = 0;
202 receiveCheck = socket->Receive(curMessage->GetPackBodyPointer(),
203 curMessage->GetPackBodySize(), m_ReadFully);
205 if (receiveCheck > 0)
207 int c = curMessage->Unpack(1);
208 if (!(c & igtl::MessageHeader::UNPACK_BODY))
218 if (std::strstr(curDevType,
"STT_") !=
nullptr)
220 this->m_MessageQueue->PushCommandMessage(curMessage);
221 this->InvokeEvent(CommandReceivedEvent());
226 MITK_INFO <<
"Received Message: " << mitk::IGTLMessage::New(curMessage)->ToString();
227 this->m_MessageQueue->PushMessage(curMessage);
228 this->InvokeEvent(MessageReceivedEvent());
234 MITK_WARN(
"IGTLDevice") <<
"Received a valid header but could not "
235 <<
"read the whole message.";
242 MITK_WARN <<
"CRC Check failed";
250 MITK_WARN <<
"IGTL status unknown";
257 m_MessageQueue->PushSendMessage(msg);
261 igtl::Socket::Pointer socket)
266 MITK_ERROR(
"IGTLDevice") <<
"Could not send message because message is not "
267 "valid. Please check.";
271 igtl::MessageBase* sendMessage = msg->GetMessage();
276 int sendSuccess = socket->Send(sendMessage->GetPackPointer(), sendMessage->GetPackSize());
280 if (m_LogMessages) { MITK_INFO <<
"Send IGTL message: " << msg->ToString(); }
281 this->InvokeEvent(MessageSentEvent());
292 if (this->GetState() != Running)
298 std::lock_guard<std::mutex> communicationFinishedLockHolder(mutex);
302 bool localStopCommunication;
305 this->m_StopCommunicationMutex.lock();
306 localStopCommunication = this->m_StopCommunication;
307 this->m_StopCommunicationMutex.unlock();
308 while ((this->GetState() == Running) && (localStopCommunication ==
false))
310 (this->*ComFunction)();
313 this->m_StopCommunicationMutex.lock();
314 localStopCommunication = m_StopCommunication;
315 this->m_StopCommunicationMutex.unlock();
318 itksys::SystemTools::Delay(1);
324 this->StopCommunication();
325 MITK_ERROR(
"IGTLDevice::RunCommunication") <<
"Error while communicating. Thread stopped.";
331 MITK_DEBUG(
"IGTLDevice::RunCommunication") <<
"Reached end of communication.";
339 if (this->GetState() != Ready)
343 this->SetState(Running);
346 this->m_Socket->SetTimeout(SOCKET_SEND_RECEIVE_TIMEOUT_MSEC);
349 this->m_StopCommunicationMutex.lock();
350 this->m_StopCommunication =
false;
351 this->m_StopCommunicationMutex.unlock();
354 m_SendingFinishedMutex.unlock();
355 m_ReceivingFinishedMutex.unlock();
356 m_ConnectingFinishedMutex.unlock();
368 if (this->GetState() == Running)
372 m_StopCommunicationMutex.lock();
373 m_StopCommunication =
true;
374 m_StopCommunicationMutex.unlock();
377 m_SendingFinishedMutex.lock();
378 m_ReceivingFinishedMutex.lock();
379 m_ConnectingFinishedMutex.lock();
383 this->SetState(Ready);
390 if (this->GetState() == Setup)
394 else if (this->GetState() == Running)
396 this->StopCommunication();
399 m_Socket->CloseSocket();
402 this->SetState(Setup);
413 std::string returnType(
"RTS_");
414 returnType.append(type);
416 igtl::MessageBase::Pointer rtsMsg =
417 this->m_MessageFactory->CreateInstance(returnType);
420 if (rtsMsg.IsNotNull())
422 this->SendMessage(mitk::IGTLMessage::New(rtsMsg));
433 MITK_DEBUG <<
"mitk::IGTLDevice::Connect();";
438 return this->m_MessageQueue->PullImage2dMessage();
443 return this->m_MessageQueue->PullImage3dMessage();
448 return this->m_MessageQueue->PullTransformMessage();
453 igtl::TrackingDataMessage::Pointer msg = this->m_MessageQueue->PullTrackingMessage();
459 return this->m_MessageQueue->PullStringMessage();
464 return this->m_MessageQueue->PullMiscMessage();
469 return m_MessageQueue->PullCommandMessage();
473 m_MessageQueue->EnableNoBufferingMode(enable);
477 mitk::IGTLMessageQueue::Pointer queue,
480 queue->EnableNoBufferingMode(enable);
Interface for all OpenIGTLink Devices.
std::mutex m_ReceivingFinishedMutex
void RunCommunication(void(IGTLDevice::*ComFunction)(void), std::mutex &mutex)
Continuously calls the given function.
void SendMessage(mitk::IGTLMessage::Pointer msg)
Adds the given message to the sending queue.
unsigned int SendMessagePrivate(mitk::IGTLMessage::Pointer msg, igtl::Socket::Pointer socket)
Sends a message.
std::mutex m_SendingFinishedMutex
igtl::StringMessage::Pointer GetNextStringMessage()
virtual void Connect()
Call this method to check for other devices that want to connect to this one.
virtual bool CloseConnection()
Closes the connection to the device.
void ThreadStartSending()
start method for the sending thread.
igtl::ImageMessage::Pointer GetNextImage3dMessage()
virtual bool TestConnection()
TestConnection() tries to connect to a IGTL device on the current ip and port.
mitk::IGTLMessageQueue::Pointer m_MessageQueue
igtl::TrackingDataMessage::Pointer GetNextTrackingDataMessage()
void ThreadStartReceiving()
start method for the receiving thread.
void ThreadStartConnecting()
start method for the connection thread.
bool StartCommunication()
Starts the communication between the two devices.
std::mutex m_ConnectingFinishedMutex
bool SendRTSMessage(const char *type)
Send RTS message of given type.
igtl::MessageBase::Pointer GetNextCommand()
Returns the oldest message in the command queue.
void EnableNoBufferingMode(mitk::IGTLMessageQueue::Pointer queue, bool enable=true)
Sets the buffering mode of the given queue.
unsigned int ReceivePrivate(igtl::Socket *device)
Call this method to receive a message from the given device.
IGTLDeviceState GetState() const
Returns current object state (Setup, Ready or Running)
virtual bool StopCommunication()
Stops the communication between the two devices.
virtual void Receive()=0
Call this method to receive a message.
virtual void Send()=0
Call this method to send a message. The message will be read from the queue.
igtl::TransformMessage::Pointer GetNextTransformMessage()
void SetState(IGTLDeviceState state)
change object state
igtl::MessageBase::Pointer GetNextMiscMessage()
igtl::ImageMessage::Pointer GetNextImage2dMessage()
Returns the oldest message in the receive queue.
IGTLDeviceState
Type for state variable. The IGTLDevice is always in one of these states.
mitk::IGTLMessageFactory::Pointer m_MessageFactory
#define IGTL_STATUS_CHECKSUM_ERROR
#define IGTL_STATUS_UNKNOWN_ERROR
#define IGTL_STATUS_TIME_OUT
#define IGTL_STATUS_NOT_PRESENT
#define IGTL_STATUS_NOT_FOUND
itkEventMacroDefinition(MessageSentEvent, itk::AnyEvent)