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


sick_scan
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Tue Jul 9 2019 05:05:35