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