Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #pragma once
00055
00056 #include <arpa/inet.h>
00057
00058 class TelegramParser {
00059
00060 #pragma pack(push,1)
00061 union TELEGRAM_COMMON1 {
00062 struct {
00063 uint32_t reply_telegram;
00064 uint16_t trigger_result;
00065 uint16_t size;
00066 uint8_t coordination_flag;
00067 uint8_t device_addresss;
00068 };
00069 uint8_t bytes[10];
00070 };
00071 union TELEGRAM_COMMON2 {
00072 struct {
00073 uint16_t protocol_version;
00074 uint16_t status;
00075 uint32_t scan_number;
00076 uint16_t telegram_number;
00077 };
00078 uint8_t bytes[10];
00079 };
00080 union TELEGRAM_COMMON3 {
00081 struct {
00082 uint16_t type;
00083 };
00084 uint8_t bytes[2];
00085 };
00086
00087 union TELEGRAM_DISTANCE {
00088 struct {
00089 uint16_t type;
00090 };
00091 uint8_t bytes[2];
00092 };
00093
00094 union TELEGRAM_TAIL {
00095 struct {
00096 uint16_t crc;
00097 };
00098 uint8_t bytes[2];
00099 };
00100
00101 union TELEGRAM_S300_DIST_2B {
00102 struct {
00103 unsigned distance : 13;
00104 unsigned bit13 : 1;
00105 unsigned protective : 1;
00106 unsigned warn_field : 1;
00107 };
00108 uint16_t val16;
00109 uint8_t bytes[2];
00110 };
00111
00112 #pragma pack(pop)
00113
00114 enum TELEGRAM_COMMON_HS {JUNK_SIZE=4};
00115 enum TELEGRAM_COMMON_TYPES {IO=0xAAAA, DISTANCE=0xBBBB, REFLEXION=0xCCCC};
00116 enum TELEGRAM_DIST_SECTOR {_1=0x1111, _2=0x2222, _3=0x3333, _4=0x4444, _5=0x5555};
00117
00118
00119 static void ntoh(TELEGRAM_COMMON1 &tc) {
00120 tc.reply_telegram = ntohl(tc.reply_telegram);
00121 tc.trigger_result = ntohs(tc.trigger_result);
00122 tc.size = ntohs(tc.size);
00123 }
00124
00125 static void ntoh(TELEGRAM_COMMON2 &tc) {
00126 tc.protocol_version = ntohs(tc.protocol_version);
00127 tc.status = ntohs(tc.status);
00128 tc.scan_number = ntohl(tc.scan_number);
00129 tc.telegram_number = ntohs(tc.telegram_number);
00130 }
00131
00132 static void ntoh(TELEGRAM_COMMON3 &tc) {
00133 tc.type = ntohs(tc.type);
00134 }
00135
00136 static void ntoh(TELEGRAM_DISTANCE &tc) {
00137 tc.type = ntohs(tc.type);
00138 }
00139
00140 static void ntoh(TELEGRAM_TAIL &tc) {
00141
00142
00143 }
00144
00145 static void print(const TELEGRAM_COMMON1 &tc) {
00146 std::cout<<"HEADER"<<std::dec<<std::endl;
00147 std::cout<<"reply_telegram"<<":"<<tc.reply_telegram<<std::endl;
00148 std::cout<<"trigger_result"<<":"<<tc.trigger_result<<std::endl;
00149 std::cout<<"size"<<":"<<2*tc.size<<std::endl;
00150 std::cout<<"coordination_flag"<<":"<< std::hex<<tc.coordination_flag<<std::endl;
00151 std::cout<<"device_addresss"<<":"<< std::hex<<(int)tc.device_addresss<<std::endl;
00152 }
00153
00154 static void print(const TELEGRAM_COMMON2 &tc) {
00155 std::cout<<"protocol_version"<<":"<< std::hex<<tc.protocol_version<<std::endl;
00156 std::cout<<"status"<<":"<<tc.status<<std::endl;
00157 std::cout<<"scan_number"<<":"<< std::hex<<tc.scan_number<<std::endl;
00158 std::cout<<"telegram_number"<<":"<< std::hex<<tc.telegram_number<<std::endl;
00159 }
00160
00161 static void print(const TELEGRAM_COMMON3 &tc) {
00162 std::cout<<"type"<<":"<< std::hex<<tc.type<<std::endl;
00163 switch(tc.type) {
00164 case IO: std::cout<<"type"<<": "<<"IO"<<std::endl; break;
00165 case DISTANCE: std::cout<<"type"<<": "<<"DISTANCE"<<std::endl; break;
00166 case REFLEXION: std::cout<<"type"<<": "<<"REFLEXION"<<std::endl; break;
00167 default: std::cout<<"type"<<": "<<"unknown "<<tc.type<<std::endl; break;
00168 }
00169 std::cout<<std::dec<<std::endl;
00170 }
00171
00172 static void print(const TELEGRAM_DISTANCE &tc) {
00173 std::cout<<"DISTANCE"<<std::endl;
00174 std::cout<<"type"<<":"<< std::hex<<tc.type<<std::endl;
00175 switch(tc.type) {
00176 case _1: std::cout<<"field 1"<<std::endl; break;
00177 case _2: std::cout<<"field 2"<<std::endl; break;
00178 case _3: std::cout<<"field 3"<<std::endl; break;
00179 case _4: std::cout<<"field 4"<<std::endl; break;
00180 case _5: std::cout<<"field 5"<<std::endl; break;
00181 default: std::cout<<"unknown "<<tc.type<<std::endl; break;
00182 }
00183 std::cout<<std::dec<<std::endl;
00184 }
00185
00186 static void print(const TELEGRAM_TAIL &tc) {
00187 std::cout<<"TAIL"<<std::endl;
00188 std::cout<<"crc"<<":"<< std::hex<<tc.crc<<std::endl;
00189 std::cout<<std::dec<<std::endl;
00190 }
00191
00192
00193 static unsigned int createCRC(uint8_t *ptrData, int Size);
00194
00195
00196 static bool check(const TELEGRAM_COMMON1 &tc, const uint8_t DEVICE_ADDR) {
00197 uint8_t TELEGRAM_COMMON_PATTERN_EQ[] = {0,0,0,0, 0,0, 0,0, 0xFF, 0&DEVICE_ADDR};
00198 uint8_t TELEGRAM_COMMON_PATTERN_OR[] = {0,0,0,0, 0,0, 0xff,0xff, 0,0xff};
00199
00200 for(size_t i=0; i<sizeof(TELEGRAM_COMMON_PATTERN_EQ); i++) {
00201 if(TELEGRAM_COMMON_PATTERN_EQ[i] != (tc.bytes[i]&(~TELEGRAM_COMMON_PATTERN_OR[i])) ) {
00202
00203 return false;
00204 }
00205 }
00206
00207 return true;
00208 }
00209
00210 TELEGRAM_COMMON1 tc1_;
00211 TELEGRAM_COMMON2 tc2_;
00212 TELEGRAM_COMMON3 tc3_;
00213 TELEGRAM_DISTANCE td_;
00214 int last_offset_;
00215 public:
00216
00217 TelegramParser() : last_offset_(0) {}
00218
00219 bool parseHeader(const unsigned char *buffer, const size_t max_size, const uint8_t DEVICE_ADDR, const bool debug)
00220 {
00221 if(sizeof(tc1_)>max_size) return false;
00222 tc1_ = *((TELEGRAM_COMMON1*)buffer);
00223
00224 if(!check(tc1_, DEVICE_ADDR)) {
00225
00226 return false;
00227 }
00228
00229 ntoh(tc1_);
00230 if(debug) print(tc1_);
00231
00232 if(tc1_.size*2+JUNK_SIZE>(int)max_size) {
00233 if(debug) std::cout<<"invalid header size"<<std::endl;
00234 return false;
00235 }
00236
00237 tc2_ = *((TELEGRAM_COMMON2*)(buffer+sizeof(TELEGRAM_COMMON1)));
00238 tc3_ = *((TELEGRAM_COMMON3*)(buffer+(sizeof(TELEGRAM_COMMON1)+sizeof(TELEGRAM_COMMON2))));
00239
00240 TELEGRAM_TAIL tt;
00241 uint16_t crc;
00242
00243 if(tc2_.protocol_version==0x102)
00244 last_offset_ = -10;
00245 tt = *((TELEGRAM_TAIL*) (buffer+(2*tc1_.size+JUNK_SIZE-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_)) );
00246 ntoh(tt);
00247 crc = createCRC((uint8_t*)buffer+JUNK_SIZE, 2*tc1_.size-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_);
00248
00249 if(tc2_.protocol_version!=0x102) {
00250 if(tt.crc!=crc) {
00251 last_offset_ = 0;
00252 if(debug) std::cout<<"CRC failed!\ntrying offset of "<<std::dec<<last_offset_<<std::endl;
00253 tt = *((TELEGRAM_TAIL*) (buffer+(2*tc1_.size+JUNK_SIZE-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_)) );
00254 ntoh(tt);
00255 crc = createCRC((uint8_t*)buffer+JUNK_SIZE, 2*tc1_.size-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_);
00256 }
00257
00258 if(tt.crc!=crc) {
00259 last_offset_ = -6;
00260 if(debug) std::cout<<"CRC failed!\ntrying offset of "<<std::dec<<last_offset_<<std::endl;
00261 tt = *((TELEGRAM_TAIL*) (buffer+(2*tc1_.size+JUNK_SIZE-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_)) );
00262 ntoh(tt);
00263 crc = createCRC((uint8_t*)buffer+JUNK_SIZE, 2*tc1_.size-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_);
00264 }
00265 }
00266
00267 if(tt.crc!=crc) {
00268 if(debug) {
00269 print(tc2_);
00270 print(tc3_);
00271 print(tt);
00272 std::cout<<"at "<<std::hex<<(2*tc1_.size+JUNK_SIZE-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_)<<std::endl;
00273 std::cout<<"invalid CRC: "<<crc<<" ("<<tt.crc<<")"<<std::endl;
00274 }
00275 return false;
00276 }
00277
00278 memset(&td_, 0, sizeof(td_));
00279 switch(tc3_.type) {
00280 case IO: break;
00281
00282 case DISTANCE:
00283 if(debug) std::cout<<"got distance"<<std::endl;
00284
00285 td_ = *((TELEGRAM_DISTANCE*)(buffer+sizeof(tc1_)+sizeof(tc2_)+sizeof(tc3_)));
00286 ntoh(td_);
00287
00288 break;
00289
00290 case REFLEXION: break;
00291 default: return false;
00292 }
00293
00294 return true;
00295 }
00296
00297 bool isDist() const {return tc3_.type==DISTANCE;}
00298 int getField() const {
00299 switch(td_.type) {
00300 case _1: return 1;
00301 case _2: return 2;
00302 case _3: return 3;
00303 case _4: return 4;
00304 case _5: return 5;
00305 default: return -1;
00306 }
00307 }
00308
00309 int getCompletePacketSize() const {
00310 return 2*tc1_.size + sizeof(tc1_) + JUNK_SIZE + last_offset_;
00311 }
00312
00313 void readDistRaw(const unsigned char *buffer, std::vector<int> &res) const
00314 {
00315 res.clear();
00316 if(!isDist()) return;
00317
00318 size_t num_points = (2*tc1_.size - (sizeof(tc1_)+sizeof(tc2_)+sizeof(tc3_)+sizeof(td_)+sizeof(TELEGRAM_TAIL)-JUNK_SIZE-last_offset_));
00319
00320 size_t i=0;
00321 for(; i<num_points; ) {
00322 TELEGRAM_S300_DIST_2B dist = *((TELEGRAM_S300_DIST_2B*) (buffer+(sizeof(tc1_)+sizeof(tc2_)+sizeof(tc3_)+sizeof(td_)+i)) );
00323
00324 res.push_back((int)dist.val16);
00325 i += sizeof(TELEGRAM_S300_DIST_2B);
00326 }
00327 }
00328
00329 };