SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TraCITestClient.cpp
Go to the documentation of this file.
1 /****************************************************************************/
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
14 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
15 /****************************************************************************/
16 //
17 // This file is part of SUMO.
18 // SUMO is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
22 //
23 /****************************************************************************/
24 /* =========================================================================
25  * included modules
26  * ======================================================================= */
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <vector>
34 #include <iostream>
35 #include <iomanip>
36 #include <fstream>
37 #include <sstream>
38 #include <ctime>
39 #include <cstdlib>
40 
41 #define BUILD_TCPIP
42 #include <foreign/tcpip/storage.h>
43 #include <foreign/tcpip/socket.h>
44 
46 #include <utils/common/SUMOTime.h>
47 #include "TraCITestClient.h"
48 
49 #ifdef CHECK_MEMORY_LEAKS
50 #include <foreign/nvwa/debug_new.h>
51 #endif // CHECK_MEMORY_LEAKS
52 
53 
54 // ===========================================================================
55 // used namespaces
56 // ===========================================================================
57 using namespace testclient;
58 
59 
60 // ===========================================================================
61 // method definitions
62 // ===========================================================================
63 
64 TraCITestClient::TraCITestClient(std::string outputFileName)
65  : socket(NULL),
66  outputFileName(outputFileName),
67  answerLog("") {
68  answerLog.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
69  answerLog.setf(std::ios::showpoint); // print decimal point
70  answerLog << std::setprecision(2);
71 }
72 
73 
75  writeResult();
76  delete socket;
77 }
78 
79 
80 void
82  time_t seconds;
83  tm* locTime;
84 
85  std::ofstream outFile(outputFileName.c_str());
86  if (!outFile) {
87  std::cerr << "Unable to write result file" << std::endl;
88  }
89  time(&seconds);
90  locTime = localtime(&seconds);
91  outFile << "TraCITestClient output file. Date: " << asctime(locTime) << std::endl;
92  outFile << answerLog.str();
93  outFile.close();
94 }
95 
96 
97 void
98 TraCITestClient::errorMsg(std::stringstream& msg) {
99  std::cerr << msg.str() << std::endl;
100  answerLog << "----" << std::endl << msg.str() << std::endl;
101 }
102 
103 
104 bool
105 TraCITestClient::connect(int port, std::string host) {
106  std::stringstream msg;
107  socket = new tcpip::Socket(host, port);
108 
109  //socket->set_blocking(true);
110 
111  try {
112  socket->connect();
113  } catch (tcpip::SocketException& e) {
114  msg << "#Error while connecting: " << e.what();
115  errorMsg(msg);
116  return false;
117  }
118 
119  return true;
120 }
121 
122 
123 bool
125  if (socket != NULL) {
126  socket->close();
127  }
128  return true;
129 }
130 
131 
132 bool
133 TraCITestClient::run(std::string fileName, int port, std::string host) {
134  std::ifstream defFile;
135  std::string fileContentStr;
136  std::stringstream fileContent;
137  std::string lineCommand;
138  std::stringstream msg;
139  int repNo = 1;
140  bool commentRead = false;
141 
142  if (!connect(port, host)) {
143  return false;
144  }
145 
146  // read definition file and trigger commands according to it
147  defFile.open(fileName.c_str());
148 
149  if (!defFile) {
150  msg << "Can not open definition file " << fileName << std::endl;
151  errorMsg(msg);
152  return false;
153  }
154  defFile.unsetf(std::ios::dec);
155 
156  while (defFile >> lineCommand) {
157  repNo = 1;
158  if (lineCommand.compare("%") == 0) {
159  // a comment was read
160  commentRead = !commentRead;
161  continue;
162  }
163  if (commentRead) {
164  // wait until end of comment is reached
165  continue;
166  }
167  if (lineCommand.compare("repeat") == 0) {
168  defFile >> repNo;
169  defFile >> lineCommand;
170  }
171  if (lineCommand.compare("simstep2") == 0) {
172  // read parameter for command simulation step and trigger command
173  std::string time;
174  defFile >> time;
175  for (int i = 0; i < repNo; i++) {
177  }
178  } else if (lineCommand.compare("posconversion2d") == 0) {
179  // trigger command PositionConversion for a 2d position
181  int destFormat;
182 
183  defFile >> pos.x;
184  defFile >> pos.y;
185  defFile >> destFormat;
186  commandPositionConversion(pos, destFormat);
187  } else if (lineCommand.compare("posconversion3d") == 0) {
188  // trigger command PositionConversion for a 3d position
190  int destFormat;
191 
192  defFile >> pos.x;
193  defFile >> pos.y;
194  defFile >> pos.z;
195  defFile >> destFormat;
196  commandPositionConversion(pos, destFormat);
197  } else if (lineCommand.compare("posconversion_roadpos") == 0) {
198  // trigger command PositionConversion for a road map position
200  int destFormat;
201 
202  defFile >> pos.roadId;
203  defFile >> pos.pos;
204  defFile >> pos.laneId;
205  defFile >> destFormat;
206  commandPositionConversion(pos, destFormat);
207  } else if (lineCommand.compare("distancerequest_3d_3d") == 0) {
208  // trigger command DistanceRequest for 2 3D positions
211  int flag;
212 
213  defFile >> pos1.x;
214  defFile >> pos1.y;
215  defFile >> pos1.z;
216  defFile >> pos2.x;
217  defFile >> pos2.y;
218  defFile >> pos2.z;
219  defFile >> flag;
220  commandDistanceRequest(pos1, pos2, flag);
221  } else if (lineCommand.compare("distancerequest_3d_roadpos") == 0) {
222  // trigger command DistanceRequest for 3D and road map position
225  int flag;
226 
227  defFile >> pos1.x;
228  defFile >> pos1.y;
229  defFile >> pos1.z;
230  defFile >> pos2.roadId;
231  defFile >> pos2.pos;
232  defFile >> pos2.laneId;
233  defFile >> flag;
234  commandDistanceRequest(pos1, pos2, flag);
235  } else if (lineCommand.compare("distancerequest_roadpos_3d") == 0) {
236  // trigger command DistanceRequest for road map and 3D position
239  int flag;
240 
241  defFile >> pos1.roadId;
242  defFile >> pos1.pos;
243  defFile >> pos1.laneId;
244  defFile >> pos2.x;
245  defFile >> pos2.y;
246  defFile >> pos2.z;
247  defFile >> flag;
248  commandDistanceRequest(pos1, pos2, flag);
249  } else if (lineCommand.compare("distancerequest_roadpos_roadpos") == 0) {
250  // trigger command DistanceRequest for 2 road map positions
253  int flag;
254 
255  defFile >> pos1.roadId;
256  defFile >> pos1.pos;
257  defFile >> pos1.laneId;
258  defFile >> pos2.roadId;
259  defFile >> pos2.pos;
260  defFile >> pos2.laneId;
261  defFile >> flag;
262  commandDistanceRequest(pos1, pos2, flag);
263  } else if (lineCommand.compare("getvariable") == 0) {
264  // trigger command GetXXXVariable
265  int domID, varID;
266  std::string objID;
267  defFile >> domID >> varID >> objID;
268  commandGetVariable(domID, varID, objID);
269  } else if (lineCommand.compare("getvariable_plus") == 0) {
270  // trigger command GetXXXVariable with one parameter
271  int domID, varID;
272  std::string objID;
273  defFile >> domID >> varID >> objID;
274  commandGetVariablePlus(domID, varID, objID, defFile);
275  } else if (lineCommand.compare("subscribevariable") == 0) {
276  // trigger command SubscribeXXXVariable
277  int domID, varNo;
278  std::string beginTime, endTime;
279  std::string objID;
280  defFile >> domID >> objID >> beginTime >> endTime >> varNo;
281  commandSubscribeVariable(domID, objID, string2time(beginTime), string2time(endTime), varNo, defFile);
282  } else if (lineCommand.compare("setvalue") == 0) {
283  // trigger command SetXXXValue
284  int domID, varID;
285  std::string objID;
286  defFile >> domID >> varID >> objID;
287  commandSetValue(domID, varID, objID, defFile);
288  } else {
289  msg << "Error in definition file: " << lineCommand
290  << " is not a valid command";
291  errorMsg(msg);
292  commandClose();
293  close();
294  return false;
295  }
296  }
297  defFile.close();
298  commandClose();
299  close();
300  return true;
301 }
302 
303 
304 bool
305 TraCITestClient::reportResultState(tcpip::Storage& inMsg, int command, bool ignoreCommandId) {
306  int cmdLength;
307  int cmdId;
308  int resultType;
309  int cmdStart;
310  std::string msg;
311 
312  try {
313  cmdStart = inMsg.position();
314  cmdLength = inMsg.readUnsignedByte();
315  cmdId = inMsg.readUnsignedByte();
316  if (cmdId != command && !ignoreCommandId) {
317  answerLog << "#Error: received status response to command: " << cmdId
318  << " but expected: " << command << std::endl;
319  return false;
320  }
321  resultType = inMsg.readUnsignedByte();
322  msg = inMsg.readString();
323  } catch (std::invalid_argument&) {
324  answerLog << "#Error: an exception was thrown while reading result state message" << std::endl;
325  return false;
326  }
327  switch (resultType) {
328  case RTYPE_ERR:
329  answerLog << ".. Answered with error to command (" << cmdId << "), [description: " << msg << "]" << std::endl;
330  return false;
332  answerLog << ".. Sent command is not implemented (" << cmdId << "), [description: " << msg << "]" << std::endl;
333  return false;
334  case RTYPE_OK:
335  answerLog << ".. Command acknowledged (" << cmdId << "), [description: " << msg << "]" << std::endl;
336  break;
337  default:
338  answerLog << ".. Answered with unknown result code(" << resultType << ") to command(" << cmdId
339  << "), [description: " << msg << "]" << std::endl;
340  return false;
341  }
342  if ((cmdStart + cmdLength) != inMsg.position()) {
343  answerLog << "#Error: command at position " << cmdStart << " has wrong length" << std::endl;
344  return false;
345  }
346 
347  return true;
348 }
349 
350 
351 void
353  tcpip::Storage outMsg;
354  tcpip::Storage inMsg;
355  std::stringstream msg;
356 
357  if (socket == NULL) {
358  msg << "#Error while sending command: no connection to server";
359  errorMsg(msg);
360  return;
361  }
362 
363  // command length
364  outMsg.writeUnsignedByte(1 + 1 + 4);
365  // command id
367  outMsg.writeInt(time);
368  // send request message
369  try {
370  socket->sendExact(outMsg);
371  } catch (tcpip::SocketException& e) {
372  msg << "Error while sending command: " << e.what();
373  errorMsg(msg);
374  return;
375  }
376  answerLog << std::endl << "-> Command sent: <SimulationStep2>:" << std::endl;
377  // receive answer message
378  try {
379  socket->receiveExact(inMsg);
380  } catch (tcpip::SocketException& e) {
381  msg << "Error while receiving command: " << e.what();
382  errorMsg(msg);
383  return;
384  }
385  // validate result state
386  if (!reportResultState(inMsg, CMD_SIMSTEP2)) {
387  return;
388  }
389  // validate answer message
391 }
392 
393 
394 void
396  commandPositionConversion(&pos, NULL, NULL, posId);
397 }
398 
399 
400 void
402  commandPositionConversion(NULL, &pos, NULL, posId);
403 }
404 
405 
406 void
408  commandPositionConversion(NULL, NULL, &pos, posId);
409 }
410 
411 
412 void
414  testclient::Position3D* pos3D,
416  int posId) {
417  tcpip::Storage outMsg;
418  tcpip::Storage inMsg;
419  tcpip::Storage tempMsg;
420  std::stringstream msg;
421 
422  if (socket == NULL) {
423  msg << "#Error while sending command: no connection to server" ;
424  errorMsg(msg);
425  return;
426  }
427 
428  // command id
430  // position
431  if (pos2D != NULL) {
433  tempMsg.writeDouble(pos2D->x);
434  tempMsg.writeDouble(pos2D->y);
435  } else if (pos3D != NULL) {
437  tempMsg.writeDouble(pos3D->x);
438  tempMsg.writeDouble(pos3D->y);
439  tempMsg.writeDouble(pos3D->z);
440  } else if (posRoad != NULL) {
442  tempMsg.writeString(posRoad->roadId);
443  tempMsg.writeDouble(posRoad->pos);
444  tempMsg.writeUnsignedByte(posRoad->laneId);
445  } else {
446  std::cerr << "Error in method commandPositionConversion: position is NULL" << std::endl;
447  return;
448  }
449  // destination position id
450  tempMsg.writeUnsignedByte(posId);
451  // command length
452  outMsg.writeUnsignedByte(1 + (int) tempMsg.size());
453  outMsg.writeStorage(tempMsg);
454 
455  // send request message
456  try {
457  socket->sendExact(outMsg);
458  } catch (tcpip::SocketException& e) {
459  msg << "Error while sending command: " << e.what();
460  errorMsg(msg);
461  return;
462  }
463 
464  answerLog << std::endl << "-> Command sent: <PositionConversion>:" << std::endl;
465  if (pos2D != NULL) {
466  answerLog << " DestPosition-2D: x=" << pos2D->x << " y=" << pos2D->y ;
467  } else if (pos3D != NULL) {
468  answerLog << " DestPosition-3D: x=" << pos3D->x << " y=" << pos3D->y << " z=" << pos3D->z;
469  } else if (posRoad != NULL) {
470  answerLog << " DestPosition-RoadMap: roadId=" << posRoad->roadId << " pos=" << posRoad->pos << " laneId=" << (int)posRoad->laneId ;
471  }
472  answerLog << " posId=" << posId << std::endl;
473 
474  // receive answer message
475  try {
476  socket->receiveExact(inMsg);
477  } catch (tcpip::SocketException& e) {
478  msg << "Error while receiving command: " << e.what();
479  errorMsg(msg);
480  return;
481  }
482 
483  // validate result state
485  return;
486  }
487 
488  // validate answer message
490 }
491 
492 
493 void
495  commandDistanceRequest(&pos1, NULL, NULL, &pos2, NULL, NULL, flag);
496 }
497 
498 
499 void
501  commandDistanceRequest(&pos1, NULL, NULL, NULL, &pos2, NULL, flag);
502 }
503 
504 
505 void
507  commandDistanceRequest(NULL, &pos1, NULL, NULL, &pos2, NULL, flag);
508 }
509 
510 
511 void
513  commandDistanceRequest(NULL, &pos1, NULL, &pos2, NULL, NULL, flag);
514 }
515 
516 
517 void
519  commandDistanceRequest(NULL, NULL, &pos1, &pos2, NULL, NULL, flag);
520 }
521 
522 
523 void
525  commandDistanceRequest(NULL, NULL, &pos1, NULL, &pos2, NULL, flag);
526 }
527 
528 
529 void
531  commandDistanceRequest(NULL, NULL, &pos1, NULL, NULL, &pos2, flag);
532 }
533 
534 
535 void
537  commandDistanceRequest(&pos1, NULL, NULL, NULL, NULL, &pos2, flag);
538 }
539 
540 
541 void
543  commandDistanceRequest(NULL, &pos1, NULL, NULL, NULL, &pos2, flag);
544 }
545 
546 
547 
548 void
550  testclient::Position3D* pos1_3D,
551  testclient::PositionRoadMap* pos1_Road,
552  testclient::Position* pos2_2D,
553  testclient::Position3D* pos2_3D,
554  testclient::PositionRoadMap* pos2_Road,
555  int flag) {
556  tcpip::Storage outMsg;
557  tcpip::Storage inMsg;
558  tcpip::Storage tempMsg;
559  std::stringstream msg;
560 
561  if (socket == NULL) {
562  msg << "#Error while sending command: no connection to server" ;
563  errorMsg(msg);
564  return;
565  }
566 
567  // command id
569  // position1
570  if (pos1_2D != NULL) {
572  tempMsg.writeDouble(pos1_2D->x);
573  tempMsg.writeDouble(pos1_2D->y);
574  } else if (pos1_3D != NULL) {
576  tempMsg.writeDouble(pos1_3D->x);
577  tempMsg.writeDouble(pos1_3D->y);
578  tempMsg.writeDouble(pos1_3D->z);
579  } else if (pos1_Road != NULL) {
581  tempMsg.writeString(pos1_Road->roadId);
582  tempMsg.writeDouble(pos1_Road->pos);
583  tempMsg.writeUnsignedByte(pos1_Road->laneId);
584  } else {
585  std::cerr << "Error in method commandDistanceRequest: position1 is NULL" << std::endl;
586  return;
587  }
588  // position2
589  if (pos2_2D != NULL) {
591  tempMsg.writeDouble(pos2_2D->x);
592  tempMsg.writeDouble(pos2_2D->y);
593  } else if (pos2_3D != NULL) {
595  tempMsg.writeDouble(pos2_3D->x);
596  tempMsg.writeDouble(pos2_3D->y);
597  tempMsg.writeDouble(pos2_3D->z);
598  } else if (pos2_Road != NULL) {
600  tempMsg.writeString(pos2_Road->roadId);
601  tempMsg.writeDouble(pos2_Road->pos);
602  tempMsg.writeUnsignedByte(pos2_Road->laneId);
603  } else {
604  std::cerr << "Error in method commandDistanceRequest: position2 is NULL" << std::endl;
605  return;
606  }
607  // flag
608  tempMsg.writeUnsignedByte(flag);
609  // command length
610  outMsg.writeUnsignedByte(1 + (int) tempMsg.size());
611  outMsg.writeStorage(tempMsg);
612 
613  // send request message
614  try {
615  socket->sendExact(outMsg);
616  } catch (tcpip::SocketException& e) {
617  msg << "Error while sending command: " << e.what();
618  errorMsg(msg);
619  return;
620  }
621 
622  answerLog << std::endl << "-> Command sent: <DistanceRequest>:" << std::endl;
623  if (pos1_2D != NULL) {
624  answerLog << " FirstPosition-2D: x=" << pos1_2D->x << " y=" << pos1_2D->y ;
625  } else if (pos1_3D != NULL) {
626  answerLog << " FirstPosition-3D: x=" << pos1_3D->x << " y=" << pos1_3D->y << " z=" << pos1_3D->z;
627  } else if (pos1_Road != NULL) {
628  answerLog << " FirstPosition-RoadMap: roadId=" << pos1_Road->roadId << " pos=" << pos1_Road->pos << " laneId=" << (int)pos1_Road->laneId ;
629  }
630  if (pos2_2D != NULL) {
631  answerLog << " SecondPosition-2D: x=" << pos2_2D->x << " y=" << pos2_2D->y ;
632  } else if (pos2_3D != NULL) {
633  answerLog << " SecondPosition-3D: x=" << pos2_3D->x << " y=" << pos2_3D->y << " z=" << pos2_3D->z;
634  } else if (pos2_Road != NULL) {
635  answerLog << " SecondPosition-RoadMap: roadId=" << pos2_Road->roadId << " pos=" << pos2_Road->pos << " laneId=" << (int)pos2_Road->laneId ;
636  }
637  answerLog << " Flag=" << flag << std::endl;
638 
639  // receive answer message
640  try {
641  socket->receiveExact(inMsg);
642  } catch (tcpip::SocketException& e) {
643  msg << "Error while receiving command: " << e.what();
644  errorMsg(msg);
645  return;
646  }
647 
648  // validate result state
649  if (!reportResultState(inMsg, CMD_DISTANCEREQUEST)) {
650  return;
651  }
652 
653  // validate answer message
655 }
656 
657 
658 void
659 TraCITestClient::commandGetVariable(int domID, int varID, const std::string& objID) {
660  tcpip::Storage outMsg, inMsg;
661  std::stringstream msg;
662  if (socket == NULL) {
663  msg << "#Error while sending command: no connection to server" ;
664  errorMsg(msg);
665  return;
666  }
667  // command length
668  outMsg.writeUnsignedByte(1 + 1 + 1 + 4 + (int) objID.length());
669  // command id
670  outMsg.writeUnsignedByte(domID);
671  // variable id
672  outMsg.writeUnsignedByte(varID);
673  // object id
674  outMsg.writeString(objID);
675 
676  // send request message
677  try {
678  socket->sendExact(outMsg);
679  } catch (tcpip::SocketException& e) {
680  msg << "Error while sending command: " << e.what();
681  errorMsg(msg);
682  return;
683  }
684  answerLog << std::endl << "-> Command sent: <GetVariable>:" << std::endl
685  << " domID=" << domID << " varID=" << varID
686  << " objID=" << objID << std::endl;
687 
688  // receive answer message
689  try {
690  socket->receiveExact(inMsg);
691  if (!reportResultState(inMsg, domID)) {
692  return;
693  }
694  } catch (tcpip::SocketException& e) {
695  msg << "Error while receiving command: " << e.what();
696  errorMsg(msg);
697  return;
698  }
699  // validate result state
700  try {
701  int respStart = inMsg.position();
702  int length = inMsg.readUnsignedByte();
703  if (length == 0) {
704  length = inMsg.readInt();
705  }
706  int cmdId = inMsg.readUnsignedByte();
707  if (cmdId != (domID + 0x10)) {
708  answerLog << "#Error: received response with command id: " << cmdId
709  << "but expected: " << (int)(domID + 0x10) << std::endl;
710  return;
711  }
712  answerLog << " CommandID=" << cmdId;
713  answerLog << " VariableID=" << inMsg.readUnsignedByte();
714  answerLog << " ObjectID=" << inMsg.readString();
715  int valueDataType = inMsg.readUnsignedByte();
716  answerLog << " valueDataType=" << valueDataType;
717  readAndReportTypeDependent(inMsg, valueDataType);
718  } catch (tcpip::SocketException& e) {
719  msg << "Error while receiving command: " << e.what();
720  errorMsg(msg);
721  return;
722  }
723 }
724 
725 
726 void
727 TraCITestClient::commandGetVariablePlus(int domID, int varID, const std::string& objID, std::ifstream& defFile) {
728  std::stringstream msg;
729  if (socket == NULL) {
730  msg << "#Error while sending command: no connection to server" ;
731  errorMsg(msg);
732  return;
733  }
734  tcpip::Storage outMsg, inMsg, tmp;
735  const int dataLength = setValueTypeDependant(tmp, defFile, msg);
736  std::string msgS = msg.str();
737  if (msgS != "") {
738  errorMsg(msg);
739  }
740  // command length (domID, varID, objID, dataType, data)
741  outMsg.writeUnsignedByte(1 + 1 + 1 + 4 + (int) objID.length() + dataLength);
742  // command id
743  outMsg.writeUnsignedByte(domID);
744  // variable id
745  outMsg.writeUnsignedByte(varID);
746  // object id
747  outMsg.writeString(objID);
748  // data type
749  outMsg.writeStorage(tmp);
750  // send request message
751  try {
752  socket->sendExact(outMsg);
753  } catch (tcpip::SocketException& e) {
754  msg << "Error while sending command: " << e.what();
755  errorMsg(msg);
756  return;
757  }
758  answerLog << std::endl << "-> Command sent: <GetVariable>:" << std::endl
759  << " domID=" << domID << " varID=" << varID
760  << " objID=" << objID << std::endl;
761 
762  // receive answer message
763  try {
764  socket->receiveExact(inMsg);
765  if (!reportResultState(inMsg, domID)) {
766  return;
767  }
768  } catch (tcpip::SocketException& e) {
769  msg << "Error while receiving command: " << e.what();
770  errorMsg(msg);
771  return;
772  }
773  // validate result state
774  try {
775  int respStart = inMsg.position();
776  int length = inMsg.readUnsignedByte();
777  if (length == 0) {
778  length = inMsg.readInt();
779  }
780  int cmdId = inMsg.readUnsignedByte();
781  if (cmdId != (domID + 0x10)) {
782  answerLog << "#Error: received response with command id: " << cmdId
783  << "but expected: " << (int)(domID + 0x10) << std::endl;
784  return;
785  }
786  answerLog << " CommandID=" << cmdId;
787  answerLog << " VariableID=" << inMsg.readUnsignedByte();
788  answerLog << " ObjectID=" << inMsg.readString();
789  int valueDataType = inMsg.readUnsignedByte();
790  answerLog << " valueDataType=" << valueDataType;
791  readAndReportTypeDependent(inMsg, valueDataType);
792  } catch (tcpip::SocketException& e) {
793  msg << "Error while receiving command: " << e.what();
794  errorMsg(msg);
795  return;
796  }
797 }
798 
799 
800 void
801 TraCITestClient::commandSubscribeVariable(int domID, const std::string& objID, int beginTime, int endTime, int varNo, std::ifstream& defFile) {
802  std::stringstream msg;
803  if (socket == NULL) {
804  msg << "#Error while sending command: no connection to server" ;
805  errorMsg(msg);
806  return;
807  }
808  tcpip::Storage outMsg, inMsg, tmp;
809  std::string msgS = msg.str();
810  if (msgS != "") {
811  errorMsg(msg);
812  }
813  // command length (domID, beginTime, endTime, objID, varNo, <vars>)
814  outMsg.writeUnsignedByte(0);
815  outMsg.writeInt(/*1 + 4 +*/ 5 + 1 + 4 + 4 + 4 + (int) objID.length() + 1 + varNo);
816  // command id
817  outMsg.writeUnsignedByte(domID);
818  // time
819  outMsg.writeInt(beginTime);
820  outMsg.writeInt(endTime);
821  // object id
822  outMsg.writeString(objID);
823  // command id
824  outMsg.writeUnsignedByte(varNo);
825  for (int i = 0; i < varNo; ++i) {
826  int var;
827  defFile >> var;
828  // variable id
829  outMsg.writeUnsignedByte(var);
830  }
831  // send request message
832  try {
833  socket->sendExact(outMsg);
834  } catch (tcpip::SocketException& e) {
835  msg << "Error while sending command: " << e.what();
836  errorMsg(msg);
837  return;
838  }
839  answerLog << std::endl << "-> Command sent: <SubscribeVariable>:" << std::endl
840  << " domID=" << domID << " objID=" << objID << " with " << varNo << " variables" << std::endl;
841 
842  // receive answer message
843  try {
844  socket->receiveExact(inMsg);
845  if (!reportResultState(inMsg, domID)) {
846  return;
847  }
848  } catch (tcpip::SocketException& e) {
849  msg << "Error while receiving command: " << e.what();
850  errorMsg(msg);
851  return;
852  }
853  // validate result state
854  try {
855  validateSubscription(inMsg);
856  } catch (tcpip::SocketException& e) {
857  msg << "Error while receiving command: " << e.what();
858  errorMsg(msg);
859  return;
860  }
861 }
862 
863 
864 
865 int
866 TraCITestClient::setValueTypeDependant(tcpip::Storage& into, std::ifstream& defFile, std::stringstream& msg) {
867  std::string dataTypeS, valueS;
868  defFile >> dataTypeS;
869  if (dataTypeS == "<airDist>") {
871  return 1;
872  } else if (dataTypeS == "<drivingDist>") {
874  return 1;
875  }
876  defFile >> valueS;
877  if (dataTypeS == "<int>") {
879  into.writeInt(atoi(valueS.c_str()));
880  return 4 + 1;
881  } else if (dataTypeS == "<byte>") {
883  into.writeByte(atoi(valueS.c_str()));
884  return 1 + 1;
885  } else if (dataTypeS == "<ubyte>") {
887  into.writeByte(atoi(valueS.c_str()));
888  return 1 + 1;
889  } else if (dataTypeS == "<float>") {
891  into.writeFloat(float(atof(valueS.c_str())));
892  return 4 + 1;
893  } else if (dataTypeS == "<double>") {
895  into.writeDouble(atof(valueS.c_str()));
896  return 8 + 1;
897  } else if (dataTypeS == "<string>") {
899  into.writeString(valueS);
900  return 4 + 1 + (int) valueS.length();
901  } else if (dataTypeS == "<string*>") {
902  std::vector<std::string> slValue;
903  int number = atoi(valueS.c_str());
904  int length = 1 + 4;
905  for (int i = 0; i < number; ++i) {
906  std::string tmp;
907  defFile >> tmp;
908  slValue.push_back(tmp);
909  length += 4 + int(tmp.length());
910  }
912  into.writeStringList(slValue);
913  return length;
914  } else if (dataTypeS == "<compound>") {
916  int number = atoi(valueS.c_str());
917  into.writeInt(number);
918  int length = 1 + 4;
919  for (int i = 0; i < number; ++i) {
920  length += setValueTypeDependant(into, defFile, msg);
921  }
922  return length;
923  } else if (dataTypeS == "<color>") {
925  into.writeUnsignedByte(atoi(valueS.c_str()));
926  for (int i = 0; i < 3; ++i) {
927  defFile >> valueS;
928  into.writeUnsignedByte(atoi(valueS.c_str()));
929  }
930  return 1 + 4;
931  } else if (dataTypeS == "<position2D>") {
933  into.writeDouble(atof(valueS.c_str()));
934  defFile >> valueS;
935  into.writeDouble(atof(valueS.c_str()));
936  return 1 + 8 + 8;
937  } else if (dataTypeS == "<position3D>") {
939  into.writeDouble(atof(valueS.c_str()));
940  defFile >> valueS;
941  into.writeDouble(atof(valueS.c_str()));
942  defFile >> valueS;
943  into.writeDouble(atof(valueS.c_str()));
944  return 1 + 8 + 8 + 8;
945  } else if (dataTypeS == "<positionRoadmap>") {
947  into.writeString(valueS);
948  int length = 1 + 8 + (int) valueS.length();
949  defFile >> valueS;
950  into.writeDouble(atof(valueS.c_str()));
951  defFile >> valueS;
952  into.writeUnsignedByte(atoi(valueS.c_str()));
953  return length + 4 + 1;
954  } else if (dataTypeS == "<shape>") {
956  int number = atoi(valueS.c_str());
957  into.writeUnsignedByte(number);
958  int length = 1 + 1;
959  for (int i = 0; i < number; ++i) {
960  std::string x, y;
961  defFile >> x >> y;
962  into.writeDouble(atof(x.c_str()));
963  into.writeDouble(atof(y.c_str()));
964  length += 8 + 8;
965  }
966  return length;
967  }
968  msg << "## Unknown data type: " << dataTypeS;
969  return 0;
970 }
971 
972 void
973 TraCITestClient::commandSetValue(int domID, int varID, const std::string& objID, std::ifstream& defFile) {
974  std::stringstream msg;
975  if (socket == NULL) {
976  msg << "#Error while sending command: no connection to server" ;
977  errorMsg(msg);
978  return;
979  }
980  tcpip::Storage outMsg, inMsg, tmp;
981  int dataLength = setValueTypeDependant(tmp, defFile, msg);
982  std::string msgS = msg.str();
983  if (msgS != "") {
984  errorMsg(msg);
985  }
986  // command length (domID, varID, objID, dataType, data)
987  outMsg.writeUnsignedByte(1 + 1 + 1 + 4 + (int) objID.length() + dataLength);
988  // command id
989  outMsg.writeUnsignedByte(domID);
990  // variable id
991  outMsg.writeUnsignedByte(varID);
992  // object id
993  outMsg.writeString(objID);
994  // data type
995  outMsg.writeStorage(tmp);
996  // send request message
997  try {
998  socket->sendExact(outMsg);
999  } catch (tcpip::SocketException& e) {
1000  msg << "Error while sending command: " << e.what();
1001  errorMsg(msg);
1002  return;
1003  }
1004  answerLog << std::endl << "-> Command sent: <SetValue>:" << std::endl
1005  << " domID=" << domID << " varID=" << varID
1006  << " objID=" << objID << std::endl;
1007 
1008  // receive answer message
1009  try {
1010  socket->receiveExact(inMsg);
1011  if (!reportResultState(inMsg, domID)) {
1012  return;
1013  }
1014  } catch (tcpip::SocketException& e) {
1015  msg << "Error while receiving command: " << e.what();
1016  errorMsg(msg);
1017  return;
1018  }
1019 }
1020 
1021 
1022 
1023 
1024 void
1026  tcpip::Storage outMsg;
1027  tcpip::Storage inMsg;
1028  std::stringstream msg;
1029 
1030  if (socket == NULL) {
1031  msg << "#Error while sending command: no connection to server" ;
1032  errorMsg(msg);
1033  return;
1034  }
1035 
1036  // command length
1037  outMsg.writeUnsignedByte(1 + 1);
1038  // command id
1039  outMsg.writeUnsignedByte(CMD_CLOSE);
1040 
1041  // send request message
1042  try {
1043  socket->sendExact(outMsg);
1044  } catch (tcpip::SocketException& e) {
1045  msg << "Error while sending command: " << e.what();
1046  errorMsg(msg);
1047  return;
1048  }
1049 
1050  answerLog << std::endl << "-> Command sent: <Close>:" << std::endl;
1051 
1052  // receive answer message
1053  try {
1054  socket->receiveExact(inMsg);
1055  } catch (tcpip::SocketException& e) {
1056  msg << "Error while receiving command: " << e.what();
1057  errorMsg(msg);
1058  return;
1059  }
1060 
1061  // validate result state
1062  if (!reportResultState(inMsg, CMD_CLOSE)) {
1063  return;
1064  }
1065 }
1066 
1067 
1068 bool
1070  try {
1071  int noSubscriptions = inMsg.readInt();
1072  for (int s = 0; s < noSubscriptions; ++s) {
1073  /*
1074  if (!reportResultState(inMsg, CMD_SIMSTEP2, true)) {
1075  return false;
1076  }
1077  */
1078  if (!validateSubscription(inMsg)) {
1079  return false;
1080  }
1081  }
1082  } catch (std::invalid_argument& e) {
1083  answerLog << "#Error while reading message:" << e.what() << std::endl;
1084  return false;
1085  }
1086  return true;
1087 }
1088 
1089 
1090 bool
1092  try {
1093  int respStart = inMsg.position();
1094  int length = inMsg.readUnsignedByte();
1095  if (length == 0) {
1096  length = inMsg.readInt();
1097  }
1098  int cmdId = inMsg.readUnsignedByte();
1099  if (cmdId < 0xe0 || cmdId > 0xef) {
1100  answerLog << "#Error: received response with command id: " << cmdId << " but expected a subscription response (0xe0-0xef)" << std::endl;
1101  return false;
1102  }
1103  answerLog << " CommandID=" << cmdId;
1104  answerLog << " ObjectID=" << inMsg.readString();
1105  unsigned int varNo = inMsg.readUnsignedByte();
1106  answerLog << " #variables=" << varNo << std::endl;
1107  for (unsigned int i = 0; i < varNo; ++i) {
1108  answerLog << " VariableID=" << inMsg.readUnsignedByte();
1109  bool ok = inMsg.readUnsignedByte() == RTYPE_OK;
1110  answerLog << " ok=" << ok;
1111  int valueDataType = inMsg.readUnsignedByte();
1112  answerLog << " valueDataType=" << valueDataType;
1113  readAndReportTypeDependent(inMsg, valueDataType);
1114  }
1115  } catch (std::invalid_argument& e) {
1116  answerLog << "#Error while reading message:" << e.what() << std::endl;
1117  return false;
1118  }
1119  return true;
1120 }
1121 
1122 
1123 bool
1125  int cmdId;
1126  int cmdLength;
1127  int posType;
1128  int reqPosType;
1129  int cmdStart;
1131  testclient::Position pos2D;
1132  testclient::Position3D pos3D;
1133 
1134  try {
1135  cmdStart = inMsg.position();
1136  cmdLength = inMsg.readUnsignedByte();
1137  // read command id
1138  cmdId = inMsg.readUnsignedByte();
1139  if (cmdId != CMD_POSITIONCONVERSION) {
1140  answerLog << "#Error: received response with command id: " << cmdId
1141  << "but expected: " << (int)CMD_POSITIONCONVERSION << std::endl;
1142  return false;
1143  }
1144  answerLog << ".. Received Response <PositionConversion>:" << std::endl;
1145  // read converted position
1146  posType = inMsg.readUnsignedByte();
1147  switch (posType) {
1148  case POSITION_2D:
1149  pos2D.x = inMsg.readDouble();
1150  pos2D.y = inMsg.readDouble();
1151  answerLog << "2D-Position: x=" << pos2D.x << " y=" << pos2D.y << std::endl;
1152  break;
1153  case POSITION_3D:
1154  answerLog << "3D-Position: ";
1155  pos3D.x = inMsg.readDouble();
1156  pos3D.y = inMsg.readDouble();
1157  pos3D.z = inMsg.readDouble();
1158  answerLog << "x=" << pos3D.x << " y=" << pos3D.y << " z=" << pos3D.z << std::endl;
1159  break;
1160  case POSITION_ROADMAP:
1161  roadPos.roadId = inMsg.readString();
1162  roadPos.pos = inMsg.readDouble();
1163  roadPos.laneId = inMsg.readUnsignedByte();
1164  answerLog << "RoadMap-Position: roadId=" << roadPos.roadId << " pos=" << roadPos.pos
1165  << " laneId=" << (int)roadPos.laneId << std::endl;
1166  break;
1167  default:
1168  answerLog << "#Error: received unknown position format" << std::endl;
1169  return false;
1170  }
1171  // read requested position type
1172  reqPosType = inMsg.readUnsignedByte();
1173  if (reqPosType != posType) {
1174  answerLog << "#Warning: requested position type (" << reqPosType
1175  << ") and received position type (" << posType << ") do not match" << std::endl;
1176  }
1177  // check command length
1178  if ((cmdStart + cmdLength) != inMsg.position()) {
1179  answerLog << "#Error: command at position " << cmdStart << " has wrong length" << std::endl;
1180  return false;
1181  }
1182  } catch (std::invalid_argument& e) {
1183  answerLog << "#Error while reading message:" << e.what() << std::endl;
1184  return false;
1185  }
1186 
1187  return true;
1188 }
1189 
1190 
1191 bool
1193  int cmdId;
1194  int cmdLength;
1195  int flag;
1196  int cmdStart;
1197  SUMOReal distance;
1198  /*testclient::PositionRoadMap roadPos;
1199  testclient::Position pos2D;
1200  testclient::Position3D pos3D;*/
1201 
1202  try {
1203  cmdStart = inMsg.position();
1204  cmdLength = inMsg.readUnsignedByte();
1205  // read command id
1206  cmdId = inMsg.readUnsignedByte();
1207  if (cmdId != CMD_DISTANCEREQUEST) {
1208  answerLog << "#Error: received response with command id: " << cmdId
1209  << "but expected: " << (int)CMD_DISTANCEREQUEST << std::endl;
1210  return false;
1211  }
1212  answerLog << ".. Received Response <DistanceRequest>:" << std::endl;
1213  // read flag
1214  flag = inMsg.readUnsignedByte();
1215  answerLog << " flag=" << flag;
1216  // read computed distance
1217  distance = inMsg.readDouble();
1218  answerLog << " distance=" << distance << std::endl;
1220  //posType = inMsg.readUnsignedByte();
1221  //switch (posType) {
1222  //case POSITION_2D:
1223  // pos2D.x = inMsg.readDouble();
1224  // pos2D.y = inMsg.readDouble();
1225  // answerLog << "2D-Position: x=" << pos2D.x << " y=" << pos2D.y;
1226  // break;
1227  //case POSITION_3D:
1228  // answerLog << "3D-Position: ";
1229  // pos3D.x = inMsg.readDouble();
1230  // pos3D.y = inMsg.readDouble();
1231  // pos3D.z = inMsg.readDouble();
1232  // answerLog << "x=" << pos3D.x << " y=" << pos3D.y << " z=" << pos3D.z;
1233  // break;
1234  //case POSITION_ROADMAP:
1235  // roadPos.roadId = inMsg.readString();
1236  // roadPos.pos = inMsg.readDouble();
1237  // roadPos.laneId = inMsg.readUnsignedByte();
1238  // answerLog << "RoadMap-Position: roadId=" << roadPos.roadId << " pos=" << roadPos.pos
1239  // << " laneId=" << (int)roadPos.laneId;
1240  // break;
1241  //default:
1242  // answerLog << "#Error: received unknown position format: " << posType << std::endl;
1243  // return false;
1244  //}
1245  // check command length
1246  if ((cmdStart + cmdLength) != inMsg.position()) {
1247  answerLog << "#Error: command at position " << cmdStart << " has wrong length" << std::endl;
1248  return false;
1249  }
1250  } catch (std::invalid_argument& e) {
1251  answerLog << "#Error while reading message:" << e.what() << std::endl;
1252  return false;
1253  }
1254 
1255  return true;
1256 }
1257 
1258 
1259 bool
1261  if (valueDataType == TYPE_UBYTE) {
1262  int ubyte = inMsg.readUnsignedByte();
1263  answerLog << " Unsigned Byte Value: " << ubyte << std::endl;
1264  } else if (valueDataType == TYPE_BYTE) {
1265  int byte = inMsg.readByte();
1266  answerLog << " Byte value: " << byte << std::endl;
1267  } else if (valueDataType == TYPE_INTEGER) {
1268  int integer = inMsg.readInt();
1269  answerLog << " Int value: " << integer << std::endl;
1270  } else if (valueDataType == TYPE_FLOAT) {
1271  float floatv = inMsg.readFloat();
1272  if (floatv < 0.1 && floatv > 0) {
1273  answerLog.setf(std::ios::scientific, std::ios::floatfield);
1274  }
1275  answerLog << " float value: " << floatv << std::endl;
1276  answerLog.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
1277  answerLog.setf(std::ios::showpoint); // print decimal point
1278  answerLog << std::setprecision(2);
1279  } else if (valueDataType == TYPE_DOUBLE) {
1280  double doublev = inMsg.readDouble();
1281  answerLog << " Double value: " << doublev << std::endl;
1282  } else if (valueDataType == TYPE_BOUNDINGBOX) {
1284  box.lowerLeft.x = inMsg.readDouble();
1285  box.lowerLeft.y = inMsg.readDouble();
1286  box.upperRight.x = inMsg.readDouble();
1287  box.upperRight.y = inMsg.readDouble();
1288  answerLog << " BoundaryBoxValue: lowerLeft x=" << box.lowerLeft.x
1289  << " y=" << box.lowerLeft.y << " upperRight x=" << box.upperRight.x
1290  << " y=" << box.upperRight.y << std::endl;
1291  } else if (valueDataType == TYPE_POLYGON) {
1292  int length = inMsg.readUnsignedByte();
1293  answerLog << " PolygonValue: ";
1294  for (int i = 0; i < length; i++) {
1295  SUMOReal x = inMsg.readDouble();
1296  SUMOReal y = inMsg.readDouble();
1297  answerLog << "(" << x << "," << y << ") ";
1298  }
1299  answerLog << std::endl;
1300  } else if (valueDataType == POSITION_3D) {
1301  SUMOReal x = inMsg.readDouble();
1302  SUMOReal y = inMsg.readDouble();
1303  SUMOReal z = inMsg.readDouble();
1304  answerLog << " Position3DValue: " << std::endl;
1305  answerLog << " x: " << x << " y: " << y
1306  << " z: " << z << std::endl;
1307  } else if (valueDataType == POSITION_ROADMAP) {
1308  std::string roadId = inMsg.readString();
1309  SUMOReal pos = inMsg.readDouble();
1310  int laneId = inMsg.readUnsignedByte();
1311  answerLog << " RoadMapPositionValue: roadId=" << roadId
1312  << " pos=" << pos
1313  << " laneId=" << laneId << std::endl;
1314  } else if (valueDataType == TYPE_TLPHASELIST) {
1315  int length = inMsg.readUnsignedByte();
1316  answerLog << " TLPhaseListValue: length=" << length << std::endl;
1317  for (int i = 0; i < length; i++) {
1318  std::string pred = inMsg.readString();
1319  std::string succ = inMsg.readString();
1320  int phase = inMsg.readUnsignedByte();
1321  answerLog << " precRoad=" << pred << " succRoad=" << succ
1322  << " phase=";
1323  switch (phase) {
1324  case TLPHASE_RED:
1325  answerLog << "red" << std::endl;
1326  break;
1327  case TLPHASE_YELLOW:
1328  answerLog << "yellow" << std::endl;
1329  break;
1330  case TLPHASE_GREEN:
1331  answerLog << "green" << std::endl;
1332  break;
1333  default:
1334  answerLog << "#Error: unknown phase value" << (int)phase << std::endl;
1335  return false;
1336  }
1337  }
1338  } else if (valueDataType == TYPE_STRING) {
1339  std::string s = inMsg.readString();
1340  answerLog << " string value: " << s << std::endl;
1341  } else if (valueDataType == TYPE_STRINGLIST) {
1342  std::vector<std::string> s = inMsg.readStringList();
1343  answerLog << " string list value: [ " << std::endl;
1344  for (std::vector<std::string>::iterator i = s.begin(); i != s.end(); ++i) {
1345  if (i != s.begin()) {
1346  answerLog << ", ";
1347  }
1348  answerLog << '"' << *i << '"';
1349  }
1350  answerLog << " ]" << std::endl;
1351  } else if (valueDataType == TYPE_COMPOUND) {
1352  int no = inMsg.readInt();
1353  answerLog << " compound value with " << no << " members: [ " << std::endl;
1354  for (int i = 0; i < no; ++i) {
1355  int currentValueDataType = inMsg.readUnsignedByte();
1356  answerLog << " valueDataType=" << currentValueDataType;
1357  readAndReportTypeDependent(inMsg, currentValueDataType);
1358  }
1359  answerLog << " ]" << std::endl;
1360  } else if (valueDataType == POSITION_2D) {
1361  SUMOReal xv = inMsg.readDouble();
1362  SUMOReal yv = inMsg.readDouble();
1363  answerLog << " position value: (" << xv << "," << yv << ")" << std::endl;
1364  } else if (valueDataType == TYPE_COLOR) {
1365  int r = inMsg.readUnsignedByte();
1366  int g = inMsg.readUnsignedByte();
1367  int b = inMsg.readUnsignedByte();
1368  int a = inMsg.readUnsignedByte();
1369  answerLog << " color value: (" << r << "," << g << "," << b << "," << a << ")" << std::endl;
1370  } else {
1371  answerLog << "#Error: unknown valueDataType!" << std::endl;
1372  return false;
1373  }
1374  return true;
1375 }