MNE-CPP  beta 1.0
mne_rt_server.cpp
Go to the documentation of this file.
1 //=============================================================================================================
36 //*************************************************************************************************************
37 //=============================================================================================================
38 // INCLUDES
39 //=============================================================================================================
40 
41 #include "mne_rt_server.h"
42 
43 #include "IConnector.h"
44 
45 
46 //*************************************************************************************************************
47 //=============================================================================================================
48 // STL INCLUDES
49 //=============================================================================================================
50 
51 #include <stdio.h>
52 #include <stdlib.h>
53 
54 
55 //*************************************************************************************************************
56 //=============================================================================================================
57 // QT INCLUDES
58 //=============================================================================================================
59 
60 #include <QtNetwork>
61 #include <QDebug>
62 
63 
64 //*************************************************************************************************************
65 //=============================================================================================================
66 // USED NAMESPACES
67 //=============================================================================================================
68 
69 using namespace RTSERVER;
70 
71 
72 const char* connectorDir = "/mne_rt_server_plugins";
75 //*************************************************************************************************************
76 //=============================================================================================================
77 // DEFINE MEMBER METHODS
78 //=============================================================================================================
79 
80 MNERTServer::MNERTServer()
81 : m_fiffStreamServer(this)
82 , m_commandServer(this)
83 , m_connectorManager(&m_fiffStreamServer, this)
84 {
85  qRegisterMetaType<MatrixXf>("MatrixXf");
86  qRegisterMetaType<QSharedPointer<Eigen::MatrixXf> >("QSharedPointer<Eigen::MatrixXf>");
87 
88  //
89  // init mne_rt_server
90  //
91  this->init();
92 
93  // connector manager
94  m_connectorManager.connectCommands();
95 
96  // fiff stream server
97  m_fiffStreamServer.connectCommands();
98 
99  // command manager
100  m_commandServer.registerCommandManager(this->getCommandManager());
101 
102  // ### Load everything ###
103  //
104  // Load Connectors
105  //
106  m_connectorManager.loadConnectors(qApp->applicationDirPath()+connectorDir);
107 
108  // ### Connect everything ###
109  //
110  // Meas Info
111  //
112 // QObject::connect( this->m_pFiffStreamServer, &FiffStreamServer::requestMeasInfo,
113 // this->m_pConnectorManager, &ConnectorManager::forwardMeasInfoRequest);
114 
115  m_connectorManager.connectActiveConnector();
116 
117  //Register Fiff Sream Server for command parsing
118 // m_pCommandServer->registerCommandParser((ICommandParser*)m_pFiffStreamServer);//OLD
119 // m_commandServer.registerCommandManager(m_fiffStreamServer.getCommandManager());//NEW
120 
121  //Register Command Managers of loaded connectors
122  for(qint32 i = 0; i < m_connectorManager.getConnectors().size(); ++i)
123  m_commandServer.registerCommandManager(m_connectorManager.getConnectors()[i]->getCommandManager());
124 
125  // ### Run everything ###
126  //
127  // Run instruction server
128  //
129  if (!m_commandServer.listen(QHostAddress::Any, 4217)) {
130  printf("Unable to start the command server: %s\n", m_commandServer.errorString().toUtf8().constData());
131  return;
132  }
133  //
134  // Run data server
135  //
136  if (!m_fiffStreamServer.listen(QHostAddress::Any, 4218)) {
137  printf("Unable to start the fiff stream server: %s\n", m_fiffStreamServer.errorString().toUtf8().constData());
138  return;
139  }
140 
141  QString ipAddress;
142  QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
143  // use the first non-localhost IPv4 address
144  for (int i = 0; i < ipAddressesList.size(); ++i) {
145  if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
146  ipAddressesList.at(i).toIPv4Address()) {
147  ipAddress = ipAddressesList.at(i).toString();
148  break;
149  }
150  }
151  // if we did not find one, use IPv4 localhost
152  if (ipAddress.isEmpty())
153  ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
154 
155  printf("mne_rt_server is running on\n\tIP:\t\t%s\n\tcommand port:\t%d\n\tfiff data port:\t%d\n\n",ipAddress.toUtf8().constData(), m_commandServer.serverPort(), m_fiffStreamServer.serverPort());
156 }
157 
158 
159 //*************************************************************************************************************
160 
161 MNERTServer::~MNERTServer()
162 {
163  qDebug() << "MNERTServer destructed";
164 }
165 
166 
167 //*************************************************************************************************************
168 
169 void MNERTServer::comClose()
170 {
171  emit closeServer();
172 }
173 
174 
175 //*************************************************************************************************************
176 
177 void MNERTServer::comHelp(Command p_command)
178 {
179  bool t_bCommandIsJson = p_command.isJson();
180  //
181  // Generate help
182  //
183  Subject::t_Observers::Iterator itObservers;
184 
185  //Map to store all commands & merging multi occurence
186  QMap<QString, Command> t_qMapCommands;
187 
188  QMap<QString, Command>::ConstIterator itCommands;
189 
190  for(itObservers = m_commandServer.getCommandParser().observers().begin(); itObservers != m_commandServer.getCommandParser().observers().end(); ++itObservers)
191  {
192  CommandManager* t_pCommandManager = static_cast<CommandManager*> (*itObservers);
193 
194  for(itCommands = t_pCommandManager->commandMap().begin(); itCommands != t_pCommandManager->commandMap().end(); ++itCommands)
195  {
196  if(t_qMapCommands.keys().contains(itCommands.key()))
197  {
198  //ToDo merge
199  qDebug() << "Merge has to be performed.";
200  }
201  else
202  t_qMapCommands.insert(itCommands.key(), itCommands.value());
203  }
204  }
205 
206  //
207  //create JSON help object
208  //
209  QJsonObject t_qJsonObjectCommands;
210 
211  for(itCommands = t_qMapCommands.begin(); itCommands != t_qMapCommands.end(); ++itCommands)
212  t_qJsonObjectCommands.insert(itCommands.key(),QJsonValue(itCommands.value().toJsonObject()));
213  QJsonObject t_qJsonObjectRoot;
214  t_qJsonObjectRoot.insert("commands", t_qJsonObjectCommands);
215  QJsonDocument p_qJsonDocument(t_qJsonObjectRoot);
216 
217 
218  if(!t_bCommandIsJson)
219  {
220  //
221  //create string formatted help and print
222  //
223  QString p_sOutput("");
224 
225  qint32 t_maxSize = 72;
226  qint32 t_maxSizeCommand = 0;
227  qint32 t_maxSizeParameters = 0;
228  qint32 t_maxSizeDescriptions = 0;
229 
230  //get max sizes
231  for(itCommands = t_qMapCommands.begin(); itCommands != t_qMapCommands.end(); ++itCommands)
232  {
233  QStringList t_sCommandList = itCommands.value().toStringList();
234 
235  if(t_sCommandList[0].size() > t_maxSizeCommand)
236  t_maxSizeCommand = t_sCommandList[0].size();
237 
238  if(t_sCommandList[1].size() > t_maxSizeParameters)
239  t_maxSizeParameters = t_sCommandList[1].size();
240  }
241 
242  t_maxSizeDescriptions = t_maxSizeCommand + t_maxSizeParameters + 2;
243  t_maxSizeDescriptions = t_maxSizeDescriptions < t_maxSize ? t_maxSize - t_maxSizeDescriptions : 20;
244 
245  //Format output
246  for(itCommands = t_qMapCommands.begin(); itCommands != t_qMapCommands.end(); ++itCommands)
247  {
248  QStringList t_sCommandList = itCommands.value().toStringList();
249  QString t_sCommand;
250  qint32 i = 0;
251  //Command
252  t_sCommand.append(QString("\t%1 ").arg(t_sCommandList[0]));
253  //Spaces
254  for(i = 0; i < t_maxSizeCommand - t_sCommandList[0].size(); ++i)
255  t_sCommand.append(QString(" "));
256  //Parameters
257  t_sCommand.append(QString("%1 ").arg(t_sCommandList[1]));
258  //Spaces
259  for(i = 0; i < t_maxSizeParameters - t_sCommandList[1].size(); ++i)
260  t_sCommand.append(QString(" "));
261  //Description
262  qint32 lines = (int)ceil((double)t_sCommandList[2].size() / (double)t_maxSizeDescriptions);
263  for(i = 0; i < lines; ++i)
264  {
265  t_sCommand.append(QString("%1").arg(t_sCommandList[2].mid(i * t_maxSizeDescriptions, t_maxSizeDescriptions)));
266  t_sCommand.append(QString("\n\r"));
267  //Spaces
268  if(i < lines-1)
269  {
270  t_sCommand.append(QString("\t"));
271  for(qint32 j = 0; j < t_maxSizeCommand + t_maxSizeParameters + 2; ++j)
272  t_sCommand.append(QString(" "));
273  }
274  }
275  p_sOutput.append(t_sCommand);
276  }
277  m_commandManager["help"].reply(p_sOutput);
278  }
279  else
280  m_commandManager["help"].reply(p_qJsonDocument.toJson());
281 }
282 
283 
284 //*************************************************************************************************************
285 
287 {
288  //insert commands
289 // //OPTION 1
290 // QStringList t_qListParamNames;
291 // QList<QVariant> t_qListParamValues;
292 // QStringList t_qListParamDescription;
293 
294 // t_qListParamNames.append("id");
295 // t_qListParamValues.append(QVariant(QVariant::String));
296 // t_qListParamDescription.append("ID/Alias");
297 
298 // m_commandManager.insert("measinfo", Command("measinfo", "sends the measurement info to the specified FiffStreamClient.", t_qListParamNames, t_qListParamValues, t_qListParamDescription));
299 // m_commandManager.insert("meas", Command("meas", "adds specified FiffStreamClient to raw data buffer receivers. If acquisition is not already strated, it is triggered.", t_qListParamNames, t_qListParamValues, t_qListParamDescription));
300 // m_commandManager.insert("stop", Command("stop", "removes specified FiffStreamClient from raw data buffer receivers.", t_qListParamNames, t_qListParamValues, t_qListParamDescription));
301 // t_qListParamNames.clear(); t_qListParamValues.clear();t_qListParamDescription.clear();
302 // m_commandManager.insert(QString("stop-all"), QString("stops the whole acquisition process."));
303 
304 // m_commandManager.insert(QString("conlist"), QString("prints and sends all available connectors"));
305 
306 // t_qListParamNames.append("ConID");
307 // t_qListParamValues.append(QVariant(QVariant::Int));
308 // t_qListParamDescription.append("Connector ID");
309 // m_commandManager.insert("\tselcon", Command("\tselcon", "selects a new connector, if a measurement is running it will be stopped.", t_qListParamNames, t_qListParamValues, t_qListParamDescription));
310 
311 // m_commandManager.insert(QString("help"), QString("prints and sends this list"));
312 
313 // m_commandManager.insert(QString("close"), QString("closes mne_rt_server"));
314 
315  //OPTION 2
316  QString t_sJsonCommand =
317  "{"
318  " \"commands\": {"
319  " \"clist\": {"
320  " \"description\": \"Prints and sends all available FiffStreamClients.\","
321  " \"parameters\": {}"
322  " },"
323  " \"close\": {"
324  " \"description\": \"Closes mne_rt_server.\","
325  " \"parameters\": {}"
326  " },"
327  " \"conlist\": {"
328  " \"description\": \"Prints and sends all available connectors.\","
329  " \"parameters\": {}"
330  " },"
331  " \"help\": {"
332  " \"description\": \"Prints and sends this list.\","
333  " \"parameters\": {}"
334  " },"
335  " \"measinfo\": {"
336  " \"description\": \"Sends the measurement info to the specified FiffStreamClient.\","
337  " \"parameters\": {"
338  " \"id\": {"
339  " \"description\": \"ID/Alias\","
340  " \"type\": \"QString\" "
341  " }"
342  " }"
343  " },"
344  " \"selcon\": {"
345  " \"description\": \"Selects a new connector, if a measurement is running it will be stopped.\","
346  " \"parameters\": {"
347  " \"ConID\": {"
348  " \"description\": \"Connector ID\","
349  " \"type\": \"int\" "
350  " }"
351  " }"
352  " },"
353  " \"start\": {"
354  " \"description\": \"Adds specified FiffStreamClient to raw data buffer receivers. If acquisition is not already started, it is triggered.\","
355  " \"parameters\": {"
356  " \"id\": {"
357  " \"description\": \"ID/Alias\","
358  " \"type\": \"QString\" "
359  " }"
360  " }"
361  " },"
362  " \"stop\": {"
363  " \"description\": \"Removes specified FiffStreamClient from raw data buffer receivers.\","
364  " \"parameters\": {"
365  " \"id\": {"
366  " \"description\": \"ID/Alias\","
367  " \"type\": \"QString\" "
368  " }"
369  " }"
370  " },"
371  " \"stop-all\": {"
372  " \"description\": \"Stops the whole acquisition process.\","
373  " \"parameters\": {}"
374  " }"
375  " }"
376  "}";
377 
378  QJsonDocument t_jsonDocumentOrigin = QJsonDocument::fromJson(t_sJsonCommand.toLatin1());
379  m_commandManager.insert(t_jsonDocumentOrigin);
380 
381  //connect slots
382  QObject::connect(&m_commandManager["help"], &Command::executed, this, &MNERTServer::comHelp);
383  QObject::connect(&m_commandManager["close"], &Command::executed, this, &MNERTServer::comClose);
384 }
void insert(const QJsonDocument &p_jsonDocument)
t_Observers & observers()
const char * connectorDir
implementation of the MNERTServer Class.
The connector interface.
void executed(Command p_command)
QMap< QString, Command > & commandMap()
CommandParser & getCommandParser()