LTKCPP-- LLRP Toolkit C Plus Plus Library
|
00001 00002 /* 00003 ***************************************************************************** 00004 * * 00005 * IMPINJ CONFIDENTIAL AND PROPRIETARY * 00006 * * 00007 * This source code is the sole property of Impinj, Inc. Reproduction or * 00008 * utilization of this source code in whole or in part is forbidden without * 00009 * the prior written consent of Impinj, Inc. * 00010 * * 00011 * (c) Copyright Impinj, Inc. 2007,2009. All rights reserved. * 00012 * * 00013 *****************************************************************************/ 00014 00044 #include <stdio.h> 00045 #include "ltkcpp.h" 00046 #include "impinj_ltkcpp.h" 00047 #include "time.h" 00048 00049 using namespace LLRP; 00050 00051 /* 00052 ** Sorry, we use this linux safe method 00053 ** to print buffers. WIndows has the same 00054 ** method, but by a different name 00055 */ 00056 #if (WIN32) 00057 #define snprintf _snprintf 00058 #endif 00059 00060 class CMyApplication 00061 { 00062 unsigned int m_messageID; 00063 00064 public: 00066 int m_Verbose; 00067 00069 CConnection * m_pConnectionToReader; 00070 00071 inline 00072 CMyApplication (void) 00073 : m_Verbose(0), m_pConnectionToReader(NULL) 00074 { 00075 m_messageID = 0; 00076 } 00077 00078 int 00079 run ( 00080 char * pReaderHostName); 00081 00082 int 00083 checkConnectionStatus (void); 00084 00085 int 00086 enableImpinjExtensions (void); 00087 00088 int 00089 resetConfigurationToFactoryDefaults (void); 00090 00091 int 00092 addROSpec (void); 00093 00094 int 00095 enableROSpec (void); 00096 00097 int 00098 startROSpec (void); 00099 00100 int 00101 stopROSpec (void); 00102 00103 int 00104 awaitAndPrintReport (int timeoutSec); 00105 00106 void 00107 printTagReportData ( 00108 CRO_ACCESS_REPORT * pRO_ACCESS_REPORT); 00109 00110 void 00111 printOneTagReportData ( 00112 CTagReportData * pTagReportData); 00113 00114 void 00115 formatOneEPC ( 00116 CParameter * pEpcParameter, 00117 char * buf, 00118 int buflen); 00119 00120 void 00121 handleReaderEventNotification ( 00122 CReaderEventNotificationData *pNtfData); 00123 00124 void 00125 handleAntennaEvent ( 00126 CAntennaEvent * pAntennaEvent); 00127 00128 void 00129 handleReaderExceptionEvent ( 00130 CReaderExceptionEvent * pReaderExceptionEvent); 00131 00132 int 00133 checkLLRPStatus ( 00134 CLLRPStatus * pLLRPStatus, 00135 char * pWhatStr); 00136 00137 CMessage * 00138 transact ( 00139 CMessage * pSendMsg); 00140 00141 CMessage * 00142 recvMessage ( 00143 int nMaxMS); 00144 00145 int 00146 sendMessage ( 00147 CMessage * pSendMsg); 00148 00149 void 00150 printXMLMessage ( 00151 CMessage * pMessage); 00152 }; 00153 00154 00155 /* BEGIN forward declarations */ 00156 int 00157 main ( 00158 int ac, 00159 char * av[]); 00160 00161 void 00162 usage ( 00163 char * pProgName); 00164 /* END forward declarations */ 00165 00166 00182 int 00183 main ( 00184 int ac, 00185 char * av[]) 00186 { 00187 CMyApplication myApp; 00188 char * pReaderHostName; 00189 int rc; 00190 00191 /* 00192 * Process comand arguments, determine reader name 00193 * and verbosity level. 00194 */ 00195 if(ac == 2) 00196 { 00197 pReaderHostName = av[1]; 00198 } 00199 else if(ac == 3) 00200 { 00201 char * p = av[1]; 00202 00203 while(*p) 00204 { 00205 switch(*p++) 00206 { 00207 case '-': /* linux conventional option warn char */ 00208 case '/': /* Windows/DOS conventional option warn char */ 00209 break; 00210 00211 case 'v': 00212 case 'V': 00213 myApp.m_Verbose++; 00214 break; 00215 00216 default: 00217 usage(av[0]); 00218 /* no return */ 00219 break; 00220 } 00221 } 00222 00223 pReaderHostName = av[2]; 00224 } 00225 else 00226 { 00227 usage(av[0]); 00228 /* no return */ 00229 } 00230 00231 /* 00232 * Run application, capture return value for exit status 00233 */ 00234 rc = myApp.run(pReaderHostName); 00235 00236 printf("INFO: Done\n"); 00237 00238 /* 00239 * Exit with the right status. 00240 */ 00241 if(0 == rc) 00242 { 00243 exit(0); 00244 } 00245 else 00246 { 00247 exit(2); 00248 } 00249 /*NOTREACHED*/ 00250 } 00251 00252 00264 void 00265 usage ( 00266 char * pProgName) 00267 { 00268 #ifdef linux 00269 printf("Usage: %s [-v[v]] READERHOSTNAME\n", pProgName); 00270 printf("\n"); 00271 printf("Each -v increases verbosity level\n"); 00272 #endif /* linux */ 00273 #ifdef WIN32 00274 printf("Usage: %s [/v[v]] READERHOSTNAME\n", pProgName); 00275 printf("\n"); 00276 printf("Each /v increases verbosity level\n"); 00277 #endif /* WIN32 */ 00278 exit(1); 00279 } 00280 00281 00315 int 00316 CMyApplication::run ( 00317 char * pReaderHostName) 00318 { 00319 CTypeRegistry * pTypeRegistry; 00320 CConnection * pConn; 00321 int rc; 00322 00323 /* 00324 * Allocate the type registry. This is needed 00325 * by the connection to decode. 00326 */ 00327 pTypeRegistry = getTheTypeRegistry(); 00328 if(NULL == pTypeRegistry) 00329 { 00330 printf("ERROR: getTheTypeRegistry failed\n"); 00331 return -1; 00332 } 00333 00334 /* 00335 * Enroll impinj extension types into the 00336 * type registry, in preparation for using 00337 * Impinj extension params. 00338 */ 00339 LLRP::enrollImpinjTypesIntoRegistry(pTypeRegistry); 00340 00341 /* 00342 * Construct a connection (LLRP::CConnection). 00343 * Using a 32kb max frame size for send/recv. 00344 * The connection object is ready for business 00345 * but not actually connected to the reader yet. 00346 */ 00347 pConn = new CConnection(pTypeRegistry, 32u*1024u); 00348 if(NULL == pConn) 00349 { 00350 printf("ERROR: new CConnection failed\n"); 00351 return -2; 00352 } 00353 00354 /* 00355 * Open the connection to the reader 00356 */ 00357 if(m_Verbose) 00358 { 00359 printf("INFO: Connecting to %s....\n", pReaderHostName); 00360 } 00361 00362 rc = pConn->openConnectionToReader(pReaderHostName); 00363 if(0 != rc) 00364 { 00365 printf("ERROR: connect: %s (%d)\n", pConn->getConnectError(), rc); 00366 delete pConn; 00367 return -3; 00368 } 00369 00370 /* 00371 * Record the pointer to the connection object so other 00372 * routines can use it. 00373 */ 00374 m_pConnectionToReader = pConn; 00375 00376 if(m_Verbose) 00377 { 00378 printf("INFO: Connected, checking status....\n"); 00379 } 00380 00381 /* 00382 * Commence the sequence and check for errors as we go. 00383 * See comments for each routine for details. 00384 * Each routine prints messages. 00385 */ 00386 rc = 1; 00387 if(0 == checkConnectionStatus()) 00388 { 00389 rc = 2; 00390 if(0 == enableImpinjExtensions()) 00391 { 00392 rc = 3; 00393 if(0 == resetConfigurationToFactoryDefaults()) 00394 { 00395 rc = 4; 00396 if(0 == addROSpec()) 00397 { 00398 rc = 5; 00399 if(0 == enableROSpec()) 00400 { 00401 //rc = 6; 00402 //if(0 == startROSpec()) 00403 //{ 00404 rc = 7; 00405 if(0 == awaitAndPrintReport(10)) 00406 { 00407 rc = 8; 00408 if(0 == stopROSpec()) 00409 { 00410 rc = 0; 00411 } 00412 } 00413 //} 00414 } 00415 } 00416 } 00417 00418 /* 00419 * After we're done, try to leave the reader 00420 * in a clean state for next use. This is best 00421 * effort and no checking of the result is done. 00422 */ 00423 if(m_Verbose) 00424 { 00425 printf("INFO: Clean up reader configuration...\n"); 00426 } 00427 resetConfigurationToFactoryDefaults(); 00428 } 00429 } 00430 00431 if(m_Verbose) 00432 { 00433 printf("INFO: Finished\n"); 00434 } 00435 00436 /* 00437 * Close the connection and release its resources 00438 */ 00439 pConn->closeConnectionToReader(); 00440 delete pConn; 00441 00442 /* 00443 * Done with the registry. 00444 */ 00445 delete pTypeRegistry; 00446 00447 /* 00448 * When we get here all allocated memory should have been deallocated. 00449 */ 00450 00451 return rc; 00452 } 00453 00454 00485 int 00486 CMyApplication::checkConnectionStatus (void) 00487 { 00488 CMessage * pMessage; 00489 CREADER_EVENT_NOTIFICATION *pNtf; 00490 CReaderEventNotificationData *pNtfData; 00491 CConnectionAttemptEvent * pEvent; 00492 00493 /* 00494 * Expect the notification within 10 seconds. 00495 * It is suppose to be the very first message sent. 00496 */ 00497 pMessage = recvMessage(10000); 00498 00499 /* 00500 * recvMessage() returns NULL if something went wrong. 00501 */ 00502 if(NULL == pMessage) 00503 { 00504 /* recvMessage already tattled */ 00505 goto fail; 00506 } 00507 00508 /* 00509 * Check to make sure the message is of the right type. 00510 * The type label (pointer) in the message should be 00511 * the type descriptor for READER_EVENT_NOTIFICATION. 00512 */ 00513 if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor != pMessage->m_pType) 00514 { 00515 goto fail; 00516 } 00517 00518 /* 00519 * Now that we are sure it is a READER_EVENT_NOTIFICATION, 00520 * traverse to the ReaderEventNotificationData parameter. 00521 */ 00522 pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage; 00523 pNtfData = pNtf->getReaderEventNotificationData(); 00524 if(NULL == pNtfData) 00525 { 00526 goto fail; 00527 } 00528 00529 /* 00530 * The ConnectionAttemptEvent parameter must be present. 00531 */ 00532 pEvent = pNtfData->getConnectionAttemptEvent(); 00533 if(NULL == pEvent) 00534 { 00535 goto fail; 00536 } 00537 00538 /* 00539 * The status in the ConnectionAttemptEvent parameter 00540 * must indicate connection success. 00541 */ 00542 if(ConnectionAttemptStatusType_Success != pEvent->getStatus()) 00543 { 00544 goto fail; 00545 } 00546 00547 /* 00548 * Done with the message 00549 */ 00550 delete pMessage; 00551 00552 if(m_Verbose) 00553 { 00554 printf("INFO: Connection status OK\n"); 00555 } 00556 00557 /* 00558 * Victory. 00559 */ 00560 return 0; 00561 00562 fail: 00563 /* 00564 * Something went wrong. Tattle. Clean up. Return error. 00565 */ 00566 printf("ERROR: checkConnectionStatus failed\n"); 00567 delete pMessage; 00568 return -1; 00569 } 00570 00588 int 00589 CMyApplication::enableImpinjExtensions (void) 00590 { 00591 CIMPINJ_ENABLE_EXTENSIONS * pCmd; 00592 CMessage * pRspMsg; 00593 CIMPINJ_ENABLE_EXTENSIONS_RESPONSE *pRsp; 00594 00595 /* 00596 * Compose the command message 00597 */ 00598 pCmd = new CIMPINJ_ENABLE_EXTENSIONS(); 00599 pCmd->setMessageID(m_messageID++); 00600 /* 00601 * Send the message, expect the response of certain type 00602 */ 00603 pRspMsg = transact(pCmd); 00604 00605 /* 00606 * Done with the command message 00607 */ 00608 delete pCmd; 00609 00610 /* 00611 * transact() returns NULL if something went wrong. 00612 */ 00613 if(NULL == pRspMsg) 00614 { 00615 /* transact already tattled */ 00616 return -1; 00617 } 00618 00619 /* 00620 * Cast to a CIMPINJ_ENABLE_EXTENSIONS_RESPONSE message. 00621 */ 00622 pRsp = (CIMPINJ_ENABLE_EXTENSIONS_RESPONSE *) pRspMsg; 00623 00624 /* 00625 * Check the LLRPStatus parameter. 00626 */ 00627 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), 00628 "enableImpinjExtensions")) 00629 { 00630 /* checkLLRPStatus already tattled */ 00631 delete pRspMsg; 00632 return -1; 00633 } 00634 00635 /* 00636 * Done with the response message. 00637 */ 00638 delete pRspMsg; 00639 00640 /* 00641 * Tattle progress, maybe 00642 */ 00643 if(m_Verbose) 00644 { 00645 printf("INFO: Impinj Extensions are enabled\n"); 00646 } 00647 00648 /* 00649 * Victory. 00650 */ 00651 return 0; 00652 } 00653 00674 int 00675 CMyApplication::resetConfigurationToFactoryDefaults (void) 00676 { 00677 CSET_READER_CONFIG * pCmd; 00678 CMessage * pRspMsg; 00679 CSET_READER_CONFIG_RESPONSE *pRsp; 00680 00681 /* 00682 * Compose the command message 00683 */ 00684 pCmd = new CSET_READER_CONFIG(); 00685 pCmd->setMessageID(m_messageID++); 00686 pCmd->setResetToFactoryDefault(1); 00687 00688 /* 00689 * Send the message, expect the response of certain type 00690 */ 00691 pRspMsg = transact(pCmd); 00692 00693 /* 00694 * Done with the command message 00695 */ 00696 delete pCmd; 00697 00698 /* 00699 * transact() returns NULL if something went wrong. 00700 */ 00701 if(NULL == pRspMsg) 00702 { 00703 /* transact already tattled */ 00704 return -1; 00705 } 00706 00707 /* 00708 * Cast to a SET_READER_CONFIG_RESPONSE message. 00709 */ 00710 pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg; 00711 00712 /* 00713 * Check the LLRPStatus parameter. 00714 */ 00715 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), 00716 "resetConfigurationToFactoryDefaults")) 00717 { 00718 /* checkLLRPStatus already tattled */ 00719 delete pRspMsg; 00720 return -1; 00721 } 00722 00723 /* 00724 * Done with the response message. 00725 */ 00726 delete pRspMsg; 00727 00728 /* 00729 * Tattle progress, maybe 00730 */ 00731 if(m_Verbose) 00732 { 00733 printf("INFO: Configuration reset to factory defaults\n"); 00734 } 00735 00736 /* 00737 * Victory. 00738 */ 00739 return 0; 00740 } 00741 00742 00790 int 00791 CMyApplication::addROSpec (void) 00792 { 00793 CROSpecStartTrigger * pROSpecStartTrigger = 00794 new CROSpecStartTrigger(); 00795 pROSpecStartTrigger->setROSpecStartTriggerType( 00796 ROSpecStartTriggerType_Immediate); 00797 00798 CROSpecStopTrigger * pROSpecStopTrigger = new CROSpecStopTrigger(); 00799 pROSpecStopTrigger->setROSpecStopTriggerType(ROSpecStopTriggerType_Null); 00800 pROSpecStopTrigger->setDurationTriggerValue(0); /* n/a */ 00801 00802 CROBoundarySpec * pROBoundarySpec = new CROBoundarySpec(); 00803 pROBoundarySpec->setROSpecStartTrigger(pROSpecStartTrigger); 00804 pROBoundarySpec->setROSpecStopTrigger(pROSpecStopTrigger); 00805 00806 CAISpecStopTrigger * pAISpecStopTrigger = new CAISpecStopTrigger(); 00807 pAISpecStopTrigger->setAISpecStopTriggerType( 00808 AISpecStopTriggerType_Tag_Observation); 00809 pAISpecStopTrigger->setDurationTrigger(0); 00810 00811 CTagObservationTrigger * pAISpecTagObsvTrigger = new CTagObservationTrigger(); 00812 pAISpecTagObsvTrigger->setTriggerType(TagObservationTriggerType_Upon_Seeing_N_Tags_Or_Timeout); 00813 pAISpecTagObsvTrigger->setNumberOfTags(100); 00814 pAISpecTagObsvTrigger->setNumberOfAttempts(0); 00815 pAISpecTagObsvTrigger->setT(0); 00816 pAISpecTagObsvTrigger->setTimeout(500); 00817 00818 pAISpecStopTrigger->setTagObservationTrigger(pAISpecTagObsvTrigger); 00819 00820 00822 00823 00824 CInventoryParameterSpec * pInventoryParameterSpec = 00825 new CInventoryParameterSpec(); 00826 pInventoryParameterSpec->setInventoryParameterSpecID(1234); 00827 pInventoryParameterSpec->setProtocolID(AirProtocols_EPCGlobalClass1Gen2); 00828 00829 CAntennaConfiguration * pAntennaConfig = new CAntennaConfiguration(); 00830 pAntennaConfig->setAntennaID(1); 00831 00832 CRFTransmitter * pRFTransmitter = new CRFTransmitter(); 00833 pRFTransmitter->setHopTableID(1); 00834 pRFTransmitter->setChannelIndex(0); 00835 pRFTransmitter->setTransmitPower(81); 00836 pAntennaConfig->setRFTransmitter(pRFTransmitter); 00837 00838 CC1G2InventoryCommand * pC1G2InventoryCmd = new CC1G2InventoryCommand(); 00839 pC1G2InventoryCmd->setTagInventoryStateAware(1); 00840 00841 // Filter 1 00842 CC1G2Filter * pC1G2Filter1 = new CC1G2Filter(); 00843 pC1G2Filter1->setT(C1G2TruncateAction_Do_Not_Truncate); 00844 00845 CC1G2TagInventoryMask * pC1G2TagInvMask1 = new CC1G2TagInventoryMask(); 00846 pC1G2TagInvMask1->setMB(2); 00847 pC1G2TagInvMask1->setPointer(0); 00848 00849 llrp_u1v_t tagMask1 = llrp_u1v_t(15); 00850 tagMask1.m_nBit = 15; 00851 tagMask1.m_pValue[0] = 0xE2; 00852 tagMask1.m_pValue[1] = 0x00; 00853 pC1G2TagInvMask1->setTagMask(tagMask1); 00854 00855 pC1G2Filter1->setC1G2TagInventoryMask(pC1G2TagInvMask1); 00856 00857 CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction1 = new CC1G2TagInventoryStateAwareFilterAction(); 00858 pC1G2TagInvStateAwareFilterAction1->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S3); 00859 pC1G2TagInvStateAwareFilterAction1->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB); 00860 00861 pC1G2Filter1->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction1); 00862 00863 pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter1); 00864 00865 // Filter 2 00866 CC1G2Filter * pC1G2Filter2 = new CC1G2Filter(); 00867 pC1G2Filter2->setT(C1G2TruncateAction_Do_Not_Truncate); 00868 00869 CC1G2TagInventoryMask * pC1G2TagInvMask2 = new CC1G2TagInventoryMask(); 00870 pC1G2TagInvMask2->setMB(1); 00871 pC1G2TagInvMask2->setPointer(0); 00872 00873 llrp_u1v_t tagMask2 = llrp_u1v_t(16); 00874 tagMask2.m_nBit = 16; 00875 tagMask2.m_pValue[0] = 0xE2; 00876 tagMask2.m_pValue[1] = 0x00; 00877 pC1G2TagInvMask2->setTagMask(tagMask2); 00878 00879 pC1G2Filter2->setC1G2TagInventoryMask(pC1G2TagInvMask2); 00880 00881 CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction2 = new CC1G2TagInventoryStateAwareFilterAction(); 00882 pC1G2TagInvStateAwareFilterAction2->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S2); 00883 pC1G2TagInvStateAwareFilterAction2->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB); 00884 00885 pC1G2Filter2->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction2); 00886 00887 pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter2); 00888 00889 // Filter 3 00890 CC1G2Filter * pC1G2Filter3 = new CC1G2Filter(); 00891 pC1G2Filter3->setT(C1G2TruncateAction_Do_Not_Truncate); 00892 00893 CC1G2TagInventoryMask * pC1G2TagInvMask3 = new CC1G2TagInventoryMask(); 00894 pC1G2TagInvMask3->setMB(3); 00895 pC1G2TagInvMask3->setPointer(0); 00896 00897 llrp_u1v_t tagMask3 = llrp_u1v_t(32); 00898 tagMask3.m_nBit = 32; 00899 tagMask3.m_pValue[0] = 0xFF; 00900 tagMask3.m_pValue[1] = 0xFF; 00901 tagMask3.m_pValue[2] = 0xE2; 00902 tagMask3.m_pValue[3] = 0x00; 00903 pC1G2TagInvMask3->setTagMask(tagMask3); 00904 00905 pC1G2Filter3->setC1G2TagInventoryMask(pC1G2TagInvMask3); 00906 00907 CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction3 = new CC1G2TagInventoryStateAwareFilterAction(); 00908 pC1G2TagInvStateAwareFilterAction3->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S1); 00909 pC1G2TagInvStateAwareFilterAction3->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB); 00910 00911 pC1G2Filter3->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction3); 00912 00913 pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter3); 00914 00915 // Filter 4 00916 CC1G2Filter * pC1G2Filter4 = new CC1G2Filter(); 00917 pC1G2Filter4->setT(C1G2TruncateAction_Do_Not_Truncate); 00918 00919 CC1G2TagInventoryMask * pC1G2TagInvMask4 = new CC1G2TagInventoryMask(); 00920 pC1G2TagInvMask4->setMB(2); 00921 pC1G2TagInvMask4->setPointer(0); 00922 00923 llrp_u1v_t tagMask4 = llrp_u1v_t(8); 00924 tagMask4.m_nBit = 8; 00925 tagMask4.m_pValue[0] = 0xAA; 00926 pC1G2TagInvMask4->setTagMask(tagMask4); 00927 00928 pC1G2Filter4->setC1G2TagInventoryMask(pC1G2TagInvMask4); 00929 00930 CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction4 = new CC1G2TagInventoryStateAwareFilterAction(); 00931 pC1G2TagInvStateAwareFilterAction4->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S0); 00932 pC1G2TagInvStateAwareFilterAction4->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB); 00933 00934 pC1G2Filter4->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction4); 00935 00936 pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter4); 00937 00938 // Filter 5 00939 CC1G2Filter * pC1G2Filter5 = new CC1G2Filter(); 00940 pC1G2Filter5->setT(C1G2TruncateAction_Do_Not_Truncate); 00941 00942 CC1G2TagInventoryMask * pC1G2TagInvMask5 = new CC1G2TagInventoryMask(); 00943 pC1G2TagInvMask5->setMB(1); 00944 pC1G2TagInvMask5->setPointer(0); 00945 00946 llrp_u1v_t tagMask5 = llrp_u1v_t(16); 00947 tagMask5.m_nBit = 16; 00948 tagMask5.m_pValue[0] = 0xFF; 00949 tagMask5.m_pValue[1] = 0xFF; 00950 pC1G2TagInvMask5->setTagMask(tagMask5); 00951 00952 pC1G2Filter5->setC1G2TagInventoryMask(pC1G2TagInvMask5); 00953 00954 CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction5 = new CC1G2TagInventoryStateAwareFilterAction(); 00955 pC1G2TagInvStateAwareFilterAction5->setTarget(C1G2StateAwareTarget_SL); 00956 pC1G2TagInvStateAwareFilterAction5->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB); 00957 00958 pC1G2Filter5->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction5); 00959 00960 pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter5); 00961 00962 // 00963 00964 00965 CC1G2SingulationControl * pC1G2SingulationControl = new CC1G2SingulationControl(); 00966 pC1G2SingulationControl->setSession(1); 00967 pC1G2SingulationControl->setTagPopulation(32); 00968 pC1G2SingulationControl->setTagTransitTime(0); 00969 00970 CC1G2TagInventoryStateAwareSingulationAction * pC1G2TagInvStateAwareSingAction = new CC1G2TagInventoryStateAwareSingulationAction(); 00971 pC1G2TagInvStateAwareSingAction->setI(C1G2TagInventoryStateAwareI_State_B); 00972 pC1G2TagInvStateAwareSingAction->setS(C1G2TagInventoryStateAwareS_SL); 00973 00974 pC1G2SingulationControl->setC1G2TagInventoryStateAwareSingulationAction(pC1G2TagInvStateAwareSingAction); 00975 00976 pC1G2InventoryCmd->setC1G2SingulationControl(pC1G2SingulationControl); 00977 00978 pAntennaConfig->addAirProtocolInventoryCommandSettings(pC1G2InventoryCmd); 00979 00980 pInventoryParameterSpec->addAntennaConfiguration(pAntennaConfig); 00981 00983 llrp_u16v_t AntennaIDs = llrp_u16v_t(1); 00984 AntennaIDs.m_pValue[0] = 1; 00985 00986 CAISpec * pAISpec = new CAISpec(); 00987 pAISpec->setAntennaIDs(AntennaIDs); 00988 pAISpec->setAISpecStopTrigger(pAISpecStopTrigger); 00989 pAISpec->addInventoryParameterSpec(pInventoryParameterSpec); 00990 00991 00993 CROReportSpec * pROReportSpec = new CROReportSpec(); 00994 pROReportSpec->setROReportTrigger(ROReportTriggerType_Upon_N_Tags_Or_End_Of_AISpec); 00995 pROReportSpec->setN(1000); 00996 00997 CTagReportContentSelector * pTagRptContentSelector = new CTagReportContentSelector(); 00998 pTagRptContentSelector->setEnableROSpecID(1); 00999 pTagRptContentSelector->setEnableSpecIndex(1); 01000 pTagRptContentSelector->setEnableInventoryParameterSpecID(1); 01001 pTagRptContentSelector->setEnableAntennaID(1); 01002 pTagRptContentSelector->setEnableChannelIndex(1); 01003 pTagRptContentSelector->setEnablePeakRSSI(1); 01004 pTagRptContentSelector->setEnableFirstSeenTimestamp(1); 01005 pTagRptContentSelector->setEnableLastSeenTimestamp(1); 01006 pTagRptContentSelector->setEnableTagSeenCount(1); 01007 pTagRptContentSelector->setEnableAccessSpecID(1); 01008 01009 pROReportSpec->setTagReportContentSelector(pTagRptContentSelector); 01011 01012 01013 CROSpec * pROSpec = new CROSpec(); 01014 pROSpec->setROSpecID(1); 01015 pROSpec->setPriority(0); 01016 pROSpec->setCurrentState(ROSpecState_Disabled); 01017 pROSpec->setROBoundarySpec(pROBoundarySpec); 01018 pROSpec->addSpecParameter(pAISpec); 01019 pROSpec->setROReportSpec(pROReportSpec); 01020 01021 CADD_ROSPEC * pCmd; 01022 CMessage * pRspMsg; 01023 CADD_ROSPEC_RESPONSE * pRsp; 01024 01025 /* 01026 * Compose the command message. 01027 * N.B.: After the message is composed, all the parameters 01028 * constructed, immediately above, are considered "owned" 01029 * by the command message. When it is destructed so 01030 * too will the parameters be. 01031 */ 01032 pCmd = new CADD_ROSPEC(); 01033 pCmd->setMessageID(m_messageID++); 01034 pCmd->setROSpec(pROSpec); 01035 01036 /* 01037 * Send the message, expect the response of certain type 01038 */ 01039 pRspMsg = transact(pCmd); 01040 01041 /* 01042 * Done with the command message. 01043 * N.B.: And the parameters 01044 */ 01045 delete pCmd; 01046 01047 /* 01048 * transact() returns NULL if something went wrong. 01049 */ 01050 if(NULL == pRspMsg) 01051 { 01052 /* transact already tattled */ 01053 return -1; 01054 } 01055 01056 /* 01057 * Cast to a ADD_ROSPEC_RESPONSE message. 01058 */ 01059 pRsp = (CADD_ROSPEC_RESPONSE *) pRspMsg; 01060 01061 /* 01062 * Check the LLRPStatus parameter. 01063 */ 01064 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "addROSpec")) 01065 { 01066 /* checkLLRPStatus already tattled */ 01067 delete pRspMsg; 01068 return -1; 01069 } 01070 01071 /* 01072 * Done with the response message. 01073 */ 01074 delete pRspMsg; 01075 01076 /* 01077 * Tattle progress, maybe 01078 */ 01079 if(m_Verbose) 01080 { 01081 printf("INFO: ROSpec added\n"); 01082 } 01083 01084 /* 01085 * Victory. 01086 */ 01087 return 0; 01088 } 01089 01090 01108 int 01109 CMyApplication::enableROSpec (void) 01110 { 01111 CENABLE_ROSPEC * pCmd; 01112 CMessage * pRspMsg; 01113 CENABLE_ROSPEC_RESPONSE * pRsp; 01114 01115 /* 01116 * Compose the command message 01117 */ 01118 pCmd = new CENABLE_ROSPEC(); 01119 pCmd->setMessageID(m_messageID++); 01120 pCmd->setROSpecID(1); 01121 01122 /* 01123 * Send the message, expect the response of certain type 01124 */ 01125 pRspMsg = transact(pCmd); 01126 01127 /* 01128 * Done with the command message 01129 */ 01130 delete pCmd; 01131 01132 /* 01133 * transact() returns NULL if something went wrong. 01134 */ 01135 if(NULL == pRspMsg) 01136 { 01137 /* transact already tattled */ 01138 return -1; 01139 } 01140 01141 /* 01142 * Cast to a ENABLE_ROSPEC_RESPONSE message. 01143 */ 01144 pRsp = (CENABLE_ROSPEC_RESPONSE *) pRspMsg; 01145 01146 /* 01147 * Check the LLRPStatus parameter. 01148 */ 01149 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "enableROSpec")) 01150 { 01151 /* checkLLRPStatus already tattled */ 01152 delete pRspMsg; 01153 return -1; 01154 } 01155 01156 /* 01157 * Done with the response message. 01158 */ 01159 delete pRspMsg; 01160 01161 /* 01162 * Tattle progress, maybe 01163 */ 01164 if(m_Verbose) 01165 { 01166 printf("INFO: ROSpec enabled\n"); 01167 } 01168 01169 /* 01170 * Victory. 01171 */ 01172 return 0; 01173 } 01174 01175 01193 int 01194 CMyApplication::startROSpec (void) 01195 { 01196 CSTART_ROSPEC * pCmd; 01197 CMessage * pRspMsg; 01198 CSTART_ROSPEC_RESPONSE * pRsp; 01199 01200 /* 01201 * Compose the command message 01202 */ 01203 pCmd = new CSTART_ROSPEC(); 01204 pCmd->setMessageID(m_messageID++); 01205 pCmd->setROSpecID(1); 01206 01207 /* 01208 * Send the message, expect the response of certain type 01209 */ 01210 pRspMsg = transact(pCmd); 01211 01212 /* 01213 * Done with the command message 01214 */ 01215 delete pCmd; 01216 01217 /* 01218 * transact() returns NULL if something went wrong. 01219 */ 01220 if(NULL == pRspMsg) 01221 { 01222 /* transact already tattled */ 01223 return -1; 01224 } 01225 01226 /* 01227 * Cast to a START_ROSPEC_RESPONSE message. 01228 */ 01229 pRsp = (CSTART_ROSPEC_RESPONSE *) pRspMsg; 01230 01231 /* 01232 * Check the LLRPStatus parameter. 01233 */ 01234 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "startROSpec")) 01235 { 01236 /* checkLLRPStatus already tattled */ 01237 delete pRspMsg; 01238 return -1; 01239 } 01240 01241 /* 01242 * Done with the response message. 01243 */ 01244 delete pRspMsg; 01245 01246 /* 01247 * Tattle progress 01248 */ 01249 if(m_Verbose) 01250 { 01251 printf("INFO: ROSpec started\n"); 01252 } 01253 01254 /* 01255 * Victory. 01256 */ 01257 return 0; 01258 } 01259 01277 int 01278 CMyApplication::stopROSpec (void) 01279 { 01280 CSTOP_ROSPEC * pCmd; 01281 CMessage * pRspMsg; 01282 CSTOP_ROSPEC_RESPONSE * pRsp; 01283 01284 /* 01285 * Compose the command message 01286 */ 01287 pCmd = new CSTOP_ROSPEC(); 01288 pCmd->setMessageID(m_messageID++); 01289 pCmd->setROSpecID(1); 01290 01291 /* 01292 * Send the message, expect the response of certain type 01293 */ 01294 pRspMsg = transact(pCmd); 01295 01296 /* 01297 * Done with the command message 01298 */ 01299 delete pCmd; 01300 01301 /* 01302 * transact() returns NULL if something went wrong. 01303 */ 01304 if(NULL == pRspMsg) 01305 { 01306 /* transact already tattled */ 01307 return -1; 01308 } 01309 01310 /* 01311 * Cast to a STOP_ROSPEC_RESPONSE message. 01312 */ 01313 pRsp = (CSTOP_ROSPEC_RESPONSE *) pRspMsg; 01314 01315 /* 01316 * Check the LLRPStatus parameter. 01317 */ 01318 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "stopROSpec")) 01319 { 01320 /* checkLLRPStatus already tattled */ 01321 delete pRspMsg; 01322 return -1; 01323 } 01324 01325 /* 01326 * Done with the response message. 01327 */ 01328 delete pRspMsg; 01329 01330 /* 01331 * Tattle progress 01332 */ 01333 if(m_Verbose) 01334 { 01335 printf("INFO: ROSpec stopped\n"); 01336 } 01337 01338 /* 01339 * Victory. 01340 */ 01341 return 0; 01342 } 01343 01344 01364 int 01365 CMyApplication::awaitAndPrintReport (int timeout) 01366 { 01367 int bDone = 0; 01368 int retVal = 0; 01369 time_t startTime = time(NULL); 01370 time_t tempTime; 01371 /* 01372 * Keep receiving messages until done or until 01373 * something bad happens. 01374 */ 01375 while(!bDone) 01376 { 01377 CMessage * pMessage; 01378 const CTypeDescriptor * pType; 01379 01380 /* 01381 * Wait up to 1 second for a report. Check 01382 * That way, we can check the timestamp even if 01383 * there are no reports coming in 01384 */ 01385 pMessage = recvMessage(1000); 01386 01387 /* validate the timestamp */ 01388 tempTime = time(NULL); 01389 if(difftime(tempTime, startTime) > timeout) 01390 { 01391 bDone=1; 01392 } 01393 01394 if(NULL == pMessage) 01395 { 01396 continue; 01397 } 01398 01399 /* 01400 * What happens depends on what kind of message 01401 * received. Use the type label (m_pType) to 01402 * discriminate message types. 01403 */ 01404 pType = pMessage->m_pType; 01405 01406 /* 01407 * Is it a tag report? If so, print it out. 01408 */ 01409 if(&CRO_ACCESS_REPORT::s_typeDescriptor == pType) 01410 { 01411 CRO_ACCESS_REPORT * pNtf; 01412 01413 pNtf = (CRO_ACCESS_REPORT *) pMessage; 01414 01415 printTagReportData(pNtf); 01416 } 01417 01418 /* 01419 * Is it a reader event? This example only recognizes 01420 * AntennaEvents. 01421 */ 01422 else if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor == pType) 01423 { 01424 CREADER_EVENT_NOTIFICATION *pNtf; 01425 CReaderEventNotificationData *pNtfData; 01426 01427 pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage; 01428 01429 pNtfData = pNtf->getReaderEventNotificationData(); 01430 if(NULL != pNtfData) 01431 { 01432 handleReaderEventNotification(pNtfData); 01433 } 01434 else 01435 { 01436 /* 01437 * This should never happen. Using continue 01438 * to keep indent depth down. 01439 */ 01440 printf("WARNING: READER_EVENT_NOTIFICATION without data\n"); 01441 } 01442 } 01443 01444 /* 01445 * Hmmm. Something unexpected. Just tattle and keep going. 01446 */ 01447 else 01448 { 01449 printf("WARNING: Ignored unexpected message during monitor: %s\n", 01450 pType->m_pName); 01451 } 01452 01453 /* 01454 * Done with the received message 01455 */ 01456 delete pMessage; 01457 } 01458 01459 return retVal; 01460 } 01461 01462 01477 void 01478 CMyApplication::printTagReportData ( 01479 CRO_ACCESS_REPORT * pRO_ACCESS_REPORT) 01480 { 01481 std::list<CTagReportData *>::iterator Cur; 01482 01483 unsigned int nEntry = 0; 01484 01485 /* 01486 * Loop through and count the number of entries 01487 */ 01488 for( 01489 Cur = pRO_ACCESS_REPORT->beginTagReportData(); 01490 Cur != pRO_ACCESS_REPORT->endTagReportData(); 01491 Cur++) 01492 { 01493 nEntry++; 01494 } 01495 01496 if(m_Verbose) 01497 { 01498 printf("INFO: %u tag report entries\n", nEntry); 01499 } 01500 01501 /* 01502 * Loop through again and print each entry. 01503 */ 01504 for( 01505 Cur = pRO_ACCESS_REPORT->beginTagReportData(); 01506 Cur != pRO_ACCESS_REPORT->endTagReportData(); 01507 Cur++) 01508 { 01509 printOneTagReportData(*Cur); 01510 } 01511 } 01512 01513 01522 void 01523 CMyApplication::formatOneEPC ( 01524 CParameter *pEPCParameter, 01525 char *buf, 01526 int buflen) 01527 { 01528 char * p = buf; 01529 int bufsize = buflen; 01530 int written = 0; 01531 01532 if(NULL != pEPCParameter) 01533 { 01534 const CTypeDescriptor * pType; 01535 llrp_u96_t my_u96; 01536 llrp_u1v_t my_u1v; 01537 llrp_u8_t * pValue = NULL; 01538 unsigned int n, i; 01539 01540 pType = pEPCParameter->m_pType; 01541 if(&CEPC_96::s_typeDescriptor == pType) 01542 { 01543 CEPC_96 *pEPC_96; 01544 01545 pEPC_96 = (CEPC_96 *) pEPCParameter; 01546 my_u96 = pEPC_96->getEPC(); 01547 pValue = my_u96.m_aValue; 01548 n = 12u; 01549 } 01550 else if(&CEPCData::s_typeDescriptor == pType) 01551 { 01552 CEPCData * pEPCData; 01553 01554 pEPCData = (CEPCData *) pEPCParameter; 01555 my_u1v = pEPCData->getEPC(); 01556 pValue = my_u1v.m_pValue; 01557 n = (my_u1v.m_nBit + 7u) / 8u; 01558 } 01559 01560 if(NULL != pValue) 01561 { 01562 for(i = 0; i < n; i++) 01563 { 01564 if(0 < i && i%2 == 0 && 1 < bufsize) 01565 { 01566 *p++ = '-'; 01567 bufsize--; 01568 } 01569 if(bufsize > 2) 01570 { 01571 written = snprintf(p, bufsize, "%02X", pValue[i]); 01572 bufsize -= written; 01573 p+= written; 01574 } 01575 } 01576 } 01577 else 01578 { 01579 written = snprintf(p, bufsize, "%s", "---unknown-epc-data-type---"); 01580 bufsize -= written; 01581 p += written; 01582 } 01583 } 01584 else 01585 { 01586 written = snprintf(p, bufsize, "%s", "--null epc---"); 01587 bufsize -= written; 01588 p += written; 01589 } 01590 01591 // null terminate this for good practice 01592 buf[buflen-1] = '\0'; 01593 01594 } 01595 01604 void 01605 CMyApplication::printOneTagReportData ( 01606 CTagReportData * pTagReportData) 01607 { 01608 char aBuf[64]; 01609 01610 /* 01611 * Print the EPC. It could be an 96-bit EPC_96 parameter 01612 * or an variable length EPCData parameter. 01613 */ 01614 01615 CParameter * pEPCParameter = 01616 pTagReportData->getEPCParameter(); 01617 01618 formatOneEPC(pEPCParameter, aBuf, 64); 01619 01620 /* 01621 * End of line 01622 */ 01623 printf("EPC: %s\n", aBuf); 01624 } 01625 01626 01640 void 01641 CMyApplication::handleReaderEventNotification ( 01642 CReaderEventNotificationData *pNtfData) 01643 { 01644 CAntennaEvent * pAntennaEvent; 01645 CReaderExceptionEvent * pReaderExceptionEvent; 01646 int nReported = 0; 01647 01648 pAntennaEvent = pNtfData->getAntennaEvent(); 01649 if(NULL != pAntennaEvent) 01650 { 01651 handleAntennaEvent(pAntennaEvent); 01652 nReported++; 01653 } 01654 01655 pReaderExceptionEvent = pNtfData->getReaderExceptionEvent(); 01656 if(NULL != pReaderExceptionEvent) 01657 { 01658 handleReaderExceptionEvent(pReaderExceptionEvent); 01659 nReported++; 01660 } 01661 01662 /* 01663 * Similarly handle other events here: 01664 * HoppingEvent 01665 * GPIEvent 01666 * ROSpecEvent 01667 * ReportBufferLevelWarningEvent 01668 * ReportBufferOverflowErrorEvent 01669 * RFSurveyEvent 01670 * AISpecEvent 01671 * ConnectionAttemptEvent 01672 * ConnectionCloseEvent 01673 * Custom 01674 */ 01675 01676 if(0 == nReported) 01677 { 01678 printf("NOTICE: Unexpected (unhandled) ReaderEvent\n"); 01679 } 01680 } 01681 01682 01694 void 01695 CMyApplication::handleAntennaEvent ( 01696 CAntennaEvent * pAntennaEvent) 01697 { 01698 EAntennaEventType eEventType; 01699 llrp_u16_t AntennaID; 01700 char * pStateStr; 01701 01702 eEventType = pAntennaEvent->getEventType(); 01703 AntennaID = pAntennaEvent->getAntennaID(); 01704 01705 switch(eEventType) 01706 { 01707 case AntennaEventType_Antenna_Disconnected: 01708 pStateStr = "disconnected"; 01709 break; 01710 01711 case AntennaEventType_Antenna_Connected: 01712 pStateStr = "connected"; 01713 break; 01714 01715 default: 01716 pStateStr = "?unknown-event?"; 01717 break; 01718 } 01719 01720 printf("NOTICE: Antenna %d is %s\n", AntennaID, pStateStr); 01721 } 01722 01723 01736 void 01737 CMyApplication::handleReaderExceptionEvent ( 01738 CReaderExceptionEvent * pReaderExceptionEvent) 01739 { 01740 llrp_utf8v_t Message; 01741 01742 Message = pReaderExceptionEvent->getMessage(); 01743 01744 if(0 < Message.m_nValue && NULL != Message.m_pValue) 01745 { 01746 printf("NOTICE: ReaderException '%.*s'\n", 01747 Message.m_nValue, Message.m_pValue); 01748 } 01749 else 01750 { 01751 printf("NOTICE: ReaderException but no message\n"); 01752 } 01753 } 01754 01755 01774 int 01775 CMyApplication::checkLLRPStatus ( 01776 CLLRPStatus * pLLRPStatus, 01777 char * pWhatStr) 01778 { 01779 /* 01780 * The LLRPStatus parameter is mandatory in all responses. 01781 * If it is missing there should have been a decode error. 01782 * This just makes sure (remember, this program is a 01783 * diagnostic and suppose to catch LTKC mistakes). 01784 */ 01785 if(NULL == pLLRPStatus) 01786 { 01787 printf("ERROR: %s missing LLRP status\n", pWhatStr); 01788 return -1; 01789 } 01790 01791 /* 01792 * Make sure the status is M_Success. 01793 * If it isn't, print the error string if one. 01794 * This does not try to pretty-print the status 01795 * code. To get that, run this program with -vv 01796 * and examine the XML output. 01797 */ 01798 if(StatusCode_M_Success != pLLRPStatus->getStatusCode()) 01799 { 01800 llrp_utf8v_t ErrorDesc; 01801 01802 ErrorDesc = pLLRPStatus->getErrorDescription(); 01803 01804 if(0 == ErrorDesc.m_nValue) 01805 { 01806 printf("ERROR: %s failed, no error description given\n", 01807 pWhatStr); 01808 } 01809 else 01810 { 01811 printf("ERROR: %s failed, %.*s\n", 01812 pWhatStr, ErrorDesc.m_nValue, ErrorDesc.m_pValue); 01813 } 01814 return -2; 01815 } 01816 01817 /* 01818 * Victory. Everything is fine. 01819 */ 01820 return 0; 01821 } 01822 01823 01847 CMessage * 01848 CMyApplication::transact ( 01849 CMessage * pSendMsg) 01850 { 01851 CConnection * pConn = m_pConnectionToReader; 01852 CMessage * pRspMsg; 01853 01854 /* 01855 * Print the XML text for the outbound message if 01856 * verbosity is 2 or higher. 01857 */ 01858 if(1 < m_Verbose) 01859 { 01860 printf("\n===================================\n"); 01861 printf("INFO: Transact sending\n"); 01862 printXMLMessage(pSendMsg); 01863 } 01864 01865 /* 01866 * Send the message, expect the response of certain type. 01867 * If LLRP::CConnection::transact() returns NULL then there was 01868 * an error. In that case we try to print the error details. 01869 */ 01870 pRspMsg = pConn->transact(pSendMsg, 5000); 01871 01872 if(NULL == pRspMsg) 01873 { 01874 const CErrorDetails * pError = pConn->getTransactError(); 01875 01876 printf("ERROR: %s transact failed, %s\n", 01877 pSendMsg->m_pType->m_pName, 01878 pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given"); 01879 01880 if(NULL != pError->m_pRefType) 01881 { 01882 printf("ERROR: ... reference type %s\n", 01883 pError->m_pRefType->m_pName); 01884 } 01885 01886 if(NULL != pError->m_pRefField) 01887 { 01888 printf("ERROR: ... reference field %s\n", 01889 pError->m_pRefField->m_pName); 01890 } 01891 01892 return NULL; 01893 } 01894 01895 /* 01896 * Print the XML text for the inbound message if 01897 * verbosity is 2 or higher. 01898 */ 01899 if(1 < m_Verbose) 01900 { 01901 printf("\n- - - - - - - - - - - - - - - - - -\n"); 01902 printf("INFO: Transact received response\n"); 01903 printXMLMessage(pRspMsg); 01904 } 01905 01906 /* 01907 * If it is an ERROR_MESSAGE (response from reader 01908 * when it can't understand the request), tattle 01909 * and declare defeat. 01910 */ 01911 if(&CERROR_MESSAGE::s_typeDescriptor == pRspMsg->m_pType) 01912 { 01913 const CTypeDescriptor * pResponseType; 01914 01915 pResponseType = pSendMsg->m_pType->m_pResponseType; 01916 01917 printf("ERROR: Received ERROR_MESSAGE instead of %s\n", 01918 pResponseType->m_pName); 01919 delete pRspMsg; 01920 pRspMsg = NULL; 01921 } 01922 01923 return pRspMsg; 01924 } 01925 01926 01951 CMessage * 01952 CMyApplication::recvMessage ( 01953 int nMaxMS) 01954 { 01955 CConnection * pConn = m_pConnectionToReader; 01956 CMessage * pMessage; 01957 01958 /* 01959 * Receive the message subject to a time limit 01960 */ 01961 pMessage = pConn->recvMessage(nMaxMS); 01962 01963 /* 01964 * If LLRP::CConnection::recvMessage() returns NULL then there was 01965 * an error. In that case we try to print the error details. 01966 */ 01967 if(NULL == pMessage) 01968 { 01969 const CErrorDetails * pError = pConn->getRecvError(); 01970 01971 /* don't warn on timeout since this is a polling example */ 01972 if(pError->m_eResultCode != RC_RecvTimeout) 01973 { 01974 printf("ERROR: recvMessage failed, %s\n", 01975 pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given"); 01976 } 01977 01978 if(NULL != pError->m_pRefType) 01979 { 01980 printf("ERROR: ... reference type %s\n", 01981 pError->m_pRefType->m_pName); 01982 } 01983 01984 if(NULL != pError->m_pRefField) 01985 { 01986 printf("ERROR: ... reference field %s\n", 01987 pError->m_pRefField->m_pName); 01988 } 01989 01990 return NULL; 01991 } 01992 01993 /* 01994 * Print the XML text for the inbound message if 01995 * verbosity is 2 or higher. 01996 */ 01997 if(1 < m_Verbose) 01998 { 01999 printf("\n===================================\n"); 02000 printf("INFO: Message received\n"); 02001 printXMLMessage(pMessage); 02002 } 02003 02004 return pMessage; 02005 } 02006 02007 02025 int 02026 CMyApplication::sendMessage ( 02027 CMessage * pSendMsg) 02028 { 02029 CConnection * pConn = m_pConnectionToReader; 02030 02031 /* 02032 * Print the XML text for the outbound message if 02033 * verbosity is 2 or higher. 02034 */ 02035 if(1 < m_Verbose) 02036 { 02037 printf("\n===================================\n"); 02038 printf("INFO: Sending\n"); 02039 printXMLMessage(pSendMsg); 02040 } 02041 02042 /* 02043 * If LLRP::CConnection::sendMessage() returns other than RC_OK 02044 * then there was an error. In that case we try to print 02045 * the error details. 02046 */ 02047 if(RC_OK != pConn->sendMessage(pSendMsg)) 02048 { 02049 const CErrorDetails * pError = pConn->getSendError(); 02050 02051 printf("ERROR: %s sendMessage failed, %s\n", 02052 pSendMsg->m_pType->m_pName, 02053 pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given"); 02054 02055 if(NULL != pError->m_pRefType) 02056 { 02057 printf("ERROR: ... reference type %s\n", 02058 pError->m_pRefType->m_pName); 02059 } 02060 02061 if(NULL != pError->m_pRefField) 02062 { 02063 printf("ERROR: ... reference field %s\n", 02064 pError->m_pRefField->m_pName); 02065 } 02066 02067 return -1; 02068 } 02069 02070 /* 02071 * Victory 02072 */ 02073 return 0; 02074 } 02075 02076 02090 void 02091 CMyApplication::printXMLMessage ( 02092 CMessage * pMessage) 02093 { 02094 char aBuf[100*1024]; 02095 02096 /* 02097 * Convert the message to an XML string. 02098 * This fills the buffer with either the XML string 02099 * or an error message. The return value could 02100 * be checked. 02101 */ 02102 02103 pMessage->toXMLString(aBuf, sizeof aBuf); 02104 02105 /* 02106 * Print the XML Text to the standard output. 02107 */ 02108 printf("%s", aBuf); 02109 }