MNE-CPP  beta 1.0
rtcmdclient.cpp
Go to the documentation of this file.
1 //=============================================================================================================
38 //*************************************************************************************************************
39 //=============================================================================================================
40 // INCLUDES
41 //=============================================================================================================
42 
43 #include "rtcmdclient.h"
44 
45 //*************************************************************************************************************
46 //=============================================================================================================
47 // QT INCLUDES
48 //=============================================================================================================
49 
50 #include <QDateTime>
51 #include <QThread>
52 
53 #include <iostream>
54 
55 
56 #define USENEW 1
57 
58 //*************************************************************************************************************
59 //=============================================================================================================
60 // USED NAMESPACES
61 //=============================================================================================================
62 
63 using namespace RTCLIENTLIB;
64 
65 //*************************************************************************************************************
66 //=============================================================================================================
67 // DEFINE MEMBER METHODS
68 //=============================================================================================================
69 
70 RtCmdClient::RtCmdClient(QObject *parent) :
71  QTcpSocket(parent)
72 {
73  QObject::connect(&m_commandManager, &CommandManager::triggered, this,
75 }
76 
77 //*************************************************************************************************************
78 
79 void RtCmdClient::connectToHost(QString &p_sRtServerHostName)
80 {
81  QTcpSocket::connectToHost(p_sRtServerHostName, 4217);
82 }
83 
84 //*************************************************************************************************************
85 
86 QString RtCmdClient::sendCLICommand(const QString &p_sCommand)
87 {
88  QString t_sCommand = QString("%1\n").arg(p_sCommand);
89  QString p_sReply;
90 
91  if (this->state() == QAbstractSocket::ConnectedState)
92  {
93  this->write(t_sCommand.toUtf8().constData(), t_sCommand.size());
94  this->waitForBytesWritten();
95 
96  //thats not the most elegant way
97  this->waitForReadyRead(1000);
98  QByteArray t_qByteArrayRaw;
99  // TODO(cpieloth): We need a break condition e.g. last byte == \0 or \n
100  // Large responses can be split to more than one packet which could be a problem on big network latencies.
101  while (this->bytesAvailable() > 0 && this->canReadLine())
102  t_qByteArrayRaw += this->readAll();
103 
104  p_sReply = QString(t_qByteArrayRaw);
105  }
106  return p_sReply;
107 }
108 
109 //*************************************************************************************************************
110 
111 void RtCmdClient::sendCommandJSON(const Command &p_command)
112 {
113  const QString t_sCommand = QString("{\"commands\":{%1}}\n").arg(
114  p_command.toStringReadySend());
115 
116  QString t_sReply;
117 
118  if (this->state() == QAbstractSocket::ConnectedState)
119  {
120  // Send request
121 #ifdef USENEW
122  QByteArray block;
123  QDataStream out(&block, QIODevice::WriteOnly);
124  out.setVersion(QDataStream::Qt_5_1);
125 
126  out << (quint16)0;
127  out << t_sCommand;
128  out.device()->seek(0);
129  out << (quint16)(block.size() - sizeof(quint16));
130 
131  this->write(block);
132  this->waitForBytesWritten();
133 
134  // Receive response
135  QDataStream in(this);
136  in.setVersion(QDataStream::Qt_5_1);
137 
138  quint16 blockSize = 0;
139 
140  bool respComplete = false;
141 
142  do
143  {
144  this->waitForReadyRead(100);
145 
146  if (blockSize == 0)
147  {
148  if (this->bytesAvailable() >= (int)sizeof(quint16))
149  in >> blockSize;
150  }
151  else if(this->bytesAvailable() >= blockSize)
152  {
153  in >> t_sReply;
154  respComplete = true;
155  }
156  } while (!respComplete && blockSize < 65000);//Sanity Check -> allowed maximal blocksize is 65.000
157 #else
158  this->write(t_sCommand.toUtf8().constData(), t_sCommand.size());
159  this->waitForBytesWritten();
160 
161  // Receive response
162  bool respComplete = false;
163  QByteArray t_qByteArrayRaw;
164  do
165  {
166  if (this->waitForReadyRead(100))
167  {
168  t_qByteArrayRaw += this->readAll();
169  // We need a break condition,
170  // because we do not have a stop character and do not know how many bytes to receive.
171  respComplete = t_qByteArrayRaw.count('{')
172  == t_qByteArrayRaw.count('}');
173  }
174  qDebug() << "Response: " << t_qByteArrayRaw.size() << " bytes";
175  } while (!respComplete);
176  t_sReply = QString(t_qByteArrayRaw);
177 #endif
178  }
179  else
180  {
181  qWarning() << "Request was not send, because client is not connected!";
182  }
183 
184  m_qMutex.lock();
185 // m_sAvailableData.append(t_sReply); //ToDo check this
186  m_sAvailableData = t_sReply;
187  m_qMutex.unlock();
188 
189  emit response(t_sReply);
190 }
191 
192 
193 //*************************************************************************************************************
194 
196 {
197  //Send
198  m_commandManager["getbufsize"].send();
199 
200  //Receive
201  m_qMutex.lock();
202  QByteArray t_sJsonCommands = m_sAvailableData.toUtf8();
203  m_qMutex.unlock();
204 
205  //Parse
206  QJsonParseError error;
207  QJsonDocument t_jsonDocumentOrigin = QJsonDocument::fromJson(t_sJsonCommands, &error);
208 
209  if (error.error == QJsonParseError::NoError)
210  {
211 // qDebug() << t_jsonDocumentOrigin;//"Received Commands" << m_commandManager.commandMap().keys();
212 
213  //Switch to command object
214  if(t_jsonDocumentOrigin.isObject() && t_jsonDocumentOrigin.object().value(QString("bufsize")) != QJsonValue::Undefined)
215  {
216  qint32 size = (qint32)t_jsonDocumentOrigin.object().value(QString("bufsize")).toDouble();
217  return size;
218  }
219  }
220 
221  qCritical() << "Unable to parse JSON response: " << error.errorString();
222  return -1;
223 }
224 
225 
226 //*************************************************************************************************************
227 
229 {
230  //No commands are present -> thats why help has to be send using a self created command
231  const QString help("help");
232  const QString description("");
233  const Command cmdHelp(help, description);
234  this->sendCommandJSON(cmdHelp);
235 
236  //Clear Commands
237  m_commandManager.clear();
238 
239  //Receive
240  m_qMutex.lock();
241  QByteArray t_sJsonCommands = m_sAvailableData.toUtf8();
242  m_qMutex.unlock();
243 
244  //Parse
245  QJsonParseError error;
246  QJsonDocument t_jsonDocumentOrigin = QJsonDocument::fromJson(
247  t_sJsonCommands, &error);
248 
249  if (error.error == QJsonParseError::NoError)
250  m_commandManager.insert(t_jsonDocumentOrigin);
251  else
252  qCritical() << "Unable to parse JSON response: " << error.errorString();
253 }
254 
255 
256 //*************************************************************************************************************
257 
258 qint32 RtCmdClient::requestConnectors(QMap<qint32, QString> &p_qMapConnectors)
259 {
260  //Send
261  m_commandManager["conlist"].send();
262 
263  //Receive
264  m_qMutex.lock();
265  QByteArray t_sJsonConnectors = m_sAvailableData.toUtf8();
266  m_qMutex.unlock();
267 
268  //Parse
269  QJsonParseError error;
270  QJsonDocument t_jsonDocumentOrigin = QJsonDocument::fromJson(
271  t_sJsonConnectors, &error);
272 
273  QJsonObject t_jsonObjectConnectors;
274 
275  //Switch to command object
276  if(t_jsonDocumentOrigin.isObject() && t_jsonDocumentOrigin.object().value(QString("connectors")) != QJsonValue::Undefined)
277  t_jsonObjectConnectors = t_jsonDocumentOrigin.object().value(QString("connectors")).toObject();
278 
279  //inits
280  qint32 p_iActiveId = -1;
281  p_qMapConnectors.clear();
282 
283  //insert connectors
284  QJsonObject::Iterator it;
285  for(it = t_jsonObjectConnectors.begin(); it != t_jsonObjectConnectors.end(); ++it)
286  {
287  QString t_qConnectorName = it.key();
288 
289  qint32 id = it.value().toObject().value(QString("id")).toDouble();
290 
291  if(!p_qMapConnectors.contains(id))
292  p_qMapConnectors.insert(id, t_qConnectorName);
293  else
294  qWarning("Warning: CommandMap contains command %s already. Insertion skipped.\n", it.key().toLatin1().constData());
295 
296  //if connector is active indicate it
297  if(it.value().toObject().value(QString("active")).toBool())
298  p_iActiveId = id;
299  }
300 
301  return p_iActiveId;
302 }
303 
304 
306 
307 //void RtCmdClient::requestMeasInfo(qint32 p_id)
308 //{
309 // QString t_sCommand = QString("measinfo %1").arg(p_id);
310 // this->sendCommand(t_sCommand);
311 //}
312 
314 
315 //void RtCmdClient::requestMeasInfo(const QString &p_Alias)
316 //{
317 // QString t_sCommand = QString("measinfo %1").arg(p_Alias);
318 // this->sendCommand(t_sCommand);
319 //}
320 
322 
323 //void RtCmdClient::requestMeas(qint32 p_id)
324 //{
325 // QString t_sCommand = QString("start %1").arg(p_id);
326 // this->sendCommand(t_sCommand);
327 //}
328 
330 
331 //void RtCmdClient::requestMeas(QString p_Alias)
332 //{
333 // QString t_sCommand = QString("start %1").arg(p_Alias);
334 // this->sendCommand(t_sCommand);
335 //}
336 
338 
339 //void RtCmdClient::stopAll()
340 //{
341 // QString t_sCommand = QString("stop-all");
342 // this->sendCommand(t_sCommand);
343 //}
344 
345 //*************************************************************************************************************
346 
347 bool RtCmdClient::waitForDataAvailable(qint32 msecs) const
348 {
349  if (m_sAvailableData.size() > 0)
350  return true;
351 
352  qint64 t_msecsStart = QDateTime::currentMSecsSinceEpoch();
353 
354  while (msecs == -1
355  || (qint64) msecs
356  < QDateTime::currentMSecsSinceEpoch() - t_msecsStart)
357  {
358  QThread::msleep(5);
359  if (m_sAvailableData.size() > 0)
360  return true;
361  }
362  return false;
363 }
364 
365 //*************************************************************************************************************
366 
367 Command& RtCmdClient::operator[](const QString &key)
368 {
369  return m_commandManager[key];
370 }
371 
372 //*************************************************************************************************************
373 
374 const Command RtCmdClient::operator[](const QString &key) const
375 {
376  return m_commandManager[key];
377 }
void insert(const QJsonDocument &p_jsonDocument)
void connectToHost(QString &p_sRtServerHostName)
Definition: rtcmdclient.cpp:79
QString sendCLICommand(const QString &p_sCommand)
Definition: rtcmdclient.cpp:86
Command & operator[](const QString &key)
void sendCommandJSON(const Command &p_command)
void response(QString p_sResponse)
void triggered(Command p_command)
QString toStringReadySend() const
Definition: command.cpp:221
RtCmdClient(QObject *parent=0)
Definition: rtcmdclient.cpp:70
bool waitForDataAvailable(qint32 msecs=30000) const
qint32 requestConnectors(QMap< qint32, QString > &p_qMapConnectors)
declaration of the RtCmdClient Class.