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(AISpecStopTriggerType_Null); 00808 pAISpecStopTrigger->setDurationTrigger(0); 00809 00811 00812 00813 CInventoryParameterSpec * pInventoryParameterSpec = 00814 new CInventoryParameterSpec(); 00815 pInventoryParameterSpec->setInventoryParameterSpecID(1234); 00816 pInventoryParameterSpec->setProtocolID(AirProtocols_EPCGlobalClass1Gen2); 00817 00818 CAntennaConfiguration * pAntennaConfig = new CAntennaConfiguration(); 00819 pAntennaConfig->setAntennaID(1); 00820 00821 CRFTransmitter * pRFTransmitter = new CRFTransmitter(); 00822 pRFTransmitter->setHopTableID(1); 00823 pRFTransmitter->setChannelIndex(0); 00824 pRFTransmitter->setTransmitPower(81); 00825 pAntennaConfig->setRFTransmitter(pRFTransmitter); 00826 00827 CC1G2InventoryCommand * pC1G2InventoryCmd = new CC1G2InventoryCommand(); 00828 pC1G2InventoryCmd->setTagInventoryStateAware(1); 00829 00830 // Filter 1 00831 CC1G2Filter * pC1G2Filter1 = new CC1G2Filter(); 00832 pC1G2Filter1->setT(C1G2TruncateAction_Do_Not_Truncate); 00833 00834 CC1G2TagInventoryMask * pC1G2TagInvMask1 = new CC1G2TagInventoryMask(); 00835 pC1G2TagInvMask1->setMB(2); 00836 pC1G2TagInvMask1->setPointer(0); 00837 00838 llrp_u1v_t tagMask1 = llrp_u1v_t(15); 00839 tagMask1.m_nBit = 15; 00840 tagMask1.m_pValue[0] = 0xE2; 00841 tagMask1.m_pValue[1] = 0x00; 00842 pC1G2TagInvMask1->setTagMask(tagMask1); 00843 00844 pC1G2Filter1->setC1G2TagInventoryMask(pC1G2TagInvMask1); 00845 00846 CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction1 = new CC1G2TagInventoryStateAwareFilterAction(); 00847 pC1G2TagInvStateAwareFilterAction1->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S3); 00848 pC1G2TagInvStateAwareFilterAction1->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB); 00849 00850 pC1G2Filter1->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction1); 00851 00852 pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter1); 00853 00854 // Filter 2 00855 CC1G2Filter * pC1G2Filter2 = new CC1G2Filter(); 00856 pC1G2Filter2->setT(C1G2TruncateAction_Do_Not_Truncate); 00857 00858 CC1G2TagInventoryMask * pC1G2TagInvMask2 = new CC1G2TagInventoryMask(); 00859 pC1G2TagInvMask2->setMB(1); 00860 pC1G2TagInvMask2->setPointer(0); 00861 00862 llrp_u1v_t tagMask2 = llrp_u1v_t(16); 00863 tagMask2.m_nBit = 16; 00864 tagMask2.m_pValue[0] = 0xE2; 00865 tagMask2.m_pValue[1] = 0x00; 00866 pC1G2TagInvMask2->setTagMask(tagMask2); 00867 00868 pC1G2Filter2->setC1G2TagInventoryMask(pC1G2TagInvMask2); 00869 00870 CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction2 = new CC1G2TagInventoryStateAwareFilterAction(); 00871 pC1G2TagInvStateAwareFilterAction2->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S2); 00872 pC1G2TagInvStateAwareFilterAction2->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB); 00873 00874 pC1G2Filter2->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction2); 00875 00876 pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter2); 00877 00878 // Filter 3 00879 CC1G2Filter * pC1G2Filter3 = new CC1G2Filter(); 00880 pC1G2Filter3->setT(C1G2TruncateAction_Do_Not_Truncate); 00881 00882 CC1G2TagInventoryMask * pC1G2TagInvMask3 = new CC1G2TagInventoryMask(); 00883 pC1G2TagInvMask3->setMB(3); 00884 pC1G2TagInvMask3->setPointer(0); 00885 00886 llrp_u1v_t tagMask3 = llrp_u1v_t(32); 00887 tagMask3.m_nBit = 32; 00888 tagMask3.m_pValue[0] = 0xFF; 00889 tagMask3.m_pValue[1] = 0xFF; 00890 tagMask3.m_pValue[2] = 0xE2; 00891 tagMask3.m_pValue[3] = 0x00; 00892 pC1G2TagInvMask3->setTagMask(tagMask3); 00893 00894 pC1G2Filter3->setC1G2TagInventoryMask(pC1G2TagInvMask3); 00895 00896 CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction3 = new CC1G2TagInventoryStateAwareFilterAction(); 00897 pC1G2TagInvStateAwareFilterAction3->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S1); 00898 pC1G2TagInvStateAwareFilterAction3->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB); 00899 00900 pC1G2Filter3->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction3); 00901 00902 pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter3); 00903 00904 // Filter 4 00905 CC1G2Filter * pC1G2Filter4 = new CC1G2Filter(); 00906 pC1G2Filter4->setT(C1G2TruncateAction_Do_Not_Truncate); 00907 00908 CC1G2TagInventoryMask * pC1G2TagInvMask4 = new CC1G2TagInventoryMask(); 00909 pC1G2TagInvMask4->setMB(2); 00910 pC1G2TagInvMask4->setPointer(0); 00911 00912 llrp_u1v_t tagMask4 = llrp_u1v_t(8); 00913 tagMask4.m_nBit = 8; 00914 tagMask4.m_pValue[0] = 0xAA; 00915 pC1G2TagInvMask4->setTagMask(tagMask4); 00916 00917 pC1G2Filter4->setC1G2TagInventoryMask(pC1G2TagInvMask4); 00918 00919 CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction4 = new CC1G2TagInventoryStateAwareFilterAction(); 00920 pC1G2TagInvStateAwareFilterAction4->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S0); 00921 pC1G2TagInvStateAwareFilterAction4->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB); 00922 00923 pC1G2Filter4->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction4); 00924 00925 pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter4); 00926 00927 // Filter 5 00928 CC1G2Filter * pC1G2Filter5 = new CC1G2Filter(); 00929 pC1G2Filter5->setT(C1G2TruncateAction_Do_Not_Truncate); 00930 00931 CC1G2TagInventoryMask * pC1G2TagInvMask5 = new CC1G2TagInventoryMask(); 00932 pC1G2TagInvMask5->setMB(1); 00933 pC1G2TagInvMask5->setPointer(0); 00934 00935 llrp_u1v_t tagMask5 = llrp_u1v_t(16); 00936 tagMask5.m_nBit = 16; 00937 tagMask5.m_pValue[0] = 0xFF; 00938 tagMask5.m_pValue[1] = 0xFF; 00939 pC1G2TagInvMask5->setTagMask(tagMask5); 00940 00941 pC1G2Filter5->setC1G2TagInventoryMask(pC1G2TagInvMask5); 00942 00943 CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction5 = new CC1G2TagInventoryStateAwareFilterAction(); 00944 pC1G2TagInvStateAwareFilterAction5->setTarget(C1G2StateAwareTarget_SL); 00945 pC1G2TagInvStateAwareFilterAction5->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB); 00946 00947 pC1G2Filter5->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction5); 00948 00949 pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter5); 00950 00951 // 00952 00953 00954 CC1G2SingulationControl * pC1G2SingulationControl = new CC1G2SingulationControl(); 00955 pC1G2SingulationControl->setSession(1); 00956 pC1G2SingulationControl->setTagPopulation(32); 00957 pC1G2SingulationControl->setTagTransitTime(0); 00958 00959 CC1G2TagInventoryStateAwareSingulationAction * pC1G2TagInvStateAwareSingAction = new CC1G2TagInventoryStateAwareSingulationAction(); 00960 pC1G2TagInvStateAwareSingAction->setI(C1G2TagInventoryStateAwareI_State_B); 00961 pC1G2TagInvStateAwareSingAction->setS(C1G2TagInventoryStateAwareS_SL); 00962 00963 pC1G2SingulationControl->setC1G2TagInventoryStateAwareSingulationAction(pC1G2TagInvStateAwareSingAction); 00964 00965 pC1G2InventoryCmd->setC1G2SingulationControl(pC1G2SingulationControl); 00966 00967 pAntennaConfig->addAirProtocolInventoryCommandSettings(pC1G2InventoryCmd); 00968 00969 pInventoryParameterSpec->addAntennaConfiguration(pAntennaConfig); 00970 00972 llrp_u16v_t AntennaIDs = llrp_u16v_t(1); 00973 AntennaIDs.m_pValue[0] = 1; 00974 00975 CAISpec * pAISpec = new CAISpec(); 00976 pAISpec->setAntennaIDs(AntennaIDs); 00977 pAISpec->setAISpecStopTrigger(pAISpecStopTrigger); 00978 pAISpec->addInventoryParameterSpec(pInventoryParameterSpec); 00979 00980 00982 CROReportSpec * pROReportSpec = new CROReportSpec(); 00983 pROReportSpec->setROReportTrigger(ROReportTriggerType_Upon_N_Tags_Or_End_Of_AISpec); 00984 pROReportSpec->setN(1000); 00985 00986 CTagReportContentSelector * pTagRptContentSelector = new CTagReportContentSelector(); 00987 pTagRptContentSelector->setEnableROSpecID(1); 00988 pTagRptContentSelector->setEnableSpecIndex(1); 00989 pTagRptContentSelector->setEnableInventoryParameterSpecID(1); 00990 pTagRptContentSelector->setEnableAntennaID(1); 00991 pTagRptContentSelector->setEnableChannelIndex(1); 00992 pTagRptContentSelector->setEnablePeakRSSI(1); 00993 pTagRptContentSelector->setEnableFirstSeenTimestamp(1); 00994 pTagRptContentSelector->setEnableLastSeenTimestamp(1); 00995 pTagRptContentSelector->setEnableTagSeenCount(1); 00996 pTagRptContentSelector->setEnableAccessSpecID(1); 00997 00998 pROReportSpec->setTagReportContentSelector(pTagRptContentSelector); 01000 01001 01002 CROSpec * pROSpec = new CROSpec(); 01003 pROSpec->setROSpecID(1); 01004 pROSpec->setPriority(0); 01005 pROSpec->setCurrentState(ROSpecState_Disabled); 01006 pROSpec->setROBoundarySpec(pROBoundarySpec); 01007 pROSpec->addSpecParameter(pAISpec); 01008 pROSpec->setROReportSpec(pROReportSpec); 01009 01010 CADD_ROSPEC * pCmd; 01011 CMessage * pRspMsg; 01012 CADD_ROSPEC_RESPONSE * pRsp; 01013 01014 /* 01015 * Compose the command message. 01016 * N.B.: After the message is composed, all the parameters 01017 * constructed, immediately above, are considered "owned" 01018 * by the command message. When it is destructed so 01019 * too will the parameters be. 01020 */ 01021 pCmd = new CADD_ROSPEC(); 01022 pCmd->setMessageID(m_messageID++); 01023 pCmd->setROSpec(pROSpec); 01024 01025 /* 01026 * Send the message, expect the response of certain type 01027 */ 01028 pRspMsg = transact(pCmd); 01029 01030 /* 01031 * Done with the command message. 01032 * N.B.: And the parameters 01033 */ 01034 delete pCmd; 01035 01036 /* 01037 * transact() returns NULL if something went wrong. 01038 */ 01039 if(NULL == pRspMsg) 01040 { 01041 /* transact already tattled */ 01042 return -1; 01043 } 01044 01045 /* 01046 * Cast to a ADD_ROSPEC_RESPONSE message. 01047 */ 01048 pRsp = (CADD_ROSPEC_RESPONSE *) pRspMsg; 01049 01050 /* 01051 * Check the LLRPStatus parameter. 01052 */ 01053 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "addROSpec")) 01054 { 01055 /* checkLLRPStatus already tattled */ 01056 delete pRspMsg; 01057 return -1; 01058 } 01059 01060 /* 01061 * Done with the response message. 01062 */ 01063 delete pRspMsg; 01064 01065 /* 01066 * Tattle progress, maybe 01067 */ 01068 if(m_Verbose) 01069 { 01070 printf("INFO: ROSpec added\n"); 01071 } 01072 01073 /* 01074 * Victory. 01075 */ 01076 return 0; 01077 } 01078 01079 01097 int 01098 CMyApplication::enableROSpec (void) 01099 { 01100 CENABLE_ROSPEC * pCmd; 01101 CMessage * pRspMsg; 01102 CENABLE_ROSPEC_RESPONSE * pRsp; 01103 01104 /* 01105 * Compose the command message 01106 */ 01107 pCmd = new CENABLE_ROSPEC(); 01108 pCmd->setMessageID(m_messageID++); 01109 pCmd->setROSpecID(1); 01110 01111 /* 01112 * Send the message, expect the response of certain type 01113 */ 01114 pRspMsg = transact(pCmd); 01115 01116 /* 01117 * Done with the command message 01118 */ 01119 delete pCmd; 01120 01121 /* 01122 * transact() returns NULL if something went wrong. 01123 */ 01124 if(NULL == pRspMsg) 01125 { 01126 /* transact already tattled */ 01127 return -1; 01128 } 01129 01130 /* 01131 * Cast to a ENABLE_ROSPEC_RESPONSE message. 01132 */ 01133 pRsp = (CENABLE_ROSPEC_RESPONSE *) pRspMsg; 01134 01135 /* 01136 * Check the LLRPStatus parameter. 01137 */ 01138 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "enableROSpec")) 01139 { 01140 /* checkLLRPStatus already tattled */ 01141 delete pRspMsg; 01142 return -1; 01143 } 01144 01145 /* 01146 * Done with the response message. 01147 */ 01148 delete pRspMsg; 01149 01150 /* 01151 * Tattle progress, maybe 01152 */ 01153 if(m_Verbose) 01154 { 01155 printf("INFO: ROSpec enabled\n"); 01156 } 01157 01158 /* 01159 * Victory. 01160 */ 01161 return 0; 01162 } 01163 01164 01182 int 01183 CMyApplication::startROSpec (void) 01184 { 01185 CSTART_ROSPEC * pCmd; 01186 CMessage * pRspMsg; 01187 CSTART_ROSPEC_RESPONSE * pRsp; 01188 01189 /* 01190 * Compose the command message 01191 */ 01192 pCmd = new CSTART_ROSPEC(); 01193 pCmd->setMessageID(m_messageID++); 01194 pCmd->setROSpecID(1); 01195 01196 /* 01197 * Send the message, expect the response of certain type 01198 */ 01199 pRspMsg = transact(pCmd); 01200 01201 /* 01202 * Done with the command message 01203 */ 01204 delete pCmd; 01205 01206 /* 01207 * transact() returns NULL if something went wrong. 01208 */ 01209 if(NULL == pRspMsg) 01210 { 01211 /* transact already tattled */ 01212 return -1; 01213 } 01214 01215 /* 01216 * Cast to a START_ROSPEC_RESPONSE message. 01217 */ 01218 pRsp = (CSTART_ROSPEC_RESPONSE *) pRspMsg; 01219 01220 /* 01221 * Check the LLRPStatus parameter. 01222 */ 01223 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "startROSpec")) 01224 { 01225 /* checkLLRPStatus already tattled */ 01226 delete pRspMsg; 01227 return -1; 01228 } 01229 01230 /* 01231 * Done with the response message. 01232 */ 01233 delete pRspMsg; 01234 01235 /* 01236 * Tattle progress 01237 */ 01238 if(m_Verbose) 01239 { 01240 printf("INFO: ROSpec started\n"); 01241 } 01242 01243 /* 01244 * Victory. 01245 */ 01246 return 0; 01247 } 01248 01266 int 01267 CMyApplication::stopROSpec (void) 01268 { 01269 CSTOP_ROSPEC * pCmd; 01270 CMessage * pRspMsg; 01271 CSTOP_ROSPEC_RESPONSE * pRsp; 01272 01273 /* 01274 * Compose the command message 01275 */ 01276 pCmd = new CSTOP_ROSPEC(); 01277 pCmd->setMessageID(m_messageID++); 01278 pCmd->setROSpecID(1); 01279 01280 /* 01281 * Send the message, expect the response of certain type 01282 */ 01283 pRspMsg = transact(pCmd); 01284 01285 /* 01286 * Done with the command message 01287 */ 01288 delete pCmd; 01289 01290 /* 01291 * transact() returns NULL if something went wrong. 01292 */ 01293 if(NULL == pRspMsg) 01294 { 01295 /* transact already tattled */ 01296 return -1; 01297 } 01298 01299 /* 01300 * Cast to a STOP_ROSPEC_RESPONSE message. 01301 */ 01302 pRsp = (CSTOP_ROSPEC_RESPONSE *) pRspMsg; 01303 01304 /* 01305 * Check the LLRPStatus parameter. 01306 */ 01307 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "stopROSpec")) 01308 { 01309 /* checkLLRPStatus already tattled */ 01310 delete pRspMsg; 01311 return -1; 01312 } 01313 01314 /* 01315 * Done with the response message. 01316 */ 01317 delete pRspMsg; 01318 01319 /* 01320 * Tattle progress 01321 */ 01322 if(m_Verbose) 01323 { 01324 printf("INFO: ROSpec stopped\n"); 01325 } 01326 01327 /* 01328 * Victory. 01329 */ 01330 return 0; 01331 } 01332 01333 01353 int 01354 CMyApplication::awaitAndPrintReport (int timeout) 01355 { 01356 int bDone = 0; 01357 int retVal = 0; 01358 time_t startTime = time(NULL); 01359 time_t tempTime; 01360 /* 01361 * Keep receiving messages until done or until 01362 * something bad happens. 01363 */ 01364 while(!bDone) 01365 { 01366 CMessage * pMessage; 01367 const CTypeDescriptor * pType; 01368 01369 /* 01370 * Wait up to 1 second for a report. Check 01371 * That way, we can check the timestamp even if 01372 * there are no reports coming in 01373 */ 01374 pMessage = recvMessage(1000); 01375 01376 /* validate the timestamp */ 01377 tempTime = time(NULL); 01378 if(difftime(tempTime, startTime) > timeout) 01379 { 01380 bDone=1; 01381 } 01382 01383 if(NULL == pMessage) 01384 { 01385 continue; 01386 } 01387 01388 /* 01389 * What happens depends on what kind of message 01390 * received. Use the type label (m_pType) to 01391 * discriminate message types. 01392 */ 01393 pType = pMessage->m_pType; 01394 01395 /* 01396 * Is it a tag report? If so, print it out. 01397 */ 01398 if(&CRO_ACCESS_REPORT::s_typeDescriptor == pType) 01399 { 01400 CRO_ACCESS_REPORT * pNtf; 01401 01402 pNtf = (CRO_ACCESS_REPORT *) pMessage; 01403 01404 printTagReportData(pNtf); 01405 } 01406 01407 /* 01408 * Is it a reader event? This example only recognizes 01409 * AntennaEvents. 01410 */ 01411 else if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor == pType) 01412 { 01413 CREADER_EVENT_NOTIFICATION *pNtf; 01414 CReaderEventNotificationData *pNtfData; 01415 01416 pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage; 01417 01418 pNtfData = pNtf->getReaderEventNotificationData(); 01419 if(NULL != pNtfData) 01420 { 01421 handleReaderEventNotification(pNtfData); 01422 } 01423 else 01424 { 01425 /* 01426 * This should never happen. Using continue 01427 * to keep indent depth down. 01428 */ 01429 printf("WARNING: READER_EVENT_NOTIFICATION without data\n"); 01430 } 01431 } 01432 01433 /* 01434 * Hmmm. Something unexpected. Just tattle and keep going. 01435 */ 01436 else 01437 { 01438 printf("WARNING: Ignored unexpected message during monitor: %s\n", 01439 pType->m_pName); 01440 } 01441 01442 /* 01443 * Done with the received message 01444 */ 01445 delete pMessage; 01446 } 01447 01448 return retVal; 01449 } 01450 01451 01466 void 01467 CMyApplication::printTagReportData ( 01468 CRO_ACCESS_REPORT * pRO_ACCESS_REPORT) 01469 { 01470 std::list<CTagReportData *>::iterator Cur; 01471 01472 unsigned int nEntry = 0; 01473 01474 /* 01475 * Loop through and count the number of entries 01476 */ 01477 for( 01478 Cur = pRO_ACCESS_REPORT->beginTagReportData(); 01479 Cur != pRO_ACCESS_REPORT->endTagReportData(); 01480 Cur++) 01481 { 01482 nEntry++; 01483 } 01484 01485 if(m_Verbose) 01486 { 01487 printf("INFO: %u tag report entries\n", nEntry); 01488 } 01489 01490 /* 01491 * Loop through again and print each entry. 01492 */ 01493 for( 01494 Cur = pRO_ACCESS_REPORT->beginTagReportData(); 01495 Cur != pRO_ACCESS_REPORT->endTagReportData(); 01496 Cur++) 01497 { 01498 printOneTagReportData(*Cur); 01499 } 01500 } 01501 01502 01511 void 01512 CMyApplication::formatOneEPC ( 01513 CParameter *pEPCParameter, 01514 char *buf, 01515 int buflen) 01516 { 01517 char * p = buf; 01518 int bufsize = buflen; 01519 int written = 0; 01520 01521 if(NULL != pEPCParameter) 01522 { 01523 const CTypeDescriptor * pType; 01524 llrp_u96_t my_u96; 01525 llrp_u1v_t my_u1v; 01526 llrp_u8_t * pValue = NULL; 01527 unsigned int n, i; 01528 01529 pType = pEPCParameter->m_pType; 01530 if(&CEPC_96::s_typeDescriptor == pType) 01531 { 01532 CEPC_96 *pEPC_96; 01533 01534 pEPC_96 = (CEPC_96 *) pEPCParameter; 01535 my_u96 = pEPC_96->getEPC(); 01536 pValue = my_u96.m_aValue; 01537 n = 12u; 01538 } 01539 else if(&CEPCData::s_typeDescriptor == pType) 01540 { 01541 CEPCData * pEPCData; 01542 01543 pEPCData = (CEPCData *) pEPCParameter; 01544 my_u1v = pEPCData->getEPC(); 01545 pValue = my_u1v.m_pValue; 01546 n = (my_u1v.m_nBit + 7u) / 8u; 01547 } 01548 01549 if(NULL != pValue) 01550 { 01551 for(i = 0; i < n; i++) 01552 { 01553 if(0 < i && i%2 == 0 && 1 < bufsize) 01554 { 01555 *p++ = '-'; 01556 bufsize--; 01557 } 01558 if(bufsize > 2) 01559 { 01560 written = snprintf(p, bufsize, "%02X", pValue[i]); 01561 bufsize -= written; 01562 p+= written; 01563 } 01564 } 01565 } 01566 else 01567 { 01568 written = snprintf(p, bufsize, "%s", "---unknown-epc-data-type---"); 01569 bufsize -= written; 01570 p += written; 01571 } 01572 } 01573 else 01574 { 01575 written = snprintf(p, bufsize, "%s", "--null epc---"); 01576 bufsize -= written; 01577 p += written; 01578 } 01579 01580 // null terminate this for good practice 01581 buf[buflen-1] = '\0'; 01582 01583 } 01584 01593 void 01594 CMyApplication::printOneTagReportData ( 01595 CTagReportData * pTagReportData) 01596 { 01597 char aBuf[64]; 01598 01599 /* 01600 * Print the EPC. It could be an 96-bit EPC_96 parameter 01601 * or an variable length EPCData parameter. 01602 */ 01603 01604 CParameter * pEPCParameter = 01605 pTagReportData->getEPCParameter(); 01606 01607 formatOneEPC(pEPCParameter, aBuf, 64); 01608 01609 /* 01610 * End of line 01611 */ 01612 printf("EPC: %s\n", aBuf); 01613 } 01614 01615 01629 void 01630 CMyApplication::handleReaderEventNotification ( 01631 CReaderEventNotificationData *pNtfData) 01632 { 01633 CAntennaEvent * pAntennaEvent; 01634 CReaderExceptionEvent * pReaderExceptionEvent; 01635 int nReported = 0; 01636 01637 pAntennaEvent = pNtfData->getAntennaEvent(); 01638 if(NULL != pAntennaEvent) 01639 { 01640 handleAntennaEvent(pAntennaEvent); 01641 nReported++; 01642 } 01643 01644 pReaderExceptionEvent = pNtfData->getReaderExceptionEvent(); 01645 if(NULL != pReaderExceptionEvent) 01646 { 01647 handleReaderExceptionEvent(pReaderExceptionEvent); 01648 nReported++; 01649 } 01650 01651 /* 01652 * Similarly handle other events here: 01653 * HoppingEvent 01654 * GPIEvent 01655 * ROSpecEvent 01656 * ReportBufferLevelWarningEvent 01657 * ReportBufferOverflowErrorEvent 01658 * RFSurveyEvent 01659 * AISpecEvent 01660 * ConnectionAttemptEvent 01661 * ConnectionCloseEvent 01662 * Custom 01663 */ 01664 01665 if(0 == nReported) 01666 { 01667 printf("NOTICE: Unexpected (unhandled) ReaderEvent\n"); 01668 } 01669 } 01670 01671 01683 void 01684 CMyApplication::handleAntennaEvent ( 01685 CAntennaEvent * pAntennaEvent) 01686 { 01687 EAntennaEventType eEventType; 01688 llrp_u16_t AntennaID; 01689 char * pStateStr; 01690 01691 eEventType = pAntennaEvent->getEventType(); 01692 AntennaID = pAntennaEvent->getAntennaID(); 01693 01694 switch(eEventType) 01695 { 01696 case AntennaEventType_Antenna_Disconnected: 01697 pStateStr = "disconnected"; 01698 break; 01699 01700 case AntennaEventType_Antenna_Connected: 01701 pStateStr = "connected"; 01702 break; 01703 01704 default: 01705 pStateStr = "?unknown-event?"; 01706 break; 01707 } 01708 01709 printf("NOTICE: Antenna %d is %s\n", AntennaID, pStateStr); 01710 } 01711 01712 01725 void 01726 CMyApplication::handleReaderExceptionEvent ( 01727 CReaderExceptionEvent * pReaderExceptionEvent) 01728 { 01729 llrp_utf8v_t Message; 01730 01731 Message = pReaderExceptionEvent->getMessage(); 01732 01733 if(0 < Message.m_nValue && NULL != Message.m_pValue) 01734 { 01735 printf("NOTICE: ReaderException '%.*s'\n", 01736 Message.m_nValue, Message.m_pValue); 01737 } 01738 else 01739 { 01740 printf("NOTICE: ReaderException but no message\n"); 01741 } 01742 } 01743 01744 01763 int 01764 CMyApplication::checkLLRPStatus ( 01765 CLLRPStatus * pLLRPStatus, 01766 char * pWhatStr) 01767 { 01768 /* 01769 * The LLRPStatus parameter is mandatory in all responses. 01770 * If it is missing there should have been a decode error. 01771 * This just makes sure (remember, this program is a 01772 * diagnostic and suppose to catch LTKC mistakes). 01773 */ 01774 if(NULL == pLLRPStatus) 01775 { 01776 printf("ERROR: %s missing LLRP status\n", pWhatStr); 01777 return -1; 01778 } 01779 01780 /* 01781 * Make sure the status is M_Success. 01782 * If it isn't, print the error string if one. 01783 * This does not try to pretty-print the status 01784 * code. To get that, run this program with -vv 01785 * and examine the XML output. 01786 */ 01787 if(StatusCode_M_Success != pLLRPStatus->getStatusCode()) 01788 { 01789 llrp_utf8v_t ErrorDesc; 01790 01791 ErrorDesc = pLLRPStatus->getErrorDescription(); 01792 01793 if(0 == ErrorDesc.m_nValue) 01794 { 01795 printf("ERROR: %s failed, no error description given\n", 01796 pWhatStr); 01797 } 01798 else 01799 { 01800 printf("ERROR: %s failed, %.*s\n", 01801 pWhatStr, ErrorDesc.m_nValue, ErrorDesc.m_pValue); 01802 } 01803 return -2; 01804 } 01805 01806 /* 01807 * Victory. Everything is fine. 01808 */ 01809 return 0; 01810 } 01811 01812 01836 CMessage * 01837 CMyApplication::transact ( 01838 CMessage * pSendMsg) 01839 { 01840 CConnection * pConn = m_pConnectionToReader; 01841 CMessage * pRspMsg; 01842 01843 /* 01844 * Print the XML text for the outbound message if 01845 * verbosity is 2 or higher. 01846 */ 01847 if(1 < m_Verbose) 01848 { 01849 printf("\n===================================\n"); 01850 printf("INFO: Transact sending\n"); 01851 printXMLMessage(pSendMsg); 01852 } 01853 01854 /* 01855 * Send the message, expect the response of certain type. 01856 * If LLRP::CConnection::transact() returns NULL then there was 01857 * an error. In that case we try to print the error details. 01858 */ 01859 pRspMsg = pConn->transact(pSendMsg, 5000); 01860 01861 if(NULL == pRspMsg) 01862 { 01863 const CErrorDetails * pError = pConn->getTransactError(); 01864 01865 printf("ERROR: %s transact failed, %s\n", 01866 pSendMsg->m_pType->m_pName, 01867 pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given"); 01868 01869 if(NULL != pError->m_pRefType) 01870 { 01871 printf("ERROR: ... reference type %s\n", 01872 pError->m_pRefType->m_pName); 01873 } 01874 01875 if(NULL != pError->m_pRefField) 01876 { 01877 printf("ERROR: ... reference field %s\n", 01878 pError->m_pRefField->m_pName); 01879 } 01880 01881 return NULL; 01882 } 01883 01884 /* 01885 * Print the XML text for the inbound message if 01886 * verbosity is 2 or higher. 01887 */ 01888 if(1 < m_Verbose) 01889 { 01890 printf("\n- - - - - - - - - - - - - - - - - -\n"); 01891 printf("INFO: Transact received response\n"); 01892 printXMLMessage(pRspMsg); 01893 } 01894 01895 /* 01896 * If it is an ERROR_MESSAGE (response from reader 01897 * when it can't understand the request), tattle 01898 * and declare defeat. 01899 */ 01900 if(&CERROR_MESSAGE::s_typeDescriptor == pRspMsg->m_pType) 01901 { 01902 const CTypeDescriptor * pResponseType; 01903 01904 pResponseType = pSendMsg->m_pType->m_pResponseType; 01905 01906 printf("ERROR: Received ERROR_MESSAGE instead of %s\n", 01907 pResponseType->m_pName); 01908 delete pRspMsg; 01909 pRspMsg = NULL; 01910 } 01911 01912 return pRspMsg; 01913 } 01914 01915 01940 CMessage * 01941 CMyApplication::recvMessage ( 01942 int nMaxMS) 01943 { 01944 CConnection * pConn = m_pConnectionToReader; 01945 CMessage * pMessage; 01946 01947 /* 01948 * Receive the message subject to a time limit 01949 */ 01950 pMessage = pConn->recvMessage(nMaxMS); 01951 01952 /* 01953 * If LLRP::CConnection::recvMessage() returns NULL then there was 01954 * an error. In that case we try to print the error details. 01955 */ 01956 if(NULL == pMessage) 01957 { 01958 const CErrorDetails * pError = pConn->getRecvError(); 01959 01960 /* don't warn on timeout since this is a polling example */ 01961 if(pError->m_eResultCode != RC_RecvTimeout) 01962 { 01963 printf("ERROR: recvMessage failed, %s\n", 01964 pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given"); 01965 } 01966 01967 if(NULL != pError->m_pRefType) 01968 { 01969 printf("ERROR: ... reference type %s\n", 01970 pError->m_pRefType->m_pName); 01971 } 01972 01973 if(NULL != pError->m_pRefField) 01974 { 01975 printf("ERROR: ... reference field %s\n", 01976 pError->m_pRefField->m_pName); 01977 } 01978 01979 return NULL; 01980 } 01981 01982 /* 01983 * Print the XML text for the inbound message if 01984 * verbosity is 2 or higher. 01985 */ 01986 if(1 < m_Verbose) 01987 { 01988 printf("\n===================================\n"); 01989 printf("INFO: Message received\n"); 01990 printXMLMessage(pMessage); 01991 } 01992 01993 return pMessage; 01994 } 01995 01996 02014 int 02015 CMyApplication::sendMessage ( 02016 CMessage * pSendMsg) 02017 { 02018 CConnection * pConn = m_pConnectionToReader; 02019 02020 /* 02021 * Print the XML text for the outbound message if 02022 * verbosity is 2 or higher. 02023 */ 02024 if(1 < m_Verbose) 02025 { 02026 printf("\n===================================\n"); 02027 printf("INFO: Sending\n"); 02028 printXMLMessage(pSendMsg); 02029 } 02030 02031 /* 02032 * If LLRP::CConnection::sendMessage() returns other than RC_OK 02033 * then there was an error. In that case we try to print 02034 * the error details. 02035 */ 02036 if(RC_OK != pConn->sendMessage(pSendMsg)) 02037 { 02038 const CErrorDetails * pError = pConn->getSendError(); 02039 02040 printf("ERROR: %s sendMessage failed, %s\n", 02041 pSendMsg->m_pType->m_pName, 02042 pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given"); 02043 02044 if(NULL != pError->m_pRefType) 02045 { 02046 printf("ERROR: ... reference type %s\n", 02047 pError->m_pRefType->m_pName); 02048 } 02049 02050 if(NULL != pError->m_pRefField) 02051 { 02052 printf("ERROR: ... reference field %s\n", 02053 pError->m_pRefField->m_pName); 02054 } 02055 02056 return -1; 02057 } 02058 02059 /* 02060 * Victory 02061 */ 02062 return 0; 02063 } 02064 02065 02079 void 02080 CMyApplication::printXMLMessage ( 02081 CMessage * pMessage) 02082 { 02083 char aBuf[100*1024]; 02084 02085 /* 02086 * Convert the message to an XML string. 02087 * This fills the buffer with either the XML string 02088 * or an error message. The return value could 02089 * be checked. 02090 */ 02091 02092 pMessage->toXMLString(aBuf, sizeof aBuf); 02093 02094 /* 02095 * Print the XML Text to the standard output. 02096 */ 02097 printf("%s", aBuf); 02098 }