colaa.cpp
Go to the documentation of this file.
00001 
00005 //
00006 // colaa.cpp
00007 //
00008 // (c) 2011 SICK AG, Hamburg, Germany
00009 #define _CRT_SECURE_NO_WARNINGS
00010 
00011 #include "sick_scan/tcp/colaa.hpp"
00012 #include <cstring>
00013 #include <cassert>
00014 #include <stdexcept>
00015 #include "sick_scan/tcp/toolbox.hpp"    // for "toString"
00016 #include "sick_scan/tcp/errorhandler.hpp"
00017 #include <stdlib.h>
00018 #include <limits>
00019 // #include "Trace.hpp"
00020 
00021 namespace colaa
00022 {
00023 
00024 //
00025 // Konvertiert ein ASCII-Zeichen (= Hex-Wert-Nibble oder Ziffer) in seinen Zahlenwert.
00026 //
00027 UINT16 getValueOfChar(UINT8 c)
00028 {
00029         UINT16 value = 0;
00030 
00031         if ((c >= '0') && (c <= '9'))
00032         {
00033                 value = c - '0';
00034         }
00035         else if ((c >= 'A') && (c <= 'F'))
00036         {
00037                 value = 10 + c - 'A';
00038         }
00039         else
00040         {
00041                 // Keine HEX-Ziffer
00042                 throw std::out_of_range("Unknown character where 0..9 or A..F was expected: '" + std::string(c, 1) + "'");
00043         }
00044 
00045         return value;
00046 }
00047 
00048 //
00049 // Konvertiere ein Hex-Nibble (0..F) nach ASCII.
00050 //
00051 // Return value: UINT8 (= Char)
00052 //
00053 UINT8 nibbleToAscii(UINT8 value)
00054 {
00055         UINT8 c;
00056 
00057         if (value > 0x0f)
00058         {
00059                 throw std::out_of_range("Tried to convert value > 0x0f into hex-nibble: " + toString((INT16)value));
00060         }
00061 
00062         if (value < 10)
00063         {
00064                 c = ('0' + value);
00065         }
00066         else
00067         {
00068                 c = ('A' + (value - 10));
00069         }
00070 
00071         return c;
00072 }
00073 
00074 
00082 void addFrameToBuffer(UINT8* sendBuffer, UINT8* cmdBuffer, UINT16* len)
00083 {
00084         UINT16 pos = 0;
00085 
00086         // Beginne mit dem 23-Frame-Header
00087         sendBuffer[pos++] = 0x02;
00088         sendBuffer[pos++] = 's';
00089 
00090         // Nun das Kommando
00091         memcpy(&(sendBuffer[pos]), cmdBuffer, *len);
00092         pos += *len;
00093 
00094 //      for (UINT16 i = 0; i<(*len); i++)
00095 //      {
00096 //              sendBuffer[pos++] = cmdBuffer[i];
00097 //      }
00098 
00099         // Schliesse den 23-Frame ab
00100         sendBuffer[pos++] = 0x03;
00101 
00102         // Fertig!
00103         *len = pos;
00104 }
00111 UINT16 addUINT8ToBuffer(UINT8* buffer, UINT8 value)
00112 {
00113         UINT16 len;
00114 
00115         len = addUINT32ToBuffer(buffer, (UINT32)value);
00116 
00117         return len;
00118 }
00125 UINT16 addUINT16ToBuffer(UINT8* buffer, UINT16 value)
00126 {
00127         UINT16 len;
00128 
00129         len = addUINT32ToBuffer(buffer, (UINT32)value);
00130 
00131         return len;
00132 }
00133 
00139 UINT16 addINT8ToBuffer(UINT8* buffer, INT8 value)
00140 {
00141         UINT16 stellenwert;
00142         UINT8 c;
00143         UINT16 pos = 0;
00144         bool firstZero = true;
00145 
00146         // Vorzeichen
00147         if (value < 0)
00148         {
00149                 buffer[pos++] = '-';
00150                 value *= -1;
00151         }
00152         else
00153         {
00154                 buffer[pos++] = '+';
00155         }
00156 
00157         // Dezimal-Konversion
00158         stellenwert = 100;
00159 
00160         while (stellenwert > 0)
00161         {
00162                 c = value / stellenwert;
00163                 if ((c != 0) || (firstZero == false) || (stellenwert == 1))
00164                 {
00165                         // Ziffer schreiben
00166                         buffer[pos++] = ('0' + c);
00167                 }
00168                 if (c != 0)
00169                 {
00170                         // Wert != 0, d.h. ab jetzt auch jede 0 schreiben
00171                         firstZero = false;
00172                 }
00173                 value -= c * stellenwert;
00174                 stellenwert /= 10;
00175         }
00176 
00177         return pos;
00178 }
00185 UINT16 addINT32ToBuffer(UINT8* buffer, INT32 value)
00186 {
00187         UINT32 uValue = (UINT32)value;
00188 
00189         UINT16 pos = addUINT32ToBuffer(buffer, uValue);
00190 
00191         return pos;
00192 }
00193 
00200 UINT16 addUINT32ToBuffer(UINT8* buffer, UINT32 value)
00201 {
00202         // Alle Nibbles durchgehen
00203         bool firstZero = true;
00204         UINT16 pos = 0;
00205         UINT8 nibble;
00206 
00207         for (INT16 i = 7; i >= 0; i -= 1)
00208         {
00209                 nibble = (value >> (i * 4)) & 0x0F;
00210                 if ((nibble != 0) || (firstZero == false) || (i == 0))
00211                 {
00212                         buffer[pos++] = nibbleToAscii(nibble);
00213                         firstZero = false;
00214                 }
00215         }
00216 
00217         return pos;
00218 }
00224 UINT16 addStringToBuffer(UINT8* buffer, const std::string& text)
00225 {
00226         UINT16 len = (UINT16)text.length();
00227 
00228         // Kopiere den String
00229         strcpy ((char*)buffer, text.c_str());
00230 
00231         return len;
00232 }
00233 
00234 UINT16 detail::writeToBuffer(BYTE* buffer, double value)
00235 {
00236         std::string tmp(toString(value, 6));
00237         printWarning("detail::writeToBuffer: Warning - Writing of floating-point values has not been cross-checked in Cola-A format!");
00238         return addStringToBuffer(buffer, tmp);
00239 }
00240 
00246 std::string getNextStringToken(std::string* rxData)
00247 {
00248         typedef std::string::size_type size_type;
00249 
00250         // Token finden
00251         size_type tokenStart = rxData->find_first_not_of(' ');  // Fuehrende Spaces loeschen
00252         size_type tokenEnd = rxData->find(' ', tokenStart);             // Folgendes Space finden
00253         size_type tokenLength = tokenEnd - tokenStart;
00254 
00255         // Token ausschneiden
00256         std::string token = rxData->substr(tokenStart, tokenLength);
00257 
00258         // Eingangsstring kuerzen
00259         *rxData = rxData->substr(tokenEnd + 1);
00260 
00261         // Rueckgabe des Token
00262         return token;
00263 }
00264 
00265 
00271 std::string getNextStringToken(UINT8* rxData)
00272 {
00273 //      typedef std::string::size_type size_type;
00274         
00275         UINT16 pos = 0;
00276         std::string token;
00277         
00278         // Fuehrende Spaces entfernen
00279         while (rxData[pos] != 0x00)
00280         {
00281                 if (rxData[pos] != ' ')
00282                 {
00283                         break;
00284                 }
00285                 pos++;
00286         }
00287         
00288         // Etwas Gueltiges gefunden?
00289         if (rxData[pos] != 0x00)
00290         {
00291                 // start zeigt auf etwas gueltiges.
00292                 // So lange weiter fuellen, bis das Ende erreicht ist.
00293                 while ((rxData[pos] != 0x00) && (rxData[pos] != ' '))
00294                 {
00295                         token += rxData[pos];
00296                         pos++;
00297                 }
00298         }
00299 
00300         // Rueckgabe des Token
00301         return token;
00302 }
00303 
00304 
00305 bool GetNibble(unsigned char data, unsigned char& rNibble)
00306 {
00307         rNibble = 0;
00308         bool validHexData = true;
00309         if ((data >= '0') && (data <= '9'))
00310         {
00311                 rNibble = (unsigned char)(data - '0');
00312         }
00313         else if ((data >= 'A') && (data <= 'F'))
00314         {
00315                 rNibble = (unsigned char)(data - 'A' + 10);
00316         }
00317         else if ((data >= 'a') && (data <= 'f'))
00318         {
00319                 rNibble = (unsigned char)(data - 'a' + 10);
00320         }
00321         else
00322         {
00323                 validHexData = false;
00324         }
00325         return validHexData;
00326 }
00327 
00332 double decodeReal(std::string* rxData)
00333 {
00334         double value = std::numeric_limits<double>::quiet_NaN();
00335         std::string text = colaa::getNextStringToken(rxData);
00336         if (text.empty() == false)
00337         {
00338                 // Check representation
00339                 if ((text[0] == '+') || (text[0] == '-'))
00340                 {
00341                         // ASCII
00342                         value = atof(text.c_str());
00343                 }
00344                 else
00345                 {
00346                         // HEX
00347                         // This simple conversion works only for fixed size!
00348                         union
00349                         {
00350                                 float f;
00351                                 unsigned char c[4];
00352                         } converter;
00353                         memset(&converter, 0, sizeof(converter));
00354 
00355                         if (text.length() == 8)
00356                         {
00357                                 int hexIndex = 0;
00358                                 int shift = 0;
00359                                 bool success = true;
00360                                 for (int i = 7; i >= 0; --i)
00361                                 {
00362                                         unsigned char nibble;
00363                                         success &= GetNibble(text[i], nibble);
00364                                         converter.c[hexIndex] |= (nibble << shift);
00365                                         hexIndex += (shift >> 2);
00366                                         shift ^= 4;
00367                                 }
00368                                 if (success == true)
00369                                 {
00370                                         value = converter.f;
00371                                 }
00372                         }
00373                 }
00374         }
00375 
00376         return value;
00377 }
00378 
00383 double decodeReal(const std::string& rxData)
00384 {
00385         double value = std::numeric_limits<double>::quiet_NaN();
00386         const std::string& text = rxData;
00387         if (text.empty() == false)
00388         {
00389                 // Check representation
00390                 if ((text[0] == '+') || (text[0] == '-'))
00391                 {
00392                         // ASCII
00393                         value = atof(text.c_str());
00394                 }
00395                 else
00396                 {
00397                         // HEX
00398                         // TODO: Simple conversion working only for fixed size
00399                         union
00400                         {
00401                                 float f;
00402                                 unsigned char c[4];
00403                         } converter;
00404                         memset(&converter, 0, sizeof(converter));
00405 
00406                         if (text.length() == 8)
00407                         {
00408                                 int hexIndex = 0;
00409                                 int shift = 0;
00410                                 bool success = true;
00411                                 for (int i = 7; i >= 0; --i)
00412                                 {
00413                                         unsigned char nibble;
00414                                         success &= GetNibble(text[i], nibble);
00415                                         converter.c[hexIndex] |= (nibble << shift);
00416                                         hexIndex += (shift >> 2);
00417                                         shift ^= 4;
00418                                 }
00419                                 if (success == true)
00420                                 {
00421                                         value = converter.f;
00422                                 }
00423                         }
00424                 }
00425         }
00426 
00427         return value;
00428 }
00429 
00430 
00434 UINT32 decodeUINT32(std::string* rxData)
00435 {
00436         UINT32 value = 0;
00437         UINT32 tempVal;
00438         UINT32 factor = 1;
00439         UINT32 baseFactor = 10;
00440         UINT16 digits;
00441 
00442         // Zahlen-String extrahieren
00443         std::string number = colaa::getNextStringToken(rxData);
00444 
00445         if (number.at(0) == '+')
00446         {
00447                 // Dezimalzahl
00448                 baseFactor = 10;
00449                 number = number.substr(1);
00450         }
00451         else
00452         {
00453                 // Hexadezimalzahl
00454                 baseFactor = 16;
00455         }
00456         digits = (UINT16)number.length();
00457 
00458         // Extrahiere die Zahl, letzte Stelle zuerst
00459         for (INT16 d = digits - 1; d >= 0; d -= 1)
00460         {
00461                 tempVal = colaa::getValueOfChar(number.at(d));
00462                 value += tempVal * factor;
00463                 factor *= baseFactor;
00464         }
00465 
00466         return value;
00467 }
00468 
00472 INT16 decodeINT16(std::string* rxData)
00473 {
00474         INT32 value = decodeINT32(rxData);
00475         assert ((value >= -32768) && (value <= 32767));
00476         return (INT16)value;
00477 }
00478 
00483 INT32 decodeINT32(std::string* rxData)
00484 {
00485         INT32 value = 0;
00486         INT32 tempVal;
00487         INT32 factor = 1;
00488         INT32 baseFactor = 10;  // 10 = dez, 16 = hex
00489         INT32 sign = 1;         // 1 oder -1
00490         UINT16 digits;
00491 
00492         // Zahlen-String extrahieren
00493         std::string number = colaa::getNextStringToken(rxData);
00494 
00495         // Unterscheidung Pos/Neg/Hex
00496         if (number.at(0) == '+')
00497         {
00498                 // pos. Dezimalzahl
00499                 number = number.substr(1);      // Vorzeichen abschneiden
00500         }
00501         else if (number.at(0) == '-')
00502         {
00503                 // neg. Dezimalzahl
00504                 sign = -1;                                      // Neg. Vorzeichen
00505                 number = number.substr(1);      // Vorzeichen abschneiden
00506         }
00507         else
00508         {
00509                 // Hexadezimalzahl
00510                 baseFactor = 16;                        // Hex.
00511         }
00512 
00513         // Anzahl Ziffern
00514         digits = (UINT16)number.length();
00515 
00516         // Extrahiere die Zahl, letzte Stelle zuerst
00517         for (INT16 d = digits - 1; d >= 0; d -= 1)
00518         {
00519                 tempVal = colaa::getValueOfChar(number.at(d));
00520                 value += tempVal * factor;
00521                 factor *= baseFactor;
00522         }
00523 
00524         // Vorzeichen einbauen
00525         value *= sign;
00526 
00527         return value;
00528 }
00529 
00530 
00534 INT16 decodeINT16(const std::string& rxData)
00535 {
00536         INT32 value = decodeINT32(rxData);
00537         assert ((value >= -32768) && (value <= 32767));
00538         return (INT16)value;
00539 }
00540 
00545 INT32 decodeINT32(const std::string& rxData)
00546 {
00547         INT32 value = 0;
00548         INT32 tempVal;
00549         INT32 factor = 1;
00550         INT32 baseFactor = 10;  // 10 = dez, 16 = hex
00551         INT32 sign = 1;         // 1 oder -1
00552         UINT16 digits;
00553         UINT16 offset = 0;
00554 
00555         // Zahlen-String extrahieren
00556         const std::string number = rxData;
00557 
00558         // Unterscheidung Pos/Neg/Hex
00559         if (number.at(0) == '+')
00560         {
00561                 // pos. Dezimalzahl
00562 //              number = number.substr(1);      // Vorzeichen abschneiden
00563                 offset = 1;
00564         }
00565         else if (number.at(0) == '-')
00566         {
00567                 // neg. Dezimalzahl
00568                 sign = -1;                                      // Neg. Vorzeichen
00569 //              number = number.substr(1);      // Vorzeichen abschneiden
00570                 offset = 1;
00571         }
00572         else
00573         {
00574                 // Hexadezimalzahl
00575                 baseFactor = 16;                        // Hex.
00576         }
00577 
00578         // Anzahl Ziffern
00579         digits = (UINT16)number.length();
00580 
00581         // Extrahiere die Zahl, letzte Stelle zuerst
00582         for (INT16 d = digits - 1; d >= offset; d -= 1)
00583         {
00584                 tempVal = colaa::getValueOfChar(number.at(d));
00585                 value += tempVal * factor;
00586                 factor *= baseFactor;
00587         }
00588 
00589         // Vorzeichen einbauen
00590         value *= sign;
00591 
00592         return value;
00593 }
00594 
00595 
00603 std::string decodeString(std::string* rxData, UINT16 len)
00604 {
00605         std::string text;
00606 
00607         // String extrahieren
00608         if (len == 0)
00609         {
00610                 // Keine spezielle Laenge gewuenscht.
00611                 text = colaa::getNextStringToken(rxData);
00612         }
00613         else
00614         {
00615                 // String bekannter Laenge ausschneiden
00616                 text = rxData->substr(0, len);
00617                 // Eingangsstring kuerzen
00618                 *rxData = rxData->substr(len + 1);
00619         }
00620 
00621         return text;
00622 }
00623 
00624 //
00625 // Lese einen UINT16-Wert aus dem Empfangspuffer.
00626 //
00627 UINT16 decodeUINT16(BYTE* buffer)
00628 {
00629         std::string data = getNextStringToken(buffer);
00630         return decodeUINT16(data);
00631 }
00632 
00633 //
00634 // Lese einen UINT16-Wert aus dem Empfangspuffer.
00635 //
00636 UINT16 decodeUINT16(std::string* rxData)
00637 {
00638         UINT32 value;
00639 
00640         value = decodeUINT32(rxData);
00641 
00642         assert (value < 0x10000);
00643         return (UINT16)value;
00644 }
00645 
00649 UINT8 decodeUINT8(std::string* rxData)
00650 {
00651         UINT32 value;
00652 
00653         value = decodeUINT32(rxData);
00654 
00655         assert (value < 256);
00656         return (UINT8)value;
00657 }
00658 
00662 UINT16 decodeUINT16(const std::string& rxData)
00663 {
00664         UINT32 value;
00665 
00666         value = decodeUINT32(rxData);
00667 
00668         assert (value < 0x10000);
00669         return (UINT16)value;
00670 }
00671 
00675 UINT8 decodeUINT8(const std::string& rxData)
00676 {
00677         UINT32 value;
00678 
00679         value = decodeUINT32(rxData);
00680 
00681         assert (value < 256);
00682         return (UINT8)value;
00683 }
00684 
00690 UINT32 decodeUINT32(const std::string& rxData)
00691 {
00692         UINT32 value = 0;
00693         UINT32 factor = 1;
00694         UINT32 tempVal;
00695         UINT32 baseFactor = 10; // 10 = dez, 16 = hex
00696         UINT16 digits;
00697         UINT16 offset = 0;
00698 
00699         // Zahlen-String extrahieren
00700         const std::string& number = rxData;
00701 
00702         // Unterscheidung Pos/Neg/Hex
00703         if (number.at(0) == '+')
00704         {
00705                 // pos. Dezimalzahl
00706 //              number = number.substr(1);      // Vorzeichen abschneiden
00707                 offset = 1;
00708         }
00709         else
00710         {
00711                 // Hexadezimalzahl
00712                 baseFactor = 16;                        // Hex.
00713         }
00714 
00715         // Anzahl Ziffern
00716         digits = (UINT16)number.length();
00717 
00718         // Extrahiere die Zahl, letzte Stelle zuerst
00719         for (INT16 d = digits - 1; d >= offset; d -= 1)
00720         {
00721                 tempVal = colaa::getValueOfChar(number.at(d));
00722                 value += tempVal * factor;
00723                 factor *= baseFactor;
00724         }
00725 
00726         return value;
00727 }
00728 
00735 UINT32 decodeXByte(std::string* rxData, UINT16 len)
00736 {
00737         UINT32 value;
00738         UINT32 result = 0;
00739 
00740         assert (len < 5);       // Wir koennen nur bis zu 4 Bytes in einen UINT32 packen
00741 
00742         for (UINT16 i = 0; i < len; i++)
00743         {
00744                 value = decodeUINT32(rxData);
00745                 assert (value < 256);
00746                 result += (value << (i * 8));
00747         }
00748 
00749         return result;
00750 }
00751 
00763 /*
00764 UINT32 decodeXByte(tokenizer::const_iterator& tok, const tokenizer::const_iterator& end, UINT16 len)
00765 {
00766         UINT32 value;
00767         UINT32 result = 0;
00768 
00769         assert (len < 5);       // Wir koennen nur bis zu 4 Bytes in einen UINT32 packen
00770 
00771         tokenizer::const_iterator last = tok;
00772 
00773         for ( UINT16 i = 0; i < len && tok != end; ++tok, ++i)
00774         {
00775                 value = decodeUINT32(*tok);
00776                 assert (value < 256);
00777                 result += (value << (i * 8));
00778 
00779                 last = tok;
00780         }
00781 
00782         // set token one position back
00783         tok = last;
00784 
00785 
00786         return result;
00787 }
00788 */
00789 
00790 //
00791 // Char-To-String-Umwandlung.
00792 //
00793 std::string convertRxBufferToString(UINT8* buffer, UINT16 bufferLen)
00794 {
00795         buffer[bufferLen-1] = 0x00;     // End-Code 0x03 ueberschreiben mit 0x00
00796         std::string result = std::string((char*)(&(buffer[2])));
00797         return result;
00798 }
00799 
00800 
00801 } // END namespace colaa


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