SopasBase.cpp
Go to the documentation of this file.
00001 //
00002 // SopasBase.cpp
00003 //
00004 //  Created on: 18.07.2011
00005 //      Author: sick
00006 //
00007 
00008 #include "SopasBase.hpp"
00009 
00010 
00011 #include "../manager.hpp"
00012 #include "../tools/errorhandler.hpp"
00013 #include "../tools/toolbox.hpp"
00014 #include "../tools/Mutex.hpp"
00015 
00016 namespace devices
00017 {
00018         
00019 #define SOPASBASE_VERSION "1.0.0"
00020 
00021 const std::string SopasBase::EVENTNAME_SUBSCRIBE_EVALCASES("LFErec");
00022 const std::string SopasBase::EVENTNAME_SUBSCRIBE_SCANS("LMDscandata");
00023 const std::string SopasBase::METHODNAME_LOGIN("SetAccessMode");
00024 const std::string SopasBase::METHODNAME_LOGOUT("Run");
00025 const std::string SopasBase::METHODNAME_SET_SCANCONFIG("mLMPsetscancfg");
00026 const std::string SopasBase::METHODNAME_START_MEASURE("LMCstartmeas");
00027 const std::string SopasBase::METHODNAME_STOP_MEASURE("LMCstopmeas");
00028 const std::string SopasBase::VARIABLENAME_SCANCONFIG("LMPscancfg");
00029 const std::string SopasBase::VARIABLENAME_DATAOUTPUTRANGE("LMPoutputRange");
00030 const std::string SopasBase::VARIABLENAME_SCANDATACONFIG("LMDscandatacfg");
00031 const std::string SopasBase::VARIABLENAME_DEVICEIDENT("DeviceIdent");
00032 
00033 // sopas commands
00034 const std::string SopasBase::COMMAND_Read_Variable_ByIndex("RI");
00035 const std::string SopasBase::COMMAND_Write_Variable_ByIndex("WI");
00036 const std::string SopasBase::COMMAND_Invoke_Method_ByIndex("MI");
00037 const std::string SopasBase::COMMAND_Method_Result_ByIndex("AI");
00038 const std::string SopasBase::COMMAND_Register_Event_ByIndex("EI");
00039 const std::string SopasBase::COMMAND_Send_Event_ByIndex("SI"); // receive data event
00040 
00041 const std::string SopasBase::COMMAND_Read_Variable_Answer("RA");
00042 const std::string SopasBase::COMMAND_Write_Variable_Answer("WA");
00043 const std::string SopasBase::COMMAND_Invoke_Method_Answer("MA");
00044 const std::string SopasBase::COMMAND_Method_Result_Answer("AA");
00045 const std::string SopasBase::COMMAND_Register_Event_Answer("EA");
00046 const std::string SopasBase::COMMAND_Event_Acknowledge("SA");
00047 
00048 const std::string SopasBase::COMMAND_Read_Variable_ByName("RN");
00049 const std::string SopasBase::COMMAND_Write_Variable_ByName("WN");
00050 const std::string SopasBase::COMMAND_Invoke_Method_ByName("MN");
00051 const std::string SopasBase::COMMAND_Method_Result_ByName("AN");
00052 const std::string SopasBase::COMMAND_Register_Event_ByName("EN");
00053 const std::string SopasBase::COMMAND_Send_Event_ByName("SN"); // receive data event
00054 
00055 const UINT16 SopasBase::INDEX_DEVICE_IDENT = 0;
00056 
00057 
00058 
00059 SopasBase::SopasBase() :
00060         m_state(CONSTRUCTED)
00061 {
00062         m_beVerbose = false;
00063         
00064         m_protocol = CoLa_A;    // Default protocol is CoLa-A
00065 }
00066 
00067 
00068 
00069 SopasBase::~SopasBase()
00070 {
00071         printInfoMessage("Sopas device destructor: Running.", m_beVerbose);
00072 
00073         // Derived device must be stopped in it's constructor. No virtual functions may be called here!
00074 //      assert(isRunning() == false);
00075 
00076         printInfoMessage("Sopas device destructor: Stopped, now disconnecting.", m_beVerbose);
00077 
00078         // Disconnect and shut down receive thread.
00079         if (isConnected() == true)
00080         {
00081                 // Change from CONNECTED to CONSTRUCTED
00082                 disconnect();
00083         }
00084 
00085 //      printInfoMessage("Sopas device destructor: Disconnected, now deleting socket.", m_beVerbose);
00086 
00087         printInfoMessage("Sopas device destructor: Done, device is deleted.", m_beVerbose);
00088 }
00089 
00090 
00091 
00092 //
00093 // Initialisation from Scanner class:
00094 // Parameter setup only. Afterwards, call connect() to connect to the scanner.
00095 //
00096 bool SopasBase::init(SopasProtocol protocol,
00097                                                 std::string ipAddress,
00098                                                 UINT16 portNumber,
00099                                                 bool weWantScanData,
00100                                                 bool weWantFieldData,
00101                                                 bool readOnlyMode,
00102                                                 Tcp::DisconnectFunction disconnectFunction,
00103                                                 void* obj)
00104 {
00105         m_protocol = protocol;
00106         m_ipAddress = ipAddress;
00107         m_portNumber = portNumber;
00108         m_weWantScanData = weWantScanData;
00109         m_weWantFieldData = weWantFieldData;
00110         setReadOnlyMode(readOnlyMode);
00111 
00112         m_tcp.setDisconnectCallbackFunction(disconnectFunction, obj);
00113 
00114         return true;
00115 }
00116 
00117 
00118 //
00119 // Verbinde mit dem unter init() eingestellten Geraet, und pruefe die Verbindung
00120 // durch einen DeviceIdent-Aufruf.
00121 //
00122 // true = Erfolgreich.
00123 //
00124 bool SopasBase::connect()
00125 {
00126         printInfoMessage("SopasBase::connect: Called.", m_beVerbose);
00127         
00128         assert (m_state == CONSTRUCTED); // must not be opened or running already
00129 
00130         // Initialise buffer variables
00131         m_numberOfBytesInReceiveBuffer = 0; // Buffer is empty
00132         m_numberOfBytesInResponseBuffer = 0; // Buffer is empty
00133         //      m_isLoggedIn = false;
00134         m_scannerName = "";
00135         m_scannerVersion = "";
00136 
00137         // Establish connection here
00138         // Set the data input callback for our TCP connection
00139         m_tcp.setReadCallbackFunction(&SopasBase::readCallbackFunctionS, this); // , this, _1, _2));
00140 
00141         bool success = openTcpConnection();
00142         if (success == true)
00143         {
00144                 // Check if scanner type matches
00145                 m_state = CONNECTED;
00146                 printInfoMessage("SopasBase::connect: Reading scanner infos", m_beVerbose);
00147                 success = action_getScannerTypeAndVersion();
00148 
00149                 if (success == true)
00150                 {
00151                         printInfoMessage("SopasBase::connect: Initialisation was successful.", m_beVerbose);
00152                 }
00153                 else
00154                 {
00155                         printError("SopasBase::connect: Failed to read scanner type and version.");
00156                 }
00157         }
00158 
00159         if (success == false)
00160         {
00161                 printWarning("SopasBase::connect: Initialisation failed!");
00162         }
00163         else
00164         {
00165                 // Here, we could unsubscribe all events to have a defined default state.
00166         }
00167 
00168         printInfoMessage("SopasBase::connect: Done.", m_beVerbose);
00169         return success;
00170 }
00171 
00172 
00173 
00174 //
00175 // True, if state is CONNECTED, that is:
00176 // - A TCP-connection exists
00177 // - Read thread is running
00178 //
00179 bool SopasBase::isConnected()
00180 {
00181         return (m_state == CONNECTED);
00182 }
00183 
00184 //
00185 // Disconnect from the scanner, and close the interface.
00186 //
00187 bool SopasBase::disconnect()
00188 {
00189         closeTcpConnection();
00190 
00191         // Change back to CONSTRUCTED
00192         m_state = CONSTRUCTED;
00193         return true;
00194 }
00195 
00196 
00197 
00198 //
00199 // (Un)set read only mode. Setting this mode, the sensor will ignore commands which will change any
00200 // parameters on the device. The sensor itself will execute such commands.
00201 //
00202 void SopasBase::setReadOnlyMode(bool mode)
00203 {
00204         m_readOnlyMode = mode;
00205 }
00206 
00207 
00208 
00209 bool SopasBase::isReadOnly()
00210 {
00211         return m_readOnlyMode;
00212 }
00213 
00214 
00215 
00221 bool SopasBase::openTcpConnection()
00222 {
00223         printInfoMessage("SopasBase::openTcpConnection: Connecting TCP/IP connection to " + m_ipAddress + ":" + toString(m_portNumber) + " ...", m_beVerbose);
00224 
00225         bool success = m_tcp.open(m_ipAddress, m_portNumber, m_beVerbose);
00226         if (success == false)
00227         {
00228                 printError("SopasBase::openTcpConnection: ERROR: Failed to establish TCP connection, aborting!");
00229                 return false;
00230         }
00231 
00232         return true;
00233 }
00234 
00235 
00236 
00237 //
00238 // Close TCP-connection and shut down read thread
00239 //
00240 void SopasBase::closeTcpConnection()
00241 {
00242         if (m_tcp.isOpen())
00243         {
00244                 m_tcp.close();
00245         }
00246 }
00247 
00248 //
00249 // Static entry point.
00250 //
00251 void SopasBase::readCallbackFunctionS(void* obj, UINT8* buffer, UINT32& numOfBytes)
00252 {
00253         ((SopasBase*)obj)->readCallbackFunction(buffer, numOfBytes);
00254 }
00255 
00256 
00261 void SopasBase::readCallbackFunction(UINT8* buffer, UINT32& numOfBytes)
00262 {
00263         bool beVerboseHere = false;
00264         printInfoMessage("SopasBase::readCallbackFunction(): Called with " + toString(numOfBytes) + " available bytes.", beVerboseHere);
00265 
00266         ScopedLock lock(&m_receiveDataMutex); // Mutex for access to the input buffer
00267         UINT32 remainingSpace = sizeof(m_receiveBuffer) - m_numberOfBytesInReceiveBuffer;
00268         UINT32 bytesToBeTransferred = numOfBytes;
00269         if (remainingSpace < numOfBytes)
00270         {
00271                 bytesToBeTransferred = remainingSpace;
00272                 printWarning("SopasBase::readCallbackFunction(): Input buffer space is to small, transferring only " +
00273                                                                                 ::toString(bytesToBeTransferred) + " of " + ::toString(numOfBytes) + " bytes.");
00274         }
00275         else
00276         {
00277                 printInfoMessage("SopasBase::readCallbackFunction(): Transferring " + ::toString(bytesToBeTransferred) +
00278                                                                                  " bytes from TCP to input buffer.", beVerboseHere);
00279         }
00280 
00281         if (bytesToBeTransferred > 0)
00282         {
00283                 // Data can be transferred into our input buffer
00284                 memcpy(&(m_receiveBuffer[m_numberOfBytesInReceiveBuffer]), buffer, bytesToBeTransferred);
00285                 m_numberOfBytesInReceiveBuffer += bytesToBeTransferred;
00286 
00287                 UINT32 size = 0;
00288 
00289                 while (1)
00290                 {
00291                         // Now work on the input buffer until all received datasets are processed
00292                         SopasEventMessage frame = findFrameInReceiveBuffer();
00293 
00294                         size = frame.size();
00295                         if (size == 0)
00296                         {
00297                                 // Framesize = 0: There is no valid frame in the buffer. The buffer is either empty or the frame
00298                                 // is incomplete, so leave the loop
00299                                 printInfoMessage("SopasBase::readCallbackFunction(): No complete frame in input buffer, we are done.", beVerboseHere);
00300 
00301                                 // Leave the loop
00302                                 break;
00303                         }
00304                         else
00305                         {
00306                                 // A frame was found in the buffer, so process it now.
00307                                 printInfoMessage("SopasBase::readCallbackFunction(): Processing a frame of length " + ::toString(frame.size()) + " bytes.", beVerboseHere);
00308                                 processFrame(frame);
00309                         }
00310                 }
00311         }
00312         else
00313         {
00314                 // There was input data from the TCP interface, but our input buffer was unable to hold a single byte.
00315                 // Either we have not read data from our buffer for a long time, or something has gone wrong. To re-sync,
00316                 // we clear the input buffer here.
00317                 m_numberOfBytesInReceiveBuffer = 0;
00318         }
00319 
00320         printInfoMessage("SopasBase::readCallbackFunction(): Leaving. Current input buffer fill level is " + 
00321                                                                          ::toString(m_numberOfBytesInReceiveBuffer) + " bytes.", beVerboseHere);
00322 }
00323 
00324 
00325 
00326 //
00327 // Look for 23-frame (STX/ETX) in receive buffer.
00328 // Move frame to start of buffer
00329 //
00330 // Return: 0 : No (complete) frame found
00331 //        >0 : Frame length
00332 //
00333 SopasEventMessage SopasBase::findFrameInReceiveBuffer()
00334 {
00335         UINT32 frameLen = 0;
00336         UINT32 i;
00337 
00338         // Depends on protocol...
00339         if (m_protocol == CoLa_A)
00340         {
00341                 //
00342                 // COLA-A
00343                 //
00344                 // Must start with STX (0x02)
00345                 if (m_receiveBuffer[0] != 0x02)
00346                 {
00347                         // Look for starting STX (0x02)
00348                         for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
00349                         {
00350                                 if (m_receiveBuffer[i] == 0x02)
00351                                 {
00352                                         break;
00353                                 }
00354                         }
00355 
00356                         // Found beginning of frame?
00357                         if (i >= m_numberOfBytesInReceiveBuffer)
00358                         {
00359                                 // No start found, everything can be discarded
00360                                 m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
00361                                 return SopasEventMessage(); // No frame found
00362                         }
00363 
00364                         // Move frame start to index 0
00365                         UINT32 newLen = m_numberOfBytesInReceiveBuffer - i;
00366                         memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), newLen);
00367                         m_numberOfBytesInReceiveBuffer = newLen;
00368                 }
00369 
00370                 // Look for ending ETX (0x03)
00371                 for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
00372                 {
00373                         if (m_receiveBuffer[i] == 0x03)
00374                         {
00375                                 break;
00376                         }
00377                 }
00378 
00379                 // Found end?
00380                 if (i >= m_numberOfBytesInReceiveBuffer)
00381                 {
00382                         // No end marker found, so it's not a complete frame (yet)
00383                         return SopasEventMessage(); // No frame found
00384                 }
00385 
00386                 // Calculate frame length in byte
00387                 frameLen = i + 1;
00388 
00389                 return SopasEventMessage(m_receiveBuffer, CoLa_A, frameLen);
00390         }
00391         else if (m_protocol == CoLa_B)
00392         {
00393                 UINT32 magicWord;
00394                 UINT32 payloadlength;
00395 
00396                 if (m_numberOfBytesInReceiveBuffer < 4)
00397                 {
00398                         return SopasEventMessage();
00399                 }
00400                 UINT16 pos = 0;
00401                 magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
00402                 if (magicWord != 0x02020202)
00403                 {
00404                         // Look for starting STX (0x02020202)
00405                         for (i = 1; i <= m_numberOfBytesInReceiveBuffer - 4; i++)
00406                         {
00407                                 pos = i; // this is needed, as the position value is updated by getIntegerFromBuffer
00408                                 magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
00409                                 if (magicWord == 0x02020202)
00410                                 {
00411                                         // found magic word
00412                                         break;
00413                                 }
00414                         }
00415 
00416                         // Found beginning of frame?
00417                         if (i > m_numberOfBytesInReceiveBuffer - 4)
00418                         {
00419                                 // No start found, everything can be discarded
00420                                 m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
00421                                 return SopasEventMessage(); // No frame found
00422                         }
00423                         else
00424                         {
00425                                 // Move frame start to index
00426                                 UINT32 bytesToMove = m_numberOfBytesInReceiveBuffer - i;
00427                                 memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), bytesToMove); // payload+magic+length+s+checksum
00428                                 m_numberOfBytesInReceiveBuffer = bytesToMove;
00429                         }
00430                 }
00431 
00432                 // Pruefe Laenge des Pufferinhalts
00433                 if (m_numberOfBytesInReceiveBuffer < 9)
00434                 {
00435                         // Es sind nicht genug Daten fuer einen Frame
00436                         printInfoMessage("SopasBase::findFrameInReceiveBuffer: Frame cannot be decoded yet, only " +
00437                                                                  ::toString(m_numberOfBytesInReceiveBuffer) + " bytes in the buffer.", m_beVerbose);
00438                         return SopasEventMessage();
00439                 }
00440 
00441                 // Read length of payload
00442                 pos = 4;
00443                 payloadlength = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
00444                 printInfoMessage("SopasBase::findFrameInReceiveBuffer: Decoded payload length is " + ::toString(payloadlength) + " bytes.", m_beVerbose);
00445                 
00446                 // Ist die Datenlaenge plausibel und wuede in den Puffer passen?
00447                 if (payloadlength > (sizeof(m_receiveBuffer) - 9))
00448                 {
00449                         // magic word + length + checksum = 9
00450                         printWarning("SopasBase::findFrameInReceiveBuffer: Frame too big for receive buffer. Frame discarded with length:"
00451                                                                                         + ::toString(payloadlength) + ".");
00452                         m_numberOfBytesInReceiveBuffer = 0;
00453                         return SopasEventMessage();
00454                 }
00455                 if ((payloadlength + 9) > m_numberOfBytesInReceiveBuffer)
00456                 {
00457                         // magic word + length + s + checksum = 10
00458                         printInfoMessage("SopasBase::findFrameInReceiveBuffer: Frame not complete yet. Waiting for the rest of it (" +
00459                                                                  ::toString(payloadlength + 9 - m_numberOfBytesInReceiveBuffer) + " bytes missing).", m_beVerbose);
00460                         return SopasEventMessage(); // frame not complete
00461                 }
00462 
00463                 // Calculate the total frame length in bytes: Len = Frame (9 bytes) + Payload
00464                 frameLen = payloadlength + 9;
00465 
00466                 //
00467                 // test checksum of payload
00468                 //
00469                 UINT8 temp = 0;
00470                 UINT8 temp_xor = 0;
00471                 UINT8 checkSum;
00472 
00473                 // Read original checksum
00474                 pos = frameLen - 1;
00475                 checkSum = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
00476 
00477                 // Erzeuge die Pruefsumme zum Vergleich
00478                 for (UINT16 i = 8; i < (frameLen - 1); i++)
00479                 {
00480                         pos = i;
00481                         temp = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
00482                         temp_xor = temp_xor ^ temp;
00483                 }
00484 
00485                 // Vergleiche die Pruefsummen
00486                 if (temp_xor != checkSum)
00487                 {
00488                         printWarning("SopasBase::findFrameInReceiveBuffer: Wrong checksum, Frame discarded.");
00489                         m_numberOfBytesInReceiveBuffer = 0;
00490                         return SopasEventMessage();
00491                 }
00492 
00493                 return SopasEventMessage(m_receiveBuffer, CoLa_B, frameLen);
00494         }
00495 
00496         // Return empty frame
00497         return SopasEventMessage();
00498 }
00499 
00500 
00501 
00507 void SopasBase::sendCommandBuffer(UINT8* buffer, UINT16 len)
00508 {
00509         UINT8 sendBuffer[1024];
00510 
00511         assert (len < 1000);
00512         assert (m_tcp.isOpen() == true);
00513 
00514         // Frame the string
00515         if (m_protocol == CoLa_A)
00516         {
00517                 colaa::addFrameToBuffer(sendBuffer, buffer, &len);
00518         }
00519         else if (m_protocol == CoLa_B)
00520         {
00521                 colab::addFrameToBuffer(sendBuffer, buffer, &len);
00522         }
00523         
00524         // Debug: Print buffer
00525 //      traceBuffer("Cmd buffer contents:", sendBuffer, len);
00526         
00527         // Send command (blocking)
00528         m_tcp.write(sendBuffer, len);
00529 }
00530 
00531 
00532 
00541 bool SopasBase::receiveAnswer(SopasCommand cmd, std::string name, UINT32 timeout, SopasAnswer*& answer)
00542 {
00543         switch (m_protocol)
00544         {
00545         case CoLa_A:
00546                 printInfoMessage("SopasBase::receiveAnswer: calling receiveAnswer_CoLa_A.", m_beVerbose);
00547                 return receiveAnswer_CoLa_A(cmd, name, timeout, answer);
00548         case CoLa_B:
00549                 printInfoMessage("SopasBase::receiveAnswer: calling receiveAnswer_CoLa_B.", m_beVerbose);
00550                 return receiveAnswer_CoLa_B(cmd, name, timeout, answer);
00551         default:
00552                 printWarning("SopasBase::receiveAnswer: Wrong protocol (is either not CoLa-A or CoLa-B).");
00553         }
00554 
00555         return false;
00556 }
00557 
00558 
00559 
00568 bool SopasBase::receiveAnswer(SopasCommand cmd, UINT16 index, UINT32 timeout, SopasAnswer*& answer)
00569 {
00570         switch (m_protocol)
00571         {
00572         case CoLa_A:
00573                 printInfoMessage("SopasBase::receiveAnswer: Calling receiveAnswer_CoLa_A.", m_beVerbose);
00574                 return receiveAnswer_CoLa_A(cmd, index, timeout, answer);
00575         case CoLa_B:
00576                 printInfoMessage("SopasBase::receiveAnswer: Calling receiveAnswer_CoLa_B.", m_beVerbose);
00577                 return receiveAnswer_CoLa_B(cmd, index, timeout, answer);
00578         default:
00579                 printWarning("SopasBase::receiveAnswer: Wrong protocol (is either not CoLa-A or CoLa-B).");
00580         }
00581 
00582         return false;
00583 }
00584 
00585 
00586 //
00587 //
00588 //
00589 bool SopasBase::receiveAnswer_CoLa_A(SopasCommand cmd, UINT16 index, UINT32 timeout, SopasAnswer*& answer)
00590 {
00591         printInfoMessage("SopasBase::receiveAnswer_CoLa_A: entering function.", m_beVerbose);
00592 
00593         SopasCommand receivedCommand;
00594         std::string rxData;
00595         if (timeout == 0)
00596         {
00597                 timeout = 1; // Check at least once
00598         }
00599 
00600         // Check until number of cycles reaches timeout
00601         for (UINT32 i = 0; i < timeout; i++)
00602         {
00603                 // Secure against read thread
00604                 {
00605                         ScopedLock lock(&m_receiveDataMutex);
00606                         if (m_numberOfBytesInResponseBuffer > 0)
00607                         {
00608                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_A: Response received (len= " +
00609                                                                                 ::toString(m_numberOfBytesInResponseBuffer) +
00610                                                                                 " bytes).", m_beVerbose);
00611                                 rxData = colaa::convertRxBufferToString(m_responseBuffer, m_numberOfBytesInResponseBuffer);
00612                                 m_numberOfBytesInResponseBuffer = 0; // Clear buffer
00613                         }
00614                 }
00615 
00616                 if (rxData.length() > 0)
00617                 {
00618                         // Decode data
00619                         receivedCommand = colaA_decodeCommand(&rxData);
00620 
00621                         if (cmd == receivedCommand)
00622                         {
00623 
00624                                 // Set variable answer
00625                                 if (receivedCommand == WA)
00626                                 {
00627                                         // Answer contains variable index only and informs about success.
00628                                         return true;
00629                                 }
00630 
00631                                 UINT16 receivedIndex = colaa::decodeUINT16(&rxData); // by name
00632 
00633                                 if (receivedIndex == index)
00634                                 {
00635                                         // Answer to Read Variable or invoke method?
00636                                         if (cmd == RA || cmd == AN)
00637                                         {
00638                                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_A: *** receive answer with data in return *** ", m_beVerbose);
00639 
00640                                                 answer = new SopasAnswer((BYTE*)rxData.c_str(), rxData.length());
00641                                                 m_numberOfBytesInResponseBuffer = 0; // Clear buffer
00642                                                 return true;
00643                                         }
00644                                         else if (receivedCommand == EA)
00645                                         {
00646                                                 // Antwort auf Event-Abonnement setzen/loeschen.
00647                                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_A: Event (by index) successfully (un)registered: " + 
00648                                                                                  ::toString(receivedIndex) + ".", m_beVerbose);
00649 
00650                                                 m_numberOfBytesInResponseBuffer = 0;
00651                                                 return true;
00652                                         }
00653                                 }
00654                                 else
00655                                 {
00656                                         printInfoMessage("SopasBase::receiveAnswer_CoLa_A: This is not the answer we are waiting for. ", m_beVerbose);
00657                                         m_numberOfBytesInResponseBuffer = 0; // Clear buffer
00658                                 }
00659                         }
00660                         // Error answer
00661                         else if (receivedCommand == FA)
00662                         {
00663                                 printInfoMessage("SopasBase::Error answer received: FA " + rxData + ".", m_beVerbose);
00664                                 answer = new SopasAnswer((BYTE*)rxData.c_str(), rxData.length());
00665                                 return false;
00666                         }
00667                         else
00668                         {
00669                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_A: This is not the answer we are waiting for. ", m_beVerbose);
00670                                 m_numberOfBytesInResponseBuffer = 0; // Clear buffer
00671                                 rxData.clear();
00672                         }
00673                 }
00674                 else
00675                 {
00676                         // No data in response buffer. Sleep some time and check again
00677                         usleep(1000);
00678                 }
00679         }
00680 
00681         // Not successful, timeout.
00682         return false;
00683 }
00684 
00685 
00686 
00687 bool SopasBase::receiveAnswer_CoLa_A(SopasCommand cmd, std::string name, UINT32 timeout, SopasAnswer*& answer)
00688 {
00689         printInfoMessage("SopasBase::receiveAnswer_CoLa_A: entering function.", m_beVerbose);
00690 
00691         SopasCommand receivedCommand;
00692         std::string rxData;
00693         if (timeout == 0)
00694         {
00695                 timeout = 1; // Check at least once
00696         }
00697 
00698         // Check until number of cycles reaches timeout
00699         for (UINT32 i = 0; i < timeout; i++)
00700         {
00701                 // Secure against read thread
00702                 {
00703                         ScopedLock lock(&m_receiveDataMutex);
00704                         if (m_numberOfBytesInResponseBuffer > 0)
00705                         {
00706                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_A: Response received (len= " +
00707                                                                  ::toString(m_numberOfBytesInResponseBuffer) + " bytes).", m_beVerbose);
00708                                 rxData = colaa::convertRxBufferToString(m_responseBuffer, m_numberOfBytesInResponseBuffer);
00709                                 m_numberOfBytesInResponseBuffer = 0; // Clear buffer
00710                         }
00711                 }
00712 
00713                 if (rxData.length() > 0)
00714                 {
00715                         // Decode data
00716                         receivedCommand = colaA_decodeCommand(&rxData);
00717 
00718                         if (cmd == receivedCommand)
00719                         {
00720 
00721                                 // Set variable answer
00722                                 if (receivedCommand == WA)
00723                                 {
00724                                         // Answer contains variable index only and informs about success.
00725                                         return true;
00726                                 }
00727 
00728                                 std::string receivedName = colaa::decodeString(&rxData); // by name
00729 
00730                                 if (receivedName == name)
00731                                 {
00732                                         // Answer to Read Variable or invoke method?
00733                                         if (cmd == RA || cmd == AN)
00734                                         {
00735                                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_A: *** receive answer with data in return *** ", m_beVerbose);
00736 
00737                                                 answer = new SopasAnswer((BYTE*)rxData.c_str(), rxData.length());
00738                                                 m_numberOfBytesInResponseBuffer = 0; // Clear buffer
00739                                                 return true;
00740                                         }
00741                                         else if (receivedCommand == EA)
00742                                         {
00743                                                 // Antwort auf Event-Abonnement setzen/loeschen.
00744 
00745                                                 printInfoMessage("SopasBase::  Event successfully (un)registered: " + receivedName + ".", m_beVerbose);
00746                                                 m_numberOfBytesInResponseBuffer = 0;
00747                                                 return true;
00748                                         }
00749                                 }
00750                                 else
00751                                 {
00752                                         printInfoMessage("SopasBase::receiveAnswer_CoLa_A: This is not the answer we are waiting for.", m_beVerbose);
00753                                         m_numberOfBytesInResponseBuffer = 0; // Clear buffer
00754                                 }
00755                         }
00756                         // Error answer
00757                         else if (receivedCommand == FA)
00758                         {
00759                                 printInfoMessage("SopasBase::  Error answer received: FA " + rxData + ".", true);
00760                                 answer = new SopasAnswer((BYTE*)rxData.c_str(), rxData.length());
00761                                 return false;
00762                         }
00763                         else
00764                         {
00765                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_A: This is not the answer we are waiting for.", m_beVerbose);
00766                                 m_numberOfBytesInResponseBuffer = 0; // Clear buffer
00767                                 rxData.clear();
00768                         }
00769                 }
00770                 else
00771                 {
00772                         // No data in response buffer. Sleep some time and check again
00773                         usleep(1000);
00774                 }
00775         }
00776 
00777         // Not successful, timeout.
00778         return false;
00779 }
00780 
00781 
00782 
00783 bool SopasBase::receiveAnswer_CoLa_B(SopasCommand cmd, std::string name, UINT32 timeout, SopasAnswer*& answer)
00784 {
00785         printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Entering function.", m_beVerbose);
00786 
00787         SopasCommand receivedCommand;
00788         UINT16 nextData;
00789         std::string receivedName;
00790 
00791         if (timeout == 0)
00792         {
00793                 timeout = 1; // Check at least once
00794         }
00795 
00796         // Check until number of cycles reaches timeout
00797         for (UINT32 i = 0; i < timeout; i++)
00798         {
00799                 if (m_numberOfBytesInResponseBuffer > 0)
00800                 {
00801 //                      if (m_beVerbose)
00802 //                      {
00803 //                              printInfoMessage("SopasBase::receiveAnswer_CoLa_B: There is something in receive buffer." << std::endl;
00804 //                      }
00805 
00806                         // protect response buffer
00807                         ScopedLock lock(&m_receiveDataMutex);
00808 
00809                         // there are only complete frames in response buffer
00810                         SopasEventMessage frame (m_responseBuffer, CoLa_B, m_numberOfBytesInResponseBuffer);
00811 
00812                         // Parse Sopas Kommando
00813                         //                      receivedCommand = stringToSopasCommand(colab::getCommandStringFromBuffer(m_responseBuffer));
00814                         receivedCommand = stringToSopasCommand(frame.getCommandString());
00815 
00816                         printInfoMessage("SopasBase::receiveAnswer_CoLa_B: receivedCommand= " + frame.getCommandString() + ".", m_beVerbose);
00817 
00818                         if (receivedCommand == FA)
00819                         {
00820                                 // Fehlermeldung vom Sensor
00821                                 nextData = 0;
00822                                 UINT16 errorCode = colab::getIntegerFromBuffer<UINT16>(&(m_responseBuffer[11]), nextData);
00823                                 printWarning("SopasBase::receiveAnswer_CoLa_B: Error from sensor! Code=" + toString(errorCode) +
00824                                                                 ", meaning: " + convertSopasErrorCodeToText(errorCode) + ".");
00825                                 m_numberOfBytesInResponseBuffer = 0;
00826                                 return false;
00827                         }
00828 
00829                         if (cmd != receivedCommand)
00830                         {
00831                                 // Nicht die gesuchte Antwort
00832                                 // da der sensor über sopas immer nur eine anfrage zur zeit bedienen kann, koennen wir die
00833                                 // Nachricht wegwerfen
00834                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B: This is not the answer (" + sopasCommandToString(receivedCommand) + ") are waiting for ("
00835                                                 + sopasCommandToString(cmd) + ").", m_beVerbose);
00836                                 m_numberOfBytesInResponseBuffer = 0;
00837                                 return false;
00838                         }
00839 
00840                         //                      UINT16 nameLength = colab::getIntegerFromBuffer<UINT16>(m_responseBuffer, nextData);
00841                         //                      receivedName = colab::getStringFromBuffer(m_responseBuffer, nextData);
00842 
00843                         receivedName = colab::getIdentifierFromBuffer(m_responseBuffer, nextData, sizeof(m_responseBuffer));
00844 
00845                         printInfoMessage("SopasBase::receiveAnswer_CoLa_B: receicedName= " + receivedName + ".", m_beVerbose);
00846 
00847                         if (name != receivedName)
00848                         {
00849                                 // Nicht die gesuchte Antwort
00850                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B: This is not the answer we are waiting for. (" + frame.getCommandString() +
00851                                                                          ", " + name + ").", m_beVerbose);
00852 
00853                                 m_numberOfBytesInResponseBuffer = 0;
00854                                 return false;
00855                         }
00856 
00857                         if (receivedCommand == WA)
00858                         {
00859                                 // Variable schreiben erfolgreich
00860                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Variable successfully set.", m_beVerbose);
00861                                 m_numberOfBytesInResponseBuffer = 0;
00862                                 return true;
00863                         }
00864 
00865                         else if (receivedCommand == EA)
00866                         {
00867                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Answer to (un)subscribe event " + receivedName + ".", m_beVerbose);
00868                                 m_numberOfBytesInResponseBuffer = 0;
00869                                 return true;
00870                         }
00871                         // Antwort auf Methode ByName
00872                         else if (receivedCommand == AN )
00873                         {
00874                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Answer to method call " + receivedName + ".", m_beVerbose);
00875                                 answer = new SopasAnswer(&m_responseBuffer[nextData], m_numberOfBytesInResponseBuffer - nextData);
00876                                 m_numberOfBytesInResponseBuffer = 0;
00877                                 return true;
00878                         }
00879                         else if (receivedCommand == RA)
00880                         {
00881                                 // Antwort auf das Lesen einer Variablen
00882                                 answer = new SopasAnswer(&m_responseBuffer[nextData], m_numberOfBytesInResponseBuffer - nextData);
00883                                 m_numberOfBytesInResponseBuffer = 0;
00884                                 return true;
00885                         }
00886 
00887                         else if (receivedCommand == CMD_UNKNOWN)
00888                         {
00889                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Unkown Sopas command.", true);
00890                                 m_numberOfBytesInResponseBuffer = 0;
00891                                 return false;
00892                         }
00893                         else
00894                         {
00895                                 // unbekannter oder unbehandelter Befehl
00896                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Untreated Sopas command.", m_beVerbose);
00897                                 m_numberOfBytesInResponseBuffer = 0;
00898                                 return false;
00899                         }
00900 
00901                 }
00902                 else
00903                 {
00904                         // No data in response buffer. Sleep some time and check again
00905                         usleep(1000);
00906                 }
00907         }
00908 
00909         // Not successful, timeout.
00910         printInfoMessage("SopasBase::receiveAnswer_CoLa_B: Leaving with timeout.", m_beVerbose);
00911 
00912         return false;
00913 }
00914 
00915 //
00916 // Convert a Sopas error code to readable text.
00917 //
00918 std::string SopasBase::convertSopasErrorCodeToText(UINT16 errorCode)
00919 {
00920         switch (errorCode)
00921         {
00922                 case 0:
00923                         return "Sopas_Ok";
00924                 case 1:
00925                         return "Sopas_Error_METHODIN_ACCESSDENIED";
00926                 case 2:
00927                         return "Sopas_Error_METHODIN_UNKNOWNINDEX";
00928                 case 3:
00929                         return "Sopas_Error_VARIABLE_UNKNOWNINDEX";
00930                 case 4:
00931                         return "Sopas_Error_LOCALCONDITIONFAILED";
00932                 case 5:
00933                         return "Sopas_Error_INVALID_DATA";
00934                 case 6:
00935                         return "Sopas_Error_UNKNOWN_ERROR";
00936                 case 7:
00937                         return "Sopas_Error_BUFFER_OVERFLOW";
00938                 case 8:
00939                         return "Sopas_Error_BUFFER_UNDERFLOW";
00940                 case 9:
00941                         return "Sopas_Error_ERROR_UNKNOWN_TYPE";
00942                 case 10:
00943                         return "Sopas_Error_VARIABLE_WRITE_ACCESSDENIED";
00944                 case 11:
00945                         return "Sopas_Error_UNKNOWN_CMD_FOR_NAMESERVER";
00946                 case 12:
00947                         return "Sopas_Error_UNKNOWN_COLA_COMMAND";
00948                 case 13:
00949                         return "Sopas_Error_METHODIN_SERVER_BUSY";
00950                 case 14:
00951                         return "Sopas_Error_FLEX_OUT_OF_BOUNDS";
00952                 case 15:
00953                         return "Sopas_Error_EVENTREG_UNKNOWNINDEX";
00954                 case 16:
00955                         return "Sopas_Error_COLA_A_VALUE_OVERFLOW";
00956                 case 17:
00957                         return "Sopas_Error_COLA_A_INVALID_CHARACTER";
00958                 case 18:
00959                         return "Sopas_Error_OSAI_NO_MESSAGE";
00960                 case 19:
00961                         return "Sopas_Error_OSAI_NO_ANSWER_MESSAGE";
00962                 case 20:
00963                         return "Sopas_Error_INTERNAL";
00964                 case 21:
00965                         return "Sopas_Error_HubAddressCorrupted";
00966                 case 22:
00967                         return "Sopas_Error_HubAddressDecoding";
00968                 case 23:
00969                         return "Sopas_Error_HubAddressAddressExceeded";
00970                 case 24:
00971                         return "Sopas_Error_HubAddressBlankExpected";
00972                 case 0x19:
00973                         return "Sopas_Error_AsyncMethodsAreSuppressed";
00974                 case 0x20:
00975                         return "Sopas_Error_ComplexArraysNotSupported";
00976                 default:
00977                         return "(unknown_Sopas_error_code)";
00978         }
00979         
00980         return "(unknown_Sopas_error_code)";
00981 }
00982 
00983 //
00984 // Decode an incoming CoLa-B answer that was addressed by index.
00985 //
00986 bool SopasBase::receiveAnswer_CoLa_B(SopasCommand cmd, UINT16 index, UINT32 timeout, SopasAnswer*& answer)
00987 {
00988         bool beVerboseHere = m_beVerbose;
00989 //      beVerboseHere = true;
00990         
00991         printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Entering function.", beVerboseHere);
00992 
00993         SopasCommand receivedCommand;
00994         UINT16 nextData;
00995 
00996         if (timeout == 0)
00997         {
00998                 timeout = 1; // Check at least once
00999         }
01000 
01001         // Check until number of cycles reaches timeout
01002         for (UINT32 i = 0; i < timeout; i++)
01003         {
01004                 if (m_numberOfBytesInResponseBuffer > 0)
01005                 {
01006                         printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: There is something in receive buffer.", beVerboseHere);
01007 
01008                         // Protect response buffer
01009                         ScopedLock lock(&m_receiveDataMutex);
01010 
01011                         // There are only complete frames in response buffer, so we can just use it here.
01012                         // Debug: Print buffer
01013 //                      traceBuffer("Response in response buffer:", m_responseBuffer, m_numberOfBytesInResponseBuffer);
01014                         SopasEventMessage frame (m_responseBuffer, CoLa_B, m_numberOfBytesInResponseBuffer);
01015 
01016                         // Parse Sopas Kommando
01017                         receivedCommand = stringToSopasCommand(frame.getCommandString());
01018 
01019                         printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: ReceivedCommand= " + frame.getCommandString() + ".", beVerboseHere);
01020 
01021                         nextData = 11; // without 0x02020202 + length(4 byte) + "sXX"
01022                         UINT16 receivedIndex = colab::getIntegerFromBuffer<UINT16>(m_responseBuffer, nextData);
01023 //                      printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: read command " + frame.getCommandString() + ".", beVerboseHere);
01024                         if (receivedCommand == FA)
01025                         {
01026                                 // Error message from the sensor. The next 2 bytes (in the receiveIndex) are not
01027                                 // the index but the error code.
01028                                 printWarning("SopasBase::receiveAnswer_CoLa_B_idx: Error from sensor! Code=" + toString(receivedIndex) +
01029                                                                 ", meaning: " + convertSopasErrorCodeToText(receivedIndex) + ".");
01030                                 m_numberOfBytesInResponseBuffer = 0;
01031                                 return false;
01032                         }
01033 
01034                         else if (index != receivedIndex)
01035                         {
01036                                 // Nicht die gesuchte Antwort
01037                                 // da der sensor über sopas immer nur eine anfrage zur zeit bedienen kann, koennen wir die
01038                                 // Nachricht wegwerfen
01039                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: This is not the index we are waiting for (expected="
01040                                                 + toString(index) + ", received=" + toString(receivedIndex) + ")." , beVerboseHere);
01041                                 m_numberOfBytesInResponseBuffer = 0;
01042                                 return false;
01043                         }
01044 
01045                         else if (cmd != receivedCommand)
01046                         {
01047                                 // Not the desired answer.
01048                                 // As the sensor can only handle one command at a time on the SOPAS interface, we can discard the message.
01049                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: This is not the answer (" + sopasCommandToString(receivedCommand) +
01050                                                 ") we are waiting for (" + sopasCommandToString(cmd) + "). ", beVerboseHere);
01051                                 m_numberOfBytesInResponseBuffer = 0;
01052                                 return false;
01053                         }
01054                         
01055                         else if (receivedCommand == WA)
01056                         {
01057                                 // Variable schreiben erfolgreich
01058                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Variable successfully set.", beVerboseHere);
01059                                 m_numberOfBytesInResponseBuffer = 0;
01060                                 return true;
01061                         }
01062 
01063                         else if (receivedCommand == EA)
01064                         {
01065                                 // Antwort auf Event-Abonnement setzen/loeschen.
01066                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Event successfully (un)registered: " + ::toString(receivedIndex) + ".", beVerboseHere);
01067                                 m_numberOfBytesInResponseBuffer = 0;
01068                                 return true;
01069                         }
01070 
01071                         else if (receivedCommand == AI )
01072                         {
01073                                 // Antwort auf entfernten Methodenaufruf (by name oder by index).
01074                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Answer to method call with index " + ::toString(receivedIndex) + ".", beVerboseHere);
01075                                 answer = new SopasAnswer(&m_responseBuffer[nextData], m_numberOfBytesInResponseBuffer - nextData);
01076                                 m_numberOfBytesInResponseBuffer = 0;
01077                                 return true;
01078                         }
01079 
01080                         else if (receivedCommand == RA)
01081                         {
01082                                 // Antwort auf das Lesen einer Variablen
01083                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Answer to read variable with index " + ::toString(receivedIndex) + ".", beVerboseHere);
01084 
01085                                 answer = new SopasAnswer(&m_responseBuffer[nextData], m_numberOfBytesInResponseBuffer - nextData);
01086                                 m_numberOfBytesInResponseBuffer = 0;
01087                                 return true;
01088                         }
01089 
01090                         else if (receivedCommand == CMD_UNKNOWN)
01091                         {
01092                                 printWarning("SopasBase::receiveAnswer_CoLa_B_idx: Unknown Sopas command.");
01093                                 m_numberOfBytesInResponseBuffer = 0;
01094                                 return false;
01095                         }
01096                         else
01097                         {
01098                                 // unbekannter oder unbehandelter Befehl
01099                                 printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Untreated Sopas command.", beVerboseHere);
01100                                 m_numberOfBytesInResponseBuffer = 0;
01101                                 return false;
01102                         }
01103                 }
01104                 else
01105                 {
01106                         // No data in response buffer. Sleep some time and check again
01107                         usleep(1000);
01108                 }
01109         }
01110 
01111         // Not successful, timeout.
01112         printInfoMessage("SopasBase::receiveAnswer_CoLa_B_idx: Leaving with timeout.", beVerboseHere);
01113 
01114         // Not successful, timeout.
01115         return false;
01116 }
01117 
01118 
01119 
01125 void SopasBase::processFrame(SopasEventMessage& frame)
01126 {
01127 
01128         if (m_protocol == CoLa_A)
01129         {
01130                 printInfoMessage("SopasBase::processFrame: Calling processFrame_CoLa_A() with " + ::toString(frame.size()) + " bytes.", m_beVerbose);
01131                 processFrame_CoLa_A(frame);
01132         }
01133         else if (m_protocol == CoLa_B)
01134         {
01135                 printInfoMessage("SopasBase::processFrame: Calling processFrame_CoLa_B() with " + ::toString(frame.size()) + " bytes.", m_beVerbose);
01136                 processFrame_CoLa_B(frame);
01137         }
01138 }
01139 
01140 
01141 
01142 //
01143 // Reads one frame from receive buffer and decodes it.
01144 //
01145 // CoLa-A protocol only.
01146 //
01147 void SopasBase::processFrame_CoLa_A(SopasEventMessage& frame)
01148 {
01149         std::string command;
01150         command = m_receiveBuffer[2];
01151         command += m_receiveBuffer[3];
01152         assert (command.length() == 2);
01153 
01154         //
01155         // Process asynchronous event data directly.
01156         // Other commands are copied to separate buffer
01157         //
01158         if (frame.getMessageType() == MSG_SEND_EVENT)
01159         {
01160                 if (frame.size() > 8)
01161                 {
01162                         // "SN" ist ein abonniertes Event, z.B. Scans oder Schutzfelder
01163                         std::string eventName;
01164                         UINT32 i = 5;// Pointer to the fist Letter of the event Name (without the first 5 bytes: "STX's''S''N'' '")
01165                         while (m_receiveBuffer[i] != ' ' && i < frame.size() )
01166                         {
01167                                 // go to the ' ' after the event Name
01168                                 i++;
01169                         }
01170                         eventName = std::string((char*) m_receiveBuffer, 5, i - 5); // get the event Name
01171 
01172                         if (m_decoderFunctionMapByName[eventName] != NULL)
01173                         {
01174                                 // Not empty
01175                                 m_decoderFunctionMapByName[eventName](frame);// call the callback of the Event
01176                         }
01177                         else
01178                         {
01179                                 // Das Event ist unbekannt
01180                                 printWarning("SopasBase::Received an unknown event! Event name is: " + eventName + ".");
01181                         }
01182 //
01183 //                      if (eventName == scanString) // Scan data (hopefully, event name not parsed yet...)
01184 //                      {
01185 //                              if (!m_decoderFunctionMapByName[eventName].empty())
01186 //                              {
01187 //                                      m_scanDecoderFunction(frame);
01188 //                              }
01189 //                              else
01190 //                              {
01191 //                                      printInfoMessage("SopasBase::no scan decoder registered - discarding data." << std::endl;
01192 //                              }
01193 //                      }
01194 //                      else if (eventName == fieldString) // eval case result data
01195 //                      {
01196 //
01197 //                              if (!m_evalCaseDecoderFunction.empty())
01198 //                              {
01199 //                                      m_evalCaseDecoderFunction(frame);
01200 //                              }
01201 //                              else
01202 //                              {
01203 //                                      printInfoMessage("SopasBase::no eval case decoder registered - discarding data." << std::endl;
01204 //                              }
01205 //                      }
01206 //                      else
01207 //                      { // Das Event ist unbekannt
01208 //                              printWarning("SopasBase::Received an unknown event! Short name is: " << eventName << "." << std::endl;
01209 //                      }
01210                 }
01211                 else
01212                 {
01213                         // Das Kommando ist insgesamt zu kurz zum dekodieren
01214                         printWarning("SopasBase::Received a very short (and unknown) event! Frame length is " + ::toString(frame.size()) +
01215                                                                                         " bytes.");
01216                 }
01217         }
01218         else
01219         {
01220                 // Copy frame to response buffer. Old contents are destroyed
01221                 // boost::mutex::scoped_lock lock(m_receiveDataMutex);
01222                 copyFrameToResposeBuffer(frame.size());
01223         }
01224 
01225         // Remove frame from receive buffer
01226         removeFrameFromReceiveBuffer(frame.size());
01227 }
01228 
01229 
01230 
01231 //
01232 // Reads and decodes a frame from the receiveBuffer. Frame format is CoLa-B.
01233 //
01234 // Note that this function typically runs in TCP callback context, not the device thread.
01235 //
01236 void SopasBase::processFrame_CoLa_B(SopasEventMessage& frame)
01237 {
01238         // Lese das "Kommando" aus
01239         std::string command = colab::getCommandStringFromBuffer(m_receiveBuffer);
01240 
01241         printInfoMessage("SopasBase::processFrame_CoLa_B: Command is " + command + ".", m_beVerbose);
01242 
01243         //
01244         // Process asynchronous event data directly.
01245         // Other commands are copied to separate buffer
01246         //
01247         bool frameWasProcessed = false;
01248         if (frame.getMessageType() == MSG_SEND_EVENT) // LDMRS: SI, LMS100: SN
01249         {
01250                 if (frame.size() > 12)
01251                 {
01252                         // "SN" or "SI" is a registered event, e.g. Scans or Eval case results.
01253                         //                      printInfoMessage("SopasBase::SN empfangen, Laenge = " << frameLength << "Bytes ." << std::endl;
01254                         std::string eventName;
01255                         UINT32 eventIndex = 0;
01256                         UINT16 pos = 0;
01257 
01258                         switch (frame.getEncodingType())
01259                         {
01260                         case ByIndex: // by index
01261                                 pos = 11;
01262                                 eventIndex = colab::getIntegerFromBuffer<UINT16>(m_receiveBuffer, pos);
01263                                 eventName = m_indexToNameMap[eventIndex];
01264 
01265                                 switch (eventIndex)
01266                                 {
01267                                         case 0x11:      // SopasEventByIndex_LDMRS::index_event_ScanData:
01268                                                 eventName = EVENTNAME_SUBSCRIBE_SCANS;
01269                                                 scanDataDecoder(frame);
01270                                                 frameWasProcessed = true;
01271                                                 break;
01272                                         case 0x29:      // SopasEventByIndex_LDMRS::index_event_aEvalCaseResult:
01273                                                 eventName = EVENTNAME_SUBSCRIBE_EVALCASES;
01274                                                 evalCaseResultDecoder(frame);
01275                                                 frameWasProcessed = true;
01276                                                 break;
01277                                         default:
01278                                                 ;
01279                                 }
01280                                 break;
01281                                 
01282                         default: // by name
01283                                 printWarning("SopasBase::processFrame_CoLa_B: Decoding of events by name is not implemented yet.");
01284                                 eventName = frame.getVariableName();
01285                                 break;
01286                         }
01287 
01288                         if (frameWasProcessed == false)
01289                         {
01290                                 // The incoming event was not handeled
01291                                 printWarning("SopasBase::processFrame_CoLa_B: Don't know how to process the incoming event with the short name <" +
01292                                                                 eventName + "> and the index " + ::toString(eventIndex) + ", ignoring it!");
01293                         }
01294                 }
01295                 else
01296                 {
01297                         // The frame was too short to be decoded
01298                         printWarning("SopasBase::processFrame_CoLa_B: Received a very short (and unknown) event! Frame length is " + ::toString(frame.size()) + " bytes.");
01299                 }
01300         }
01301         else
01302         {
01303                 // Copy frame to response buffer. Old contents are destroyed.
01304                 copyFrameToResposeBuffer(frame.size());
01305         }
01306 
01307         removeFrameFromReceiveBuffer(frame.size());
01308 }
01309 
01310 
01311 
01312 //
01313 // Copies a complete frame - in any protocol - from the main input buffer to
01314 // the response buffer.
01315 // The frame is *not* removed from the main input buffer.
01316 //
01317 void SopasBase::copyFrameToResposeBuffer(UINT32 frameLength)
01318 {
01319         printInfoMessage("SopasBase::copyFrameToResposeBuffer: Copying a frame of " + ::toString(frameLength) +
01320                                                                  " bytes to response buffer.", m_beVerbose);
01321 
01322         if (frameLength <= sizeof(m_responseBuffer))
01323         {
01324                 // Wir duerfen kopieren
01325                 memcpy(m_responseBuffer, m_receiveBuffer, frameLength);
01326                 m_numberOfBytesInResponseBuffer = frameLength;
01327         }
01328         else
01329         {
01330                 // Der respose-Buffer ist zu klein
01331                 printError("SopasBase::copyFrameToResposeBuffer: Failed to copy frame (Length=" + ::toString(frameLength) +
01332                                                                            " bytes) to response buffer because the response buffer is too small (buffer size=" +
01333                                                                            ::toString(sizeof(m_responseBuffer)) + " bytes).");
01334                 m_numberOfBytesInResponseBuffer = 0;
01335         }
01336 }
01337 
01338 
01339 
01340 //
01341 // Removes a complete frame - in any protocol - from the main input buffer.
01342 //
01343 void SopasBase::removeFrameFromReceiveBuffer(UINT32 frameLength)
01344 {
01345         // Remove frame from receive buffer
01346         if (frameLength < m_numberOfBytesInReceiveBuffer)
01347         {
01348                 // More data in buffer, move them to the buffer start
01349                 UINT32 newLen = m_numberOfBytesInReceiveBuffer - frameLength;
01350                 printInfoMessage("SopasBase::removeFrameFromReceiveBuffer: Removing " + ::toString(frameLength) +
01351                                                          " bytes from the input buffer. New length is " + ::toString(newLen) + " bytes.", m_beVerbose);
01352                 memmove(m_receiveBuffer, &(m_receiveBuffer[frameLength]), newLen);
01353                 m_numberOfBytesInReceiveBuffer = newLen;
01354         }
01355         else
01356         {
01357                 // No other data in buffer, just mark as empty
01358                 printInfoMessage("SopasBase::removeFrameFromReceiveBuffer: Done, no more data in input buffer.", m_beVerbose);
01359                 m_numberOfBytesInReceiveBuffer = 0;
01360         }
01361 }
01362 
01363 
01364 
01370 SopasBase::SopasCommand SopasBase::colaA_decodeCommand(std::string* rxData)
01371 {
01372         return stringToSopasCommand(colaa::getNextStringToken(rxData));
01373 }
01374 
01375 
01376 
01377 SopasBase::SopasCommand SopasBase::stringToSopasCommand(const std::string& cmdString)
01378 {
01379         // Request by Name
01380         if (cmdString == "RN")
01381         {
01382                 return RN;
01383         } // Read Variable
01384         //      else if (cmdString == "WN") { return WN; }      // Write Variable
01385         //      else if (cmdString == "MN") { return MN; }      // Invoke Method
01386         else if (cmdString == "AN")
01387         {
01388                 return AN;
01389         } // Method Result (Answer)
01390         //      else if (cmdString == "EN") { return EN; }      // Register Event
01391         else if (cmdString == "SN")
01392         {
01393                 return SN;
01394         } // Send Event
01395 
01396         // Request by Index
01397         if (cmdString == "RI")
01398         {
01399                 return RI;
01400         } // Read Variable
01401         else if (cmdString == "WI")
01402         {
01403                 return WI;
01404         } // Write Variable
01405         else if (cmdString == "MI")
01406         {
01407                 return MI;
01408         } // Invoke Method
01409         else if (cmdString == "AI")
01410         {
01411                 return AI;
01412         } // Method Result (Answer)
01413         else if (cmdString == "EI")
01414         {
01415                 return EI;
01416         } // Register Event
01417         else if (cmdString == "SI")
01418         {
01419                 return SI;
01420         } // Send Event
01421 
01422         // Response
01423         else if (cmdString == "RA")
01424         {
01425                 return RA;
01426         } // Read Variable
01427         else if (cmdString == "WA")
01428         {
01429                 return WA;
01430         } // Write Variable
01431         else if (cmdString == "MA")
01432         {
01433                 return MA;
01434         } // Invoke Method
01435         else if (cmdString == "AA")
01436         {
01437                 return AA;
01438         } // Method Result (Answer)
01439         else if (cmdString == "EA")
01440         {
01441                 return EA;
01442         } // Register Event
01443         else if (cmdString == "SA")
01444         {
01445                 return SA;
01446         } // Event Acknowledge (Only used for reliable events
01447         else if (cmdString == "FA")
01448         {
01449                 return FA;
01450         } // Error
01451 
01452         else
01453         {
01454                 printError("SopasBase::stringToSopasCommand: Trying to resolve an unknown command: " + cmdString + ".");
01455         }
01456         return CMD_UNKNOWN;
01457 }
01458 
01459 //
01460 // For debugging: Convert the command into a readable string.
01461 //
01462 std::string SopasBase::sopasCommandToString(SopasCommand cmd)
01463 {
01464         
01465         if (cmd == RN)
01466         {
01467                 return ("RN");  // Request by Name
01468         }
01469         //      else if (cmdString == "WN") { return WN; }      // Write Variable
01470         //      else if (cmdString == "MN") { return MN; }      // Invoke Method
01471         else if (cmd == AN)
01472         {
01473                 return ("AN");  // Method Result, by name
01474         }
01475         //      else if (cmdString == "EN") { return EN; }      // Register Event
01476         else if (cmd == SN)
01477         {
01478                 return ("SN");   // Send Event
01479         }
01480         if (cmd == RI)
01481         {
01482                 return ("RI");          // Request by Index
01483         } // Read Variable
01484         else if (cmd == WI)
01485         {
01486                 return ("WI");          // Write Variable
01487         } 
01488         else if (cmd == MI)
01489         {
01490                 return ("MI");          // Invoke Method
01491         }
01492         else if (cmd == AI)
01493         {
01494                 return ("AI");          // Method Result (Answer)
01495         } 
01496         else if (cmd == EI)
01497         {
01498                 return ("EI");          // Register Event
01499         }
01500         else if (cmd == SI)
01501         {
01502                 return ("SI");
01503         } // Send Event
01504 
01505         // Response
01506         else if (cmd == RA)
01507         {
01508                 return ("RA");
01509         } // Read Variable
01510         else if (cmd == WA)
01511         {
01512                 return ("WA");          // Write Variable
01513         }
01514         else if (cmd == MA)
01515         {
01516                 return ("MA");
01517         } // Invoke Method
01518         else if (cmd == AA)
01519         {
01520                 return ("AA");
01521         } // Method Result (Answer)
01522         else if (cmd == EA)
01523         {
01524                 return ("EA");
01525         } // Register Event
01526         else if (cmd == SA)
01527         {
01528                 return ("SA");
01529         } // Event Acknowledge (Only used for reliable events)
01530         else if (cmd == FA)
01531         {
01532                 return ("FA");          // Error
01533         } 
01534         else
01535         {
01536                 printError("SopasBase::sopasCommandToString: Trying to resolve an unknown command!");
01537         }
01538         
01539         return "(unknown)";
01540 }
01541 
01542 
01543 
01550 bool SopasBase::action_getScannerTypeAndVersion()
01551 {
01552         // every scanner must support ByName !!!
01553 
01554         bool result = false;
01555 
01556         // Clear old data.
01557         m_scannerName.empty();
01558         m_scannerVersion.empty();
01559 
01560         SopasAnswer* answer = NULL;
01561         result = readVariable(INDEX_DEVICE_IDENT, answer);
01562 
01563         if (result && answer != NULL && answer->isValid())
01564         {
01565 
01566                 // decode answer
01567                 std::string colaaAnswer;
01568                 switch (m_protocol)
01569                 {
01570                 case CoLa_A:
01571                         colaaAnswer = std::string((char*)answer->getBuffer(), answer->size());
01572                         colaA_decodeScannerTypeAndVersion(&colaaAnswer);
01573                         break;
01574                 case CoLa_B:
01575                         colaB_decodeScannerTypeAndVersion(answer->getBuffer(), 0);
01576                         break;
01577                 }
01578 
01579                 if (!m_scannerName.empty() && !m_scannerVersion.empty())
01580                 {
01581                         result = true;
01582                 }
01583         }
01584 
01585         if (answer != NULL)
01586         {
01587                 delete answer;
01588         }
01589 
01590         return result;
01591 }
01592 
01593 
01594 
01598 void SopasBase::colaA_decodeScannerTypeAndVersion(std::string* rxData)
01599 {
01600         //
01601         // 1. part: Type
01602         //
01603         // String length
01604         UINT16 len = colaa::decodeUINT16(rxData);
01605 
01606         // Read string
01607         m_scannerName.clear();
01608         m_scannerName = rxData->substr(0, len);
01609 
01610         // Move input data
01611         *rxData = rxData->substr(len + 1);
01612 
01613         //
01614         // 2. part: Version
01615         //
01616         // String length
01617         len = colaa::decodeUINT16(rxData);
01618 
01619         // Read string
01620         m_scannerVersion.clear();
01621         m_scannerVersion = rxData->substr(0, len);
01622 }
01623 
01624 
01625 //
01626 //
01627 //
01628 void SopasBase::colaB_decodeScannerTypeAndVersion(UINT8* buffer, UINT16 pos)
01629 {
01630         printInfoMessage("SopasBase::colaB_decodeScannerTypeAndVersion: Entering function.", m_beVerbose);
01631 
01632         UINT16 fieldLength;
01633 
01634         // read device type
01635         fieldLength = colab::getIntegerFromBuffer<UINT16>(buffer, pos);
01636         m_scannerName = colab::getStringFromBuffer(buffer, pos, fieldLength);
01637 
01638         // read device version
01639         fieldLength = colab::getIntegerFromBuffer<UINT16>(buffer, pos);
01640         m_scannerVersion = colab::getStringFromBuffer(buffer, pos, fieldLength);
01641 
01642         printInfoMessage("SopasBase::colaB_decodeScannerTypeAndVersion: scanner '" + m_scannerName + "', version '"
01643                                                                          + m_scannerVersion + "'.", m_beVerbose);
01644 }
01645 
01646 
01647 //
01648 //
01649 //
01650 bool SopasBase::invokeMethod(const std::string& methodeName, BYTE* parameters, UINT16 parametersLength, SopasAnswer*& answer)
01651 {
01652         // Build command
01653         BYTE cmdBuffer[128];
01654         UINT16 cmdBufferLen = 0;
01655 
01656         switch (m_protocol)
01657         {
01658         case CoLa_A:
01659                 cmdBufferLen += colaa::addStringToBuffer(cmdBuffer, COMMAND_Invoke_Method_ByName);
01660                 cmdBuffer[cmdBufferLen++] = ' ';
01661                 //Name
01662                 cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[cmdBufferLen]), methodeName);
01663 
01664                 if (parametersLength > 0)
01665                 {
01666                         cmdBuffer[cmdBufferLen++] = ' ';
01667                 }
01668                 break;
01669         case CoLa_B:
01670                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Invoke_Method_ByName);
01671                 // add length of string as UINT16
01672                 colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, methodeName.size());
01673                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, methodeName); // remote method name
01674                 break;
01675         }
01676 
01677         if (parametersLength > 0)
01678         {
01679                 // add parameters (which must be already in the right encoding (colaa or colab))
01680                 memcpy(&cmdBuffer[cmdBufferLen], parameters, parametersLength);
01681                 cmdBufferLen += parametersLength;
01682         }
01683 
01684         // Send command
01685         sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen);
01686 
01687         // Wait for answer (the answer of a method is "AN" - not "EA")
01688         bool result = receiveAnswer(AN, methodeName, 2000, answer);
01689 
01690         // Evaluate answer
01691         if (result == true)
01692         {
01693                 printInfoMessage("SopasBase::invokeMethod: Calling of " + methodeName + " was successful.", m_beVerbose);
01694         }
01695         else
01696         {
01697                 printWarning("SopasBase::invokeMethod: Calling of " + methodeName + " was NOT successful.");
01698         }
01699 
01700         return result;
01701 }
01702 
01703 
01704 //
01705 //
01706 //
01707 bool SopasBase::invokeMethod(UINT16 index, BYTE* parameters, UINT16 parametersLength, SopasAnswer*& answer)
01708 {
01709         // Build command
01710         BYTE cmdBuffer[128];
01711         UINT16 cmdBufferLen = 0;
01712 
01713         switch (m_protocol)
01714         {
01715         case CoLa_A:
01716                 printError("SopasBase::invokeMethod: Invoke method cola-a by index not supported.");
01717                 return false;
01718                 break;
01719         case CoLa_B:
01720                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Invoke_Method_ByIndex);
01721                 // add length of string as UINT16
01722                 colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, index);
01723                 break;
01724         }
01725 
01726         if (parametersLength > 0)
01727         {
01728                 // add parameters (which must be already in the right encoding (colaa or colab))
01729                 memcpy(&cmdBuffer[cmdBufferLen], parameters, parametersLength);
01730                 cmdBufferLen += parametersLength;
01731         }
01732 
01733         // Send command
01734         sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen);
01735 
01736         // Wait for answer
01737         bool result = receiveAnswer(AI, index, 2000, answer);
01738 
01739         // Evaluate answer
01740         if (result == true)
01741         {
01742                 printInfoMessage("SopasBase::invokeMethod: Calling of method with index=" + ::toString(index) + " was successful.", m_beVerbose);
01743         }
01744         else
01745         {
01746                 printWarning("SopasBase::invokeMethod: Calling of method with index=" + ::toString(index) + " was NOT successful.");
01747         }
01748 
01749         return result;
01750 }
01751 
01752 
01753 //
01754 //
01755 //
01756 bool SopasBase::readVariable(const std::string& variableName, SopasAnswer*& answer)
01757 {
01758         // Build command
01759         BYTE cmdBuffer[128];
01760         UINT16 cmdBufferLen = 0;
01761 
01762         if (m_protocol == CoLa_A)
01763         {
01764                 cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Read_Variable_ByName);
01765                 cmdBuffer[cmdBufferLen++] = ' ';
01766                 cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[cmdBufferLen]), variableName);
01767         }
01768         else
01769         {
01770                 // up to now only tested with LD-MRS
01771                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Read_Variable_ByName);
01772                 cmdBuffer[cmdBufferLen++] = ' ';
01773                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, variableName);
01774         }
01775 
01776         // Send
01777         sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen);
01778 
01779         // Wait for answer
01780         bool result = receiveAnswer(RA, variableName, 2000, answer);
01781 
01782         if (result)
01783         {
01784                 printInfoMessage("SopasBase::readVariable: Answer to " + variableName + " received.", m_beVerbose);
01785         }
01786         else
01787         {
01788                 printWarning("SopasBase::readVariable: Answer to " + variableName + " not successful.");
01789         }
01790 
01791         return result;
01792 }
01793 
01794 
01795 //
01796 //
01797 //
01798 bool SopasBase::readVariable(UINT16 index, SopasAnswer*& answer)
01799 {
01800         // Build command
01801         BYTE cmdBuffer[128];
01802         UINT16 cmdBufferLen = 0;
01803 
01804         if (m_protocol == CoLa_A)
01805         {
01806                 cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Read_Variable_ByIndex);
01807                 cmdBuffer[cmdBufferLen++] = ' ';
01808                 cmdBufferLen += colaa::addUINT32ToBuffer(&(cmdBuffer[cmdBufferLen]), (UINT32)index);
01809         }
01810         else
01811         {
01812                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Read_Variable_ByIndex);
01813                 colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, index);
01814         }
01815 
01816         // Send
01817         sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen);
01818 
01819         // Wait for answer
01820         bool result = receiveAnswer(RA, index, 2000, answer);
01821 
01822         if (result)
01823         {
01824                 printInfoMessage("SopasBase::readVariable: Answer to " + ::toString(index) + " received.", m_beVerbose);
01825         }
01826         else
01827         {
01828                 printWarning("SopasBase::readVariable: Answer to " + ::toString(index) + " not successful.");
01829         }
01830 
01831         return result;
01832 }
01833 
01834 
01835 
01836 bool SopasBase::writeVariable(const std::string& variableName, BYTE* parameters, UINT16 parametersLength)
01837 {
01838         if (m_readOnlyMode)
01839         {
01840                 printInfoMessage("SopasBase::writeVariable: ReadOnly Modus - ignore writing to variable '" +
01841                                                         variableName + "'", m_beVerbose);
01842                 return true;
01843         }
01844 
01845         // Build command
01846         BYTE cmdBuffer[128];
01847         UINT16 cmdBufferLen = 0;
01848 
01849         if (m_protocol == CoLa_A)
01850         {
01851                 cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Write_Variable_ByName);
01852                 cmdBuffer[cmdBufferLen++] = ' ';
01853                 cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[cmdBufferLen]), variableName);
01854                 if (parametersLength > 0)
01855                 {
01856                         cmdBuffer[cmdBufferLen++] = ' ';
01857                 }
01858         }
01859         else
01860         {
01861                 printError("SopasBase::writeVariable: Write variable cola-b by Name: NOT IMPLEMENTED");
01862                 return false;
01863 //              colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Write_Variable_ByName);
01864 //              colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, variableName.size()); // add length of string as UINT16
01865 //              colab::addStringToBuffer(cmdBuffer, cmdBufferLen, variableName);
01866 //              or ?
01867 //              colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Write_Variable_ByName);
01868 //              colab::addStringToBuffer(cmdBuffer, cmdBufferLen, variableName);
01869         }
01870 
01871 
01872         if (parametersLength > 0)
01873         {
01874                 // add parameters (which must be already in the right encoding (colaa or colab))
01875                 memcpy(&cmdBuffer[cmdBufferLen], parameters, parametersLength);
01876                 cmdBufferLen += parametersLength;
01877         }
01878 
01879 
01880         // Send
01881         sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen);
01882         SopasAnswer* answer = NULL;
01883         // Wait for answer
01884         bool result = receiveAnswer(WA, variableName, 2000, answer);
01885         // free memory for answer
01886         if (answer != NULL)
01887         {
01888                 delete answer;
01889         }
01890 
01891         if (result)
01892         {
01893                 printInfoMessage("SopasBase::writeVariable: Answer to " + variableName + " received.", m_beVerbose);
01894         }
01895         else
01896         {
01897                 printInfoMessage("SopasBase::writeVariable: Answer to " + variableName + " not successful.", m_beVerbose);
01898         }
01899 
01900         return result;
01901 }
01902 
01903 
01904 //
01905 // Write a variable, addressed by index.
01906 //
01907 bool SopasBase::writeVariable(UINT16 variableIndex, BYTE* parameters, UINT16 parametersLength)
01908 {
01909         bool beVerboseHere = m_beVerbose;
01910 //      beVerboseHere = true;
01911         
01912         if (m_readOnlyMode == true)
01913         {
01914                 printInfoMessage("SopasBase::writeVariable: ReadOnly Modus - ignore writing to variable index '" + ::toString(variableIndex) +
01915                                                                          "'", m_beVerbose);
01916                 return true;
01917         }
01918 
01919         // Create the command buffer
01920         UINT32 cmdBufferLen = parametersLength + 4;
01921         BYTE* cmdBuffer = new BYTE[cmdBufferLen];
01922         
01923         // Add the command
01924         colab::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Write_Variable_ByIndex);
01925         
01926         // Add the index
01927         BYTE* buffer = &(cmdBuffer[2]);
01928         memwrite_UINT16(buffer, variableIndex);
01929 //      UINT16 pos = 0;
01930 //      colab::addIntegerToBuffer<UINT16>(&(cmdBuffer[2]), pos, variableIndex);
01931         
01932         // Copy the data
01933         memcpy(&(cmdBuffer[4]), parameters, parametersLength);
01934         
01935         // Send. The frame is added automatically.
01936         printInfoMessage("SopasBase::writeVariable: Sending command buffer now (payload len=" + toString(parametersLength+4) + " bytes).", beVerboseHere);
01937         sendCommandBuffer(cmdBuffer, cmdBufferLen);
01938         
01939         printInfoMessage("SopasBase::writeVariable: Command sent, waiting for reply...", beVerboseHere);
01940         SopasAnswer* answer = NULL;
01941         // Wait for answer
01942         bool result = receiveAnswer(WA, variableIndex, 2000, answer);
01943         // free memory for answer
01944         if (answer != NULL)
01945         {
01946                 delete answer;
01947         }
01948         if (result)
01949         {
01950                 printInfoMessage("SopasBase::writeVariable: Answer to " + toString(variableIndex) + " received.", beVerboseHere);
01951         }
01952         else
01953         {
01954                 printWarning("SopasBase::writeVariable: Answer to " + toString(variableIndex) + " not successful!");
01955         }
01956 
01957         printInfoMessage("SopasBase::writeVariable: All done, leaving.", beVerboseHere);
01958         return result;
01959 }
01960 
01961 
01962 
01963 bool SopasBase::registerEvent(const std::string& eventName)
01964 {
01965         BYTE cmdBuffer[128];
01966         UINT16 cmdBufferLen = 0;
01967 
01968         if (m_protocol == CoLa_A)
01969         {
01970                 cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Register_Event_ByName);
01971                 cmdBuffer[cmdBufferLen++] = ' ';
01972                 cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[cmdBufferLen]), eventName);
01973                 cmdBuffer[cmdBufferLen++] = ' ';
01974                 cmdBuffer[cmdBufferLen++] = '1';
01975         }
01976         else
01977         {
01978                 //traceError(SOPASBASE_VERSION) << "register event cola-B by name not supported." << std::endl;
01979                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Register_Event_ByName);
01980                 cmdBuffer[cmdBufferLen++] = ' ';
01981                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, eventName);
01982                 cmdBuffer[cmdBufferLen++] = ' ';
01983                 colab::addIntegerToBuffer<UINT8>(cmdBuffer, cmdBufferLen, 1);
01984 
01985                 // return false;
01986         }
01987 
01988         // Send
01989         sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen);
01990         SopasAnswer* answer = NULL;
01991         // Wait for answer
01992         bool result = receiveAnswer(EA, eventName, 2000, answer);
01993 
01994 
01995         // free memory for answer
01996         if (answer != NULL)
01997         {
01998                 delete answer;
01999         }
02000         return result;
02001 }
02002 
02003 
02004 //
02005 //
02006 //
02007 bool SopasBase::registerEvent(UINT16 index)
02008 {
02009         // Build command
02010         BYTE cmdBuffer[128];
02011         UINT16 cmdBufferLen = 0;
02012 
02013         switch (m_protocol)
02014         {
02015         case CoLa_A:
02016                 printError("SopasBase::register event cola-a by index not supported, aborting.");
02017 
02018                 return false;
02019 
02020                 break;
02021         case CoLa_B:
02022                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Register_Event_ByIndex);
02023                 colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, index);
02024                 colab::addIntegerToBuffer<UINT8>(cmdBuffer, cmdBufferLen, 1);  // 1 to subscribe
02025                 break;
02026         }
02027 
02028         // Send command
02029         sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen);
02030 
02031         // Wait for answer
02032         SopasAnswer* answer = NULL;
02033         bool result = receiveAnswer(EA, index, 2000, answer);
02034 
02035         // there will be no answer (but to be sure to prevent memory leaks)
02036         if (answer != NULL)
02037         {
02038                 delete answer;
02039         }
02040 
02041         // Evaluate answer
02042         if (result == true)
02043         {
02044                 printInfoMessage("SopasBase::registerEvent: Calling of register with index=" + ::toString(index) + " was successful.", m_beVerbose);
02045         }
02046         else
02047         {
02048                 printError("SopasBase::registerEvent: Calling of method with index=" + ::toString(index) + " was NOT successful.");
02049         }
02050         return result;
02051 }
02052 
02053 
02054 
02055 bool SopasBase::unregisterEvent(UINT16 index)
02056 {
02057         // Build command
02058         BYTE cmdBuffer[128];
02059         UINT16 cmdBufferLen = 0;
02060 
02061         switch (m_protocol)
02062         {
02063         case CoLa_A:
02064                 printError("SopasBase::unregisterEvent: Unregister event cola-a by index not supported.");
02065 
02066                 return false;
02067 
02068                 break;
02069         case CoLa_B:
02070                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Register_Event_ByIndex);
02071                 colab::addIntegerToBuffer<UINT16>(cmdBuffer, cmdBufferLen, index);
02072                 colab::addIntegerToBuffer<UINT8>(cmdBuffer, cmdBufferLen, 0);  // 1 to subscribe
02073                 break;
02074         }
02075 
02076         // Send command
02077         sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen);
02078 
02079         // Wait for answer
02080         SopasAnswer* answer = NULL;
02081         bool result = receiveAnswer(EA, index, 2000, answer);
02082 
02083         // there will be no answer (but to be sure to prevent memory leaks)
02084         if (answer != NULL)
02085         {
02086                 delete answer;
02087         }
02088 
02089         // Evaluate answer
02090         if (result == true)
02091         {
02092                 printInfoMessage("SopasBase::calling of register with index=" + ::toString(index) + " was successful.", m_beVerbose);
02093         }
02094         else
02095         {
02096                 printInfoMessage("SopasBase::calling of register with index=" + ::toString(index) + " was NOT successful.", m_beVerbose);
02097         }
02098 
02099         return result;
02100 }
02101 
02102 
02103 
02104 bool SopasBase::unregisterEvent(const std::string& eventName)
02105 {
02106         BYTE cmdBuffer[128];
02107         UINT16 cmdBufferLen = 0;
02108 
02109         if (m_protocol == CoLa_A)
02110         {
02111                 cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[0]), COMMAND_Register_Event_ByName);
02112                 cmdBuffer[cmdBufferLen++] = ' ';
02113                 cmdBufferLen += colaa::addStringToBuffer(&(cmdBuffer[cmdBufferLen]), eventName);
02114                 cmdBuffer[cmdBufferLen++] = ' ';
02115                 cmdBuffer[cmdBufferLen++] = '0';
02116         }
02117         else
02118         {
02119 //              traceError(SOPASBASE_VERSION) << "unregister event cola-B by name not supported." << std::endl;
02120                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, COMMAND_Register_Event_ByName);
02121                 cmdBuffer[cmdBufferLen++] = ' ';
02122                 colab::addStringToBuffer(cmdBuffer, cmdBufferLen, eventName);
02123                 cmdBuffer[cmdBufferLen++] = ' ';
02124                 colab::addIntegerToBuffer<UINT8>(cmdBuffer, cmdBufferLen, 0);
02125 //              return false;
02126         }
02127 
02128         // Send
02129         sendCommandBuffer(&(cmdBuffer[0]), cmdBufferLen);
02130         SopasAnswer* answer = NULL;
02131         // Wait for answer
02132         bool result = receiveAnswer(EA, eventName, 2000, answer);
02133 
02134 
02135         // free memory for answer
02136         if (answer != NULL)
02137         {
02138                 delete answer;
02139         }
02140         return result;
02141 }
02142 
02143 
02144 
02148 double SopasBase::makeAngleValid(double angle)
02149 {
02150         return ::normalizeRadians(angle);
02151 }
02152 
02153 
02154 
02155 //
02156 // ************************* SOPAS FRAME ************************************************** //
02157 //
02158 SopasEventMessage::SopasEventMessage() :
02159         m_buffer(NULL), m_protocol(SopasBase::CoLa_A), m_frameLength(0), m_encoding(SopasBase::ByName)
02160 {
02161 }
02162 
02163 
02164 
02165 SopasEventMessage::SopasEventMessage(BYTE* buffer, SopasBase::SopasProtocol protocol, UINT32 frameLength) :
02166         m_buffer(buffer), m_protocol(protocol), m_frameLength(frameLength), m_encoding(SopasBase::ByName)
02167 {
02168         detectEncoding();
02169         detectMessageType();
02170 }
02171 
02172 
02173 
02174 UINT32 SopasEventMessage::getPayLoadLength() const
02175 {
02176         UINT32 payLoadLength = 0;
02177 
02178         switch (m_protocol)
02179         {
02180         case SopasBase::CoLa_A:
02181                 payLoadLength = m_frameLength - 2; // everything except the 0x02 0x03 frame
02182                 break;
02183         case SopasBase::CoLa_B:
02184                 payLoadLength = m_frameLength - 9; // everything except start 0x02020202(4byte), payloadLength(4byte) and checksum(1 byte)
02185         }
02186 
02187         return payLoadLength;
02188 }
02189 
02190 
02191 
02192 std::string SopasEventMessage::getCommandString() const
02193 {
02194         std::string commandString;
02195 
02196         switch (m_protocol)
02197         {
02198         case SopasBase::CoLa_A:
02199                 commandString = std::string((char*) &m_buffer[2], 2);
02200                 break;
02201         case SopasBase::CoLa_B:
02202                 commandString = std::string((char*) &m_buffer[9], 2);
02203         }
02204 
02205         return commandString;
02206 }
02207 
02208 
02209 //
02210 // Returns a pointer to the first payload byte. 
02211 // CoLa-A: Points beyond the leading "0x02" to the "s..." data.
02212 // CoLa-B: Points beyond the magic word and length bytes, to the "s..." data.
02213 //
02214 BYTE* SopasEventMessage::getPayLoad()
02215 {
02216         BYTE* bufferPos = NULL;
02217 
02218         switch (m_protocol)
02219         {
02220         case SopasBase::CoLa_A:
02221                 bufferPos = &m_buffer[1];
02222                 break;
02223         case SopasBase::CoLa_B:
02224                 bufferPos = &m_buffer[8];
02225                 break;
02226         }
02227 
02228         return bufferPos;
02229 }
02230 
02231 
02232 
02233 INT32 SopasEventMessage::getVariableIndex()
02234 {
02235         INT32 index = -1;
02236 
02237         if (m_encoding != SopasBase::ByIndex)
02238         {
02239                 // Encoding is not byIndex, so abort here
02240                 printWarning("SopasEventMessage::getVariableIndex: Encoding is not ByIndex, aborting!");
02241                 return index;
02242         }
02243         
02244         BYTE* bufferPos = &getPayLoad()[3];
02245         switch (m_protocol)
02246         {
02247                 case SopasBase::CoLa_A:
02248                         index = (INT32)(colaa::decodeUINT16(bufferPos));
02249                         break;
02250                 case SopasBase::CoLa_B:
02251                         index = (INT32)(colab::decodeUINT16(bufferPos));
02252                         break;
02253                 default:
02254                         printError("SopasEventMessage::getVariableIndex: Unknown protocol!");
02255         }
02256 
02257         return index;
02258 }
02259 
02260 //
02261 // Read the variable name from a sensor message. This works only if the encoding "ByName" is used!
02262 //
02263 std::string SopasEventMessage::getVariableName()
02264 {
02265         std::string name;
02266         UINT32 i;
02267         BYTE* bufferPos;
02268 
02269         if (m_encoding == SopasBase::ByName)
02270         {
02271                 switch (m_protocol)
02272                 {
02273                 case SopasBase::CoLa_A:
02274                         printError("SopasEventMessage::getVariableName: Protocol CoLa-A is not supported, aborting!");
02275                         return "";
02276                         break;
02277                 case SopasBase::CoLa_B:
02278                         bufferPos = &getPayLoad()[4];
02279                         i = 4;
02280 
02281                         // example for message "sSI <variablename> 0x000binarydata"
02282 
02283                         // search for the next white space
02284                         while ((*bufferPos != ' ') && (i < getPayLoadLength()))
02285                         {
02286                                 name += *bufferPos;
02287                                 bufferPos++;
02288                                 i++;
02289                         }
02290                         break;
02291                 }
02292         }
02293 
02294         return name;
02295 }
02296 
02297 
02298 //
02299 // Detects the encoding method (ByName or ByIndex) from the sensor message.
02300 //
02301 void SopasEventMessage::detectEncoding()
02302 {
02303         // if the third byte of the payload is an 'I', the encoding is ByIndex
02304         // sXI: sAI, sRI, sWI, sMI, sEI, sSI
02305         if (getPayLoad()[2] == 'I')
02306         {
02307                 m_encoding = SopasBase::ByIndex;
02308         }
02309 }
02310 
02311 
02312 
02313 void SopasEventMessage::detectMessageType()
02314 {
02315         std::string command = getCommandString();
02316 
02317         if (command == SopasBase::COMMAND_Event_Acknowledge)
02318         {
02319                 m_messageType = SopasBase::MSG_EVENT_ACKNOWLEDGE;
02320         }
02321         else if (command == SopasBase::COMMAND_Invoke_Method_Answer)
02322         {
02323                 m_messageType = SopasBase::MSG_INVOKE_METHOD_ANSWER;
02324         }
02325         else if (command == SopasBase::COMMAND_Method_Result_Answer)
02326         {
02327                 m_messageType = SopasBase::MSG_METHOD_RESULT_ANSWER;
02328         }
02329         else if (command == SopasBase::COMMAND_Send_Event_ByIndex || command == SopasBase::COMMAND_Send_Event_ByName)
02330         {
02331                 m_messageType = SopasBase::MSG_SEND_EVENT;
02332         }
02333         else if (command == SopasBase::COMMAND_Read_Variable_Answer)
02334         {
02335                 m_messageType = SopasBase::MSG_READ_VARIABLE_ANSWER;
02336         }
02337         else if (command == SopasBase::COMMAND_Write_Variable_Answer)
02338         {
02339                 m_messageType = SopasBase::MSG_WRITE_VARIABLE_ANSWER;
02340         }
02341         else
02342         {
02343                 m_messageType = SopasBase::MSG_UNKNOWN;
02344         }
02345 }
02346 
02347 SopasAnswer::SopasAnswer(const BYTE* answer, UINT32 answerLength) : m_answerLength(answerLength)
02348 {
02349         if (answerLength > 0)
02350         {
02351                 m_answerBuffer = new BYTE[m_answerLength];
02352                 memcpy(m_answerBuffer, answer, answerLength);
02353         }
02354         else
02355         {
02356                 m_answerBuffer = NULL;
02357         }
02358 }
02359 
02360 SopasAnswer::~SopasAnswer()
02361 {
02362         if (m_answerBuffer != NULL)
02363         {
02364                 delete[] m_answerBuffer;
02365                 m_answerLength = 0;
02366         }
02367 }
02368 
02369 }       // namespace devices


libsick_ldmrs
Author(s): SICK AG , Martin Günther , Jochen Sprickerhof
autogenerated on Wed Jun 14 2017 04:04:50