SopasBase.cpp
Go to the documentation of this file.
1 //
2 // SopasBase.cpp
3 //
4 // Created on: 18.07.2011
5 // Author: sick
6 //
7 
9 // #include "../manager.hpp"
12 #include "sick_scan/tcp/Mutex.hpp"
13 
14 namespace devices
15 {
16 
17 #define SOPASBASE_VERSION "1.0.0"
18 
19 const std::string SopasBase::EVENTNAME_SUBSCRIBE_EVALCASES("LFErec");
20 const std::string SopasBase::EVENTNAME_SUBSCRIBE_SCANS("LMDscandata");
21 const std::string SopasBase::METHODNAME_LOGIN("SetAccessMode");
22 const std::string SopasBase::METHODNAME_LOGOUT("Run");
23 const std::string SopasBase::METHODNAME_SET_SCANCONFIG("mLMPsetscancfg");
24 const std::string SopasBase::METHODNAME_START_MEASURE("LMCstartmeas");
25 const std::string SopasBase::METHODNAME_STOP_MEASURE("LMCstopmeas");
26 const std::string SopasBase::VARIABLENAME_SCANCONFIG("LMPscancfg");
27 const std::string SopasBase::VARIABLENAME_DATAOUTPUTRANGE("LMPoutputRange");
28 const std::string SopasBase::VARIABLENAME_SCANDATACONFIG("LMDscandatacfg");
29 const std::string SopasBase::VARIABLENAME_DEVICEIDENT("DeviceIdent");
30 
31 // sopas commands
32 const std::string SopasBase::COMMAND_Read_Variable_ByIndex("RI");
33 const std::string SopasBase::COMMAND_Write_Variable_ByIndex("WI");
34 const std::string SopasBase::COMMAND_Invoke_Method_ByIndex("MI");
35 const std::string SopasBase::COMMAND_Method_Result_ByIndex("AI");
36 const std::string SopasBase::COMMAND_Register_Event_ByIndex("EI");
37 const std::string SopasBase::COMMAND_Send_Event_ByIndex("SI"); // receive data event
38 
39 const std::string SopasBase::COMMAND_Read_Variable_Answer("RA");
40 const std::string SopasBase::COMMAND_Write_Variable_Answer("WA");
41 const std::string SopasBase::COMMAND_Invoke_Method_Answer("MA");
42 const std::string SopasBase::COMMAND_Method_Result_Answer("AA");
43 const std::string SopasBase::COMMAND_Register_Event_Answer("EA");
44 const std::string SopasBase::COMMAND_Event_Acknowledge("SA");
45 
46 const std::string SopasBase::COMMAND_Read_Variable_ByName("RN");
47 const std::string SopasBase::COMMAND_Write_Variable_ByName("WN");
48 const std::string SopasBase::COMMAND_Invoke_Method_ByName("MN");
49 const std::string SopasBase::COMMAND_Method_Result_ByName("AN");
50 const std::string SopasBase::COMMAND_Register_Event_ByName("EN");
51 const std::string SopasBase::COMMAND_Send_Event_ByName("SN"); // receive data event
52 
54 
55 
56 
58  m_state(CONSTRUCTED)
59 {
60  m_beVerbose = false;
61 
62  m_protocol = CoLa_A; // Default protocol is CoLa-A
63 }
64 
65 
66 
68 {
69  printInfoMessage("Sopas device destructor: Running.", m_beVerbose);
70 
71  // Derived device must be stopped in it's constructor. No virtual functions may be called here!
72 // assert(isRunning() == false);
73 
74  printInfoMessage("Sopas device destructor: Stopped, now disconnecting.", m_beVerbose);
75 
76  // Disconnect and shut down receive thread.
77  if (isConnected() == true)
78  {
79  // Change from CONNECTED to CONSTRUCTED
80  disconnect();
81  }
82 
83 // printInfoMessage("Sopas device destructor: Disconnected, now deleting socket.", m_beVerbose);
84 
85  printInfoMessage("Sopas device destructor: Done, device is deleted.", m_beVerbose);
86 }
87 
88 
89 
90 //
91 // Initialisation from Scanner class:
92 // Parameter setup only. Afterwards, call connect() to connect to the scanner.
93 //
95  std::string ipAddress,
96  UINT16 portNumber,
97  bool weWantScanData,
98  bool weWantFieldData,
99  bool readOnlyMode,
100  Tcp::DisconnectFunction disconnectFunction,
101  void* obj)
102 {
103  m_protocol = protocol;
104  m_ipAddress = ipAddress;
105  m_portNumber = portNumber;
106  m_weWantScanData = weWantScanData;
107  m_weWantFieldData = weWantFieldData;
108  setReadOnlyMode(readOnlyMode);
109 
110  m_tcp.setDisconnectCallbackFunction(disconnectFunction, obj);
111 
112  return true;
113 }
114 
115 
116 //
117 // Verbinde mit dem unter init() eingestellten Geraet, und pruefe die Verbindung
118 // durch einen DeviceIdent-Aufruf.
119 //
120 // true = Erfolgreich.
121 //
123 {
124  printInfoMessage("SopasBase::connect: Called.", m_beVerbose);
125 
126  assert (m_state == CONSTRUCTED); // must not be opened or running already
127 
128  // Initialise buffer variables
129  m_numberOfBytesInReceiveBuffer = 0; // Buffer is empty
130  m_numberOfBytesInResponseBuffer = 0; // Buffer is empty
131  // m_isLoggedIn = false;
132  m_scannerName = "";
133  m_scannerVersion = "";
134 
135  // Establish connection here
136  // Set the data input callback for our TCP connection
138 
139  bool success = openTcpConnection();
140  if (success == true)
141  {
142  // Check if scanner type matches
143  m_state = CONNECTED;
144  printInfoMessage("SopasBase::connect: Reading scanner infos", m_beVerbose);
146 
147  if (success == true)
148  {
149  printInfoMessage("SopasBase::connect: Initialisation was successful.", m_beVerbose);
150  }
151  else
152  {
153  printError("SopasBase::connect: Failed to read scanner type and version.");
154  }
155  }
156 
157  if (success == false)
158  {
159  printWarning("SopasBase::connect: Initialisation failed!");
160  }
161  else
162  {
163  // Here, we could unsubscribe all events to have a defined default state.
164  }
165 
166  printInfoMessage("SopasBase::connect: Done.", m_beVerbose);
167  return success;
168 }
169 
170 
171 
172 //
173 // True, if state is CONNECTED, that is:
174 // - A TCP-connection exists
175 // - Read thread is running
176 //
178 {
179  return (m_state == CONNECTED);
180 }
181 
182 //
183 // Disconnect from the scanner, and close the interface.
184 //
186 {
188 
189  // Change back to CONSTRUCTED
191  return true;
192 }
193 
194 
195 
196 //
197 // (Un)set read only mode. Setting this mode, the sensor will ignore commands which will change any
198 // parameters on the device. The sensor itself will execute such commands.
199 //
201 {
203 }
204 
205 
206 
208 {
209  return m_readOnlyMode;
210 }
211 
212 
213 
220 {
221  printInfoMessage("SopasBase::openTcpConnection: Connecting TCP/IP connection to " + m_ipAddress + ":" + toString(m_portNumber) + " ...", m_beVerbose);
222 
223  bool success = m_tcp.open(m_ipAddress, m_portNumber, m_beVerbose);
224  if (success == false)
225  {
226  printError("SopasBase::openTcpConnection: ERROR: Failed to establish TCP connection, aborting!");
227  return false;
228  }
229 
230  return true;
231 }
232 
233 
234 
235 //
236 // Close TCP-connection and shut down read thread
237 //
239 {
240  if (m_tcp.isOpen())
241  {
242  m_tcp.close();
243  }
244 }
245 
246 //
247 // Static entry point.
248 //
249 void SopasBase::readCallbackFunctionS(void* obj, UINT8* buffer, UINT32& numOfBytes)
250 {
251  ((SopasBase*)obj)->readCallbackFunction(buffer, numOfBytes);
252 }
253 
254 
259 void SopasBase::readCallbackFunction(UINT8* buffer, UINT32& numOfBytes)
260 {
261  bool beVerboseHere = false;
262  printInfoMessage("SopasBase::readCallbackFunction(): Called with " + toString(numOfBytes) + " available bytes.", beVerboseHere);
263 
264  ScopedLock lock(&m_receiveDataMutex); // Mutex for access to the input buffer
265  UINT32 remainingSpace = sizeof(m_receiveBuffer) - m_numberOfBytesInReceiveBuffer;
266  UINT32 bytesToBeTransferred = numOfBytes;
267  if (remainingSpace < numOfBytes)
268  {
269  bytesToBeTransferred = remainingSpace;
270  printWarning("SopasBase::readCallbackFunction(): Input buffer space is to small, transferring only " +
271  ::toString(bytesToBeTransferred) + " of " + ::toString(numOfBytes) + " bytes.");
272  }
273  else
274  {
275  printInfoMessage("SopasBase::readCallbackFunction(): Transferring " + ::toString(bytesToBeTransferred) +
276  " bytes from TCP to input buffer.", beVerboseHere);
277  }
278 
279  if (bytesToBeTransferred > 0)
280  {
281  // Data can be transferred into our input buffer
282  memcpy(&(m_receiveBuffer[m_numberOfBytesInReceiveBuffer]), buffer, bytesToBeTransferred);
283  m_numberOfBytesInReceiveBuffer += bytesToBeTransferred;
284 
285  UINT32 size = 0;
286 
287  while (1)
288  {
289  // Now work on the input buffer until all received datasets are processed
291 
292  size = frame.size();
293  if (size == 0)
294  {
295  // Framesize = 0: There is no valid frame in the buffer. The buffer is either empty or the frame
296  // is incomplete, so leave the loop
297  printInfoMessage("SopasBase::readCallbackFunction(): No complete frame in input buffer, we are done.", beVerboseHere);
298 
299  // Leave the loop
300  break;
301  }
302  else
303  {
304  // A frame was found in the buffer, so process it now.
305  printInfoMessage("SopasBase::readCallbackFunction(): Processing a frame of length " + ::toString(frame.size()) + " bytes.", beVerboseHere);
306  processFrame(frame);
307  }
308  }
309  }
310  else
311  {
312  // There was input data from the TCP interface, but our input buffer was unable to hold a single byte.
313  // Either we have not read data from our buffer for a long time, or something has gone wrong. To re-sync,
314  // we clear the input buffer here.
316  }
317 
318  printInfoMessage("SopasBase::readCallbackFunction(): Leaving. Current input buffer fill level is " +
319  ::toString(m_numberOfBytesInReceiveBuffer) + " bytes.", beVerboseHere);
320 }
321 
322 
323 
324 //
325 // Look for 23-frame (STX/ETX) in receive buffer.
326 // Move frame to start of buffer
327 //
328 // Return: 0 : No (complete) frame found
329 // >0 : Frame length
330 //
332 {
333  UINT32 frameLen = 0;
334  UINT32 i;
335 
336  // Depends on protocol...
337  if (m_protocol == CoLa_A)
338  {
339  //
340  // COLA-A
341  //
342  // Must start with STX (0x02)
343  if (m_receiveBuffer[0] != 0x02)
344  {
345  // Look for starting STX (0x02)
346  for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
347  {
348  if (m_receiveBuffer[i] == 0x02)
349  {
350  break;
351  }
352  }
353 
354  // Found beginning of frame?
356  {
357  // No start found, everything can be discarded
358  m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
359  return SopasEventMessage(); // No frame found
360  }
361 
362  // Move frame start to index 0
364  memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), newLen);
366  }
367 
368  // Look for ending ETX (0x03)
369  for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
370  {
371  if (m_receiveBuffer[i] == 0x03)
372  {
373  break;
374  }
375  }
376 
377  // Found end?
379  {
380  // No end marker found, so it's not a complete frame (yet)
381  return SopasEventMessage(); // No frame found
382  }
383 
384  // Calculate frame length in byte
385  frameLen = i + 1;
386 
387  return SopasEventMessage(m_receiveBuffer, CoLa_A, frameLen);
388  }
389  else if (m_protocol == CoLa_B)
390  {
391  UINT32 magicWord;
392  UINT32 payloadlength;
393 
395  {
396  return SopasEventMessage();
397  }
398  UINT16 pos = 0;
399  magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
400  if (magicWord != 0x02020202)
401  {
402  // Look for starting STX (0x02020202)
403  for (i = 1; i <= m_numberOfBytesInReceiveBuffer - 4; i++)
404  {
405  pos = i; // this is needed, as the position value is updated by getIntegerFromBuffer
406  magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
407  if (magicWord == 0x02020202)
408  {
409  // found magic word
410  break;
411  }
412  }
413 
414  // Found beginning of frame?
415  if (i > m_numberOfBytesInReceiveBuffer - 4)
416  {
417  // No start found, everything can be discarded
418  m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
419  return SopasEventMessage(); // No frame found
420  }
421  else
422  {
423  // Move frame start to index
424  UINT32 bytesToMove = m_numberOfBytesInReceiveBuffer - i;
425  memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), bytesToMove); // payload+magic+length+s+checksum
426  m_numberOfBytesInReceiveBuffer = bytesToMove;
427  }
428  }
429 
430  // Pruefe Laenge des Pufferinhalts
432  {
433  // Es sind nicht genug Daten fuer einen Frame
434  printInfoMessage("SopasBase::findFrameInReceiveBuffer: Frame cannot be decoded yet, only " +
435  ::toString(m_numberOfBytesInReceiveBuffer) + " bytes in the buffer.", m_beVerbose);
436  return SopasEventMessage();
437  }
438 
439  // Read length of payload
440  pos = 4;
441  payloadlength = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
442  printInfoMessage("SopasBase::findFrameInReceiveBuffer: Decoded payload length is " + ::toString(payloadlength) + " bytes.", m_beVerbose);
443 
444  // Ist die Datenlaenge plausibel und wuede in den Puffer passen?
445  if (payloadlength > (sizeof(m_receiveBuffer) - 9))
446  {
447  // magic word + length + checksum = 9
448  printWarning("SopasBase::findFrameInReceiveBuffer: Frame too big for receive buffer. Frame discarded with length:"
449  + ::toString(payloadlength) + ".");
451  return SopasEventMessage();
452  }
453  if ((payloadlength + 9) > m_numberOfBytesInReceiveBuffer)
454  {
455  // magic word + length + s + checksum = 10
456  printInfoMessage("SopasBase::findFrameInReceiveBuffer: Frame not complete yet. Waiting for the rest of it (" +
457  ::toString(payloadlength + 9 - m_numberOfBytesInReceiveBuffer) + " bytes missing).", m_beVerbose);
458  return SopasEventMessage(); // frame not complete
459  }
460 
461  // Calculate the total frame length in bytes: Len = Frame (9 bytes) + Payload
462  frameLen = payloadlength + 9;
463 
464  //
465  // test checksum of payload
466  //
467  UINT8 temp = 0;
468  UINT8 temp_xor = 0;
469  UINT8 checkSum;
470 
471  // Read original checksum
472  pos = frameLen - 1;
473  checkSum = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
474 
475  // Erzeuge die Pruefsumme zum Vergleich
476  for (UINT16 i = 8; i < (frameLen - 1); i++)
477  {
478  pos = i;
479  temp = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
480  temp_xor = temp_xor ^ temp;
481  }
482 
483  // Vergleiche die Pruefsummen
484  if (temp_xor != checkSum)
485  {
486  printWarning("SopasBase::findFrameInReceiveBuffer: Wrong checksum, Frame discarded.");
488  return SopasEventMessage();
489  }
490 
491  return SopasEventMessage(m_receiveBuffer, CoLa_B, frameLen);
492  }
493 
494  // Return empty frame
495  return SopasEventMessage();
496 }
497 
498 
499 
506 {
507  UINT8 sendBuffer[1024];
508 
509  assert (len < 1000);
510  assert (m_tcp.isOpen() == true);
511 
512  // Frame the string
513  if (m_protocol == CoLa_A)
514  {
515  colaa::addFrameToBuffer(sendBuffer, buffer, &len);
516  }
517  else if (m_protocol == CoLa_B)
518  {
519  colab::addFrameToBuffer(sendBuffer, buffer, &len);
520  }
521 
522  // Debug: Print buffer
523 // traceBuffer("Cmd buffer contents:", sendBuffer, len);
524 
525  // Send command (blocking)
526  return m_tcp.write(sendBuffer, len);
527 }
528 
529 
530 
540 {
541  switch (m_protocol)
542  {
543  case CoLa_A:
544  printInfoMessage("SopasBase::receiveAnswer: calling receiveAnswer_CoLa_A.", m_beVerbose);
545  return receiveAnswer_CoLa_A(cmd, name, timeout, answer);
546  case CoLa_B:
547  printInfoMessage("SopasBase::receiveAnswer: calling receiveAnswer_CoLa_B.", m_beVerbose);
548  return receiveAnswer_CoLa_B(cmd, name, timeout, answer);
549  default:
550  printWarning("SopasBase::receiveAnswer: Wrong protocol (is either not CoLa-A or CoLa-B).");
551  }
552 
553  return false;
554 }
555 
556 
557 
567 {
568  switch (m_protocol)
569  {
570  case CoLa_A:
571  printInfoMessage("SopasBase::receiveAnswer: Calling receiveAnswer_CoLa_A.", m_beVerbose);
572  return receiveAnswer_CoLa_A(cmd, index, timeout, answer);
573  case CoLa_B:
574  printInfoMessage("SopasBase::receiveAnswer: Calling receiveAnswer_CoLa_B.", m_beVerbose);
575  return receiveAnswer_CoLa_B(cmd, index, timeout, answer);
576  default:
577  printWarning("SopasBase::receiveAnswer: Wrong protocol (is either not CoLa-A or CoLa-B).");
578  }
579 
580  return false;
581 }
582 
583 
584 //
585 //
586 //
588 {
589  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: entering function.", m_beVerbose);
590 
591  SopasCommand receivedCommand;
592  std::string rxData;
593  if (timeout == 0)
594  {
595  timeout = 1; // Check at least once
596  }
597 
598  // Check until number of cycles reaches timeout
599  for (UINT32 i = 0; i < timeout; i++)
600  {
601  // Secure against read thread
602  {
605  {
606  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: Response received (len= " +
608  " bytes).", m_beVerbose);
610  m_numberOfBytesInResponseBuffer = 0; // Clear buffer
611  }
612  }
613 
614  if (rxData.length() > 0)
615  {
616  // Decode data
617  receivedCommand = colaA_decodeCommand(&rxData);
618 
619  if (cmd == receivedCommand)
620  {
621 
622  // Set variable answer
623  if (receivedCommand == WA)
624  {
625  // Answer contains variable index only and informs about success.
626  return true;
627  }
628 
629  UINT16 receivedIndex = colaa::decodeUINT16(&rxData); // by name
630 
631  if (receivedIndex == index)
632  {
633  // Answer to Read Variable or invoke method?
634  if (cmd == RA || cmd == AN)
635  {
636  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: *** receive answer with data in return *** ", m_beVerbose);
637 
638  answer = new SopasAnswer((BYTE*)rxData.c_str(), rxData.length());
639  m_numberOfBytesInResponseBuffer = 0; // Clear buffer
640  return true;
641  }
642  else if (receivedCommand == EA)
643  {
644  // Antwort auf Event-Abonnement setzen/loeschen.
645  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: Event (by index) successfully (un)registered: " +
646  ::toString(receivedIndex) + ".", m_beVerbose);
647 
649  return true;
650  }
651  }
652  else
653  {
654  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: This is not the answer we are waiting for. ", m_beVerbose);
655  m_numberOfBytesInResponseBuffer = 0; // Clear buffer
656  }
657  }
658  // Error answer
659  else if (receivedCommand == FA)
660  {
661  printInfoMessage("SopasBase::Error answer received: FA " + rxData + ".", m_beVerbose);
662  answer = new SopasAnswer((BYTE*)rxData.c_str(), rxData.length());
663  return false;
664  }
665  else
666  {
667  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: This is not the answer we are waiting for. ", m_beVerbose);
668  m_numberOfBytesInResponseBuffer = 0; // Clear buffer
669  rxData.clear();
670  }
671  }
672  else
673  {
674  // No data in response buffer. Sleep some time and check again
675  usleep(1000);
676  }
677  }
678 
679  // Not successful, timeout.
680  return false;
681 }
682 
683 
684 
686 {
687  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: entering function.", m_beVerbose);
688 
689  SopasCommand receivedCommand;
690  std::string rxData;
691  if (timeout == 0)
692  {
693  timeout = 1; // Check at least once
694  }
695 
696  // Check until number of cycles reaches timeout
697  for (UINT32 i = 0; i < timeout; i++)
698  {
699  // Secure against read thread
700  {
703  {
704  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: Response received (len= " +
707  m_numberOfBytesInResponseBuffer = 0; // Clear buffer
708  }
709  }
710 
711  if (rxData.length() > 0)
712  {
713  // Decode data
714  receivedCommand = colaA_decodeCommand(&rxData);
715 
716  if (cmd == receivedCommand)
717  {
718 
719  // Set variable answer
720  if (receivedCommand == WA)
721  {
722  // Answer contains variable index only and informs about success.
723  return true;
724  }
725 
726  std::string receivedName = colaa::decodeString(&rxData); // by name
727 
728  if (receivedName == name)
729  {
730  // Answer to Read Variable or invoke method?
731  if (cmd == RA || cmd == AN)
732  {
733  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: *** receive answer with data in return *** ", m_beVerbose);
734 
735  answer = new SopasAnswer((BYTE*)rxData.c_str(), rxData.length());
736  m_numberOfBytesInResponseBuffer = 0; // Clear buffer
737  return true;
738  }
739  else if (receivedCommand == EA)
740  {
741  // Antwort auf Event-Abonnement setzen/loeschen.
742 
743  printInfoMessage("SopasBase:: Event successfully (un)registered: " + receivedName + ".", m_beVerbose);
745  return true;
746  }
747  }
748  else
749  {
750  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: This is not the answer we are waiting for.", m_beVerbose);
751  m_numberOfBytesInResponseBuffer = 0; // Clear buffer
752  }
753  }
754  // Error answer
755  else if (receivedCommand == FA)
756  {
757  printInfoMessage("SopasBase:: Error answer received: FA " + rxData + ".", true);
758  answer = new SopasAnswer((BYTE*)rxData.c_str(), rxData.length());
759  return false;
760  }
761  else
762  {
763  printInfoMessage("SopasBase::receiveAnswer_CoLa_A: This is not the answer we are waiting for.", m_beVerbose);
764  m_numberOfBytesInResponseBuffer = 0; // Clear buffer
765  rxData.clear();
766  }
767  }
768  else
769  {
770  // No data in response buffer. Sleep some time and check again
771  usleep(1000);
772  }
773  }
774 
775  // Not successful, timeout.
776  return false;
777 }
778 
779 
780 
782 {
783  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Entering function.", m_beVerbose);
784 
785  SopasCommand receivedCommand;
786  UINT16 nextData;
787  std::string receivedName;
788 
789  if (timeout == 0)
790  {
791  timeout = 1; // Check at least once
792  }
793 
794  // Check until number of cycles reaches timeout
795  for (UINT32 i = 0; i < timeout; i++)
796  {
798  {
799 // if (m_beVerbose)
800 // {
801 // printInfoMessage("SopasBase::receiveAnswer_CoLa_B: There is something in receive buffer." << std::endl;
802 // }
803 
804  // protect response buffer
806 
807  // there are only complete frames in response buffer
809 
810  // Parse Sopas Kommando
811  // receivedCommand = stringToSopasCommand(colab::getCommandStringFromBuffer(m_responseBuffer));
812  receivedCommand = stringToSopasCommand(frame.getCommandString());
813 
814  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: receivedCommand= " + frame.getCommandString() + ".", m_beVerbose);
815 
816  if (receivedCommand == FA)
817  {
818  // Fehlermeldung vom Sensor
819  nextData = 0;
820  UINT16 errorCode = colab::getIntegerFromBuffer<UINT16>(&(m_responseBuffer[11]), nextData);
821  printWarning("SopasBase::receiveAnswer_CoLa_B: Error from sensor! Code=" + toString(errorCode) +
822  ", meaning: " + convertSopasErrorCodeToText(errorCode) + ".");
824  return false;
825  }
826 
827  if (cmd != receivedCommand)
828  {
829  // Nicht die gesuchte Antwort
830  // da der sensor über sopas immer nur eine anfrage zur zeit bedienen kann, koennen wir die
831  // Nachricht wegwerfen
832  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: This is not the answer (" + sopasCommandToString(receivedCommand) + ") are waiting for ("
835  return false;
836  }
837 
838  // UINT16 nameLength = colab::getIntegerFromBuffer<UINT16>(m_responseBuffer, nextData);
839  // receivedName = colab::getStringFromBuffer(m_responseBuffer, nextData);
840 
841  receivedName = colab::getIdentifierFromBuffer(m_responseBuffer, nextData, sizeof(m_responseBuffer));
842 
843  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: receicedName= " + receivedName + ".", m_beVerbose);
844 
845  if (name != receivedName)
846  {
847  // Nicht die gesuchte Antwort
848  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: This is not the answer we are waiting for. (" + frame.getCommandString() +
849  ", " + name + ").", m_beVerbose);
850 
852  return false;
853  }
854 
855  if (receivedCommand == WA)
856  {
857  // Variable schreiben erfolgreich
858  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Variable successfully set.", m_beVerbose);
860  return true;
861  }
862 
863  else if (receivedCommand == EA)
864  {
865  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Answer to (un)subscribe event " + receivedName + ".", m_beVerbose);
867  return true;
868  }
869  // Antwort auf Methode ByName
870  else if (receivedCommand == AN )
871  {
872  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Answer to method call " + receivedName + ".", m_beVerbose);
873  answer = new SopasAnswer(&m_responseBuffer[nextData], m_numberOfBytesInResponseBuffer - nextData);
875  return true;
876  }
877  else if (receivedCommand == RA)
878  {
879  // Antwort auf das Lesen einer Variablen
880  answer = new SopasAnswer(&m_responseBuffer[nextData], m_numberOfBytesInResponseBuffer - nextData);
882  return true;
883  }
884 
885  else if (receivedCommand == CMD_UNKNOWN)
886  {
887  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Unkown Sopas command.", true);
889  return false;
890  }
891  else
892  {
893  // unbekannter oder unbehandelter Befehl
894  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Untreated Sopas command.", m_beVerbose);
896  return false;
897  }
898 
899  }
900  else
901  {
902  // No data in response buffer. Sleep some time and check again
903  usleep(1000);
904  }
905  }
906 
907  // Not successful, timeout.
908  printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Leaving with timeout.", m_beVerbose);
909 
910  return false;
911 }
912 
913 //
914 // Convert a Sopas error code to readable text.
915 //
917 {
918  switch (errorCode)
919  {
920  case 0:
921  return "Sopas_Ok";
922  case 1:
923  return "Sopas_Error_METHODIN_ACCESSDENIED";
924  case 2:
925  return "Sopas_Error_METHODIN_UNKNOWNINDEX";
926  case 3:
927  return "Sopas_Error_VARIABLE_UNKNOWNINDEX";
928  case 4:
929  return "Sopas_Error_LOCALCONDITIONFAILED";
930  case 5:
931  return "Sopas_Error_INVALID_DATA";
932  case 6:
933  return "Sopas_Error_UNKNOWN_ERROR";
934  case 7:
935  return "Sopas_Error_BUFFER_OVERFLOW";
936  case 8:
937  return "Sopas_Error_BUFFER_UNDERFLOW";
938  case 9:
939  return "Sopas_Error_ERROR_UNKNOWN_TYPE";
940  case 10:
941  return "Sopas_Error_VARIABLE_WRITE_ACCESSDENIED";
942  case 11:
943  return "Sopas_Error_UNKNOWN_CMD_FOR_NAMESERVER";
944  case 12:
945  return "Sopas_Error_UNKNOWN_COLA_COMMAND";
946  case 13:
947  return "Sopas_Error_METHODIN_SERVER_BUSY";
948  case 14:
949  return "Sopas_Error_FLEX_OUT_OF_BOUNDS";
950  case 15:
951  return "Sopas_Error_EVENTREG_UNKNOWNINDEX";
952  case 16:
953  return "Sopas_Error_COLA_A_VALUE_OVERFLOW";
954  case 17:
955  return "Sopas_Error_COLA_A_INVALID_CHARACTER";
956  case 18:
957  return "Sopas_Error_OSAI_NO_MESSAGE";
958  case 19:
959  return "Sopas_Error_OSAI_NO_ANSWER_MESSAGE";
960  case 20:
961  return "Sopas_Error_INTERNAL";
962  case 21:
963  return "Sopas_Error_HubAddressCorrupted";
964  case 22:
965  return "Sopas_Error_HubAddressDecoding";
966  case 23:
967  return "Sopas_Error_HubAddressAddressExceeded";
968  case 24:
969  return "Sopas_Error_HubAddressBlankExpected";
970  case 0x19:
971  return "Sopas_Error_AsyncMethodsAreSuppressed";
972  case 0x20:
973  return "Sopas_Error_ComplexArraysNotSupported";
974  default:
975  return "(unknown_Sopas_error_code)";
976  }
977 
978  return "(unknown_Sopas_error_code)";
979 }
980 
981 //
982 // Decode an incoming CoLa-B answer that was addressed by index.
983 //
985 {
986  bool beVerboseHere = m_beVerbose;
987 // beVerboseHere = true;
988 
989  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Entering function.", beVerboseHere);
990 
991  SopasCommand receivedCommand;
992  UINT16 nextData;
993 
994  if (timeout == 0)
995  {
996  timeout = 1; // Check at least once
997  }
998 
999  // Check until number of cycles reaches timeout
1000  for (UINT32 i = 0; i < timeout; i++)
1001  {
1003  {
1004  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: There is something in receive buffer.", beVerboseHere);
1005 
1006  // Protect response buffer
1008 
1009  // There are only complete frames in response buffer, so we can just use it here.
1010  // Debug: Print buffer
1011 // traceBuffer("Response in response buffer:", m_responseBuffer, m_numberOfBytesInResponseBuffer);
1013 
1014  // Parse Sopas Kommando
1015  receivedCommand = stringToSopasCommand(frame.getCommandString());
1016 
1017  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: ReceivedCommand= " + frame.getCommandString() + ".", beVerboseHere);
1018 
1019  nextData = 11; // without 0x02020202 + length(4 byte) + "sXX"
1020  UINT16 receivedIndex = colab::getIntegerFromBuffer<UINT16>(m_responseBuffer, nextData);
1021 // printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: read command " + frame.getCommandString() + ".", beVerboseHere);
1022  if (receivedCommand == FA)
1023  {
1024  // Error message from the sensor. The next 2 bytes (in the receiveIndex) are not
1025  // the index but the error code.
1026  printWarning("SopasBase::receiveAnswer_CoLa_B_idx: Error from sensor! Code=" + toString(receivedIndex) +
1027  ", meaning: " + convertSopasErrorCodeToText(receivedIndex) + ".");
1029  return false;
1030  }
1031 
1032  else if (index != receivedIndex)
1033  {
1034  // Nicht die gesuchte Antwort
1035  // da der sensor über sopas immer nur eine anfrage zur zeit bedienen kann, koennen wir die
1036  // Nachricht wegwerfen
1037  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: This is not the index we are waiting for (expected="
1038  + toString(index) + ", received=" + toString(receivedIndex) + ")." , beVerboseHere);
1040  return false;
1041  }
1042 
1043  else if (cmd != receivedCommand)
1044  {
1045  // Not the desired answer.
1046  // As the sensor can only handle one command at a time on the SOPAS interface, we can discard the message.
1047  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: This is not the answer (" + sopasCommandToString(receivedCommand) +
1048  ") we are waiting for (" + sopasCommandToString(cmd) + "). ", beVerboseHere);
1050  return false;
1051  }
1052 
1053  else if (receivedCommand == WA)
1054  {
1055  // Variable schreiben erfolgreich
1056  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Variable successfully set.", beVerboseHere);
1058  return true;
1059  }
1060 
1061  else if (receivedCommand == EA)
1062  {
1063  // Antwort auf Event-Abonnement setzen/loeschen.
1064  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Event successfully (un)registered: " + ::toString(receivedIndex) + ".", beVerboseHere);
1066  return true;
1067  }
1068 
1069  else if (receivedCommand == AI )
1070  {
1071  // Antwort auf entfernten Methodenaufruf (by name oder by index).
1072  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Answer to method call with index " + ::toString(receivedIndex) + ".", beVerboseHere);
1073  answer = new SopasAnswer(&m_responseBuffer[nextData], m_numberOfBytesInResponseBuffer - nextData);
1075  return true;
1076  }
1077 
1078  else if (receivedCommand == RA)
1079  {
1080  // Antwort auf das Lesen einer Variablen
1081  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Answer to read variable with index " + ::toString(receivedIndex) + ".", beVerboseHere);
1082 
1083  answer = new SopasAnswer(&m_responseBuffer[nextData], m_numberOfBytesInResponseBuffer - nextData);
1085  return true;
1086  }
1087 
1088  else if (receivedCommand == CMD_UNKNOWN)
1089  {
1090  printWarning("SopasBase::receiveAnswer_CoLa_B_idx: Unknown Sopas command.");
1092  return false;
1093  }
1094  else
1095  {
1096  // unbekannter oder unbehandelter Befehl
1097  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Untreated Sopas command.", beVerboseHere);
1099  return false;
1100  }
1101  }
1102  else
1103  {
1104  // No data in response buffer. Sleep some time and check again
1105  usleep(1000);
1106  }
1107  }
1108 
1109  // Not successful, timeout.
1110  printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Leaving with timeout.", beVerboseHere);
1111 
1112  // Not successful, timeout.
1113  return false;
1114 }
1115 
1116 
1117 
1124 {
1125 
1126  if (m_protocol == CoLa_A)
1127  {
1128  printInfoMessage("SopasBase::processFrame: Calling processFrame_CoLa_A() with " + ::toString(frame.size()) + " bytes.", m_beVerbose);
1129  processFrame_CoLa_A(frame);
1130  }
1131  else if (m_protocol == CoLa_B)
1132  {
1133  printInfoMessage("SopasBase::processFrame: Calling processFrame_CoLa_B() with " + ::toString(frame.size()) + " bytes.", m_beVerbose);
1134  processFrame_CoLa_B(frame);
1135  }
1136 }
1137 
1138 
1139 
1140 //
1141 // Reads one frame from receive buffer and decodes it.
1142 //
1143 // CoLa-A protocol only.
1144 //
1146 {
1147  std::string command;
1148  command = m_receiveBuffer[2];
1149  command += m_receiveBuffer[3];
1150  assert (command.length() == 2);
1151 
1152  //
1153  // Process asynchronous event data directly.
1154  // Other commands are copied to separate buffer
1155  //
1156  if (frame.getMessageType() == MSG_SEND_EVENT)
1157  {
1158  if (frame.size() > 8)
1159  {
1160  // "SN" ist ein abonniertes Event, z.B. Scans oder Schutzfelder
1161  std::string eventName;
1162  UINT32 i = 5;// Pointer to the fist Letter of the event Name (without the first 5 bytes: "STX's''S''N'' '")
1163  while (m_receiveBuffer[i] != ' ' && i < frame.size() )
1164  {
1165  // go to the ' ' after the event Name
1166  i++;
1167  }
1168  eventName = std::string((char*) m_receiveBuffer, 5, i - 5); // get the event Name
1169 
1170  if (m_decoderFunctionMapByName[eventName] != NULL)
1171  {
1172  // Not empty
1173  m_decoderFunctionMapByName[eventName](frame);// call the callback of the Event
1174  }
1175  else
1176  {
1177  // Das Event ist unbekannt
1178  printWarning("SopasBase::Received an unknown event! Event name is: " + eventName + ".");
1179  }
1180 //
1181 // if (eventName == scanString) // Scan data (hopefully, event name not parsed yet...)
1182 // {
1183 // if (!m_decoderFunctionMapByName[eventName].empty())
1184 // {
1185 // m_scanDecoderFunction(frame);
1186 // }
1187 // else
1188 // {
1189 // printInfoMessage("SopasBase::no scan decoder registered - discarding data." << std::endl;
1190 // }
1191 // }
1192 // else if (eventName == fieldString) // eval case result data
1193 // {
1194 //
1195 // if (!m_evalCaseDecoderFunction.empty())
1196 // {
1197 // m_evalCaseDecoderFunction(frame);
1198 // }
1199 // else
1200 // {
1201 // printInfoMessage("SopasBase::no eval case decoder registered - discarding data." << std::endl;
1202 // }
1203 // }
1204 // else
1205 // { // Das Event ist unbekannt
1206 // printWarning("SopasBase::Received an unknown event! Short name is: " << eventName << "." << std::endl;
1207 // }
1208  }
1209  else
1210  {
1211  // Das Kommando ist insgesamt zu kurz zum dekodieren
1212  printWarning("SopasBase::Received a very short (and unknown) event! Frame length is " + ::toString(frame.size()) +
1213  " bytes.");
1214  }
1215  }
1216  else
1217  {
1218  // Copy frame to response buffer. Old contents are destroyed
1219  // std::lock_guard<std::mutex> lock(m_receiveDataMutex);
1220  copyFrameToResposeBuffer(frame.size());
1221  }
1222 
1223  // Remove frame from receive buffer
1225 }
1226 
1227 
1228 
1229 //
1230 // Reads and decodes a frame from the receiveBuffer. Frame format is CoLa-B.
1231 //
1232 // Note that this function typically runs in TCP callback context, not the device thread.
1233 //
1235 {
1236  // Lese das "Kommando" aus
1238 
1239  printInfoMessage("SopasBase::processFrame_CoLa_B: Command is " + command + ".", m_beVerbose);
1240 
1241  //
1242  // Process asynchronous event data directly.
1243  // Other commands are copied to separate buffer
1244  //
1245  bool frameWasProcessed = false;
1246  if (frame.getMessageType() == MSG_SEND_EVENT) // LDMRS: SI, LMS100: SN
1247  {
1248  if (frame.size() > 12)
1249  {
1250  // "SN" or "SI" is a registered event, e.g. Scans or Eval case results.
1251  // printInfoMessage("SopasBase::SN empfangen, Laenge = " << frameLength << "Bytes ." << std::endl;
1252  std::string eventName;
1253  UINT32 eventIndex = 0;
1254  UINT16 pos = 0;
1255 
1256  switch (frame.getEncodingType())
1257  {
1258  case ByIndex: // by index
1259  pos = 11;
1260  eventIndex = colab::getIntegerFromBuffer<UINT16>(m_receiveBuffer, pos);
1261  eventName = m_indexToNameMap[eventIndex];
1262 
1263  switch (eventIndex)
1264  {
1265  case 0x11: // SopasEventByIndex_LDMRS::index_event_ScanData:
1266  eventName = EVENTNAME_SUBSCRIBE_SCANS;
1267  scanDataDecoder(frame);
1268  frameWasProcessed = true;
1269  break;
1270  case 0x29: // SopasEventByIndex_LDMRS::index_event_aEvalCaseResult:
1271  eventName = EVENTNAME_SUBSCRIBE_EVALCASES;
1272  evalCaseResultDecoder(frame);
1273  frameWasProcessed = true;
1274  break;
1275  default:
1276  ;
1277  }
1278  break;
1279 
1280  default: // by name
1281  printWarning("SopasBase::processFrame_CoLa_B: Decoding of events by name is not implemented yet.");
1282  eventName = frame.getVariableName();
1283  break;
1284  }
1285 
1286  if (frameWasProcessed == false)
1287  {
1288  // The incoming event was not handeled
1289  printWarning("SopasBase::processFrame_CoLa_B: Don't know how to process the incoming event with the short name <" +
1290  eventName + "> and the index " + ::toString(eventIndex) + ", ignoring it!");
1291  }
1292  }
1293  else
1294  {
1295  // The frame was too short to be decoded
1296  printWarning("SopasBase::processFrame_CoLa_B: Received a very short (and unknown) event! Frame length is " + ::toString(frame.size()) + " bytes.");
1297  }
1298  }
1299  else
1300  {
1301  // Copy frame to response buffer. Old contents are destroyed.
1302  copyFrameToResposeBuffer(frame.size());
1303  }
1304 
1306 }
1307 
1308 
1309 
1310 //
1311 // Copies a complete frame - in any protocol - from the main input buffer to
1312 // the response buffer.
1313 // The frame is *not* removed from the main input buffer.
1314 //
1316 {
1317  printInfoMessage("SopasBase::copyFrameToResposeBuffer: Copying a frame of " + ::toString(frameLength) +
1318  " bytes to response buffer.", m_beVerbose);
1319 
1320  if (frameLength <= sizeof(m_responseBuffer))
1321  {
1322  // Wir duerfen kopieren
1323  memcpy(m_responseBuffer, m_receiveBuffer, frameLength);
1324  m_numberOfBytesInResponseBuffer = frameLength;
1325  }
1326  else
1327  {
1328  // Der respose-Buffer ist zu klein
1329  printError("SopasBase::copyFrameToResposeBuffer: Failed to copy frame (Length=" + ::toString(frameLength) +
1330  " bytes) to response buffer because the response buffer is too small (buffer size=" +
1331  ::toString(sizeof(m_responseBuffer)) + " bytes).");
1333  }
1334 }
1335 
1336 
1337 
1338 //
1339 // Removes a complete frame - in any protocol - from the main input buffer.
1340 //
1342 {
1343  // Remove frame from receive buffer
1344  if (frameLength < m_numberOfBytesInReceiveBuffer)
1345  {
1346  // More data in buffer, move them to the buffer start
1347  UINT32 newLen = m_numberOfBytesInReceiveBuffer - frameLength;
1348  printInfoMessage("SopasBase::removeFrameFromReceiveBuffer: Removing " + ::toString(frameLength) +
1349  " bytes from the input buffer. New length is " + ::toString(newLen) + " bytes.", m_beVerbose);
1350  memmove(m_receiveBuffer, &(m_receiveBuffer[frameLength]), newLen);
1352  }
1353  else
1354  {
1355  // No other data in buffer, just mark as empty
1356  printInfoMessage("SopasBase::removeFrameFromReceiveBuffer: Done, no more data in input buffer.", m_beVerbose);
1358  }
1359 }
1360 
1361 
1362 
1369 {
1371 }
1372 
1373 
1374 
1376 {
1377  // Request by Name
1378  if (cmdString == "RN")
1379  {
1380  return RN;
1381  } // Read Variable
1382  // else if (cmdString == "WN") { return WN; } // Write Variable
1383  // else if (cmdString == "MN") { return MN; } // Invoke Method
1384  else if (cmdString == "AN")
1385  {
1386  return AN;
1387  } // Method Result (Answer)
1388  // else if (cmdString == "EN") { return EN; } // Register Event
1389  else if (cmdString == "SN")
1390  {
1391  return SN;
1392  } // Send Event
1393 
1394  // Request by Index
1395  if (cmdString == "RI")
1396  {
1397  return RI;
1398  } // Read Variable
1399  else if (cmdString == "WI")
1400  {
1401  return WI;
1402  } // Write Variable
1403  else if (cmdString == "MI")
1404  {
1405  return MI;
1406  } // Invoke Method
1407  else if (cmdString == "AI")
1408  {
1409  return AI;
1410  } // Method Result (Answer)
1411  else if (cmdString == "EI")
1412  {
1413  return EI;
1414  } // Register Event
1415  else if (cmdString == "SI")
1416  {
1417  return SI;
1418  } // Send Event
1419 
1420  // Response
1421  else if (cmdString == "RA")
1422  {
1423  return RA;
1424  } // Read Variable
1425  else if (cmdString == "WA")
1426  {
1427  return WA;
1428  } // Write Variable
1429  else if (cmdString == "MA")
1430  {
1431  return MA;
1432  } // Invoke Method
1433  else if (cmdString == "AA")
1434  {
1435  return AA;
1436  } // Method Result (Answer)
1437  else if (cmdString == "EA")
1438  {
1439  return EA;
1440  } // Register Event
1441  else if (cmdString == "SA")
1442  {
1443  return SA;
1444  } // Event Acknowledge (Only used for reliable events
1445  else if (cmdString == "FA")
1446  {
1447  return FA;
1448  } // Error
1449 
1450  else
1451  {
1452  printError("SopasBase::stringToSopasCommand: Trying to resolve an unknown command: " + cmdString + ".");
1453  }
1454  return CMD_UNKNOWN;
1455 }
1456 
1457 //
1458 // For debugging: Convert the command into a readable string.
1459 //
1461 {
1462 
1463  if (cmd == RN)
1464  {
1465  return ("RN"); // Request by Name
1466  }
1467  // else if (cmdString == "WN") { return WN; } // Write Variable
1468  // else if (cmdString == "MN") { return MN; } // Invoke Method
1469  else if (cmd == AN)
1470  {
1471  return ("AN"); // Method Result, by name
1472  }
1473  // else if (cmdString == "EN") { return EN; } // Register Event
1474  else if (cmd == SN)
1475  {
1476  return ("SN"); // Send Event
1477  }
1478  if (cmd == RI)
1479  {
1480  return ("RI"); // Request by Index
1481  } // Read Variable
1482  else if (cmd == WI)
1483  {
1484  return ("WI"); // Write Variable
1485  }
1486  else if (cmd == MI)
1487  {
1488  return ("MI"); // Invoke Method
1489  }
1490  else if (cmd == AI)
1491  {
1492  return ("AI"); // Method Result (Answer)
1493  }
1494  else if (cmd == EI)
1495  {
1496  return ("EI"); // Register Event
1497  }
1498  else if (cmd == SI)
1499  {
1500  return ("SI");
1501  } // Send Event
1502 
1503  // Response
1504  else if (cmd == RA)
1505  {
1506  return ("RA");
1507  } // Read Variable
1508  else if (cmd == WA)
1509  {
1510  return ("WA"); // Write Variable
1511  }
1512  else if (cmd == MA)
1513  {
1514  return ("MA");
1515  } // Invoke Method
1516  else if (cmd == AA)
1517  {
1518  return ("AA");
1519  } // Method Result (Answer)
1520  else if (cmd == EA)
1521  {
1522  return ("EA");
1523  } // Register Event
1524  else if (cmd == SA)
1525  {
1526  return ("SA");
1527  } // Event Acknowledge (Only used for reliable events)
1528  else if (cmd == FA)
1529  {
1530  return ("FA"); // Error
1531  }
1532  else
1533  {
1534  printError("SopasBase::sopasCommandToString: Trying to resolve an unknown command!");
1535  }
1536 
1537  return "(unknown)";
1538 }
1539 
1540 
1541 
1549 {
1550  // every scanner must support ByName !!!
1551 
1552  bool result = false;
1553 
1554  // Clear old data.
1555  m_scannerName.empty();
1556  m_scannerVersion.empty();
1557 
1558  SopasAnswer* answer = NULL;
1559  result = readVariable(INDEX_DEVICE_IDENT, answer);
1560 
1561  if (result && answer != NULL && answer->isValid())
1562  {
1563 
1564  // decode answer
1565  std::string colaaAnswer;
1566  switch (m_protocol)
1567  {
1568  case CoLa_A:
1569  colaaAnswer = std::string((char*)answer->getBuffer(), answer->size());
1570  colaA_decodeScannerTypeAndVersion(&colaaAnswer);
1571  break;
1572  case CoLa_B:
1574  break;
1575  }
1576 
1577  if (!m_scannerName.empty() && !m_scannerVersion.empty())
1578  {
1579  result = true;
1580  }
1581  }
1582 
1583  if (answer != NULL)
1584  {
1585  delete answer;
1586  }
1587 
1588  return result;
1589 }
1590 
1591 
1592 
1597 {
1598  //
1599  // 1. part: Type
1600  //
1601  // String length
1602  UINT16 len = colaa::decodeUINT16(rxData);
1603 
1604  // Read string
1605  m_scannerName.clear();
1606  m_scannerName = rxData->substr(0, len);
1607 
1608  // Move input data
1609  *rxData = rxData->substr(len + 1);
1610 
1611  //
1612  // 2. part: Version
1613  //
1614  // String length
1615  len = colaa::decodeUINT16(rxData);
1616 
1617  // Read string
1618  m_scannerVersion.clear();
1619  m_scannerVersion = rxData->substr(0, len);
1620 }
1621 
1622 
1623 //
1624 //
1625 //
1627 {
1628  printInfoMessage("SopasBase::colaB_decodeScannerTypeAndVersion: Entering function.", m_beVerbose);
1629 
1630  UINT16 fieldLength;
1631 
1632  // read device type
1633  fieldLength = colab::getIntegerFromBuffer<UINT16>(buffer, pos);
1634  m_scannerName = colab::getStringFromBuffer(buffer, pos, fieldLength);
1635 
1636  // read device version
1637  fieldLength = colab::getIntegerFromBuffer<UINT16>(buffer, pos);
1638  m_scannerVersion = colab::getStringFromBuffer(buffer, pos, fieldLength);
1639 
1640  printInfoMessage("SopasBase::colaB_decodeScannerTypeAndVersion: scanner '" + m_scannerName + "', version '"
1641  + m_scannerVersion + "'.", m_beVerbose);
1642 }
1643 
1644 
1645 //
1646 //
1647 //
1648 bool SopasBase::invokeMethod(const std::string& methodeName, BYTE* parameters, UINT16 parametersLength, SopasAnswer*& answer)
1649 {
1650  // Build command
1651  BYTE cmdBuffer[128];
1652  UINT16 cmdBufferLen = 0;
1653 
1654  switch (m_protocol)
1655  {
1656  case CoLa_A:
1657  cmdBufferLen += colaa::addStringToBuffer(cmdBuffer, COMMAND_Invoke_Method_ByName);
1658  cmdBuffer[cmdBufferLen++] = ' ';
1659  //Name
1660  cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[cmdBufferLen]), methodeName);
1661 
1662  if (parametersLength > 0)
1663  {
1664  cmdBuffer[cmdBufferLen++] = ' ';
1665  }
1666  break;
1667  case CoLa_B:
1668  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Invoke_Method_ByName);
1669  // add length of string as UINT16
1670  colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, methodeName.size());
1671  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, methodeName); // remote method name
1672  break;
1673  }
1674 
1675  if (parametersLength > 0)
1676  {
1677  // add parameters (which must be already in the right encoding (colaa or colab))
1678  memcpy(&cmdBuffer[cmdBufferLen], parameters, parametersLength);
1679  cmdBufferLen += parametersLength;
1680  }
1681 
1682  // Send command
1683  if(!sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen))
1684  {
1685  ROS_ERROR("## ERROR in SopasBase::invokeMethod(): sendCommandBuffer failed")
1686  return false;
1687  }
1688 
1689  // Wait for answer (the answer of a method is "AN" - not "EA")
1690  bool result = receiveAnswer(AN, methodeName, 2000, answer);
1691 
1692  // Evaluate answer
1693  if (result == true)
1694  {
1695  printInfoMessage("SopasBase::invokeMethod: Calling of " + methodeName + " was successful.", m_beVerbose);
1696  }
1697  else
1698  {
1699  printWarning("SopasBase::invokeMethod: Calling of " + methodeName + " was NOT successful.");
1700  }
1701 
1702  return result;
1703 }
1704 
1705 
1706 //
1707 //
1708 //
1709 bool SopasBase::invokeMethod(UINT16 index, BYTE* parameters, UINT16 parametersLength, SopasAnswer*& answer)
1710 {
1711  // Build command
1712  BYTE cmdBuffer[128];
1713  UINT16 cmdBufferLen = 0;
1714 
1715  switch (m_protocol)
1716  {
1717  case CoLa_A:
1718  printError("SopasBase::invokeMethod: Invoke method cola-a by index not supported.");
1719  return false;
1720  break;
1721  case CoLa_B:
1722  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Invoke_Method_ByIndex);
1723  // add length of string as UINT16
1724  colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, index);
1725  break;
1726  }
1727 
1728  if (parametersLength > 0)
1729  {
1730  // add parameters (which must be already in the right encoding (colaa or colab))
1731  memcpy(&cmdBuffer[cmdBufferLen], parameters, parametersLength);
1732  cmdBufferLen += parametersLength;
1733  }
1734 
1735  // Send command
1736  if (!sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen))
1737  {
1738  ROS_ERROR("## ERROR in SopasBase::invokeMethod(): sendCommandBuffer failed")
1739  return false;
1740  }
1741 
1742  // Wait for answer
1743  bool result = receiveAnswer(AI, index, 2000, answer);
1744 
1745  // Evaluate answer
1746  if (result == true)
1747  {
1748  printInfoMessage("SopasBase::invokeMethod: Calling of method with index=" + ::toString(index) + " was successful.", m_beVerbose);
1749  }
1750  else
1751  {
1752  printWarning("SopasBase::invokeMethod: Calling of method with index=" + ::toString(index) + " was NOT successful.");
1753  }
1754 
1755  return result;
1756 }
1757 
1758 
1759 //
1760 //
1761 //
1762 bool SopasBase::readVariable(const std::string& variableName, SopasAnswer*& answer)
1763 {
1764  // Build command
1765  BYTE cmdBuffer[128];
1766  UINT16 cmdBufferLen = 0;
1767 
1768  if (m_protocol == CoLa_A)
1769  {
1770  cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Read_Variable_ByName);
1771  cmdBuffer[cmdBufferLen++] = ' ';
1772  cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[cmdBufferLen]), variableName);
1773  }
1774  else
1775  {
1776  // up to now only tested with LD-MRS
1777  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Read_Variable_ByName);
1778  cmdBuffer[cmdBufferLen++] = ' ';
1779  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, variableName);
1780  }
1781 
1782  // Send
1783  if (!sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen))
1784  {
1785  ROS_ERROR("## ERROR in SopasBase::readVariable(): sendCommandBuffer failed")
1786  return false;
1787  }
1788 
1789  // Wait for answer
1790  bool result = receiveAnswer(RA, variableName, 2000, answer);
1791 
1792  if (result)
1793  {
1794  printInfoMessage("SopasBase::readVariable: Answer to " + variableName + " received.", m_beVerbose);
1795  }
1796  else
1797  {
1798  printWarning("SopasBase::readVariable: Answer to " + variableName + " not successful.");
1799  }
1800 
1801  return result;
1802 }
1803 
1804 
1805 //
1806 //
1807 //
1809 {
1810  // Build command
1811  BYTE cmdBuffer[128];
1812  UINT16 cmdBufferLen = 0;
1813 
1814  if (m_protocol == CoLa_A)
1815  {
1816  cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Read_Variable_ByIndex);
1817  cmdBuffer[cmdBufferLen++] = ' ';
1818  cmdBufferLen += colaa::addUINT32ToBuffer(&(cmdBuffer[cmdBufferLen]), (UINT32)index);
1819  }
1820  else
1821  {
1822  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Read_Variable_ByIndex);
1823  colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, index);
1824  }
1825 
1826  // Send
1827  if (!sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen))
1828  {
1829  ROS_ERROR("## ERROR in SopasBase::readVariable(): sendCommandBuffer failed")
1830  return false;
1831  }
1832 
1833  // Wait for answer
1834  bool result = receiveAnswer(RA, index, 2000, answer);
1835 
1836  if (result)
1837  {
1838  printInfoMessage("SopasBase::readVariable: Answer to " + ::toString(index) + " received.", m_beVerbose);
1839  }
1840  else
1841  {
1842  printWarning("SopasBase::readVariable: Answer to " + ::toString(index) + " not successful.");
1843  }
1844 
1845  return result;
1846 }
1847 
1848 
1849 
1850 bool SopasBase::writeVariable(const std::string& variableName, BYTE* parameters, UINT16 parametersLength)
1851 {
1852  if (m_readOnlyMode)
1853  {
1854  printInfoMessage("SopasBase::writeVariable: ReadOnly Modus - ignore writing to variable '" +
1855  variableName + "'", m_beVerbose);
1856  return true;
1857  }
1858 
1859  // Build command
1860  BYTE cmdBuffer[128];
1861  UINT16 cmdBufferLen = 0;
1862 
1863  if (m_protocol == CoLa_A)
1864  {
1865  cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Write_Variable_ByName);
1866  cmdBuffer[cmdBufferLen++] = ' ';
1867  cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[cmdBufferLen]), variableName);
1868  if (parametersLength > 0)
1869  {
1870  cmdBuffer[cmdBufferLen++] = ' ';
1871  }
1872  }
1873  else
1874  {
1875  printError("SopasBase::writeVariable: Write variable cola-b by Name: NOT IMPLEMENTED");
1876  return false;
1877 // colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Write_Variable_ByName);
1878 // colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, variableName.size()); // add length of string as UINT16
1879 // colab::addStringToBuffer(cmdBuffer, cmdBufferLen, variableName);
1880 // or ?
1881 // colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Write_Variable_ByName);
1882 // colab::addStringToBuffer(cmdBuffer, cmdBufferLen, variableName);
1883  }
1884 
1885 
1886  if (parametersLength > 0)
1887  {
1888  // add parameters (which must be already in the right encoding (colaa or colab))
1889  memcpy(&cmdBuffer[cmdBufferLen], parameters, parametersLength);
1890  cmdBufferLen += parametersLength;
1891  }
1892 
1893 
1894  // Send
1895  if (!sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen))
1896  {
1897  ROS_ERROR("## ERROR in SopasBase::writeVariable(): sendCommandBuffer failed")
1898  return false;
1899  }
1900  SopasAnswer* answer = NULL;
1901  // Wait for answer
1902  bool result = receiveAnswer(WA, variableName, 2000, answer);
1903  // free memory for answer
1904  if (answer != NULL)
1905  {
1906  delete answer;
1907  }
1908 
1909  if (result)
1910  {
1911  printInfoMessage("SopasBase::writeVariable: Answer to " + variableName + " received.", m_beVerbose);
1912  }
1913  else
1914  {
1915  printInfoMessage("SopasBase::writeVariable: Answer to " + variableName + " not successful.", m_beVerbose);
1916  }
1917 
1918  return result;
1919 }
1920 
1921 
1922 //
1923 // Write a variable, addressed by index.
1924 //
1925 bool SopasBase::writeVariable(UINT16 variableIndex, BYTE* parameters, UINT16 parametersLength)
1926 {
1927  bool beVerboseHere = m_beVerbose;
1928 // beVerboseHere = true;
1929 
1930  if (m_readOnlyMode == true)
1931  {
1932  printInfoMessage("SopasBase::writeVariable: ReadOnly Modus - ignore writing to variable index '" + ::toString(variableIndex) +
1933  "'", m_beVerbose);
1934  return true;
1935  }
1936 
1937  // Create the command buffer
1938  UINT32 cmdBufferLen = parametersLength + 4;
1939  BYTE* cmdBuffer = new BYTE[cmdBufferLen];
1940 
1941  // Add the command
1943 
1944  // Add the index
1945  BYTE* buffer = &(cmdBuffer[2]);
1946  memwrite_UINT16(buffer, variableIndex);
1947 // UINT16 pos = 0;
1948 // colab::addIntegerToBuffer<UINT16>(&(cmdBuffer[2]), pos, variableIndex);
1949 
1950  // Copy the data
1951  memcpy(&(cmdBuffer[4]), parameters, parametersLength);
1952 
1953  // Send. The frame is added automatically.
1954  printInfoMessage("SopasBase::writeVariable: Sending command buffer now (payload len=" + toString(parametersLength+4) + " bytes).", beVerboseHere);
1955  if (!sendCommandBuffer(cmdBuffer, cmdBufferLen))
1956  {
1957  ROS_ERROR("## ERROR in SopasBase::writeVariable(): sendCommandBuffer failed")
1958  return false;
1959  }
1960 
1961  printInfoMessage("SopasBase::writeVariable: Command sent, waiting for reply...", beVerboseHere);
1962  SopasAnswer* answer = NULL;
1963  // Wait for answer
1964  bool result = receiveAnswer(WA, variableIndex, 2000, answer);
1965  // free memory for answer
1966  if (answer != NULL)
1967  {
1968  delete answer;
1969  }
1970  if (result)
1971  {
1972  printInfoMessage("SopasBase::writeVariable: Answer to " + toString(variableIndex) + " received.", beVerboseHere);
1973  }
1974  else
1975  {
1976  printWarning("SopasBase::writeVariable: Answer to " + toString(variableIndex) + " not successful!");
1977  }
1978 
1979  printInfoMessage("SopasBase::writeVariable: All done, leaving.", beVerboseHere);
1980  return result;
1981 }
1982 
1983 
1984 
1985 bool SopasBase::registerEvent(const std::string& eventName)
1986 {
1987  BYTE cmdBuffer[128];
1988  UINT16 cmdBufferLen = 0;
1989 
1990  if (m_protocol == CoLa_A)
1991  {
1992  cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Register_Event_ByName);
1993  cmdBuffer[cmdBufferLen++] = ' ';
1994  cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[cmdBufferLen]), eventName);
1995  cmdBuffer[cmdBufferLen++] = ' ';
1996  cmdBuffer[cmdBufferLen++] = '1';
1997  }
1998  else
1999  {
2000  //traceError(SOPASBASE_VERSION) << "register event cola-B by name not supported." << std::endl;
2001  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Register_Event_ByName);
2002  cmdBuffer[cmdBufferLen++] = ' ';
2003  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, eventName);
2004  cmdBuffer[cmdBufferLen++] = ' ';
2005  colab::addIntegerToBuffer<UINT8>(cmdBuffer, cmdBufferLen, 1);
2006 
2007  // return false;
2008  }
2009 
2010  // Send
2011  if (!sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen))
2012  {
2013  ROS_ERROR("## ERROR in SopasBase::registerEvent(): sendCommandBuffer failed")
2014  return false;
2015  }
2016  SopasAnswer* answer = NULL;
2017  // Wait for answer
2018  bool result = receiveAnswer(EA, eventName, 2000, answer);
2019 
2020 
2021  // free memory for answer
2022  if (answer != NULL)
2023  {
2024  delete answer;
2025  }
2026  return result;
2027 }
2028 
2029 
2030 //
2031 //
2032 //
2034 {
2035  // Build command
2036  BYTE cmdBuffer[128];
2037  UINT16 cmdBufferLen = 0;
2038 
2039  switch (m_protocol)
2040  {
2041  case CoLa_A:
2042  printError("SopasBase::register event cola-a by index not supported, aborting.");
2043 
2044  return false;
2045 
2046  break;
2047  case CoLa_B:
2048  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Register_Event_ByIndex);
2049  colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, index);
2050  colab::addIntegerToBuffer<UINT8>(cmdBuffer, cmdBufferLen, 1); // 1 to subscribe
2051  break;
2052  }
2053 
2054  // Send command
2055  if (!sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen))
2056  {
2057  ROS_ERROR("## ERROR in SopasBase::registerEvent(): sendCommandBuffer failed")
2058  return false;
2059  }
2060 
2061  // Wait for answer
2062  SopasAnswer* answer = NULL;
2063  bool result = receiveAnswer(EA, index, 2000, answer);
2064 
2065  // there will be no answer (but to be sure to prevent memory leaks)
2066  if (answer != NULL)
2067  {
2068  delete answer;
2069  }
2070 
2071  // Evaluate answer
2072  if (result == true)
2073  {
2074  printInfoMessage("SopasBase::registerEvent: Calling of register with index=" + ::toString(index) + " was successful.", m_beVerbose);
2075  }
2076  else
2077  {
2078  printError("SopasBase::registerEvent: Calling of method with index=" + ::toString(index) + " was NOT successful.");
2079  }
2080  return result;
2081 }
2082 
2083 
2084 
2086 {
2087  // Build command
2088  BYTE cmdBuffer[128];
2089  UINT16 cmdBufferLen = 0;
2090 
2091  switch (m_protocol)
2092  {
2093  case CoLa_A:
2094  printError("SopasBase::unregisterEvent: Unregister event cola-a by index not supported.");
2095 
2096  return false;
2097 
2098  break;
2099  case CoLa_B:
2100  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Register_Event_ByIndex);
2101  colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, index);
2102  colab::addIntegerToBuffer<UINT8>(cmdBuffer, cmdBufferLen, 0); // 1 to subscribe
2103  break;
2104  }
2105 
2106  // Send command
2107  if (!sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen))
2108  {
2109  ROS_ERROR("## ERROR in SopasBase::unregisterEvent(): sendCommandBuffer failed")
2110  return false;
2111  }
2112 
2113  // Wait for answer
2114  SopasAnswer* answer = NULL;
2115  bool result = receiveAnswer(EA, index, 2000, answer);
2116 
2117  // there will be no answer (but to be sure to prevent memory leaks)
2118  if (answer != NULL)
2119  {
2120  delete answer;
2121  }
2122 
2123  // Evaluate answer
2124  if (result == true)
2125  {
2126  printInfoMessage("SopasBase::calling of register with index=" + ::toString(index) + " was successful.", m_beVerbose);
2127  }
2128  else
2129  {
2130  printInfoMessage("SopasBase::calling of register with index=" + ::toString(index) + " was NOT successful.", m_beVerbose);
2131  }
2132 
2133  return result;
2134 }
2135 
2136 
2137 
2138 bool SopasBase::unregisterEvent(const std::string& eventName)
2139 {
2140  BYTE cmdBuffer[128];
2141  UINT16 cmdBufferLen = 0;
2142 
2143  if (m_protocol == CoLa_A)
2144  {
2145  cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Register_Event_ByName);
2146  cmdBuffer[cmdBufferLen++] = ' ';
2147  cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[cmdBufferLen]), eventName);
2148  cmdBuffer[cmdBufferLen++] = ' ';
2149  cmdBuffer[cmdBufferLen++] = '0';
2150  }
2151  else
2152  {
2153 // traceError(SOPASBASE_VERSION) << "unregister event cola-B by name not supported." << std::endl;
2154  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Register_Event_ByName);
2155  cmdBuffer[cmdBufferLen++] = ' ';
2156  colab::addStringToBuffer(cmdBuffer, cmdBufferLen, eventName);
2157  cmdBuffer[cmdBufferLen++] = ' ';
2158  colab::addIntegerToBuffer<UINT8>(cmdBuffer, cmdBufferLen, 0);
2159 // return false;
2160  }
2161 
2162  // Send
2163  if (!sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen))
2164  {
2165  ROS_ERROR("## ERROR in SopasBase::unregisterEvent(): sendCommandBuffer failed")
2166  return false;
2167  }
2168  SopasAnswer* answer = NULL;
2169  // Wait for answer
2170  bool result = receiveAnswer(EA, eventName, 2000, answer);
2171 
2172 
2173  // free memory for answer
2174  if (answer != NULL)
2175  {
2176  delete answer;
2177  }
2178  return result;
2179 }
2180 
2185 {
2187 }
2188 
2189 
2193 double SopasBase::makeAngleValid(double angle)
2194 {
2195  return ::normalizeRadians(angle);
2196 }
2197 
2198 
2199 
2200 //
2201 // ************************* SOPAS FRAME ************************************************** //
2202 //
2204  m_buffer(NULL), m_protocol(SopasBase::CoLa_A), m_frameLength(0), m_encoding(SopasBase::ByName)
2205 {
2206 }
2207 
2208 
2209 
2211  m_buffer(buffer), m_protocol(protocol), m_frameLength(frameLength), m_encoding(SopasBase::ByName)
2212 {
2213  detectEncoding();
2215 }
2216 
2217 
2218 
2220 {
2221  UINT32 payLoadLength = 0;
2222 
2223  switch (m_protocol)
2224  {
2225  case SopasBase::CoLa_A:
2226  payLoadLength = m_frameLength - 2; // everything except the 0x02 0x03 frame
2227  break;
2228  case SopasBase::CoLa_B:
2229  payLoadLength = m_frameLength - 9; // everything except start 0x02020202(4byte), payloadLength(4byte) and checksum(1 byte)
2230  }
2231 
2232  return payLoadLength;
2233 }
2234 
2235 
2236 
2238 {
2239  std::string commandString;
2240 
2241  switch (m_protocol)
2242  {
2243  case SopasBase::CoLa_A:
2244  commandString = std::string((char*) &m_buffer[2], 2);
2245  break;
2246  case SopasBase::CoLa_B:
2247  commandString = std::string((char*) &m_buffer[9], 2);
2248  }
2249 
2250  return commandString;
2251 }
2252 
2253 
2254 //
2255 // Returns a pointer to the first payload byte.
2256 // CoLa-A: Points beyond the leading "0x02" to the "s..." data.
2257 // CoLa-B: Points beyond the magic word and length bytes, to the "s..." data.
2258 //
2260 {
2261  BYTE* bufferPos = NULL;
2262 
2263  switch (m_protocol)
2264  {
2265  case SopasBase::CoLa_A:
2266  bufferPos = &m_buffer[1];
2267  break;
2268  case SopasBase::CoLa_B:
2269  bufferPos = &m_buffer[8];
2270  break;
2271  }
2272 
2273  return bufferPos;
2274 }
2275 
2276 
2277 
2279 {
2280  INT32 index = -1;
2281 
2283  {
2284  // Encoding is not byIndex, so abort here
2285  printWarning("SopasEventMessage::getVariableIndex: Encoding is not ByIndex, aborting!");
2286  return index;
2287  }
2288 
2289  BYTE* bufferPos = &getPayLoad()[3];
2290  switch (m_protocol)
2291  {
2292  case SopasBase::CoLa_A:
2293  index = (INT32)(colaa::decodeUINT16(bufferPos));
2294  break;
2295  case SopasBase::CoLa_B:
2296  index = (INT32)(colab::decodeUINT16(bufferPos));
2297  break;
2298  default:
2299  printError("SopasEventMessage::getVariableIndex: Unknown protocol!");
2300  }
2301 
2302  return index;
2303 }
2304 
2305 //
2306 // Read the variable name from a sensor message. This works only if the encoding "ByName" is used!
2307 //
2309 {
2310  std::string name;
2311  UINT32 i;
2312  BYTE* bufferPos;
2313 
2315  {
2316  switch (m_protocol)
2317  {
2318  case SopasBase::CoLa_A:
2319  printError("SopasEventMessage::getVariableName: Protocol CoLa-A is not supported, aborting!");
2320  return "";
2321  break;
2322  case SopasBase::CoLa_B:
2323  bufferPos = &getPayLoad()[4];
2324  i = 4;
2325 
2326  // example for message "sSI <variablename> 0x000binarydata"
2327 
2328  // search for the next white space
2329  while ((*bufferPos != ' ') && (i < getPayLoadLength()))
2330  {
2331  name += *bufferPos;
2332  bufferPos++;
2333  i++;
2334  }
2335  break;
2336  }
2337  }
2338 
2339  return name;
2340 }
2341 
2342 
2343 //
2344 // Detects the encoding method (ByName or ByIndex) from the sensor message.
2345 //
2347 {
2348  // if the third byte of the payload is an 'I', the encoding is ByIndex
2349  // sXI: sAI, sRI, sWI, sMI, sEI, sSI
2350  if (getPayLoad()[2] == 'I')
2351  {
2353  }
2354 }
2355 
2356 
2357 
2359 {
2360  std::string command = getCommandString();
2361 
2363  {
2365  }
2367  {
2369  }
2371  {
2373  }
2375  {
2377  }
2379  {
2381  }
2383  {
2385  }
2386  else
2387  {
2389  }
2390 }
2391 
2392 SopasAnswer::SopasAnswer(const BYTE* answer, UINT32 answerLength) : m_answerLength(answerLength)
2393 {
2394  if (answerLength > 0)
2395  {
2397  memcpy(m_answerBuffer, answer, answerLength);
2398  }
2399  else
2400  {
2401  m_answerBuffer = NULL;
2402  }
2403 }
2404 
2406 {
2407  if (m_answerBuffer != NULL)
2408  {
2409  delete[] m_answerBuffer;
2410  m_answerLength = 0;
2411  }
2412 }
2413 
2414 } // namespace devices
devices::SopasBase::VARIABLENAME_DEVICEIDENT
static const std::string VARIABLENAME_DEVICEIDENT
Definition: SopasBase.hpp:46
devices::SopasBase::WA
@ WA
Write Variable Answer.
Definition: SopasBase.hpp:290
UINT16
uint16_t UINT16
Definition: BasicDatatypes.hpp:73
UINT8
uint8_t UINT8
Definition: BasicDatatypes.hpp:75
devices::SopasBase::CoLa_A
@ CoLa_A
Command Language ASCI.
Definition: SopasBase.hpp:77
devices::SopasBase::invokeMethod
bool invokeMethod(const std::string &methodeName, BYTE *parameters, UINT16 parametersLength, SopasAnswer *&answer)
Invoke a method on the sensor.
Definition: SopasBase.cpp:1648
devices::SopasBase::CONNECTED
@ CONNECTED
Definition: SopasBase.hpp:309
devices::SopasBase::m_numberOfBytesInResponseBuffer
UINT32 m_numberOfBytesInResponseBuffer
Number of bytes in buffer.
Definition: SopasBase.hpp:402
devices::SopasBase::COMMAND_Event_Acknowledge
static const std::string COMMAND_Event_Acknowledge
Definition: SopasBase.hpp:64
devices::SopasBase::WI
@ WI
Write Variable.
Definition: SopasBase.hpp:284
Tcp::isOpen
bool isOpen()
Definition: tcp.cpp:107
devices::SopasBase::unregisterEvent
bool unregisterEvent(const std::string &eventName)
Unregisters an event by name.
Definition: SopasBase.cpp:2138
devices::SopasEventMessage::m_frameLength
UINT32 m_frameLength
Definition: SopasBase.hpp:482
devices::SopasEventMessage::m_encoding
SopasBase::SopasEncoding m_encoding
Definition: SopasBase.hpp:483
devices::SopasAnswer::m_answerLength
UINT32 m_answerLength
Definition: SopasBase.hpp:504
devices::SopasBase::RN
@ RN
Read Variable (by name)
Definition: SopasBase.hpp:295
NULL
#define NULL
devices::SopasBase::SI
@ SI
Send Event.
Definition: SopasBase.hpp:288
devices::SopasBase::SopasCommand
SopasCommand
Definition: SopasBase.hpp:280
devices::SopasBase::m_numberOfBytesInReceiveBuffer
UINT32 m_numberOfBytesInReceiveBuffer
Number of bytes in buffer.
Definition: SopasBase.hpp:407
errorhandler.hpp
angle
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
ScopedLock
Definition: Mutex.hpp:39
devices::SopasAnswer::size
UINT32 size()
Definition: SopasBase.hpp:499
devices::SopasEventMessage::getMessageType
SopasBase::SopasMessageType getMessageType() const
Definition: SopasBase.hpp:448
devices::SopasAnswer::~SopasAnswer
~SopasAnswer()
Destructor. Frees the memory for the copied buffer.
Definition: SopasBase.cpp:2405
devices::SopasBase::connect
bool connect()
Connects to a sensor via tcp and reads the device name.
Definition: SopasBase.cpp:122
devices::SopasBase::COMMAND_Write_Variable_ByIndex
static const std::string COMMAND_Write_Variable_ByIndex
Definition: SopasBase.hpp:53
devices::SopasBase::METHODNAME_SET_SCANCONFIG
static const std::string METHODNAME_SET_SCANCONFIG
Definition: SopasBase.hpp:43
devices::SopasBase::MSG_READ_VARIABLE_ANSWER
@ MSG_READ_VARIABLE_ANSWER
Read Variable Answer.
Definition: SopasBase.hpp:97
devices::SopasBase::processFrame_CoLa_B
void processFrame_CoLa_B(SopasEventMessage &frame)
Definition: SopasBase.cpp:1234
devices::SopasBase::CoLa_B
@ CoLa_B
Command Language binary.
Definition: SopasBase.hpp:78
devices::SopasBase::COMMAND_Method_Result_ByName
static const std::string COMMAND_Method_Result_ByName
Definition: SopasBase.hpp:69
devices::SopasBase::m_scannerVersion
std::string m_scannerVersion
Read from scanner.
Definition: SopasBase.hpp:358
devices::SopasBase::COMMAND_Register_Event_Answer
static const std::string COMMAND_Register_Event_Answer
Definition: SopasBase.hpp:63
devices::SopasBase::SopasBase
SopasBase()
Default constructor.
Definition: SopasBase.cpp:57
devices
Definition: SopasBase.cpp:14
BYTE
unsigned char BYTE
devices::SopasBase::COMMAND_Read_Variable_ByName
static const std::string COMMAND_Read_Variable_ByName
Definition: SopasBase.hpp:66
colab::addFrameToBuffer
void addFrameToBuffer(UINT8 *sendBuffer, UINT8 *cmdBuffer, UINT16 *len)
Definition: colab.cpp:99
devices::SopasBase::COMMAND_Read_Variable_Answer
static const std::string COMMAND_Read_Variable_Answer
Definition: SopasBase.hpp:59
devices::SopasAnswer::SopasAnswer
SopasAnswer(const BYTE *answer, UINT32 answerLength)
Constructor. Copies the content of the answer into the buffer of this object.
Definition: SopasBase.cpp:2392
devices::SopasBase::MSG_INVOKE_METHOD_ANSWER
@ MSG_INVOKE_METHOD_ANSWER
Invoke Method Answer.
Definition: SopasBase.hpp:99
devices::SopasEventMessage::m_protocol
SopasBase::SopasProtocol m_protocol
Definition: SopasBase.hpp:481
Tcp::DisconnectFunction
void(* DisconnectFunction)(void *obj)
Definition: tcp.hpp:59
devices::SopasBase::findFrameInReceiveBuffer
SopasEventMessage findFrameInReceiveBuffer()
Depending on the protocol the start and end of a frame will be found.
Definition: SopasBase.cpp:331
devices::SopasBase::registerEvent
bool registerEvent(const std::string &eventName)
Registers an event by name.
Definition: SopasBase.cpp:1985
devices::SopasBase::colaA_decodeScannerTypeAndVersion
void colaA_decodeScannerTypeAndVersion(std::string *rxData)
Definition: SopasBase.cpp:1596
devices::SopasBase::openTcpConnection
bool openTcpConnection()
Definition: SopasBase.cpp:219
colaa::getNextStringToken
std::string getNextStringToken(std::string *rxData)
Definition: colaa.cpp:246
devices::SopasAnswer::getBuffer
BYTE * getBuffer()
Definition: SopasBase.hpp:497
devices::SopasBase::COMMAND_Invoke_Method_ByIndex
static const std::string COMMAND_Invoke_Method_ByIndex
Definition: SopasBase.hpp:54
devices::SopasEventMessage::detectMessageType
void detectMessageType()
Definition: SopasBase.cpp:2358
devices::SopasBase::COMMAND_Write_Variable_ByName
static const std::string COMMAND_Write_Variable_ByName
Definition: SopasBase.hpp:67
memwrite_UINT16
void memwrite_UINT16(BYTE *&buffer, UINT16 value)
Definition: toolbox.cpp:584
devices::SopasBase::readCallbackFunction
void readCallbackFunction(UINT8 *buffer, UINT32 &numOfBytes)
Definition: SopasBase.cpp:259
devices::SopasBase::METHODNAME_LOGIN
static const std::string METHODNAME_LOGIN
Definition: SopasBase.hpp:41
devices::SopasBase::stringToSopasCommand
SopasCommand stringToSopasCommand(const std::string &cmdString)
Converts strings in sopas answer buffer to SopasCommand enum.
Definition: SopasBase.cpp:1375
devices::SopasBase::MI
@ MI
Invoke Method.
Definition: SopasBase.hpp:285
devices::SopasBase::ByIndex
@ ByIndex
read/write variable, invoke methods by index (indexes will be generated !!!)
Definition: SopasBase.hpp:84
devices::SopasBase::COMMAND_Read_Variable_ByIndex
static const std::string COMMAND_Read_Variable_ByIndex
Definition: SopasBase.hpp:52
toString
std::string toString(INT32 value)
Definition: toolbox.cpp:279
devices::SopasBase::RA
@ RA
Read Variable Answer.
Definition: SopasBase.hpp:289
devices::SopasEventMessage::getPayLoadLength
UINT32 getPayLoadLength() const
contains 's' + command string(2 byte) + content(payload length - 3)
Definition: SopasBase.cpp:2219
colaa::convertRxBufferToString
std::string convertRxBufferToString(UINT8 *buffer, UINT16 bufferLen)
Definition: colaa.cpp:793
INT32
int32_t INT32
Definition: BasicDatatypes.hpp:71
devices::SopasBase::makeAngleValid
double makeAngleValid(double angle)
Definition: SopasBase.cpp:2193
devices::SopasBase::COMMAND_Send_Event_ByIndex
static const std::string COMMAND_Send_Event_ByIndex
Definition: SopasBase.hpp:57
colab::getStringFromBuffer
std::string getStringFromBuffer(UINT8 *buffer, UINT16 &pos, UINT16 length)
Definition: colab.cpp:39
devices::SopasBase::m_tcp
Tcp m_tcp
Definition: SopasBase.hpp:411
devices::SopasBase::MSG_WRITE_VARIABLE_ANSWER
@ MSG_WRITE_VARIABLE_ANSWER
Write Variable Answer.
Definition: SopasBase.hpp:98
devices::SopasBase::COMMAND_Register_Event_ByIndex
static const std::string COMMAND_Register_Event_ByIndex
Definition: SopasBase.hpp:56
devices::SopasBase::COMMAND_Invoke_Method_Answer
static const std::string COMMAND_Invoke_Method_Answer
Definition: SopasBase.hpp:61
printInfoMessage
#define printInfoMessage(a, b)
Definition: errorhandler.hpp:14
devices::SopasBase::CMD_UNKNOWN
@ CMD_UNKNOWN
Unknown command.
Definition: SopasBase.hpp:282
CoLa_A
@ CoLa_A
Command Language ASCI.
Definition: sick_scan_common_nw.h:33
devices::SopasAnswer::isValid
bool isValid()
Definition: SopasBase.hpp:501
printWarning
void printWarning(std::string message)
Definition: errorhandler.cpp:80
devices::SopasEventMessage::getVariableName
std::string getVariableName()
Returns the name of a variable (answer to read variable by name). In case of error an empty value wil...
Definition: SopasBase.cpp:2308
devices::SopasEventMessage::m_buffer
BYTE * m_buffer
Definition: SopasBase.hpp:480
devices::SopasBase::MA
@ MA
Invoke Method Answer.
Definition: SopasBase.hpp:291
Tcp::write
bool write(UINT8 *buffer, UINT32 numberOfBytes)
Definition: tcp.cpp:57
devices::SopasEventMessage::getPayLoad
BYTE * getPayLoad()
contains 's' + command string(2 byte) + content(payload length - 3)
Definition: SopasBase.cpp:2259
devices::SopasBase::receiveAnswer
bool receiveAnswer(SopasCommand cmd, std::string name, UINT32 timeout, SopasAnswer *&answer)
Take answer from read thread and decode it. Waits for a certain answer by name. Event data (scans) ar...
Definition: SopasBase.cpp:539
Tcp::setDisconnectCallbackFunction
void setDisconnectCallbackFunction(DisconnectFunction discFunction, void *obj)
Definition: tcp.cpp:94
devices::SopasBase::COMMAND_Write_Variable_Answer
static const std::string COMMAND_Write_Variable_Answer
Definition: SopasBase.hpp:60
devices::SopasBase::getNanosecTimestampLastTcpMessageReceived
uint64_t getNanosecTimestampLastTcpMessageReceived(void)
Definition: SopasBase.cpp:2184
usleep
void usleep(__int64 usec)
Definition: usleep.c:3
Mutex.hpp
devices::SopasBase::CONSTRUCTED
@ CONSTRUCTED
Object has been constructed. Use init() to go into CONNECTED state.
Definition: SopasBase.hpp:305
devices::SopasBase::colaB_decodeScannerTypeAndVersion
void colaB_decodeScannerTypeAndVersion(UINT8 *buffer, UINT16 pos)
Definition: SopasBase.cpp:1626
api.setup.name
name
Definition: python/api/setup.py:12
devices::SopasBase::action_getScannerTypeAndVersion
bool action_getScannerTypeAndVersion()
Reads the scanner type and version variable from the sensor and stores it in the member variables....
Definition: SopasBase.cpp:1548
devices::SopasBase::m_responseBuffer
UINT8 m_responseBuffer[1024]
Receive buffer for everything except scan data and eval case data.
Definition: SopasBase.hpp:403
devices::SopasAnswer::m_answerBuffer
BYTE * m_answerBuffer
Definition: SopasBase.hpp:505
devices::SopasBase::isConnected
bool isConnected()
Returns true if the tcp connection is established.
Definition: SopasBase.cpp:177
devices::SopasBase::m_receiveDataMutex
Mutex m_receiveDataMutex
Access mutex for buffer.
Definition: SopasBase.hpp:404
devices::SopasBase::closeTcpConnection
void closeTcpConnection()
Definition: SopasBase.cpp:238
devices::SopasEventMessage
Class that represents a message that was sent by a sensor. (Event message)
Definition: SopasBase.hpp:420
toolbox.hpp
devices::SopasBase::VARIABLENAME_DATAOUTPUTRANGE
static const std::string VARIABLENAME_DATAOUTPUTRANGE
Definition: SopasBase.hpp:48
devices::SopasBase::m_decoderFunctionMapByName
DecoderFunctionMapByName m_decoderFunctionMapByName
Definition: SopasBase.hpp:392
devices::SopasBase::ByName
@ ByName
read/write variable, invoke methods by name
Definition: SopasBase.hpp:83
devices::SopasBase::FA
@ FA
Error.
Definition: SopasBase.hpp:298
devices::SopasBase::sopasCommandToString
std::string sopasCommandToString(SopasCommand cmd)
Definition: SopasBase.cpp:1460
devices::SopasBase::MSG_EVENT_ACKNOWLEDGE
@ MSG_EVENT_ACKNOWLEDGE
Event Acknowledge -Answer to register event.
Definition: SopasBase.hpp:102
devices::SopasEventMessage::getCommandString
std::string getCommandString() const
Definition: SopasBase.cpp:2237
multiscan_receiver.mode
string mode
Definition: multiscan_receiver.py:348
devices::SopasBase::isReadOnly
bool isReadOnly()
Definition: SopasBase.cpp:207
colaa::decodeUINT16
UINT16 decodeUINT16(BYTE *buffer)
Definition: colaa.cpp:627
devices::SopasBase::MSG_SEND_EVENT
@ MSG_SEND_EVENT
Send Event.
Definition: SopasBase.hpp:96
devices::SopasBase::m_portNumber
UINT16 m_portNumber
Definition: SopasBase.hpp:413
devices::SopasAnswer
Class that encapsulates a buffer that was sent as return to a sync call. (variable / method)
Definition: SopasBase.hpp:488
devices::SopasBase::METHODNAME_LOGOUT
static const std::string METHODNAME_LOGOUT
Definition: SopasBase.hpp:42
devices::SopasBase::receiveAnswer_CoLa_B
bool receiveAnswer_CoLa_B(SopasCommand cmd, std::string name, UINT32 timeout, SopasAnswer *&answer)
Definition: SopasBase.cpp:781
devices::SopasBase::COMMAND_Register_Event_ByName
static const std::string COMMAND_Register_Event_ByName
Definition: SopasBase.hpp:70
printError
void printError(std::string message)
Definition: errorhandler.cpp:102
devices::SopasBase::AN
@ AN
Method Result (ny name)
Definition: SopasBase.hpp:296
devices::SopasBase::AA
@ AA
Method Result Answer.
Definition: SopasBase.hpp:292
devices::SopasBase::m_scannerName
std::string m_scannerName
Read from scanner.
Definition: SopasBase.hpp:357
devices::SopasBase::~SopasBase
virtual ~SopasBase()
Destructor.
Definition: SopasBase.cpp:67
Tcp::setReadCallbackFunction
void setReadCallbackFunction(ReadFunction readFunction, void *obj)
Definition: tcp.cpp:122
devices::SopasBase::readVariable
bool readVariable(const std::string &variableName, SopasAnswer *&answer)
Reads a variable from the sensor by name.
Definition: SopasBase.cpp:1762
devices::SopasBase::sendCommandBuffer
bool sendCommandBuffer(UINT8 *buffer, UINT16 len)
Sends the content of the buffer via TCP to the sensor.
Definition: SopasBase.cpp:505
devices::SopasBase::METHODNAME_STOP_MEASURE
static const std::string METHODNAME_STOP_MEASURE
Definition: SopasBase.hpp:45
devices::SopasBase::scanDataDecoder
virtual void scanDataDecoder(SopasEventMessage &msg)=0
devices::SopasBase::m_readOnlyMode
bool m_readOnlyMode
Definition: SopasBase.hpp:415
devices::SopasBase::m_indexToNameMap
IndexToNameMap m_indexToNameMap
Definition: SopasBase.hpp:399
colaa::decodeString
std::string decodeString(std::string *rxData, UINT16 len)
Definition: colaa.cpp:603
Tcp::getNanosecTimestampLastTcpMessageReceived
uint64_t getNanosecTimestampLastTcpMessageReceived(void)
Definition: tcp.hpp:62
devices::SopasBase::COMMAND_Method_Result_ByIndex
static const std::string COMMAND_Method_Result_ByIndex
Definition: SopasBase.hpp:55
colaa::addUINT32ToBuffer
UINT16 addUINT32ToBuffer(UINT8 *buffer, UINT32 value)
Definition: colaa.cpp:200
devices::SopasBase::EVENTNAME_SUBSCRIBE_SCANS
static const std::string EVENTNAME_SUBSCRIBE_SCANS
Definition: SopasBase.hpp:40
devices::SopasBase
Definition: SopasBase.hpp:36
devices::SopasBase::receiveAnswer_CoLa_A
bool receiveAnswer_CoLa_A(SopasCommand cmd, std::string name, UINT32 timeout, SopasAnswer *&answer)
Definition: SopasBase.cpp:685
devices::SopasEventMessage::detectEncoding
void detectEncoding()
Definition: SopasBase.cpp:2346
devices::SopasBase::writeVariable
bool writeVariable(const std::string &variableName, BYTE *parameters, UINT16 parametersLength)
Write a variable to the sensor by name.
Definition: SopasBase.cpp:1850
ROS_ERROR
#define ROS_ERROR(...)
Definition: sick_scan_logging.h:127
devices::SopasBase::disconnect
bool disconnect()
Closes the connection to the LMS. This is the opposite of init().
Definition: SopasBase.cpp:185
devices::SopasBase::AI
@ AI
Method Result.
Definition: SopasBase.hpp:286
devices::SopasEventMessage::size
UINT32 size() const
Definition: SopasBase.hpp:453
colaa::addStringToBuffer
UINT16 addStringToBuffer(UINT8 *buffer, const std::string &text)
Definition: colaa.cpp:224
devices::SopasBase::m_weWantScanData
bool m_weWantScanData
Flag to enable/disable scan data reception.
Definition: SopasBase.hpp:352
devices::SopasBase::m_protocol
SopasProtocol m_protocol
Used protocol (ColaA oder ColaB)
Definition: SopasBase.hpp:384
devices::SopasBase::copyFrameToResposeBuffer
void copyFrameToResposeBuffer(UINT32 frameLength)
Definition: SopasBase.cpp:1315
devices::SopasEventMessage::m_messageType
SopasBase::SopasMessageType m_messageType
Definition: SopasBase.hpp:484
devices::SopasBase::readCallbackFunctionS
static void readCallbackFunctionS(void *obj, UINT8 *buffer, UINT32 &numOfBytes)
Function that will be called on incomming data via tcp.
Definition: SopasBase.cpp:249
devices::SopasBase::processFrame_CoLa_A
void processFrame_CoLa_A(SopasEventMessage &frame)
Definition: SopasBase.cpp:1145
devices::SopasBase::SA
@ SA
Event Acknowledge.
Definition: SopasBase.hpp:294
sick_generic_device_finder.timeout
timeout
Definition: sick_generic_device_finder.py:113
devices::SopasBase::COMMAND_Invoke_Method_ByName
static const std::string COMMAND_Invoke_Method_ByName
Definition: SopasBase.hpp:68
devices::SopasBase::EVENTNAME_SUBSCRIBE_EVALCASES
static const std::string EVENTNAME_SUBSCRIBE_EVALCASES
Definition: SopasBase.hpp:39
devices::SopasBase::RI
@ RI
Read Variable.
Definition: SopasBase.hpp:283
devices::SopasBase::m_state
State m_state
Device info.
Definition: SopasBase.hpp:356
devices::SopasBase::colaA_decodeCommand
SopasCommand colaA_decodeCommand(std::string *rxData)
Definition: SopasBase.cpp:1368
UINT32
uint32_t UINT32
Definition: BasicDatatypes.hpp:72
devices::SopasEventMessage::SopasEventMessage
SopasEventMessage()
Default constructor.
Definition: SopasBase.cpp:2203
Tcp::close
void close()
Definition: tcp.cpp:373
devices::SopasBase::m_weWantFieldData
bool m_weWantFieldData
Flag to enable/disable protection field data reception.
Definition: SopasBase.hpp:353
devices::SopasBase::EA
@ EA
Register Event Answer.
Definition: SopasBase.hpp:293
devices::SopasBase::COMMAND_Method_Result_Answer
static const std::string COMMAND_Method_Result_Answer
Definition: SopasBase.hpp:62
devices::SopasBase::removeFrameFromReceiveBuffer
void removeFrameFromReceiveBuffer(UINT32 frameLength)
Definition: SopasBase.cpp:1341
devices::SopasBase::MSG_METHOD_RESULT_ANSWER
@ MSG_METHOD_RESULT_ANSWER
Method Result Answer.
Definition: SopasBase.hpp:100
roswrap::package::command
ROSLIB_DECL std::string command(const std::string &cmd)
Runs a rospack command of the form 'rospack <cmd>', returning the output as a single string.
devices::SopasBase::INDEX_DEVICE_IDENT
static const UINT16 INDEX_DEVICE_IDENT
Definition: SopasBase.hpp:73
devices::SopasBase::SN
@ SN
Send Event (by name, receive)
Definition: SopasBase.hpp:297
devices::SopasBase::SopasProtocol
SopasProtocol
Definition: SopasBase.hpp:75
cmd
string cmd
devices::SopasBase::evalCaseResultDecoder
virtual void evalCaseResultDecoder(SopasEventMessage &msg)=0
devices::SopasEventMessage::getEncodingType
SopasBase::SopasEncoding getEncodingType() const
Definition: SopasBase.hpp:443
colab::decodeUINT16
UINT16 decodeUINT16(BYTE *buffer)
Definition: colab.cpp:142
devices::SopasBase::m_ipAddress
std::string m_ipAddress
Definition: SopasBase.hpp:412
devices::SopasBase::VARIABLENAME_SCANCONFIG
static const std::string VARIABLENAME_SCANCONFIG
Definition: SopasBase.hpp:47
devices::SopasBase::setReadOnlyMode
void setReadOnlyMode(bool mode)
Definition: SopasBase.cpp:200
colaa::addFrameToBuffer
void addFrameToBuffer(UINT8 *sendBuffer, UINT8 *cmdBuffer, UINT16 *len)
Definition: colaa.cpp:82
devices::SopasEventMessage::getVariableIndex
INT32 getVariableIndex()
Returns the index of a variable (answer to read variable by index). In case of error a negative value...
Definition: SopasBase.cpp:2278
devices::SopasBase::COMMAND_Send_Event_ByName
static const std::string COMMAND_Send_Event_ByName
Definition: SopasBase.hpp:71
devices::SopasBase::init
virtual bool init(SopasProtocol protocol, std::string ipAddress, UINT16 portNumber, bool weWantScanData, bool weWantFieldData, bool readOnlyMode, Tcp::DisconnectFunction disconnectFunction, void *obj)
Initialization.
Definition: SopasBase.cpp:94
devices::SopasBase::m_receiveBuffer
UINT8 m_receiveBuffer[25000]
Low-Level receive buffer for all data (25000 should be enough for NAV300 Events)
Definition: SopasBase.hpp:408
colab::addStringToBuffer
void addStringToBuffer(UINT8 *buffer, UINT16 &pos, const std::string &stringValue)
Definition: colab.cpp:21
devices::SopasBase::EI
@ EI
Register Event.
Definition: SopasBase.hpp:287
devices::SopasBase::convertSopasErrorCodeToText
static std::string convertSopasErrorCodeToText(UINT16 errorCode)
Definition: SopasBase.cpp:916
devices::SopasBase::MSG_UNKNOWN
@ MSG_UNKNOWN
Unknown message.
Definition: SopasBase.hpp:90
SopasBase.hpp
devices::SopasBase::VARIABLENAME_SCANDATACONFIG
static const std::string VARIABLENAME_SCANDATACONFIG
Definition: SopasBase.hpp:49
devices::SopasBase::processFrame
void processFrame(SopasEventMessage &frame)
Reads one frame from receive buffer and decodes it.
Definition: SopasBase.cpp:1123
devices::SopasBase::m_beVerbose
bool m_beVerbose
Definition: SopasBase.hpp:360
colab::getCommandStringFromBuffer
std::string getCommandStringFromBuffer(UINT8 *buffer)
Definition: colab.cpp:56
Tcp::open
bool open(std::string ipAddress, UINT16 port, bool enableVerboseDebugOutput=false)
Definition: tcp.cpp:148
devices::SopasBase::METHODNAME_START_MEASURE
static const std::string METHODNAME_START_MEASURE
Definition: SopasBase.hpp:44
colab::getIdentifierFromBuffer
std::string getIdentifierFromBuffer(UINT8 *buffer, UINT16 &nextData, UINT16 bufferLength)
Definition: colab.cpp:61


sick_scan_xd
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Fri Oct 25 2024 02:47:12