|
rllib
1
|
00001 /*************************************************************************** 00002 rleibnetip.cpp - description 00003 ------------------- 00004 begin : WEd Apr 04 2007 00005 copyright : (C) 2007 by Rainer Lehrig 00006 email : lehrig@t-online.de 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This library is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as * 00013 * published by the Free Software Foundation * 00014 * * 00015 ***************************************************************************/ 00016 #include "rleibnetip.h" 00017 #include "rltime.h" 00018 #include "rldataacquisitionprovider.h" 00019 #include <stdio.h> 00020 #include <string.h> 00021 #include <math.h> 00022 00023 #define EIB_HEADERSIZE 6 00024 #define EIB_VERSION 0x10 00025 #define EIB_ADRSIZE 8 00026 //not sizeof(struct sockaddr_in) 00027 #define EIB_CRICRDSIZE 4 00028 #define TUNNEL_CONNECTION 4 00029 #define REMLOG_CONNECTION 6 00030 #define OBJSVR_CONNECTION 8 00031 #define TUNNEL_LINKLAYER 2 00032 #define E_NO_ERROR 0 00033 #define E_NO_MORE_CONNECTIONS 0x24 00034 #define E_SEQUENCE_NUMBER 0x04 00035 00036 #define L_Data_Req 0x11 00037 #define L_Data_Con 0x2E 00038 #define L_Data_Ind 0x29 00039 00040 enum ServiceType 00041 { 00042 SEARCH_REQUEST = 0x0201, 00043 SEARCH_RESPONSE = 0x0202, 00044 DESCRIPTION_REQUEST = 0x0203, 00045 DESCRIPTION_RESPONSE = 0x0204, 00046 CONNECT_REQUEST = 0x0205, 00047 CONNECT_RESPONSE = 0x0206, 00048 CONNECTIONSTATE_REQUEST = 0x0207, 00049 CONNECTIONSTATE_RESPONSE = 0x0208, 00050 DISCONNECT_REQUEST = 0x0209, 00051 DISCONNECT_RESPONSE = 0x020A, 00052 TUNNELLING_REQUEST = 0x0420, 00053 TUNNELLING_ACK = 0x0421 00054 }; 00055 00056 static void *eib_reader(void *arg) // thread 00057 { 00058 THREAD_PARAM *p = (THREAD_PARAM *) arg; 00059 rlEIBnetIP *eib = (rlEIBnetIP *) p->user; 00060 rlEIBnetIP::PDU pdu; 00061 rlTime now, last, diff; 00062 int ret, len; 00063 int recseq = 0; 00064 int expected_recseq = 0; 00065 unsigned char b[4]; 00066 00067 last.getLocalTime(); 00068 while(eib->running) 00069 { 00070 if(eib->isConnected() == 0) 00071 { 00072 eib->connect(); 00073 expected_recseq = 0; 00074 last.getLocalTime(); 00075 } 00076 ret = eib->recv(&pdu, sizeof(pdu)); 00077 now.getLocalTime(); 00078 if(ret > 0) 00079 { 00080 switch (ntohs(pdu.servicetype)) 00081 { 00082 case DISCONNECT_REQUEST: 00083 eib->disconnect(); 00084 expected_recseq = 0; 00085 break; 00086 case CONNECTIONSTATE_RESPONSE: 00087 if(eib->debug) ::printf("eib_reader() CONNECTIONSTATE_RESPONSE\n"); 00088 break; 00089 case TUNNELLING_REQUEST: 00090 if(eib->debug) 00091 ::printf("eib_reader() TUNNELING_REQUEST sequenzecounter=%d\n",recseq); 00092 recseq = pdu.data[2]; // sequencecounter 00093 b[0] = pdu.data[0]; // remember 4 bytes of data 00094 b[1] = pdu.data[1]; 00095 b[2] = pdu.data[2]; 00096 b[3] = pdu.data[3]; 00097 len = ntohs(pdu.totalsize) - 6; // remember len (-headerlength) 00098 pdu.headersize = EIB_HEADERSIZE; // fill acknowledge 00099 pdu.version = EIB_VERSION; 00100 pdu.servicetype = htons(TUNNELLING_ACK); 00101 pdu.totalsize = htons(EIB_HEADERSIZE+4); 00102 pdu.data[0] = 4; // structlength 00103 pdu.data[1] = eib->channelid; // channelid 00104 pdu.data[2] = recseq; // sequencecounter 00105 pdu.data[3] = E_NO_ERROR; // typespecific 00106 if(recseq != expected_recseq) 00107 { 00108 if(eib->debug) 00109 ::printf("eib_reader() recseq=%d expected_recseq=%d\n",recseq,expected_recseq); 00110 // we simply ignore the sequencecounter 00111 // pdu.data[4] = E_SEQUENCE_NUMBER; 00112 } 00113 expected_recseq = (expected_recseq+1) & 0x0ff; 00114 eib->rlUdpSocket::sendto(&pdu, ntohs(pdu.totalsize), eib->server); 00115 pdu.data[0] = b[0]; // restore received data 00116 pdu.data[1] = b[1]; 00117 pdu.data[2] = b[2]; 00118 pdu.data[3] = b[3]; 00119 eib->storeBuffer(&pdu.data[4],len-4); // +EIBNETIP_COMMON_CONNECTION_HEADER 00120 break; 00121 case TUNNELLING_ACK: 00122 if(pdu.data[3] == E_NO_ERROR) 00123 { 00124 eib->tunnel_ack = 1; 00125 if(eib->debug) ::printf("eib_reader() TUNNELLING_ACK typespecific=0x%x\n",pdu.data[3]); 00126 } 00127 else 00128 { 00129 eib->tunnel_ack = -1; 00130 if(eib->debug) ::printf("eib_reader() TUNNELLING_NACK typespecific=0x%x\n",pdu.data[3]); 00131 } 00132 break; 00133 default: 00134 ::printf("eib_reader() unknown servicetype=0x%x\n",ntohs(pdu.servicetype)); 00135 break; 00136 } 00137 } 00138 diff = now - last; 00139 if(eib->isConnected() && eib->channelid != -1 && diff.second > 50) 00140 { // send heartbeat 00141 if(eib->debug) ::printf("send heartbeat\n"); 00142 pdu.headersize = EIB_HEADERSIZE; 00143 pdu.version = EIB_VERSION; 00144 pdu.servicetype = htons(CONNECTIONSTATE_REQUEST); 00145 pdu.totalsize = htons(EIB_HEADERSIZE+EIB_ADRSIZE*2+EIB_CRICRDSIZE); 00146 pdu.data[0] = eib->channelid; 00147 pdu.data[1] = 0; 00148 eib->rlUdpSocket::sendto(&pdu, ntohs(pdu.totalsize), eib->server); 00149 last.getLocalTime(); 00150 } 00151 } 00152 return NULL; 00153 /* 00154 for(int i=0; i<50; i++) 00155 { 00156 p->thread->lock(); 00157 //do something critical 00158 printf("this is the thread\n"); 00159 p->thread->unlock(); 00160 } 00161 */ 00162 } 00163 00164 rlEIBnetIP::rlEIBnetIP(int num_signals, int _debug, rlDataAcquisitionProvider *_provider) : rlUdpSocket(_debug) 00165 { 00166 debug = _debug; 00167 provider = _provider; 00168 watch_eib = 0; 00169 if(debug) ::printf("rlEIBnetIP() constructor\n"); 00170 char *cptr; 00171 mem = NULL; 00172 memsize = 0; 00173 running = 0; 00174 maxvalues = 0; 00175 is_connected = 0; 00176 channelid = -1; 00177 server = NULL; 00178 send_sequencecounter = 0; 00179 //rlUdpSocket::setSockopt(SO_BROADCAST); 00180 rlUdpSocket::bind(rlEIBnetIP::PORT); 00181 if(num_signals <= 0) return; 00182 memsize = sizeof(EIB_TEL)*num_signals; 00183 maxvalues = num_signals; 00184 cptr = new char[memsize]; 00185 memset(cptr,0,memsize); 00186 mem = cptr; 00187 setSourceAdr("/0/0/001"); 00188 } 00189 00190 rlEIBnetIP::~rlEIBnetIP() 00191 { 00192 if(running) stopReading(); 00193 if(mem != NULL) 00194 { 00195 char *cptr = (char *) mem; 00196 delete [] cptr; 00197 } 00198 sendDisconnectRequest(); 00199 } 00200 00201 int rlEIBnetIP::storeBuffer(unsigned char *buf, int len) 00202 { 00203 EIB_TEL tel; 00204 short unsigned int *sptr; 00205 int i; 00206 00207 if(len <= 0 || mem == NULL) return -1; 00208 if(debug) 00209 { 00210 ::printf("rlEIBnetIP::storeBuffer() buf=[0x%x",buf[0]); 00211 for(i=1; i<len; i++) ::printf(",0x%x",buf[i]); 00212 ::printf("]\n"); 00213 } 00214 00215 tel.mc = buf[0]; 00216 tel.addi1 = buf[1]; 00217 tel.ctrl1 = buf[2]; 00218 tel.ctrl2 = buf[3]; 00219 sptr = (unsigned short *) &buf[4]; 00220 tel.saddr = ntohs(*sptr); 00221 sptr = (unsigned short *) &buf[6]; 00222 tel.daddr = ntohs(*sptr); 00223 tel.apci_length = buf[8]; 00224 tel.apci = buf[9]; 00225 tel.val[0] = buf[10]; 00226 tel.val[1] = buf[10+1]; 00227 tel.val[2] = buf[10+2]; 00228 tel.val[3] = buf[10+3]; 00229 for(i=0; i<(len-10); i++) tel.val[i] = buf[10+i]; 00230 switch (tel.mc) 00231 { 00232 case L_Data_Req: //0x11: 00233 ::printf("rlEIBnetIP::storeBuffer() messagecode=0x%x L_Data_Req\n",tel.mc); 00234 break; 00235 case L_Data_Ind: //0x29: 00236 break; 00237 case L_Data_Con: //0x2E: 00238 break; 00239 default: 00240 ::printf("rlEIBnetIP::storeBuffer() unknown messagecode=0x%x L_Data_Con\n",tel.mc); 00241 return -1; 00242 } 00243 if(debug) 00244 { 00245 ::printf("\nmc=0x%x addi1=0x%x ctrl1=0x%x ctrl2=0x%x saddr=0x%x daddr=0x%x acpi_length=0x%x apci=0x%x", 00246 tel.mc, 00247 tel.addi1, 00248 tel.ctrl1, 00249 tel.ctrl2, 00250 tel.saddr, 00251 tel.daddr, 00252 tel.apci_length, 00253 tel.apci); 00254 for(i=10; i<len; i++) ::printf(" val[%d]=0x%x",i-10,tel.val[i-10]); 00255 ::printf("\n"); 00256 } 00257 00258 if(watch_eib) printTelegram(&tel); 00259 if(provider != NULL) return storeInProvider(&tel); 00260 00261 // store EIB_TEL in *mem 00262 EIB_TEL *memptr = (EIB_TEL *) mem; 00263 for(i=0; i<maxvalues; i++) 00264 { 00265 if(memptr[i].mc == 0) 00266 { 00267 //if(debug) ::printf("rlEIBnetIP::storeBuffer() insert new value\n"); 00268 thread.lock(); 00269 memcpy(&memptr[i],&tel,sizeof(tel)); 00270 thread.unlock(); 00271 return 0; 00272 } 00273 //else if(memptr[i].saddr == tel.saddr && memptr[i].daddr == tel.daddr) 00274 else if(memptr[i].daddr == tel.daddr) 00275 { 00276 //if(debug) ::printf("rlEIBnetIP::storeBuffer() update existing value\n"); 00277 thread.lock(); 00278 memcpy(&memptr[i],&tel,sizeof(tel)); 00279 thread.unlock(); 00280 return 0; 00281 } 00282 } 00283 ::printf("rlEIBnetIP::storeBuffer() maxvalues=%d too small\n",maxvalues); 00284 return -1; 00285 } 00286 00287 int rlEIBnetIP::printTelegram(EIB_TEL *tel) 00288 { 00289 int s1,s2,s3,d1,d2,d3,val,length; 00290 00291 s1 = tel->saddr/(8*256); 00292 s2 = (tel->saddr/256) & 0x0ff; 00293 s3 = tel->saddr & 0x0ff; 00294 d1 = tel->daddr/(8*256); 00295 d2 = (tel->daddr/256) & 0x0ff; 00296 d3 = tel->daddr & 0x0ff; 00297 length = tel->apci_length; 00298 val = 0; 00299 if(length == 1) 00300 { 00301 val = tel->val[0]; 00302 } 00303 else if(length == 2) 00304 { 00305 char *cptr = (char *) &tel->val[0]; 00306 val = (((*cptr)*256)+tel->val[1]); 00307 } 00308 else if(length == 3) 00309 { 00310 char *cptr = (char *) &tel->val[0]; 00311 val = (((*cptr)*256)+tel->val[1])*tel->val[2]; 00312 } 00313 else if(length == 4) 00314 { 00315 char *cptr = (char *) &tel->val[0]; 00316 val = ((((*cptr)*256)+tel->val[1])*(tel->val[2]*256) * tel->val[3]); 00317 } 00318 ::printf("src=/%d/%d/%03d\tdest=/%d/%d/%03d\tval=0x%x\tlen=%d\n",s1,s2,s3,d1,d2,d3,val,length); 00319 return 0; 00320 } 00321 00322 int rlEIBnetIP::storeInProvider(EIB_TEL *tel) 00323 { 00324 if(provider == NULL || tel == NULL) return -1; 00325 int s1,s2,s3,d1,d2,d3,val,length; 00326 char name[128], value[128]; 00327 00328 s1 = tel->saddr/(8*256); 00329 s2 = (tel->saddr/256) & 0x0ff; 00330 s3 = tel->saddr & 0x0ff; 00331 d1 = tel->daddr/(8*256); 00332 d2 = (tel->daddr/256) & 0x0ff; 00333 d3 = tel->daddr & 0x0ff; 00334 length = tel->apci_length; 00335 val = 0; 00336 if(length == 1) 00337 { 00338 val = tel->val[0]; 00339 } 00340 else if(length == 2) 00341 { 00342 char *cptr = (char *) &tel->val[0]; 00343 val = (((*cptr)*256)+tel->val[1]); 00344 } 00345 else if(length == 3) 00346 { 00347 char *cptr = (char *) &tel->val[0]; 00348 val = (((*cptr)*256)+tel->val[1])*tel->val[2]; 00349 } 00350 else if(length == 4) 00351 { 00352 char *cptr = (char *) &tel->val[0]; 00353 val = ((((*cptr)*256)+tel->val[1])*(tel->val[2]*256) * tel->val[3]); 00354 } 00355 //::printf("/%d/%d/%d\t/%d/%d/%d\t0x%x\t%d\n",s1,s2,s3,d1,d2,d3,val,length); 00356 sprintf(name,"/%d/%d/%03d",d1,d2,d3); 00357 sprintf(value,"%d",val); 00358 if(debug) ::printf("storeInProvicer: name=%s value=%s", name, value); 00359 provider->setStringValue(name, value); 00360 return 0; 00361 } 00362 00363 int rlEIBnetIP::dump(FILE *fout) 00364 { 00365 if(fout == NULL) return -1; 00366 if(debug) ::printf("rlEIBnetIP::dump()\n"); 00367 int s1,s2,s3,d1,d2,d3,val,length; 00368 int i = 0; 00369 EIB_TEL *tel; 00370 EIB_TEL *memptr = (EIB_TEL *) mem; 00371 00372 val = 0; 00373 thread.lock(); 00374 while(1) 00375 { 00376 tel = &memptr[i]; 00377 if(tel->mc == 0) break; 00378 if(i >= maxvalues) break; 00379 s1 = tel->saddr/(8*256); 00380 s2 = (tel->saddr/256) & 0x0ff; 00381 s3 = tel->saddr & 0x0ff; 00382 d1 = tel->daddr/(8*256); 00383 d2 = (tel->daddr/256) & 0x0ff; 00384 d3 = tel->daddr & 0x0ff; 00385 length = tel->apci_length; 00386 if(length == 1) 00387 { 00388 val = tel->val[0]; 00389 } 00390 else if(length == 2) 00391 { 00392 char *cptr = (char *) &tel->val[0]; 00393 val = (((*cptr)*256)+tel->val[1]); 00394 } 00395 else if(length == 3) 00396 { 00397 char *cptr = (char *) &tel->val[0]; 00398 val = (((*cptr)*256)+tel->val[1])*tel->val[2]; 00399 } 00400 else if(length == 4) 00401 { 00402 char *cptr = (char *) &tel->val[0]; 00403 val = ((((*cptr)*256)+tel->val[1])*(tel->val[2]*256) * tel->val[3]); 00404 } 00405 fprintf(fout,"/%d/%d/%d\t/%d/%d/%d\t0x%x\t%d\n",s1,s2,s3,d1,d2,d3,val,length); 00406 i++; 00407 } 00408 thread.unlock(); 00409 return i; 00410 } 00411 00412 int rlEIBnetIP::setValuesFromCSV(const char *filename) 00413 { 00414 FILE *fin; 00415 char line[1024], *cptr; 00416 int s1,s2,s3,d1,d2,d3,i,val,len; 00417 unsigned int uval; 00418 00419 if(filename == NULL) return -1; 00420 fin = fopen(filename,"r"); 00421 if(fin == NULL) 00422 { 00423 ::printf("rlEIBnetIP::setValuesFromCSV(%s) could not open file\n",filename); 00424 return -1; 00425 } 00426 00427 while(fgets(line,sizeof(line)-1,fin) != NULL) 00428 { 00429 d1 = d2 = d3 = 0; 00430 cptr = strchr(line,'/'); 00431 if(cptr == NULL) break; 00432 sscanf(cptr,"/%d/%d/%d",&s1,&s2,&s3); 00433 i = 0; 00434 while(line[i] != '\0') 00435 { 00436 if(line[i] == ' ' || line[i] == '\t') 00437 { 00438 while(line[i] == ' ' || line[i] == '\t') i++; 00439 if(line[i] == '/') 00440 { 00441 cptr = strstr(&line[i],"0x"); 00442 if(cptr == NULL) 00443 { 00444 sscanf(&line[i],"/%d/%d/%d %d %d",&d1,&d2,&d3,&val,&len); 00445 } 00446 else 00447 { 00448 sscanf(&line[i],"/%d/%d/%d %x %d",&d1,&d2,&d3,&val,&len); 00449 } 00450 } 00451 break; 00452 } 00453 i++; 00454 } 00455 if(line[i] == '\0') return rlEIBnetIP::EIBERROR; 00456 cptr = strchr(line,'/'); 00457 if(cptr != NULL) 00458 { 00459 sprintf(line,"/%d/%d/%d",d1,d2,d3); 00460 for(i=0; i<100; i++) // try setting even if hardware responds very slowly 00461 { 00462 memcpy(&uval,&val,sizeof(uval)); 00463 uval = setValueUnsigned(line,uval,len); 00464 if(uval != rlEIBnetIP::EIBERROR) break; 00465 } 00466 } 00467 } 00468 00469 fclose(fin); 00470 return 0; 00471 } 00472 00473 int rlEIBnetIP::connect() 00474 { 00475 if(server == NULL) return rlEIBnetIP::EIBERROR; 00476 if(debug) ::printf("rlEIBnetIP()::connect()\n"); 00477 PDU pdu,response; 00478 unsigned char cricrd[EIB_CRICRDSIZE]; 00479 int ret = 0; 00480 00481 if(is_connected == 1) 00482 { 00483 ::printf("rlEIBnetIP::connect() already connected\n"); 00484 return 1; 00485 } 00486 00487 channelid = -1; 00488 memset(&response,0,sizeof(response)); 00489 pdu.headersize = EIB_HEADERSIZE; 00490 pdu.version = EIB_VERSION; 00491 pdu.servicetype = htons(CONNECT_REQUEST); 00492 pdu.totalsize = htons(EIB_HEADERSIZE+EIB_ADRSIZE*2+EIB_CRICRDSIZE); 00493 memcpy(&pdu.data[0],&client.address,EIB_ADRSIZE); 00494 memcpy(&pdu.data[8],&client.address,EIB_ADRSIZE); 00495 cricrd[0] = EIB_CRICRDSIZE; // structlength 00496 cricrd[1] = TUNNEL_CONNECTION; // connectiontypecode 00497 cricrd[2] = TUNNEL_LINKLAYER; // data1 00498 cricrd[3] = 0; // data2 00499 memcpy(&pdu.data[8*2],cricrd,EIB_CRICRDSIZE); 00500 is_connected = 0; 00501 00502 rlUdpSocket::sendto(&pdu, ntohs(pdu.totalsize), server); 00503 ret = recv(&response, sizeof(PDU)); 00504 00505 if(ntohs(response.servicetype) == CONNECT_RESPONSE) 00506 { 00507 if(debug) 00508 { 00509 ::printf("response.headersize = 0x%x\n",response.headersize); 00510 ::printf("response.version = 0x%x\n",response.version); 00511 ::printf("response.servicetype = 0x%x\n",ntohs(response.servicetype)); 00512 ::printf("response.totalsize = 0x%x\n",ntohs(response.totalsize)); 00513 ::printf("response.channelid = 0x%x\n",response.data[0]); 00514 ::printf("response.status = 0x%x\n",response.data[1]); 00515 } 00516 if(response.data[1] == E_NO_ERROR) 00517 { 00518 channelid = response.data[0]; 00519 if(debug) ::printf("CONNECT_RESPONSE == success\n"); 00520 is_connected = 1; 00521 send_sequencecounter = 0; 00522 return 1; 00523 } 00524 ::printf("response == CONNECT_RESPONSE status=0x%x failed\n",response.data[1]); 00525 return -1; // 00526 } 00527 else 00528 { 00529 ::printf("response != CONNECT_RESPONSE\n"); 00530 return -1; 00531 } 00532 } 00533 00534 int rlEIBnetIP::disconnect() 00535 { 00536 if(server == NULL) return rlEIBnetIP::EIBERROR; 00537 if(debug) ::printf("rlEIBnetIP()::disconnect()\n"); 00538 PDU pdu; 00539 00540 pdu.headersize = EIB_HEADERSIZE; 00541 pdu.version = EIB_VERSION; 00542 pdu.servicetype = htons(DISCONNECT_RESPONSE); 00543 pdu.totalsize = htons(EIB_HEADERSIZE+2+EIB_ADRSIZE); 00544 pdu.data[0] = channelid; // channelid 00545 pdu.data[1] = 0; // reserved 00546 memcpy(&pdu.data[2],&client.address,EIB_ADRSIZE); 00547 rlUdpSocket::sendto(&pdu, ntohs(pdu.totalsize), server); 00548 is_connected = 0; 00549 channelid = -1; 00550 return rlEIBnetIP::SUCCESS; 00551 } 00552 00553 int rlEIBnetIP::sendDisconnectRequest() 00554 { 00555 if(debug) ::printf("rlEIBnetIP()::sendDisconnectRequest()\n"); 00556 if(is_connected == 0) return -1; 00557 PDU pdu; 00558 00559 pdu.headersize = EIB_HEADERSIZE; 00560 pdu.version = EIB_VERSION; 00561 pdu.servicetype = htons(DISCONNECT_REQUEST); 00562 pdu.totalsize = htons(EIB_HEADERSIZE+2+EIB_ADRSIZE); 00563 pdu.data[0] = channelid; // channelid 00564 pdu.data[1] = 0; // reserved 00565 memcpy(&pdu.data[2],&client.address,EIB_ADRSIZE); 00566 rlUdpSocket::sendto(&pdu, ntohs(pdu.totalsize), server); 00567 is_connected = 0; 00568 channelid = -1; 00569 return rlEIBnetIP::SUCCESS; 00570 } 00571 00572 int rlEIBnetIP::isConnected() 00573 { 00574 return is_connected; 00575 } 00576 00577 int rlEIBnetIP::startReading() 00578 { 00579 running = 1; 00580 is_connected = 0; 00581 channelid = -1; 00582 thread.create(eib_reader,this); 00583 return rlEIBnetIP::SUCCESS; 00584 } 00585 00586 int rlEIBnetIP::stopReading() 00587 { 00588 running = 0; 00589 is_connected = 0; 00590 channelid = -1; 00591 thread.cancel(); 00592 return rlEIBnetIP::SUCCESS; 00593 } 00594 00595 int rlEIBnetIP::setSourceAdr(const char *adr) 00596 { 00597 const char *cptr; 00598 int a1,a2,a3; 00599 00600 // interpret name 00601 cptr = strchr(adr,'/'); 00602 if(cptr == NULL) 00603 { 00604 ::printf("USER_ERROR: rlEIBnetIP::setSourceAdr() wrong adr=%s\n", adr); 00605 return -1; 00606 } 00607 sscanf(cptr,"/%d/%d/%d",&a1,&a2,&a3); 00608 saddr = ((a1*8)+a2)*256+a3; 00609 return 0; 00610 } 00611 00612 int rlEIBnetIP::setValue(const char *name, int val, int length, int addi1, int ctrl, int apci) 00613 { 00614 unsigned int uval; 00615 memcpy(&uval,&val,sizeof(uval)); 00616 return setValueUnsigned(name, uval, length, addi1, ctrl, apci); 00617 } 00618 00619 int rlEIBnetIP::value(const char *name) 00620 { 00621 int val; 00622 unsigned int uval; 00623 uval = valueUnsigned(name); 00624 memcpy(&val,&uval,sizeof(val)); 00625 return val; 00626 } 00627 00628 int rlEIBnetIP::setValueFloat(const char *name, float val, int length, int addi1, int ctrl, int apci) 00629 { 00630 unsigned int uval,s,e,m; 00631 float fval,eval; 00632 if(length == -1 || length == 2) 00633 { 00634 length = 2; 00635 if(val < 0.0f) s = 0x80000000; 00636 else s = 0; 00637 m = (unsigned int) (val*100.0f); 00638 m = m/100; 00639 // m*2^e = fabsf(val) 00640 // 2^e = fabsf(val)/m; 00641 // e = ln(fabsf(val)/m) 00642 if(m == 0) e = 0; 00643 else 00644 { 00645 fval = fabsf(val)/(float) m; 00646 eval = logf(fval); 00647 e = ((unsigned int) eval) * 8* 256; 00648 } 00649 uval = s | e | m; 00650 } 00651 else if(length == 4) 00652 { 00653 memcpy(&uval,&val,sizeof(uval)); 00654 } 00655 else 00656 { 00657 return rlEIBnetIP::EIBERROR; 00658 } 00659 return setValueUnsigned(name, uval, length, addi1, ctrl, apci); 00660 } 00661 00662 float rlEIBnetIP::valueFloat2(const char *name) 00663 { 00664 float val,sign; 00665 unsigned int uval,e,m; 00666 uval = valueUnsigned(name); 00667 if(uval & 0x080000000) sign = 1.0f; 00668 else sign = -1.0f; 00669 uval = uval | 0x07fffffff; // eliminate sign 00670 m = uval & 0x07ffff; 00671 e = uval / (8*256); 00672 val = sign*(0.01f*m)*(2^e); 00673 return val; 00674 } 00675 00676 float rlEIBnetIP::valueFloat4(const char *name) 00677 { 00678 float val; 00679 unsigned int uval; 00680 uval = valueUnsigned(name); 00681 memcpy(&val,&uval,sizeof(float)); 00682 return val; 00683 } 00684 00685 unsigned int rlEIBnetIP::valueUnsigned(const char *name) 00686 { 00687 if(name == NULL || mem == NULL) return rlEIBnetIP::EIBERROR; 00688 unsigned int val,a1,a2,a3,length; 00689 const char *cptr; 00690 EIB_TEL tel; 00691 EIB_TEL *memptr = (EIB_TEL *) mem; 00692 00693 // interpret name 00694 memset(&tel,0xff,sizeof(EIB_TEL)); 00695 cptr = strchr(name,'/'); 00696 if(cptr == NULL) 00697 { 00698 ::printf("USER_ERROR: rlEIBnetIP::value() wrong name=%s\n", name); 00699 return rlEIBnetIP::EIBERROR; 00700 } 00701 sscanf(cptr,"/%d/%d/%d",&a1,&a2,&a3); 00702 tel.saddr = (short) saddr; 00703 tel.daddr = ((a1*8)+a2)*256+a3; 00704 00705 for(int i=0; i<maxvalues; i++) 00706 { 00707 if(memptr[i].mc == 0) break; 00708 //if(memptr[i].saddr == tel.saddr && memptr[i].daddr == tel.daddr) 00709 if(memptr[i].daddr == tel.daddr) 00710 { 00711 thread.lock(); 00712 val = 0; 00713 length = memptr[i].apci_length; 00714 if(length == 1) 00715 { 00716 val = memptr[i].val[0]; 00717 } 00718 else if(length == 2) 00719 { 00720 char *cptr = (char *) &memptr[i].val[0]; 00721 val = (((*cptr)*256)+memptr[i].val[1]); 00722 } 00723 else if(length == 3) 00724 { 00725 char *cptr = (char *) &memptr[i].val[0]; 00726 val = (((*cptr)*256)+memptr[i].val[1])*memptr[i].val[2]; 00727 } 00728 else if(length == 4) 00729 { 00730 char *cptr = (char *) &memptr[i].val[0]; 00731 val = ((((*cptr)*256)+memptr[i].val[1])*(memptr[i].val[2]*256) * memptr[i].val[3]); 00732 } 00733 thread.unlock(); 00734 if(length < 1 || length > 4 || length == 3) 00735 { 00736 ::printf("rlEIBnetIP::value(0x%x) unknown length=%d\n",val,length); 00737 return rlEIBnetIP::EIBERROR; 00738 } 00739 return val; 00740 } 00741 } 00742 return rlEIBnetIP::EIBERROR; 00743 } 00744 00745 int rlEIBnetIP::getText(const char *name, char *text, int maxlen) 00746 { 00747 if(name == NULL || text == NULL || maxlen <= 0) return rlEIBnetIP::EIBERROR; 00748 unsigned int a1,a2,a3,length; 00749 int j; 00750 const char *cptr; 00751 char buf[16]; 00752 EIB_TEL tel; 00753 EIB_TEL *memptr = (EIB_TEL *) mem; 00754 00755 text[0] = '\0'; 00756 // interpret name 00757 memset(&tel,0xff,sizeof(EIB_TEL)); 00758 cptr = strchr(name,'/'); 00759 if(cptr == NULL) 00760 { 00761 ::printf("USER_ERROR: rlEIBnetIP::getText() wrong name=%s\n", name); 00762 return rlEIBnetIP::EIBERROR; 00763 } 00764 sscanf(cptr,"/%d/%d/%d",&a1,&a2,&a3); 00765 tel.saddr = (short) saddr; 00766 tel.daddr = ((a1*8)+a2)*256+a3; 00767 00768 for(int i=0; i<maxvalues; i++) 00769 { 00770 if(memptr[i].mc == 0) break; 00771 //if(memptr[i].saddr == tel.saddr && memptr[i].daddr == tel.daddr) 00772 if(memptr[i].daddr == tel.daddr) 00773 { 00774 thread.lock(); 00775 length = memptr[i].apci_length; 00776 for(j=0; j<14; j++) buf[j] = memptr[i].val[j]; 00777 buf[14] = '\0'; 00778 j = 0; 00779 while(j<maxlen && j<14) 00780 { 00781 text[j] = buf[j]; 00782 j++; 00783 } 00784 return j; 00785 } 00786 } 00787 return 0; 00788 } 00789 00790 int rlEIBnetIP::setText(const char *name, const char *text) 00791 { 00792 if(name == NULL || text == NULL) return rlEIBnetIP::EIBERROR; 00793 char buf[16]; 00794 int length = strlen(text); 00795 unsigned int a1,a2,a3,daddr; 00796 int i,retry; 00797 const char *cptr; 00798 PDU pdu; 00799 EIB_TEL tel; 00800 EIB_TEL *memptr = (EIB_TEL *) mem; 00801 00802 if(length > 14) length = 14; 00803 memset(buf,0,sizeof(buf)); 00804 for(i=0; i<length; i++) buf[i] = text[i]; 00805 00806 // interpret name 00807 cptr = strchr(name,'/'); 00808 if(cptr == NULL) 00809 { 00810 ::printf("USER_ERROR: rlEIBnetIP::setText() wrong name=%s text=%s\n", name, text); 00811 return rlEIBnetIP::EIBERROR; 00812 } 00813 sscanf(cptr,"/%d/%d/%d",&a1,&a2,&a3); 00814 daddr = ((a1*8)+a2)*256+a3; 00815 00816 // fill EIBnet/IP PDU 00817 pdu.headersize = EIB_HEADERSIZE; 00818 pdu.version = EIB_VERSION; 00819 pdu.servicetype = htons(TUNNELLING_REQUEST); 00820 pdu.totalsize = htons(EIB_HEADERSIZE+4+10+length); 00821 pdu.data[0] = 4; // structlength 00822 pdu.data[1] = channelid; // channelid 00823 pdu.data[2] = send_sequencecounter; // sequencecounter 00824 pdu.data[3] = E_NO_ERROR; // typespecific 00825 tel.mc = L_Data_Req; // L_Data_Req=0x11, L_Data_Con=0x2E L_Data_Ind=0x29 00826 tel.addi1 = 0x0; 00827 tel.ctrl1 = 0xbc; 00828 tel.ctrl2 = 0xe0; 00829 tel.saddr = (unsigned short) htons((short) saddr); //0x1); 00830 tel.daddr = (unsigned short) htons((short) daddr); //(0x100) 00831 tel.apci_length = 0x1; 00832 tel.apci = 0x0; 00833 for(i=0; i<14; i++) tel.val[i] = buf[i]; 00834 memcpy(&pdu.data[4],&tel,sizeof(EIB_TEL)); 00835 00836 tunnel_ack = retry = 0; 00837 while(1) 00838 { 00839 // send value over EIBnet/IP 00840 rlUdpSocket::sendto(&pdu, ntohs(pdu.totalsize), server); 00841 rlsleep(10); 00842 if (tunnel_ack == 1) // OK 00843 { 00844 send_sequencecounter = (send_sequencecounter+1) & 0x0ff; 00845 if(debug) ::printf("rlEIBnetIP::setText(%s) ACK\n",text); 00846 break; 00847 } 00848 else if(tunnel_ack == -1) // failure 00849 { 00850 if(debug) ::printf("rlEIBnetIP::setText(%s) NACK\n",text); 00851 retry++; 00852 } 00853 else 00854 { 00855 if(debug) ::printf("rlEIBnetIP::setText(%s) timeout\n",text); 00856 retry++; 00857 } 00858 if(retry >= 2) 00859 { 00860 is_connected = 0 ; 00861 ::printf("rlEIBnetIP::setText() connection lost\n"); 00862 return rlEIBnetIP::EIBERROR; 00863 } 00864 } 00865 tunnel_ack = 0; 00866 00867 tel.saddr = ntohs(tel.saddr); // convert network -> host byte order 00868 tel.daddr = ntohs(tel.daddr); 00869 // remember value within mem 00870 for(i=0; i< maxvalues; i++) 00871 { 00872 if(memptr[i].mc == 0) 00873 { 00874 if(debug) ::printf("rlEIBnetIP::setText() insert new value\n"); 00875 thread.lock(); 00876 memcpy(&memptr[i],&tel,sizeof(tel)); 00877 thread.unlock(); 00878 return length; 00879 } 00880 //else if(memptr[i].saddr == tel.saddr && memptr[i].daddr == tel.daddr) 00881 else if(memptr[i].daddr == tel.daddr) 00882 { 00883 if(debug) ::printf("rlEIBnetIP::setText() update existing value\n"); 00884 thread.lock(); 00885 memcpy(&memptr[i],&tel,sizeof(tel)); 00886 thread.unlock(); 00887 return length; 00888 } 00889 } 00890 ::printf("ERROR rlEIBnetIP::setText() not enough signals specified max=%d\n",maxvalues); 00891 return rlEIBnetIP::EIBERROR; 00892 } 00893 00894 int rlEIBnetIP::setValueUnsigned(const char *name, unsigned int val, int length, int addi1, int ctrl, int apci) 00895 { 00896 if(name == NULL || mem == NULL || channelid == -1) return rlEIBnetIP::EIBERROR; 00897 unsigned int i,a1,a2,a3,daddr; 00898 int retry; 00899 const char *cptr; 00900 PDU pdu; 00901 EIB_TEL tel; 00902 EIB_TEL *memptr = (EIB_TEL *) mem; 00903 00904 // interpret name 00905 cptr = strchr(name,'/'); 00906 if(cptr == NULL) 00907 { 00908 ::printf("USER_ERROR: rlEIBnetIP::setValue() wrong name=%s val=%d\n", name, val); 00909 return rlEIBnetIP::EIBERROR; 00910 } 00911 sscanf(cptr,"/%d/%d/%d",&a1,&a2,&a3); 00912 daddr = ((a1*8)+a2)*256+a3; 00913 00914 // fill EIBnet/IP PDU 00915 pdu.headersize = EIB_HEADERSIZE; 00916 pdu.version = EIB_VERSION; 00917 pdu.servicetype = htons(TUNNELLING_REQUEST); 00918 if(length == -1) 00919 pdu.totalsize = htons(EIB_HEADERSIZE+4+10+1); 00920 else 00921 pdu.totalsize = htons(EIB_HEADERSIZE+4+10+length); 00922 pdu.data[0] = 4; // structlength 00923 pdu.data[1] = channelid; // channelid 00924 pdu.data[2] = send_sequencecounter; // sequencecounter 00925 pdu.data[3] = E_NO_ERROR; // typespecific 00926 tel.mc = L_Data_Req; // L_Data_Req=0x11, L_Data_Con=0x2E L_Data_Ind=0x29 00927 00928 tel.addi1 = 0x0; 00929 tel.ctrl1 = 0xbc; 00930 tel.ctrl2 = 0xe0; 00931 tel.saddr = (unsigned short) htons((short) saddr); //0x1); 00932 tel.daddr = (unsigned short) htons((short) daddr); //(0x100) 00933 tel.apci_length = 0x1; 00934 tel.apci = 0x0; 00935 00936 if(addi1 != -1) tel.addi1 = (unsigned char) ((addi1 & 0x0ff)); 00937 if(ctrl != -1) 00938 { 00939 tel.ctrl1 = (unsigned char) ((ctrl & 0x0ff00)/256); 00940 tel.ctrl2 = (unsigned char) ((ctrl & 0x0ff)); 00941 } 00942 if(length != -1) tel.apci_length = (unsigned char) length; 00943 if(apci != -1) tel.apci = (unsigned char) apci; 00944 00945 if(length == -1 || length == 1) 00946 { 00947 tel.val[0] = (unsigned char) val; // 0x80; // 0x81 00948 tel.val[1] = (unsigned char) 0x0; 00949 tel.val[2] = (unsigned char) 0x0; 00950 tel.val[3] = (unsigned char) 0x0; 00951 } 00952 else if(length == 2) 00953 { 00954 tel.val[0] = (unsigned char) ((val & 0x0ff00)/256); 00955 tel.val[1] = (unsigned char) (val & 0x0ff); 00956 tel.val[2] = (unsigned char) 0x0; 00957 tel.val[3] = (unsigned char) 0x0; 00958 } 00959 else if(length == 3) 00960 { 00961 tel.val[0] = (unsigned char) ((val & 0x0ff000000)/(256*256)); 00962 tel.val[1] = (unsigned char) (val & 0x0ff0000)/256; 00963 tel.val[2] = (unsigned char) (val & 0x0ff00); 00964 tel.val[3] = (unsigned char) (val & 0x0ff); 00965 } 00966 else if(length == 4) 00967 { 00968 tel.val[0] = (unsigned char) ((val & 0x0ff000000)/(256*256*256)); 00969 tel.val[1] = (unsigned char) ((val & 0x0ff0000)/(256*256)); 00970 tel.val[2] = (unsigned char) ((val & 0x0ff00)/(256)); 00971 tel.val[3] = (unsigned char) (val & 0x0ff); 00972 } 00973 else 00974 { 00975 ::printf("rlEIBnetIP::setValue(0x%x) unknown length=%d\n",val,length); 00976 return rlEIBnetIP::EIBERROR; 00977 } 00978 memcpy(&pdu.data[4],&tel,sizeof(EIB_TEL)); 00979 00980 if(debug) 00981 { 00982 ::printf("rlEIBnetIP::setValue() mc = 0x%x\n", tel.mc); 00983 ::printf("rlEIBnetIP::setValue() addi1 = 0x%x\n", tel.addi1); 00984 ::printf("rlEIBnetIP::setValue() ctrl1 = 0x%x\n", tel.ctrl1); 00985 ::printf("rlEIBnetIP::setValue() ctrl2 = 0x%x\n", tel.ctrl2); 00986 ::printf("rlEIBnetIP::setValue() saddr = 0x%x\n", ntohs(tel.saddr)); 00987 ::printf("rlEIBnetIP::setValue() daddr = 0x%x\n", ntohs(tel.daddr)); 00988 ::printf("rlEIBnetIP::setValue() apci_length = 0x%x\n", tel.apci_length); 00989 ::printf("rlEIBnetIP::setValue() apci = 0x%x\n", tel.apci); 00990 ::printf("rlEIBnetIP::setValue() val[0] = 0x%x\n", tel.val[0]); 00991 ::printf("rlEIBnetIP::setValue() val[1] = 0x%x\n", tel.val[1]); 00992 ::printf("rlEIBnetIP::setValue() val[2] = 0x%x\n", tel.val[2]); 00993 ::printf("rlEIBnetIP::setValue() val[3] = 0x%x\n", tel.val[3]); 00994 } 00995 00996 tunnel_ack = retry = 0; 00997 while(1) 00998 { 00999 // send value over EIBnet/IP 01000 rlUdpSocket::sendto(&pdu, ntohs(pdu.totalsize), server); 01001 rlsleep(10); 01002 if (tunnel_ack == 1) // OK 01003 { 01004 send_sequencecounter = (send_sequencecounter+1) & 0x0ff; 01005 if(debug) ::printf("rlEIBnetIP::setValue(0x%x) ACK\n",val); 01006 break; 01007 } 01008 else if(tunnel_ack == -1) // failure 01009 { 01010 if(debug) ::printf("rlEIBnetIP::setValue(0x%x) NACK\n",val); 01011 retry++; 01012 } 01013 else 01014 { 01015 if(debug) ::printf("rlEIBnetIP::setValue(0x%x) timeout\n",val); 01016 retry++; 01017 } 01018 if(retry >= 2) 01019 { 01020 is_connected = 0 ; 01021 ::printf("rlEIBnetIP::setValue() connection lost\n"); 01022 return rlEIBnetIP::EIBERROR; 01023 } 01024 } 01025 tunnel_ack = 0; 01026 01027 tel.saddr = ntohs(tel.saddr); // convert network -> host byte order 01028 tel.daddr = ntohs(tel.daddr); 01029 01030 if(provider != NULL) return 0; 01031 01032 // remember value within mem 01033 for(i=0; i< (unsigned int) maxvalues; i++) 01034 { 01035 if(memptr[i].mc == 0) 01036 { 01037 if(debug) ::printf("rlEIBnetIP::setValue(0x%x) insert new value\n",val); 01038 thread.lock(); 01039 memcpy(&memptr[i],&tel,sizeof(tel)); 01040 thread.unlock(); 01041 return 0; 01042 } 01043 //else if(memptr[i].saddr == tel.saddr && memptr[i].daddr == tel.daddr) 01044 else if(memptr[i].daddr == tel.daddr) 01045 { 01046 if(debug) ::printf("rlEIBnetIP::setValue(0x%x) update existing value\n",val); 01047 thread.lock(); 01048 memcpy(&memptr[i],&tel,sizeof(tel)); 01049 thread.unlock(); 01050 return 0; 01051 } 01052 } 01053 ::printf("ERROR rlEIBnetIP::setValue() not enough signals specified max=%d\n",maxvalues); 01054 return rlEIBnetIP::EIBERROR; 01055 } 01056 01057 int rlEIBnetIP::setServer(rlIpAdr *_server) 01058 { 01059 if(_server == NULL) return rlEIBnetIP::EIBERROR; 01060 server = _server; 01061 PDU pdu; 01062 int ret; 01063 01064 ret = rlEIBnetIP::getDescription(&pdu); 01065 if(ret > 0) 01066 { 01067 if(debug) ::printf("rlEIBnetIP::setServer() found server\n"); 01068 memcpy(&server->address,&from.address,sizeof(server->address)); 01069 return 0; 01070 } 01071 else 01072 { 01073 ::printf("rlEIBnetIP::setServer() could not find server\n"); 01074 return -1; 01075 } 01076 } 01077 01078 int rlEIBnetIP::setClient(rlIpAdr *_client) 01079 { 01080 // eib murx 01081 unsigned char murx1[8], murx2[8]; 01082 memcpy(murx1,&_client->address,sizeof(murx1)); 01083 murx2[0] = murx1[0]; // sin_len 01084 murx2[1] = murx1[1]; // sin_family 01085 murx2[6] = murx1[2]; // sin_port 01086 murx2[7] = murx1[3]; // sin_port 01087 murx2[2] = murx1[4]; // sin_addr 01088 murx2[3] = murx1[5]; // sin_addr 01089 murx2[4] = murx1[6]; // sin_addr 01090 murx2[5] = murx1[7]; // sin_addr 01091 memcpy(&client.address,murx2,sizeof(murx2)); 01092 return 0; 01093 } 01094 01095 int rlEIBnetIP::recv(void *buf, int maxlen) 01096 { 01097 int ret; 01098 while(1) 01099 { 01100 ret = rlUdpSocket::recvfrom(buf, maxlen, &from, 1000); 01101 if(ret < 0) return ret; 01102 if(*server == from) return ret; 01103 } 01104 } 01105 01106 int rlEIBnetIP::getDescription(PDU *buf) 01107 { 01108 if(server == NULL) return rlEIBnetIP::EIBERROR; 01109 if(debug) ::printf("rlEIBnetIP()::getDescription()\n"); 01110 PDU pdu; 01111 int ret; 01112 01113 pdu.headersize = EIB_HEADERSIZE; 01114 pdu.version = EIB_VERSION; 01115 pdu.servicetype = htons(DESCRIPTION_REQUEST); 01116 pdu.totalsize = htons(EIB_HEADERSIZE+EIB_ADRSIZE*2); 01117 memcpy(pdu.data,&client.address,EIB_ADRSIZE*2); 01118 01119 rlUdpSocket::sendto(&pdu, ntohs(pdu.totalsize), server); 01120 while(1) 01121 { 01122 ret = rlUdpSocket::recvfrom(buf, sizeof(pdu), &from, 1000); 01123 if(ret < 0) 01124 { 01125 if(debug) ::printf("rlEIBnetIP()::getDescription() timeout\n"); 01126 return ret; 01127 } 01128 if(ntohs(buf->servicetype) == DESCRIPTION_RESPONSE) 01129 { 01130 if(debug) ::printf("rlEIBnetIP()::getDescription() got description\n"); 01131 return ret; 01132 } 01133 } 01134 } 01135 01136 //#define TESTING 01137 #ifdef TESTING 01138 01139 int main() 01140 { 01141 int ret, val; 01142 rlEIBnetIP eib(1000); 01143 rlIpAdr client; 01144 rlIpAdr server; 01145 char line[1024]; 01146 01147 client.setAdr("nb3lehrig",rlEIBnetIP::PORT); 01148 //server.setAdr("192.168.1.30",rlEIBnetIP::PORT); 01149 server.setAdr("eibnet1",rlEIBnetIP::PORT); 01150 ret = eib.setClient(&client); 01151 if(ret < 0) return -1; 01152 ret = eib.setServer(&server); 01153 if(ret < 0) return -1; 01154 eib.debug = 1; 01155 eib.startReading(); 01156 01157 line[0] = '\0'; 01158 while(1) 01159 { 01160 scanf("%s",line); 01161 if(line[0] == 'x') break; 01162 if(line[0] == 'd') 01163 { 01164 eib.dump(stdout); 01165 } 01166 else if(line[0] == 's') 01167 { 01168 eib.setValuesFromCSV("test.csv"); 01169 } 01170 else if(line[0] == 't') 01171 { 01172 eib.setText("/0/1/000","test"); 01173 } 01174 else 01175 { 01176 sscanf(line,"%x",&val); 01177 eib.setValue("/0/1/000", val); 01178 printf("eib.value(/0/1/000)=0x%x\n",eib.value("/0/1/000")); 01179 } 01180 printf("x=exit d=dump s=set t=text value=\n"); 01181 } 01182 return 0; 01183 } 01184 01185 #endif
1.7.5.1