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,2010. All rights reserved. * 00012 * * 00013 *****************************************************************************/ 00014 00048 #include <stdio.h> 00049 #include "ltkcpp.h" 00050 #include "impinj_ltkcpp.h" 00051 #include "time.h" 00052 00053 using namespace LLRP; 00054 00055 /* 00056 ** Sorry, we use this linux safe method 00057 ** to print buffers. WIndows has the same 00058 ** method, but by a different name 00059 */ 00060 #if (WIN32) 00061 #define snprintf _snprintf 00062 #endif 00063 00064 class CMyApplication 00065 { 00066 private: 00067 00068 unsigned int m_PowerLevelIndex; 00069 unsigned int m_messageID; 00070 00071 public: 00072 /* Store the command line parsing here */ 00073 /* Verbose level, incremented by each -v on command line */ 00074 int m_Verbose; 00075 unsigned int m_password; 00076 unsigned short int m_qtmode; 00077 unsigned short int m_tid; 00078 EImpinjQTAccessRange m_shortRange; 00079 unsigned int m_newPassword; 00080 00082 CConnection * m_pConnectionToReader; 00083 00084 inline 00085 CMyApplication (void) 00086 : m_Verbose(0), m_pConnectionToReader(NULL) 00087 { 00088 m_messageID = 0; 00089 m_shortRange=ImpinjQTAccessRange_Normal_Range; 00090 m_password = 0; 00091 m_qtmode = 0; 00092 m_tid = 0; 00093 m_Verbose = 0; 00094 } 00095 00096 int 00097 run ( 00098 char * pReaderHostName); 00099 00100 int 00101 checkConnectionStatus (void); 00102 00103 int 00104 enableImpinjExtensions (void); 00105 00106 int 00107 resetConfigurationToFactoryDefaults (void); 00108 00109 int 00110 getReaderCapabilities(void); 00111 00112 int 00113 setImpinjReaderConfig(void); 00114 00115 int 00116 addROSpec (void); 00117 00118 int 00119 enableROSpec (void); 00120 00121 int 00122 startROSpec (void); 00123 00124 int 00125 stopROSpec (void); 00126 00127 int 00128 addAccessSpec(void); 00129 00130 int 00131 enableAccessSpec(void); 00132 00133 int 00134 awaitAndPrintReport (int timeoutSec); 00135 00136 void 00137 printTagReportData ( 00138 CRO_ACCESS_REPORT * pRO_ACCESS_REPORT); 00139 00140 void 00141 printOneTagReportData ( 00142 CTagReportData * pTagReportData); 00143 00144 int 00145 formatOneEPC ( 00146 CParameter *pEPCParameter, 00147 char * buf, 00148 int buflen, 00149 char * startStr); 00150 00151 int 00152 formatOneWriteResult ( 00153 CParameter * pWriteResilt, 00154 char * buf, 00155 int buflen, 00156 char * startStr); 00157 int 00158 formatOneSetQTConfigResult ( 00159 CParameter * pQTResilt, 00160 char * buf, 00161 int buflen, 00162 char * startStr); 00163 00164 int 00165 formatOneGetQTConfigResult ( 00166 CParameter * pQTResilt, 00167 char * buf, 00168 int buflen, 00169 char * startStr); 00170 00171 int 00172 formatOneSerializedTID ( 00173 CParameter * pTID, 00174 char * buf, 00175 int buflen, 00176 char * startStr); 00177 00178 int 00179 formatOneReadResult ( 00180 CParameter * pReadResult, 00181 char * buf, 00182 int buflen, 00183 char * startStr); 00184 00185 void 00186 handleReaderEventNotification ( 00187 CReaderEventNotificationData *pNtfData); 00188 00189 void 00190 handleAntennaEvent ( 00191 CAntennaEvent * pAntennaEvent); 00192 00193 void 00194 handleReaderExceptionEvent ( 00195 CReaderExceptionEvent * pReaderExceptionEvent); 00196 00197 int 00198 checkLLRPStatus ( 00199 CLLRPStatus * pLLRPStatus, 00200 char * pWhatStr); 00201 00202 CMessage * 00203 transact ( 00204 CMessage * pSendMsg); 00205 00206 CMessage * 00207 recvMessage ( 00208 int nMaxMS); 00209 00210 int 00211 sendMessage ( 00212 CMessage * pSendMsg); 00213 00214 void 00215 printXMLMessage ( 00216 CMessage * pMessage); 00217 }; 00218 00219 00220 /* BEGIN forward declarations */ 00221 int 00222 main ( 00223 int ac, 00224 char * av[]); 00225 00226 void 00227 usage ( 00228 char * pProgName); 00229 /* END forward declarations */ 00230 00231 00247 int 00248 main ( 00249 int ac, 00250 char * av[]) 00251 { 00252 CMyApplication myApp; 00253 char * pReaderHostName; 00254 int rc; 00255 int i; 00256 00257 /* 00258 * Process comand arguments, determine reader name 00259 * and verbosity level. 00260 */ 00261 00262 if( ac < 2) 00263 { 00264 usage(av[0]); 00265 return -1; 00266 } 00267 00268 srand((unsigned int) time(NULL)); 00269 00270 00271 /* get the options. Skip the last one as its the hostname */ 00272 for( i = 1; i < ac-1; i++) 00273 { 00274 if((0 == strcmp(av[i],"-p")) && (i < (ac-1))) 00275 { 00276 i++; 00277 myApp.m_password = atoi(av[i]); 00278 } 00279 else if((0 == strcmp(av[i],"-n")) && (i < (ac-1))) 00280 { 00281 i++; 00282 myApp.m_newPassword = atoi(av[i]); 00283 } 00284 else if(0==strcmp(av[i], "-t")) 00285 { 00286 myApp.m_tid=1; 00287 } 00288 else if(0==strcmp(av[i], "-s")) 00289 { 00290 myApp.m_shortRange=ImpinjQTAccessRange_Short_Range ; 00291 } 00292 else if((0 == strcmp(av[i],"-v")) && (i < (ac-1))) 00293 { 00294 i++; 00295 myApp.m_Verbose = atoi(av[i]); 00296 } 00297 else if((0 == strcmp(av[i],"-q")) && (i < (ac-1))) 00298 { 00299 i++; 00300 myApp.m_qtmode = atoi(av[i]); 00301 } 00302 else 00303 { 00304 usage(av[0]); 00305 return -1; 00306 } 00307 } 00308 00309 pReaderHostName = av[i]; 00310 00311 /* 00312 * Run application, capture return value for exit status 00313 */ 00314 rc = myApp.run(pReaderHostName ); 00315 00316 printf("INFO: Done\n"); 00317 00318 /* 00319 * Exit with the right status. 00320 */ 00321 if(0 == rc) 00322 { 00323 exit(0); 00324 } 00325 else 00326 { 00327 exit(2); 00328 } 00329 /*NOTREACHED*/ 00330 } 00331 00332 00344 void 00345 usage ( 00346 char * pProgName) 00347 { 00348 printf("Usage: %s [options] READERHOSTNAME\n", pProgName); 00349 printf(" -p <password> -- specify an optional password for operations\n"); 00350 printf(" -n <password> -- specifies a new password for the set password command\n"); 00351 printf(" -t -- specify to automatically backscatter the TID\n"); 00352 printf(" -s -- if setting QT config, -s will short range the tag\n"); 00353 printf(" -q <n> -- run QT scenario n where n is defined as \n"); 00354 printf(" 0 -- Read standard TID memory\n"); 00355 printf(" 1 -- set tag password (uses -p, -n )\n"); 00356 printf(" 2 -- Read private memory data without QT commands\n"); 00357 printf(" 3 -- read QT status of tag (uses -p)\n"); 00358 printf(" 4 -- set QT status of tag to private (uses -p, -s)\n"); 00359 printf(" 5 -- set QT status of tag to public (uses -p, -s)\n"); 00360 printf(" 6 -- Peek at private memory data with temporary QT command (uses -p)\n"); 00361 printf(" 7 -- Write 32 words of user data to random values\n"); 00362 printf(" 8 -- Write 6 words of public EPC data to random values\n"); 00363 printf(" 9 -- Read Reserved memory\n"); 00364 printf("\n"); 00365 00366 exit(1); 00367 } 00368 00369 00414 int 00415 CMyApplication::run ( 00416 char * pReaderHostName) 00417 { 00418 CTypeRegistry * pTypeRegistry; 00419 CConnection * pConn; 00420 int rc; 00421 00422 /* 00423 * Allocate the type registry. This is needed 00424 * by the connection to decode. 00425 */ 00426 pTypeRegistry = getTheTypeRegistry(); 00427 if(NULL == pTypeRegistry) 00428 { 00429 printf("ERROR: getTheTypeRegistry failed\n"); 00430 return -1; 00431 } 00432 00433 /* 00434 * Enroll impinj extension types into the 00435 * type registry, in preparation for using 00436 * Impinj extension params. 00437 */ 00438 LLRP::enrollImpinjTypesIntoRegistry(pTypeRegistry); 00439 00440 /* 00441 * Construct a connection (LLRP::CConnection). 00442 * Using a 32kb max frame size for send/recv. 00443 * The connection object is ready for business 00444 * but not actually connected to the reader yet. 00445 */ 00446 pConn = new CConnection(pTypeRegistry, 32u*1024u); 00447 if(NULL == pConn) 00448 { 00449 printf("ERROR: new CConnection failed\n"); 00450 return -2; 00451 } 00452 00453 /* 00454 * Open the connection to the reader 00455 */ 00456 if(m_Verbose) 00457 { 00458 printf("INFO: Connecting to %s....\n", pReaderHostName); 00459 } 00460 00461 rc = pConn->openConnectionToReader(pReaderHostName); 00462 if(0 != rc) 00463 { 00464 printf("ERROR: connect: %s (%d)\n", pConn->getConnectError(), rc); 00465 delete pConn; 00466 return -3; 00467 } 00468 00469 /* 00470 * Record the pointer to the connection object so other 00471 * routines can use it. 00472 */ 00473 m_pConnectionToReader = pConn; 00474 00475 if(m_Verbose) 00476 { 00477 printf("INFO: Connected, checking status....\n"); 00478 } 00479 00480 /* 00481 * Commence the sequence and check for errors as we go. 00482 * See comments for each routine for details. 00483 * Each routine prints messages. 00484 */ 00485 rc = 1; 00486 if(0 == checkConnectionStatus()) 00487 { 00488 rc = 2; 00489 if(0 == enableImpinjExtensions()) 00490 { 00491 rc = 3; 00492 if(0 == resetConfigurationToFactoryDefaults()) 00493 { 00494 rc = 4; 00495 if(0 == getReaderCapabilities()) 00496 { 00497 rc = 5; 00498 if(0 == setImpinjReaderConfig()) 00499 { 00500 rc = 6; 00501 if(0 == addROSpec()) 00502 { 00503 rc = 7; 00504 if(0 == addAccessSpec()) 00505 { 00506 rc = 8; 00507 if(0 == enableAccessSpec()) 00508 { 00509 rc = 9; 00510 if(0 == enableROSpec()) 00511 { 00512 rc = 10; 00513 if(0 == startROSpec()) 00514 { 00515 rc = 11; 00516 if(0 == awaitAndPrintReport(1)) 00517 { 00518 rc = 12; 00519 if(0 == stopROSpec()) 00520 { 00521 rc = 0; 00522 } 00523 } 00524 } 00525 } 00526 } 00527 } 00528 } 00529 } 00530 } 00531 } 00532 00533 /* 00534 * After we're done, try to leave the reader 00535 * in a clean state for next use. This is best 00536 * effort and no checking of the result is done. 00537 */ 00538 if(m_Verbose) 00539 { 00540 printf("INFO: Clean up reader configuration...\n"); 00541 } 00542 resetConfigurationToFactoryDefaults(); 00543 } 00544 } 00545 00546 if(m_Verbose) 00547 { 00548 printf("INFO: Finished\n"); 00549 } 00550 00551 /* 00552 * Close the connection and release its resources 00553 */ 00554 pConn->closeConnectionToReader(); 00555 delete pConn; 00556 00557 /* 00558 * Done with the registry. 00559 */ 00560 delete pTypeRegistry; 00561 00562 /* 00563 * When we get here all allocated memory should have been deallocated. 00564 */ 00565 00566 return rc; 00567 } 00568 00569 00600 int 00601 CMyApplication::checkConnectionStatus (void) 00602 { 00603 CMessage * pMessage; 00604 CREADER_EVENT_NOTIFICATION *pNtf; 00605 CReaderEventNotificationData *pNtfData; 00606 CConnectionAttemptEvent * pEvent; 00607 00608 /* 00609 * Expect the notification within 10 seconds. 00610 * It is suppose to be the very first message sent. 00611 */ 00612 pMessage = recvMessage(10000); 00613 00614 /* 00615 * recvMessage() returns NULL if something went wrong. 00616 */ 00617 if(NULL == pMessage) 00618 { 00619 /* recvMessage already tattled */ 00620 goto fail; 00621 } 00622 00623 /* 00624 * Check to make sure the message is of the right type. 00625 * The type label (pointer) in the message should be 00626 * the type descriptor for READER_EVENT_NOTIFICATION. 00627 */ 00628 if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor != pMessage->m_pType) 00629 { 00630 goto fail; 00631 } 00632 00633 /* 00634 * Now that we are sure it is a READER_EVENT_NOTIFICATION, 00635 * traverse to the ReaderEventNotificationData parameter. 00636 */ 00637 pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage; 00638 pNtfData = pNtf->getReaderEventNotificationData(); 00639 if(NULL == pNtfData) 00640 { 00641 goto fail; 00642 } 00643 00644 /* 00645 * The ConnectionAttemptEvent parameter must be present. 00646 */ 00647 pEvent = pNtfData->getConnectionAttemptEvent(); 00648 if(NULL == pEvent) 00649 { 00650 goto fail; 00651 } 00652 00653 /* 00654 * The status in the ConnectionAttemptEvent parameter 00655 * must indicate connection success. 00656 */ 00657 if(ConnectionAttemptStatusType_Success != pEvent->getStatus()) 00658 { 00659 goto fail; 00660 } 00661 00662 /* 00663 * Done with the message 00664 */ 00665 delete pMessage; 00666 00667 if(m_Verbose) 00668 { 00669 printf("INFO: Connection status OK\n"); 00670 } 00671 00672 /* 00673 * Victory. 00674 */ 00675 return 0; 00676 00677 fail: 00678 /* 00679 * Something went wrong. Tattle. Clean up. Return error. 00680 */ 00681 printf("ERROR: checkConnectionStatus failed\n"); 00682 delete pMessage; 00683 return -1; 00684 } 00685 00703 int 00704 CMyApplication::enableImpinjExtensions (void) 00705 { 00706 CIMPINJ_ENABLE_EXTENSIONS * pCmd; 00707 CMessage * pRspMsg; 00708 CIMPINJ_ENABLE_EXTENSIONS_RESPONSE *pRsp; 00709 00710 /* 00711 * Compose the command message 00712 */ 00713 pCmd = new CIMPINJ_ENABLE_EXTENSIONS(); 00714 pCmd->setMessageID(m_messageID++); 00715 /* 00716 * Send the message, expect the response of certain type 00717 */ 00718 pRspMsg = transact(pCmd); 00719 00720 /* 00721 * Done with the command message 00722 */ 00723 delete pCmd; 00724 00725 /* 00726 * transact() returns NULL if something went wrong. 00727 */ 00728 if(NULL == pRspMsg) 00729 { 00730 /* transact already tattled */ 00731 return -1; 00732 } 00733 00734 /* 00735 * Cast to a CIMPINJ_ENABLE_EXTENSIONS_RESPONSE message. 00736 */ 00737 pRsp = (CIMPINJ_ENABLE_EXTENSIONS_RESPONSE *) pRspMsg; 00738 00739 /* 00740 * Check the LLRPStatus parameter. 00741 */ 00742 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), 00743 "enableImpinjExtensions")) 00744 { 00745 /* checkLLRPStatus already tattled */ 00746 delete pRspMsg; 00747 return -1; 00748 } 00749 00750 /* 00751 * Done with the response message. 00752 */ 00753 delete pRspMsg; 00754 00755 /* 00756 * Tattle progress, maybe 00757 */ 00758 if(m_Verbose) 00759 { 00760 printf("INFO: Impinj Extensions are enabled\n"); 00761 } 00762 00763 /* 00764 * Victory. 00765 */ 00766 return 0; 00767 } 00768 00789 int 00790 CMyApplication::resetConfigurationToFactoryDefaults (void) 00791 { 00792 CSET_READER_CONFIG * pCmd; 00793 CMessage * pRspMsg; 00794 CSET_READER_CONFIG_RESPONSE *pRsp; 00795 00796 /* 00797 * Compose the command message 00798 */ 00799 pCmd = new CSET_READER_CONFIG(); 00800 pCmd->setMessageID(m_messageID++); 00801 pCmd->setResetToFactoryDefault(1); 00802 00803 /* 00804 * Send the message, expect the response of certain type 00805 */ 00806 pRspMsg = transact(pCmd); 00807 00808 /* 00809 * Done with the command message 00810 */ 00811 delete pCmd; 00812 00813 /* 00814 * transact() returns NULL if something went wrong. 00815 */ 00816 if(NULL == pRspMsg) 00817 { 00818 /* transact already tattled */ 00819 return -1; 00820 } 00821 00822 /* 00823 * Cast to a SET_READER_CONFIG_RESPONSE message. 00824 */ 00825 pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg; 00826 00827 /* 00828 * Check the LLRPStatus parameter. 00829 */ 00830 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), 00831 "resetConfigurationToFactoryDefaults")) 00832 { 00833 /* checkLLRPStatus already tattled */ 00834 delete pRspMsg; 00835 return -1; 00836 } 00837 00838 /* 00839 * Done with the response message. 00840 */ 00841 delete pRspMsg; 00842 00843 /* 00844 * Tattle progress, maybe 00845 */ 00846 if(m_Verbose) 00847 { 00848 printf("INFO: Configuration reset to factory defaults\n"); 00849 } 00850 00851 /* 00852 * Victory. 00853 */ 00854 return 0; 00855 } 00856 00857 00871 int 00872 CMyApplication::getReaderCapabilities(void) 00873 { 00874 CGET_READER_CAPABILITIES *pCmd; 00875 CMessage * pRspMsg; 00876 CGET_READER_CAPABILITIES_RESPONSE *pRsp; 00877 CGeneralDeviceCapabilities *pDevCap; 00878 unsigned int bMajorVersion, bMinorVersion, bDevVersion, bBuildVersion = 0; 00879 00880 00881 /* 00882 * Compose the command message 00883 */ 00884 pCmd = new CGET_READER_CAPABILITIES(); 00885 pCmd->setMessageID(m_messageID++); 00886 pCmd->setRequestedData(GetReaderCapabilitiesRequestedData_All); 00887 00888 /* 00889 * Send the message, expect the response of certain type 00890 */ 00891 pRspMsg = transact(pCmd); 00892 00893 /* 00894 * Done with the command message 00895 */ 00896 delete pCmd; 00897 00898 /* 00899 * transact() returns NULL if something went wrong. 00900 */ 00901 if(NULL == pRspMsg) 00902 { 00903 /* transact already tattled */ 00904 return -1; 00905 } 00906 00907 /* 00908 * Cast to a CGET_READER_CAPABILITIES_RESPONSE message. 00909 */ 00910 pRsp = (CGET_READER_CAPABILITIES_RESPONSE *) pRspMsg; 00911 00912 /* 00913 * Check the LLRPStatus parameter. 00914 */ 00915 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), 00916 "getReaderCapabilities")) 00917 { 00918 /* checkLLRPStatus already tattled */ 00919 delete pRspMsg; 00920 return -1; 00921 } 00922 00923 /* 00924 ** Get out the general device capabilities 00925 */ 00926 if(NULL == (pDevCap = pRsp->getGeneralDeviceCapabilities())) 00927 { 00928 delete pRspMsg; 00929 return -1; 00930 } 00931 00932 00933 /* if this parameter is missing, or if this is not an Impinj 00934 ** reader, we can't determine its capabilities so we exit 00935 ** Impinj Private Enterprise NUmber is 25882 */ 00936 if( (NULL == (pDevCap = pRsp->getGeneralDeviceCapabilities())) || 00937 (25882 != pDevCap->getDeviceManufacturerName())) 00938 { 00939 delete pRspMsg; 00940 return -1; 00941 } 00942 00943 00944 /* 00945 * Get the version information from the reader and make sure we are 4.4 or better. 00946 */ 00947 if ( pDevCap->getReaderFirmwareVersion().m_nValue < 3) 00948 { 00949 printf("ERROR: Must have Firmware 4.4 or later for low level data example \n"); 00950 delete pRspMsg; 00951 return -1; 00952 } 00953 00954 /* 00955 * Parse to make sure it is really 4.4 or better 00956 */ 00957 sscanf((char *) pDevCap->getReaderFirmwareVersion().m_pValue, "%u.%u.%u.%u", &bMajorVersion, &bMinorVersion, &bDevVersion, &bBuildVersion); 00958 00959 if( (bMajorVersion < 4) && (bMinorVersion < 4) ) 00960 { 00961 printf("ERROR: Must have Firmware 4.4 or later for low level data example \n"); 00962 delete pRspMsg; 00963 return -1; 00964 } 00965 00966 /* 00967 * Done with the response message. 00968 */ 00969 delete pRspMsg; 00970 00971 /* 00972 * Tattle progress, maybe 00973 */ 00974 if(m_Verbose) 00975 { 00976 printf("INFO: Found LLRP Capabilities \n"); 00977 } 00978 00979 /* 00980 * Victory. 00981 */ 00982 return 0; 00983 } 00984 00985 01000 int 01001 CMyApplication::setImpinjReaderConfig(void) 01002 { 01003 CSET_READER_CONFIG *pCmd; 01004 CMessage * pRspMsg; 01005 CSET_READER_CONFIG_RESPONSE *pRsp; 01006 01007 /* 01008 * Compose the command message 01009 */ 01010 pCmd = new CSET_READER_CONFIG(); 01011 pCmd->setMessageID(m_messageID++); 01012 01013 CAntennaConfiguration *pAnt = new(CAntennaConfiguration); 01014 01015 /* 01016 ** Apply this configuration to all antennas 01017 */ 01018 pAnt->setAntennaID(0); 01019 01020 /* 01021 ** Create the container Inventory command to hold all the parameters 01022 */ 01023 CC1G2InventoryCommand *pC1G2Inv = new CC1G2InventoryCommand(); 01024 01025 /* set the mode to auto-set max throughput */ 01026 CC1G2RFControl *pC1G2Rf = new CC1G2RFControl(); 01027 pC1G2Rf->setModeIndex(2); /* DRM M=4 */ 01028 pC1G2Rf->setTari(0); /* tari is ignored by the reader */ 01029 pC1G2Inv->setC1G2RFControl(pC1G2Rf); 01030 01031 CC1G2SingulationControl *pC1G2Sing = new CC1G2SingulationControl(); 01032 pC1G2Sing->setSession(1); 01033 pC1G2Sing->setTagPopulation(1); 01034 pC1G2Sing->setTagTransitTime(0); 01035 pC1G2Inv->setC1G2SingulationControl(pC1G2Sing); 01036 01037 pC1G2Inv->setTagInventoryStateAware(false); 01038 01039 /* set the Impinj Inventory search mode as per the use case */ 01040 CImpinjInventorySearchMode *pImpIsm = new CImpinjInventorySearchMode(); 01041 pImpIsm->setInventorySearchMode(ImpinjInventorySearchType_Single_Target); 01042 pC1G2Inv->addCustom(pImpIsm); 01043 01044 /* 01045 ** set the Impinj Low Duty Cycle mode as per the use case 01046 */ 01047 CImpinjLowDutyCycle *pImpLdc = new CImpinjLowDutyCycle(); 01048 pImpLdc->setEmptyFieldTimeout(10000); 01049 pImpLdc->setFieldPingInterval(200); 01050 pImpLdc->setLowDutyCycleMode(ImpinjLowDutyCycleMode_Enabled); 01051 pC1G2Inv->addCustom(pImpLdc); 01052 01053 /* 01054 ** Don't forget to add the InventoryCommand to the antenna 01055 ** configuration, and then add the antenna configuration to the 01056 ** config message 01057 */ 01058 pAnt->addAirProtocolInventoryCommandSettings(pC1G2Inv); 01059 pCmd->addAntennaConfiguration(pAnt); 01060 01061 /* 01062 ** report every tag (N=1) since that is required for tag direction 01063 */ 01064 CROReportSpec *pROrs = new CROReportSpec(); 01065 pROrs->setROReportTrigger(ROReportTriggerType_Upon_N_Tags_Or_End_Of_ROSpec); 01066 pROrs->setN(1); 01067 01068 /* 01069 ** Turn off off report data that we don't need since our use 01070 ** case suggests we are bandwidth constrained 01071 */ 01072 CTagReportContentSelector *pROcontent = new CTagReportContentSelector(); 01073 pROcontent->setEnableAccessSpecID(false); 01074 pROcontent->setEnableAntennaID(false); 01075 pROcontent->setEnableChannelIndex(false); 01076 pROcontent->setEnableFirstSeenTimestamp(true); 01077 pROcontent->setEnableInventoryParameterSpecID(false); 01078 pROcontent->setEnableLastSeenTimestamp(false); 01079 pROcontent->setEnablePeakRSSI(false); 01080 pROcontent->setEnableROSpecID(false); 01081 pROcontent->setEnableSpecIndex(false); 01082 pROcontent->setEnableTagSeenCount(false); 01083 CC1G2EPCMemorySelector *pC1G2Mem = new CC1G2EPCMemorySelector(); 01084 pC1G2Mem->setEnableCRC(false); 01085 pC1G2Mem->setEnablePCBits(false); 01086 pROcontent->addAirProtocolEPCMemorySelector(pC1G2Mem); 01087 pROrs->setTagReportContentSelector(pROcontent); 01088 01089 /* Optionally turn on EPC/TID backscatter. leave the others off as 01090 ** low level data is another example */ 01091 CImpinjTagReportContentSelector * pImpTagCnt = new CImpinjTagReportContentSelector(); 01092 01093 CImpinjEnableRFPhaseAngle * pEnableRfPhase = new CImpinjEnableRFPhaseAngle(); 01094 pEnableRfPhase->setRFPhaseAngleMode(ImpinjRFPhaseAngleMode_Disabled); 01095 pImpTagCnt->setImpinjEnableRFPhaseAngle(pEnableRfPhase); 01096 01097 CImpinjEnablePeakRSSI * pEnablePeakRssi = new CImpinjEnablePeakRSSI(); 01098 pEnablePeakRssi->setPeakRSSIMode(ImpinjPeakRSSIMode_Disabled); 01099 pImpTagCnt->setImpinjEnablePeakRSSI(pEnablePeakRssi); 01100 01101 CImpinjEnableSerializedTID * pEnableSerializedTID = new CImpinjEnableSerializedTID(); 01102 01103 /* Here's where we set the backscatter of the TID */ 01104 if(m_tid) 01105 pEnableSerializedTID->setSerializedTIDMode(ImpinjSerializedTIDMode_Enabled); 01106 else 01107 pEnableSerializedTID->setSerializedTIDMode(ImpinjSerializedTIDMode_Disabled); 01108 01109 pImpTagCnt->setImpinjEnableSerializedTID(pEnableSerializedTID); 01110 01111 pROrs->addCustom(pImpTagCnt); 01112 01113 pCmd->setROReportSpec(pROrs); 01114 01115 /* 01116 * Send the message, expect the response of certain type 01117 */ 01118 pRspMsg = transact(pCmd); 01119 01120 /* 01121 * Done with the command message 01122 */ 01123 delete pCmd; 01124 01125 /* 01126 * transact() returns NULL if something went wrong. 01127 */ 01128 if(NULL == pRspMsg) 01129 { 01130 /* transact already tattled */ 01131 return -1; 01132 } 01133 01134 /* 01135 * Cast to a CSET_READER_CONFIG_RESPONSE message. 01136 */ 01137 pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg; 01138 01139 /* 01140 * Check the LLRPStatus parameter. 01141 */ 01142 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), 01143 "setImpinjReaderConfig")) 01144 { 01145 /* checkLLRPStatus already tattled */ 01146 delete pRspMsg; 01147 return -1; 01148 } 01149 01150 /* 01151 * Done with the response message. 01152 */ 01153 delete pRspMsg; 01154 01155 /* 01156 * Tattle progress, maybe 01157 */ 01158 if(m_Verbose) 01159 { 01160 printf("INFO: Set Impinj Reader Configuration \n"); 01161 } 01162 01163 /* 01164 * Victory. 01165 */ 01166 return 0; 01167 } 01168 01246 int 01247 CMyApplication::addROSpec (void) 01248 { 01249 CROSpecStartTrigger * pROSpecStartTrigger = 01250 new CROSpecStartTrigger(); 01251 pROSpecStartTrigger->setROSpecStartTriggerType( 01252 ROSpecStartTriggerType_Null); 01253 01254 CROSpecStopTrigger * pROSpecStopTrigger = new CROSpecStopTrigger(); 01255 pROSpecStopTrigger->setROSpecStopTriggerType(ROSpecStopTriggerType_Null); 01256 pROSpecStopTrigger->setDurationTriggerValue(0); /* n/a */ 01257 01258 CROBoundarySpec * pROBoundarySpec = new CROBoundarySpec(); 01259 pROBoundarySpec->setROSpecStartTrigger(pROSpecStartTrigger); 01260 pROBoundarySpec->setROSpecStopTrigger(pROSpecStopTrigger); 01261 01262 CAISpecStopTrigger * pAISpecStopTrigger = new CAISpecStopTrigger(); 01263 pAISpecStopTrigger->setAISpecStopTriggerType( 01264 AISpecStopTriggerType_Null); 01265 pAISpecStopTrigger->setDurationTrigger(0); 01266 01267 CInventoryParameterSpec * pInventoryParameterSpec = 01268 new CInventoryParameterSpec(); 01269 pInventoryParameterSpec->setInventoryParameterSpecID(1234); 01270 pInventoryParameterSpec->setProtocolID(AirProtocols_EPCGlobalClass1Gen2); 01271 01272 /* Build the antennaConfiguration to Contain this */ 01273 CAntennaConfiguration * pAntennaConfiguration = 01274 new CAntennaConfiguration(); 01275 pAntennaConfiguration->setAntennaID(0); 01276 01277 /* don't forget to add this to the INventory Parameter Spec above */ 01278 pInventoryParameterSpec->addAntennaConfiguration(pAntennaConfiguration); 01279 01280 /* 01281 ** Use all Antennas 01282 */ 01283 llrp_u16v_t AntennaIDs = llrp_u16v_t(1); 01284 AntennaIDs.m_pValue[0] = 0; 01285 01286 CAISpec * pAISpec = new CAISpec(); 01287 pAISpec->setAntennaIDs(AntennaIDs); 01288 pAISpec->setAISpecStopTrigger(pAISpecStopTrigger); 01289 pAISpec->addInventoryParameterSpec(pInventoryParameterSpec); 01290 01291 CROSpec * pROSpec = new CROSpec(); 01292 pROSpec->setROSpecID(1111); 01293 pROSpec->setPriority(0); 01294 pROSpec->setCurrentState(ROSpecState_Disabled); 01295 pROSpec->setROBoundarySpec(pROBoundarySpec); 01296 pROSpec->addSpecParameter(pAISpec); 01297 01298 CADD_ROSPEC * pCmd; 01299 CMessage * pRspMsg; 01300 CADD_ROSPEC_RESPONSE * pRsp; 01301 01302 /* 01303 * Compose the command message. 01304 * N.B.: After the message is composed, all the parameters 01305 * constructed, immediately above, are considered "owned" 01306 * by the command message. When it is destructed so 01307 * too will the parameters be. 01308 */ 01309 pCmd = new CADD_ROSPEC(); 01310 pCmd->setMessageID(m_messageID++); 01311 pCmd->setROSpec(pROSpec); 01312 01313 /* 01314 * Send the message, expect the response of certain type 01315 */ 01316 pRspMsg = transact(pCmd); 01317 01318 /* 01319 * Done with the command message. 01320 * N.B.: And the parameters 01321 */ 01322 delete pCmd; 01323 01324 /* 01325 * transact() returns NULL if something went wrong. 01326 */ 01327 if(NULL == pRspMsg) 01328 { 01329 /* transact already tattled */ 01330 return -1; 01331 } 01332 01333 /* 01334 * Cast to a ADD_ROSPEC_RESPONSE message. 01335 */ 01336 pRsp = (CADD_ROSPEC_RESPONSE *) pRspMsg; 01337 01338 /* 01339 * Check the LLRPStatus parameter. 01340 */ 01341 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "addROSpec")) 01342 { 01343 /* checkLLRPStatus already tattled */ 01344 delete pRspMsg; 01345 return -1; 01346 } 01347 01348 /* 01349 * Done with the response message. 01350 */ 01351 delete pRspMsg; 01352 01353 /* 01354 * Tattle progress, maybe 01355 */ 01356 if(m_Verbose) 01357 { 01358 printf("INFO: ROSpec added\n"); 01359 } 01360 01361 /* 01362 * Victory. 01363 */ 01364 return 0; 01365 } 01366 01367 01385 int 01386 CMyApplication::enableROSpec (void) 01387 { 01388 CENABLE_ROSPEC * pCmd; 01389 CMessage * pRspMsg; 01390 CENABLE_ROSPEC_RESPONSE * pRsp; 01391 01392 /* 01393 * Compose the command message 01394 */ 01395 pCmd = new CENABLE_ROSPEC(); 01396 pCmd->setMessageID(m_messageID++); 01397 pCmd->setROSpecID(1111); 01398 01399 /* 01400 * Send the message, expect the response of certain type 01401 */ 01402 pRspMsg = transact(pCmd); 01403 01404 /* 01405 * Done with the command message 01406 */ 01407 delete pCmd; 01408 01409 /* 01410 * transact() returns NULL if something went wrong. 01411 */ 01412 if(NULL == pRspMsg) 01413 { 01414 /* transact already tattled */ 01415 return -1; 01416 } 01417 01418 /* 01419 * Cast to a ENABLE_ROSPEC_RESPONSE message. 01420 */ 01421 pRsp = (CENABLE_ROSPEC_RESPONSE *) pRspMsg; 01422 01423 /* 01424 * Check the LLRPStatus parameter. 01425 */ 01426 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "enableROSpec")) 01427 { 01428 /* checkLLRPStatus already tattled */ 01429 delete pRspMsg; 01430 return -1; 01431 } 01432 01433 /* 01434 * Done with the response message. 01435 */ 01436 delete pRspMsg; 01437 01438 /* 01439 * Tattle progress, maybe 01440 */ 01441 if(m_Verbose) 01442 { 01443 printf("INFO: ROSpec enabled\n"); 01444 } 01445 01446 /* 01447 * Victory. 01448 */ 01449 return 0; 01450 } 01451 01452 01470 int 01471 CMyApplication::startROSpec (void) 01472 { 01473 CSTART_ROSPEC * pCmd; 01474 CMessage * pRspMsg; 01475 CSTART_ROSPEC_RESPONSE * pRsp; 01476 01477 /* 01478 * Compose the command message 01479 */ 01480 pCmd = new CSTART_ROSPEC(); 01481 pCmd->setMessageID(m_messageID++); 01482 pCmd->setROSpecID(1111); 01483 01484 /* 01485 * Send the message, expect the response of certain type 01486 */ 01487 pRspMsg = transact(pCmd); 01488 01489 /* 01490 * Done with the command message 01491 */ 01492 delete pCmd; 01493 01494 /* 01495 * transact() returns NULL if something went wrong. 01496 */ 01497 if(NULL == pRspMsg) 01498 { 01499 /* transact already tattled */ 01500 return -1; 01501 } 01502 01503 /* 01504 * Cast to a START_ROSPEC_RESPONSE message. 01505 */ 01506 pRsp = (CSTART_ROSPEC_RESPONSE *) pRspMsg; 01507 01508 /* 01509 * Check the LLRPStatus parameter. 01510 */ 01511 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "startROSpec")) 01512 { 01513 /* checkLLRPStatus already tattled */ 01514 delete pRspMsg; 01515 return -1; 01516 } 01517 01518 /* 01519 * Done with the response message. 01520 */ 01521 delete pRspMsg; 01522 01523 /* 01524 * Tattle progress 01525 */ 01526 if(m_Verbose) 01527 { 01528 printf("INFO: ROSpec started\n"); 01529 } 01530 01531 /* 01532 * Victory. 01533 */ 01534 return 0; 01535 } 01536 01554 int 01555 CMyApplication::stopROSpec (void) 01556 { 01557 CSTOP_ROSPEC * pCmd; 01558 CMessage * pRspMsg; 01559 CSTOP_ROSPEC_RESPONSE * pRsp; 01560 01561 /* 01562 * Compose the command message 01563 */ 01564 pCmd = new CSTOP_ROSPEC(); 01565 pCmd->setMessageID(m_messageID++); 01566 pCmd->setROSpecID(1111); 01567 01568 /* 01569 * Send the message, expect the response of certain type 01570 */ 01571 pRspMsg = transact(pCmd); 01572 01573 /* 01574 * Done with the command message 01575 */ 01576 delete pCmd; 01577 01578 /* 01579 * transact() returns NULL if something went wrong. 01580 */ 01581 if(NULL == pRspMsg) 01582 { 01583 /* transact already tattled */ 01584 return -1; 01585 } 01586 01587 /* 01588 * Cast to a STOP_ROSPEC_RESPONSE message. 01589 */ 01590 pRsp = (CSTOP_ROSPEC_RESPONSE *) pRspMsg; 01591 01592 /* 01593 * Check the LLRPStatus parameter. 01594 */ 01595 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "stopROSpec")) 01596 { 01597 /* checkLLRPStatus already tattled */ 01598 delete pRspMsg; 01599 return -1; 01600 } 01601 01602 /* 01603 * Done with the response message. 01604 */ 01605 delete pRspMsg; 01606 01607 /* 01608 * Tattle progress 01609 */ 01610 if(m_Verbose) 01611 { 01612 printf("INFO: ROSpec stopped\n"); 01613 } 01614 01615 /* 01616 * Victory. 01617 */ 01618 return 0; 01619 } 01620 01633 int 01634 CMyApplication::addAccessSpec (void) 01635 { 01636 CADD_ACCESSSPEC * pCmd; 01637 CMessage * pRspMsg; 01638 CADD_ACCESSSPEC_RESPONSE * pRsp; 01639 01640 pCmd = new CADD_ACCESSSPEC(); 01641 pCmd->setMessageID(m_messageID++); 01642 01643 /* build the C1G2Target Tag with the AccessSpec filter */ 01644 CC1G2TargetTag *ptargetTag = new CC1G2TargetTag(); 01645 ptargetTag->setMatch(true); 01646 ptargetTag->setMB(1); 01647 ptargetTag->setPointer(16); 01648 01649 /* match any tag */ 01650 llrp_u1v_t tagData = llrp_u1v_t(0); 01651 tagData.m_nBit = 0; 01652 ptargetTag->setTagData(tagData); 01653 llrp_u1v_t tagMask = llrp_u1v_t(0); 01654 tagMask.m_nBit = 0; 01655 ptargetTag->setTagMask(tagMask); 01656 01657 /* build the AirProtocolTagSpec Add the filter */ 01658 CC1G2TagSpec *ptagSpec = new CC1G2TagSpec(); 01659 ptagSpec->addC1G2TargetTag(ptargetTag); 01660 01661 /* Create the AccessCommand. Add the TagSpec and the OpSpec */ 01662 CAccessCommand *pAccessCommand = new CAccessCommand(); 01663 pAccessCommand->setAirProtocolTagSpec(ptagSpec); 01664 01665 /* Build the read Op Spec and add to the access command */ 01666 /* 01667 ** -q <n> -- run QT scenario n where n is defined as 01668 ** 0 -- Read standard TID memory 01669 ** 1 -- set tag password (uses -p, -n) 01670 ** 2 -- Read private memory data without QT commands 01671 ** 3 -- read QT status of tag (uses -p) 01672 ** 4 -- set QT status of tag to private (uses -p, -s) 01673 ** 5 -- set QT status of tag to public (uses -p, -s) 01674 ** 6 -- Peek at private memory data with temporary QT command (uses -p) 01675 ** 7 -- write random data to user memory 01676 ** 8 -- write random data to the public EPC space 01677 */ 01678 01679 switch(m_qtmode) 01680 { 01681 case 0: 01682 { 01683 CC1G2Read *preadStdTID = new CC1G2Read(); 01684 preadStdTID->setAccessPassword(0); /* no access required to read */ 01685 preadStdTID->setMB(2); 01686 preadStdTID->setOpSpecID(1); 01687 preadStdTID->setWordCount(2); /* standard TID */ 01688 preadStdTID->setWordPointer(0); 01689 pAccessCommand->addAccessCommandOpSpec(preadStdTID); 01690 } 01691 break; 01692 case 1: 01693 { 01694 llrp_u16v_t Data = llrp_u16v_t(2); 01695 Data.m_pValue[0] = ((m_newPassword >> 16) & 0x0000ffff); 01696 Data.m_pValue[1] = (m_newPassword & 0x0000ffff); 01697 01698 CC1G2Write *pwrite = new CC1G2Write(); 01699 pwrite->setOpSpecID(10); 01700 pwrite->setMB(0); 01701 pwrite->setAccessPassword(m_password); 01702 pwrite->setWordPointer(2); 01703 pwrite->setWriteData(Data); 01704 pAccessCommand->addAccessCommandOpSpec(pwrite); 01705 } 01706 break; 01707 case 2: 01708 { 01709 CC1G2Read *preadSTID = new CC1G2Read(); 01710 preadSTID->setAccessPassword(0); /* no access required to read */ 01711 preadSTID->setMB(2); 01712 preadSTID->setOpSpecID(2); 01713 preadSTID->setWordCount(6); /* standard TID plus 48 bit STID */ 01714 preadSTID->setWordPointer(0); 01715 pAccessCommand->addAccessCommandOpSpec(preadSTID); 01716 01717 CC1G2Read *preadPEPC = new CC1G2Read(); 01718 preadPEPC->setAccessPassword(0); /* no access required to read */ 01719 preadPEPC->setMB(2); 01720 preadPEPC->setOpSpecID(2); 01721 preadPEPC->setWordCount(6); /* Public EPC memory */ 01722 preadPEPC->setWordPointer(6); 01723 pAccessCommand->addAccessCommandOpSpec(preadPEPC); 01724 01725 CC1G2Read *preadUser = new CC1G2Read(); 01726 preadUser->setAccessPassword(0); /* no access required to read */ 01727 preadUser->setMB(3); 01728 preadUser->setOpSpecID(3); 01729 preadUser->setWordCount(32); /* 512 bits of user memory */ 01730 preadUser->setWordPointer(0); 01731 pAccessCommand->addAccessCommandOpSpec(preadUser); 01732 } 01733 break; 01734 default: 01735 /* for unknown, just try to read QT status */ 01736 case 3: 01737 { 01738 CImpinjGetQTConfig *pgetQT = new CImpinjGetQTConfig(); 01739 pgetQT->setAccessPassword(m_password); /* use password if provided */ 01740 pgetQT->setOpSpecID(4); 01741 pAccessCommand->addAccessCommandOpSpec(pgetQT); 01742 } 01743 break; 01744 case 4: 01745 { 01746 CImpinjSetQTConfig *psetQT = new CImpinjSetQTConfig(); 01747 psetQT->setAccessPassword(m_password); 01748 psetQT->setOpSpecID(5); 01749 psetQT->setAccessRange(m_shortRange); 01750 psetQT->setDataProfile(ImpinjQTDataProfile_Private); 01751 psetQT->setPersistence(ImpinjQTPersistence_Permanent); 01752 pAccessCommand->addAccessCommandOpSpec(psetQT); 01753 } 01754 break; 01755 case 5: 01756 { 01757 CImpinjSetQTConfig *psetQT = new CImpinjSetQTConfig(); 01758 psetQT->setAccessPassword(m_password); 01759 psetQT->setOpSpecID(6); 01760 psetQT->setAccessRange(m_shortRange); 01761 psetQT->setDataProfile(ImpinjQTDataProfile_Public); 01762 psetQT->setPersistence(ImpinjQTPersistence_Permanent); 01763 pAccessCommand->addAccessCommandOpSpec(psetQT); 01764 } 01765 break; 01766 case 6: 01767 { 01768 CImpinjSetQTConfig *psetQT = new CImpinjSetQTConfig(); 01769 psetQT->setAccessPassword(m_password); 01770 psetQT->setOpSpecID(6); 01771 psetQT->setAccessRange(ImpinjQTAccessRange_Normal_Range ); 01772 psetQT->setDataProfile(ImpinjQTDataProfile_Private); 01773 psetQT->setPersistence(ImpinjQTPersistence_Temporary ); 01774 pAccessCommand->addAccessCommandOpSpec(psetQT); 01775 01776 CC1G2Read *preadPrivEPC = new CC1G2Read(); 01777 preadPrivEPC->setAccessPassword(0); /* no access required to read */ 01778 preadPrivEPC->setMB(1); 01779 preadPrivEPC->setOpSpecID(7); 01780 preadPrivEPC->setWordCount(8); /* assume 128-bit */ 01781 preadPrivEPC->setWordPointer(2); 01782 pAccessCommand->addAccessCommandOpSpec(preadPrivEPC); 01783 01784 CC1G2Read *preadSTID = new CC1G2Read(); 01785 preadSTID->setAccessPassword(0); /* no access required to read */ 01786 preadSTID->setMB(2); 01787 preadSTID->setOpSpecID(8); 01788 preadSTID->setWordCount(6); /* standard TID plus 48 bit STID */ 01789 preadSTID->setWordPointer(0); 01790 pAccessCommand->addAccessCommandOpSpec(preadSTID); 01791 01792 CC1G2Read *preadUser = new CC1G2Read(); 01793 preadUser->setAccessPassword(0); /* no access required to read */ 01794 preadUser->setMB(3); 01795 preadUser->setOpSpecID(9); 01796 preadUser->setWordCount(32); 01797 preadUser->setWordPointer(0); 01798 pAccessCommand->addAccessCommandOpSpec(preadUser); 01799 } 01800 break; 01801 case 7: 01802 { 01803 llrp_u16v_t Data = llrp_u16v_t(32); 01804 01805 for(int x = 0; x < 32; x++) 01806 { 01807 Data.m_pValue[x] = rand(); 01808 } 01809 01810 CC1G2Write *pwrite = new CC1G2Write(); 01811 pwrite->setOpSpecID(10); 01812 pwrite->setMB(3); 01813 pwrite->setAccessPassword(m_password); 01814 pwrite->setWordPointer(0); 01815 pwrite->setWriteData(Data); 01816 pAccessCommand->addAccessCommandOpSpec(pwrite); 01817 } 01818 break; 01819 case 8: 01820 { 01821 llrp_u16v_t Data = llrp_u16v_t(6); 01822 01823 for(int x = 0; x < 6; x++) 01824 { 01825 Data.m_pValue[x] = rand(); 01826 } 01827 01828 CC1G2Write *pwrite = new CC1G2Write(); 01829 pwrite->setOpSpecID(11); 01830 pwrite->setMB(2); 01831 pwrite->setAccessPassword(m_password); 01832 pwrite->setWordPointer(6); 01833 pwrite->setWriteData(Data); 01834 pAccessCommand->addAccessCommandOpSpec(pwrite); 01835 } 01836 break; 01837 case 9: 01838 { 01839 CC1G2Read *preadRsvd = new CC1G2Read(); 01840 preadRsvd->setAccessPassword(0); /* no access required to read */ 01841 preadRsvd->setMB(0); 01842 preadRsvd->setOpSpecID(12); 01843 preadRsvd->setWordCount(4); /* Access and Kill */ 01844 preadRsvd->setWordPointer(0); 01845 pAccessCommand->addAccessCommandOpSpec(preadRsvd); 01846 } 01847 break; 01848 } 01849 01850 /* set up the Access Report Spec rule to report only with ROSpecs */ 01851 CAccessReportSpec *pAccessReportSpec = new CAccessReportSpec(); 01852 pAccessReportSpec->setAccessReportTrigger( 01853 AccessReportTriggerType_Whenever_ROReport_Is_Generated); 01854 01855 /* set up the stop trigger for the access spec. Do not stop */ 01856 CAccessSpecStopTrigger *pAccessStopTrigger = new CAccessSpecStopTrigger(); 01857 pAccessStopTrigger->setAccessSpecStopTrigger( 01858 AccessSpecStopTriggerType_Null); 01859 pAccessStopTrigger->setOperationCountValue(0); /* ignored */ 01860 01861 /* Create and configure the AccessSpec */ 01862 CAccessSpec *pAccessSpec = new CAccessSpec(); 01863 pAccessSpec->setAccessSpecID(23); 01864 pAccessSpec->setAntennaID(0); /* valid for all antennas */ 01865 pAccessSpec->setCurrentState(AccessSpecState_Disabled); 01866 pAccessSpec->setProtocolID(AirProtocols_EPCGlobalClass1Gen2); 01867 pAccessSpec->setROSpecID(0); /* valid for All RoSpecs */ 01868 pAccessSpec->setAccessSpecStopTrigger(pAccessStopTrigger); 01869 pAccessSpec->setAccessReportSpec(pAccessReportSpec); 01870 pAccessSpec->setAccessCommand(pAccessCommand); 01871 01872 /* Add the AccessSpec to the ADD_ACCESS_SPEC message */ 01873 pCmd->setAccessSpec(pAccessSpec); 01874 01875 /* 01876 * Send the message, expect the response of certain type 01877 */ 01878 pRspMsg = transact(pCmd); 01879 01880 /* 01881 * Done with the command message 01882 */ 01883 delete pCmd; 01884 01885 /* 01886 * transact() returns NULL if something went wrong. 01887 */ 01888 if(NULL == pRspMsg) 01889 { 01890 /* transact already tattled */ 01891 return -1; 01892 } 01893 01894 /* 01895 * Cast to a ADD_ACCESSSPEC_RESPONSE message. 01896 */ 01897 pRsp = (CADD_ACCESSSPEC_RESPONSE *) pRspMsg; 01898 01899 /* 01900 * Check the LLRPStatus parameter. 01901 */ 01902 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "addAccessSpec")) 01903 { 01904 /* checkLLRPStatus already tattled */ 01905 delete pRspMsg; 01906 return -1; 01907 } 01908 01909 /* 01910 * Done with the response message. 01911 */ 01912 delete pRspMsg; 01913 01914 /* 01915 * Tattle progress, maybe 01916 */ 01917 if(m_Verbose) 01918 { 01919 printf("INFO: AccessSpec added\n"); 01920 } 01921 01922 /* 01923 * Victory. 01924 */ 01925 return 0; 01926 } 01927 01928 01942 int 01943 CMyApplication::enableAccessSpec (void) 01944 { 01945 CENABLE_ACCESSSPEC * pCmd; 01946 CMessage * pRspMsg; 01947 CENABLE_ACCESSSPEC_RESPONSE * pRsp; 01948 01949 /* 01950 * Compose the command message 01951 */ 01952 pCmd = new CENABLE_ACCESSSPEC(); 01953 pCmd->setMessageID(m_messageID++); 01954 pCmd->setAccessSpecID(23); 01955 01956 /* 01957 * Send the message, expect the response of certain type 01958 */ 01959 pRspMsg = transact(pCmd); 01960 01961 /* 01962 * Done with the command message 01963 */ 01964 delete pCmd; 01965 01966 /* 01967 * transact() returns NULL if something went wrong. 01968 */ 01969 if(NULL == pRspMsg) 01970 { 01971 /* transact already tattled */ 01972 return -1; 01973 } 01974 01975 /* 01976 * Cast to a ENABLE_ACCESSSPEC_RESPONSE message. 01977 */ 01978 pRsp = (CENABLE_ACCESSSPEC_RESPONSE *) pRspMsg; 01979 01980 /* 01981 * Check the LLRPStatus parameter. 01982 */ 01983 if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "enableAccessSpec")) 01984 { 01985 /* checkLLRPStatus already tattled */ 01986 delete pRspMsg; 01987 return -1; 01988 } 01989 01990 /* 01991 * Done with the response message. 01992 */ 01993 delete pRspMsg; 01994 01995 /* 01996 * Tattle progress, maybe 01997 */ 01998 if(m_Verbose) 01999 { 02000 printf("INFO: AccessSpec enabled\n"); 02001 } 02002 02003 /* 02004 * Victory. 02005 */ 02006 return 0; 02007 } 02008 02009 02029 int 02030 CMyApplication::awaitAndPrintReport (int timeout) 02031 { 02032 int bDone = 0; 02033 int retVal = 0; 02034 time_t startTime = time(NULL); 02035 time_t tempTime; 02036 /* 02037 * Keep receiving messages until done or until 02038 * something bad happens. 02039 */ 02040 while(!bDone) 02041 { 02042 CMessage * pMessage; 02043 const CTypeDescriptor * pType; 02044 02045 /* 02046 * Wait up to 1 second for a report. Check 02047 * That way, we can check the timestamp even if 02048 * there are no reports coming in 02049 */ 02050 pMessage = recvMessage(1000); 02051 02052 /* validate the timestamp */ 02053 tempTime = time(NULL); 02054 if(difftime(tempTime, startTime) > timeout) 02055 { 02056 bDone=1; 02057 } 02058 02059 if(NULL == pMessage) 02060 { 02061 continue; 02062 } 02063 02064 /* 02065 * What happens depends on what kind of message 02066 * received. Use the type label (m_pType) to 02067 * discriminate message types. 02068 */ 02069 pType = pMessage->m_pType; 02070 02071 /* 02072 * Is it a tag report? If so, print it out. 02073 */ 02074 if(&CRO_ACCESS_REPORT::s_typeDescriptor == pType) 02075 { 02076 CRO_ACCESS_REPORT * pNtf; 02077 02078 pNtf = (CRO_ACCESS_REPORT *) pMessage; 02079 02080 printTagReportData(pNtf); 02081 } 02082 02083 /* 02084 * Is it a reader event? This example only recognizes 02085 * AntennaEvents. 02086 */ 02087 else if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor == pType) 02088 { 02089 CREADER_EVENT_NOTIFICATION *pNtf; 02090 CReaderEventNotificationData *pNtfData; 02091 02092 pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage; 02093 02094 pNtfData = pNtf->getReaderEventNotificationData(); 02095 if(NULL != pNtfData) 02096 { 02097 handleReaderEventNotification(pNtfData); 02098 } 02099 else 02100 { 02101 /* 02102 * This should never happen. Using continue 02103 * to keep indent depth down. 02104 */ 02105 printf("WARNING: READER_EVENT_NOTIFICATION without data\n"); 02106 } 02107 } 02108 02109 /* 02110 * Hmmm. Something unexpected. Just tattle and keep going. 02111 */ 02112 else 02113 { 02114 printf("WARNING: Ignored unexpected message during monitor: %s\n", 02115 pType->m_pName); 02116 } 02117 02118 /* 02119 * Done with the received message 02120 */ 02121 delete pMessage; 02122 } 02123 02124 return retVal; 02125 } 02126 02127 02142 void 02143 CMyApplication::printTagReportData ( 02144 CRO_ACCESS_REPORT * pRO_ACCESS_REPORT) 02145 { 02146 std::list<CTagReportData *>::iterator Cur; 02147 02148 unsigned int nEntry = 0; 02149 02150 /* 02151 * Loop through and count the number of entries 02152 */ 02153 for( 02154 Cur = pRO_ACCESS_REPORT->beginTagReportData(); 02155 Cur != pRO_ACCESS_REPORT->endTagReportData(); 02156 Cur++) 02157 { 02158 nEntry++; 02159 } 02160 02161 if(m_Verbose) 02162 { 02163 printf("INFO: %u tag report entries\n", nEntry); 02164 } 02165 02166 /* 02167 * Loop through again and print each entry. 02168 */ 02169 for( 02170 Cur = pRO_ACCESS_REPORT->beginTagReportData(); 02171 Cur != pRO_ACCESS_REPORT->endTagReportData(); 02172 Cur++) 02173 { 02174 printOneTagReportData(*Cur); 02175 } 02176 } 02177 02178 02187 int 02188 CMyApplication::formatOneEPC ( 02189 CParameter *pEPCParameter, 02190 char *buf, 02191 int buflen, 02192 char * startStr) 02193 { 02194 char * p = buf; 02195 int bufsize = buflen; 02196 int written = 0; 02197 02198 written = snprintf(p, bufsize, "%s", startStr); 02199 bufsize -= written; 02200 p += written; 02201 02202 if(NULL != pEPCParameter) 02203 { 02204 const CTypeDescriptor * pType; 02205 llrp_u96_t my_u96; 02206 llrp_u1v_t my_u1v; 02207 llrp_u8_t * pValue = NULL; 02208 unsigned int n, i; 02209 02210 pType = pEPCParameter->m_pType; 02211 if(&CEPC_96::s_typeDescriptor == pType) 02212 { 02213 CEPC_96 *pEPC_96; 02214 02215 pEPC_96 = (CEPC_96 *) pEPCParameter; 02216 my_u96 = pEPC_96->getEPC(); 02217 pValue = my_u96.m_aValue; 02218 n = 12u; 02219 } 02220 else if(&CEPCData::s_typeDescriptor == pType) 02221 { 02222 CEPCData * pEPCData; 02223 02224 pEPCData = (CEPCData *) pEPCParameter; 02225 my_u1v = pEPCData->getEPC(); 02226 pValue = my_u1v.m_pValue; 02227 n = (my_u1v.m_nBit + 7u) / 8u; 02228 } 02229 02230 if(NULL != pValue) 02231 { 02232 for(i = 0; i < n; i++) 02233 { 02234 if(0 < i && i%2 == 0 && 1 < bufsize) 02235 { 02236 *p++ = '-'; 02237 bufsize--; 02238 } 02239 if(bufsize > 2) 02240 { 02241 written = snprintf(p, bufsize, "%02X", pValue[i]); 02242 bufsize -= written; 02243 p+= written; 02244 } 02245 } 02246 } 02247 else 02248 { 02249 written = snprintf(p, bufsize, "%s", "---unknown-epc-data-type---"); 02250 bufsize -= written; 02251 p += written; 02252 } 02253 } 02254 else 02255 { 02256 written = snprintf(p, bufsize, "%s", "--null epc---"); 02257 bufsize -= written; 02258 p += written; 02259 } 02260 02261 // null terminate this for good practice 02262 buf[buflen-1] = '\0'; 02263 02264 return buflen - bufsize; 02265 } 02266 02275 int 02276 CMyApplication::formatOneReadResult ( 02277 CParameter *pOpSpecReadResult, 02278 char *buf, 02279 int buflen, 02280 char * startStr) 02281 { 02282 EC1G2ReadResultType result; 02283 char * p = buf; 02284 int written = 0; 02285 int bufsize = buflen; 02286 int i; 02287 llrp_u16v_t readData; 02288 CC1G2ReadOpSpecResult *pread = (CC1G2ReadOpSpecResult*) pOpSpecReadResult; 02289 02290 written = snprintf(p, bufsize, "%s", startStr); 02291 bufsize -= written; 02292 p += written; 02293 02294 result = pread->getResult(); 02295 written = snprintf(p, bufsize, "result=%d", result); 02296 p+= written; 02297 bufsize -= written; 02298 02299 if(result == C1G2ReadResultType_Success) 02300 { 02301 readData = pread->getReadData(); 02302 02303 written = snprintf(p, bufsize, " Data="); 02304 p+= written; 02305 bufsize -= written; 02306 02307 for(i = 0; i < readData.m_nValue - 1 ; i++) 02308 { 02309 written =snprintf(p, bufsize, "%04x-", readData.m_pValue[i]); 02310 p+= written; 02311 bufsize -= written; 02312 } 02313 if(readData.m_nValue) 02314 { 02315 written =snprintf(p, bufsize, "%04x", readData.m_pValue[i]); 02316 p+= written; 02317 bufsize -= written; 02318 } 02319 } 02320 buf[buflen-1] = '\0'; 02321 return buflen - bufsize; 02322 } 02323 02332 int 02333 CMyApplication::formatOneWriteResult ( 02334 CParameter *pOpSpecReadResult, 02335 char *buf, 02336 int buflen, 02337 char * startStr) 02338 { 02339 EC1G2WriteResultType result; 02340 char * p = buf; 02341 int written = 0; 02342 int bufsize = buflen; 02343 llrp_u16v_t readData; 02344 CC1G2WriteOpSpecResult *pwrite = (CC1G2WriteOpSpecResult*) pOpSpecReadResult; 02345 02346 written = snprintf(p, bufsize, "%s", startStr); 02347 bufsize -= written; 02348 p += written; 02349 02350 result = pwrite->getResult(); 02351 written = snprintf(p, bufsize, "result=%d", result); 02352 p+= written; 02353 bufsize -= written; 02354 02355 buf[buflen-1] = '\0'; 02356 return buflen - bufsize; 02357 } 02358 02367 int 02368 CMyApplication::formatOneSetQTConfigResult ( 02369 CParameter *pSetQTConfig, 02370 char *buf, 02371 int buflen, 02372 char * startStr) 02373 { 02374 EImpinjSetQTConfigResultType result; 02375 char * p = buf; 02376 02377 int written = 0; 02378 int bufsize = buflen; 02379 llrp_u16v_t readData; 02380 CImpinjSetQTConfigOpSpecResult *pset = (CImpinjSetQTConfigOpSpecResult*) pSetQTConfig; 02381 02382 written = snprintf(p, bufsize, "%s", startStr); 02383 bufsize -= written; 02384 p += written; 02385 02386 result = pset->getResult(); 02387 02388 written = snprintf(p, bufsize, "result=%d", result); 02389 p+= written; 02390 bufsize -= written; 02391 02392 buf[buflen-1] = '\0'; 02393 return buflen - bufsize; 02394 } 02395 02404 int 02405 CMyApplication::formatOneGetQTConfigResult ( 02406 CParameter *pSetQTConfig, 02407 char *buf, 02408 int buflen, 02409 char * startStr) 02410 { 02411 EImpinjGetQTConfigResultType result; 02412 char * p = buf; 02413 int written = 0; 02414 int bufsize = buflen; 02415 llrp_u16v_t readData; 02416 const char * dataStrings[3] = { "Unknown", 02417 "Private", 02418 "Public"}; 02419 02420 const char * rangeStrings[3] = { "Unknown", 02421 "Normal", 02422 "Short"}; 02423 02424 CImpinjGetQTConfigOpSpecResult *pset = (CImpinjGetQTConfigOpSpecResult*) pSetQTConfig; 02425 02426 written = snprintf(p, bufsize, "%s", startStr); 02427 bufsize -= written; 02428 p += written; 02429 02430 result = pset->getResult(); 02431 written = snprintf(p, bufsize, "result=%d ", result); 02432 p+= written; 02433 bufsize -= written; 02434 02435 if(ImpinjGetQTConfigResultType_Success == result) 02436 { 02437 written = snprintf(p, bufsize, "data=%s range=%s\n", 02438 dataStrings[pset->getDataProfile()], 02439 rangeStrings[pset->getAccessRange()]); 02440 p+= written; 02441 bufsize -= written; 02442 } 02443 02444 buf[buflen-1] = '\0'; 02445 return buflen - bufsize; 02446 } 02447 02448 02457 int 02458 CMyApplication::formatOneSerializedTID ( 02459 CParameter *pSerializedTID, 02460 char *buf, 02461 int buflen, 02462 char * startStr) 02463 { 02464 char * p = buf; 02465 int written = 0; 02466 int bufsize = buflen; 02467 02468 CImpinjSerializedTID *pTID = (CImpinjSerializedTID*) pSerializedTID; 02469 02470 written = snprintf(p, bufsize, "%s", startStr); 02471 bufsize -= written; 02472 p += written; 02473 02474 llrp_u16v_t tid = pTID->getTID(); 02475 02476 for(int i = 0; i < tid.m_nValue; i++) 02477 { 02478 if(0 < i && i%2 == 0 && 1 < bufsize) 02479 { 02480 *p++ = '-'; 02481 bufsize--; 02482 } 02483 if(bufsize > 2) 02484 { 02485 written = snprintf(p, bufsize, "%02X", tid.m_pValue[i]); 02486 bufsize -= written; 02487 p+= written; 02488 } 02489 } 02490 02491 buf[buflen-1] = '\0'; 02492 return buflen - bufsize; 02493 } 02494 02503 void 02504 CMyApplication::printOneTagReportData ( 02505 CTagReportData * pTagReportData) 02506 { 02507 const int bufSize = 1024; 02508 char aBuf[bufSize]; 02509 char *ptr = aBuf; 02510 int written = 0; 02511 int bufLimit = bufSize; 02512 02513 std::list<CParameter *>::iterator OpSpecResults; 02514 std::list<CParameter *>::iterator Cur; 02515 02516 /* 02517 * Print the EPC. It could be an 96-bit EPC_96 parameter 02518 * or an variable length EPCData parameter. 02519 */ 02520 02521 CParameter * pEPCParameter = 02522 pTagReportData->getEPCParameter(); 02523 02524 written = formatOneEPC(pEPCParameter, ptr, bufLimit, "epc="); 02525 ptr += written; 02526 bufLimit-=written; 02527 02528 aBuf[bufSize-1] = '\0'; 02529 /* 02530 ** Handle a few of the op Spec result types 02531 */ 02532 for ( 02533 OpSpecResults = pTagReportData->beginAccessCommandOpSpecResult(); 02534 OpSpecResults != pTagReportData->endAccessCommandOpSpecResult(); 02535 OpSpecResults++) 02536 { 02537 if( (*OpSpecResults)->m_pType == &CC1G2ReadOpSpecResult::s_typeDescriptor) 02538 { 02539 written = formatOneReadResult(*OpSpecResults, ptr, bufLimit, "\n READ "); 02540 ptr += written; 02541 bufLimit-=written; 02542 } 02543 else if( (*OpSpecResults)->m_pType == &CC1G2WriteOpSpecResult::s_typeDescriptor) 02544 { 02545 written = formatOneWriteResult(*OpSpecResults, ptr, bufLimit, "\n WRITE "); 02546 ptr += written; 02547 bufLimit-=written; 02548 } 02549 else if( (*OpSpecResults)->m_pType == &CImpinjSetQTConfigOpSpecResult::s_typeDescriptor) 02550 { 02551 written = formatOneSetQTConfigResult(*OpSpecResults, ptr, bufLimit, "\n SETQT "); 02552 ptr += written; 02553 bufLimit-=written; 02554 } 02555 else if( (*OpSpecResults)->m_pType == &CImpinjGetQTConfigOpSpecResult::s_typeDescriptor) 02556 { 02557 written = formatOneGetQTConfigResult(*OpSpecResults, ptr, bufLimit, "\n GETQT "); 02558 ptr += written; 02559 bufLimit-=written; 02560 } 02561 } 02562 02563 /* look for custom parameters like TID */ 02564 for( 02565 Cur = pTagReportData->beginCustom(); 02566 Cur != pTagReportData->endCustom(); 02567 Cur++) 02568 { 02569 /* look for our special Impinj Tag Report Data */ 02570 if(&CImpinjSerializedTID ::s_typeDescriptor == (*Cur)->m_pType) 02571 { 02572 written = formatOneSerializedTID(*Cur, ptr, bufLimit, "\n SERIAL-TID "); 02573 ptr += written; 02574 bufLimit -= written; 02575 } 02576 } 02577 02578 /* 02579 * End of line 02580 */ 02581 printf("%s\n", aBuf); 02582 } 02583 02584 02598 void 02599 CMyApplication::handleReaderEventNotification ( 02600 CReaderEventNotificationData *pNtfData) 02601 { 02602 CAntennaEvent * pAntennaEvent; 02603 CReaderExceptionEvent * pReaderExceptionEvent; 02604 int nReported = 0; 02605 02606 pAntennaEvent = pNtfData->getAntennaEvent(); 02607 if(NULL != pAntennaEvent) 02608 { 02609 handleAntennaEvent(pAntennaEvent); 02610 nReported++; 02611 } 02612 02613 pReaderExceptionEvent = pNtfData->getReaderExceptionEvent(); 02614 if(NULL != pReaderExceptionEvent) 02615 { 02616 handleReaderExceptionEvent(pReaderExceptionEvent); 02617 nReported++; 02618 } 02619 02620 /* 02621 * Similarly handle other events here: 02622 * HoppingEvent 02623 * GPIEvent 02624 * ROSpecEvent 02625 * ReportBufferLevelWarningEvent 02626 * ReportBufferOverflowErrorEvent 02627 * RFSurveyEvent 02628 * AISpecEvent 02629 * ConnectionAttemptEvent 02630 * ConnectionCloseEvent 02631 * Custom 02632 */ 02633 02634 if(0 == nReported) 02635 { 02636 printf("NOTICE: Unexpected (unhandled) ReaderEvent\n"); 02637 } 02638 } 02639 02640 02652 void 02653 CMyApplication::handleAntennaEvent ( 02654 CAntennaEvent * pAntennaEvent) 02655 { 02656 EAntennaEventType eEventType; 02657 llrp_u16_t AntennaID; 02658 char * pStateStr; 02659 02660 eEventType = pAntennaEvent->getEventType(); 02661 AntennaID = pAntennaEvent->getAntennaID(); 02662 02663 switch(eEventType) 02664 { 02665 case AntennaEventType_Antenna_Disconnected: 02666 pStateStr = "disconnected"; 02667 break; 02668 02669 case AntennaEventType_Antenna_Connected: 02670 pStateStr = "connected"; 02671 break; 02672 02673 default: 02674 pStateStr = "?unknown-event?"; 02675 break; 02676 } 02677 02678 printf("NOTICE: Antenna %d is %s\n", AntennaID, pStateStr); 02679 } 02680 02681 02694 void 02695 CMyApplication::handleReaderExceptionEvent ( 02696 CReaderExceptionEvent * pReaderExceptionEvent) 02697 { 02698 llrp_utf8v_t Message; 02699 02700 Message = pReaderExceptionEvent->getMessage(); 02701 02702 if(0 < Message.m_nValue && NULL != Message.m_pValue) 02703 { 02704 printf("NOTICE: ReaderException '%.*s'\n", 02705 Message.m_nValue, Message.m_pValue); 02706 } 02707 else 02708 { 02709 printf("NOTICE: ReaderException but no message\n"); 02710 } 02711 } 02712 02713 02732 int 02733 CMyApplication::checkLLRPStatus ( 02734 CLLRPStatus * pLLRPStatus, 02735 char * pWhatStr) 02736 { 02737 /* 02738 * The LLRPStatus parameter is mandatory in all responses. 02739 * If it is missing there should have been a decode error. 02740 * This just makes sure (remember, this program is a 02741 * diagnostic and suppose to catch LTKC mistakes). 02742 */ 02743 if(NULL == pLLRPStatus) 02744 { 02745 printf("ERROR: %s missing LLRP status\n", pWhatStr); 02746 return -1; 02747 } 02748 02749 /* 02750 * Make sure the status is M_Success. 02751 * If it isn't, print the error string if one. 02752 * This does not try to pretty-print the status 02753 * code. To get that, run this program with -vv 02754 * and examine the XML output. 02755 */ 02756 if(StatusCode_M_Success != pLLRPStatus->getStatusCode()) 02757 { 02758 llrp_utf8v_t ErrorDesc; 02759 02760 ErrorDesc = pLLRPStatus->getErrorDescription(); 02761 02762 if(0 == ErrorDesc.m_nValue) 02763 { 02764 printf("ERROR: %s failed, no error description given\n", 02765 pWhatStr); 02766 } 02767 else 02768 { 02769 printf("ERROR: %s failed, %.*s\n", 02770 pWhatStr, ErrorDesc.m_nValue, ErrorDesc.m_pValue); 02771 } 02772 return -2; 02773 } 02774 02775 /* 02776 * Victory. Everything is fine. 02777 */ 02778 return 0; 02779 } 02780 02781 02805 CMessage * 02806 CMyApplication::transact ( 02807 CMessage * pSendMsg) 02808 { 02809 CConnection * pConn = m_pConnectionToReader; 02810 CMessage * pRspMsg; 02811 02812 /* 02813 * Print the XML text for the outbound message if 02814 * verbosity is 2 or higher. 02815 */ 02816 if(1 < m_Verbose) 02817 { 02818 printf("\n===================================\n"); 02819 printf("INFO: Transact sending\n"); 02820 printXMLMessage(pSendMsg); 02821 } 02822 02823 /* 02824 * Send the message, expect the response of certain type. 02825 * If LLRP::CConnection::transact() returns NULL then there was 02826 * an error. In that case we try to print the error details. 02827 */ 02828 pRspMsg = pConn->transact(pSendMsg, 5000); 02829 02830 if(NULL == pRspMsg) 02831 { 02832 const CErrorDetails * pError = pConn->getTransactError(); 02833 02834 printf("ERROR: %s transact failed, %s\n", 02835 pSendMsg->m_pType->m_pName, 02836 pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given"); 02837 02838 if(NULL != pError->m_pRefType) 02839 { 02840 printf("ERROR: ... reference type %s\n", 02841 pError->m_pRefType->m_pName); 02842 } 02843 02844 if(NULL != pError->m_pRefField) 02845 { 02846 printf("ERROR: ... reference field %s\n", 02847 pError->m_pRefField->m_pName); 02848 } 02849 02850 return NULL; 02851 } 02852 02853 /* 02854 * Print the XML text for the inbound message if 02855 * verbosity is 2 or higher. 02856 */ 02857 if(1 < m_Verbose) 02858 { 02859 printf("\n- - - - - - - - - - - - - - - - - -\n"); 02860 printf("INFO: Transact received response\n"); 02861 printXMLMessage(pRspMsg); 02862 } 02863 02864 /* 02865 * If it is an ERROR_MESSAGE (response from reader 02866 * when it can't understand the request), tattle 02867 * and declare defeat. 02868 */ 02869 if(&CERROR_MESSAGE::s_typeDescriptor == pRspMsg->m_pType) 02870 { 02871 const CTypeDescriptor * pResponseType; 02872 02873 pResponseType = pSendMsg->m_pType->m_pResponseType; 02874 02875 printf("ERROR: Received ERROR_MESSAGE instead of %s\n", 02876 pResponseType->m_pName); 02877 delete pRspMsg; 02878 pRspMsg = NULL; 02879 } 02880 02881 return pRspMsg; 02882 } 02883 02884 02909 CMessage * 02910 CMyApplication::recvMessage ( 02911 int nMaxMS) 02912 { 02913 CConnection * pConn = m_pConnectionToReader; 02914 CMessage * pMessage; 02915 02916 /* 02917 * Receive the message subject to a time limit 02918 */ 02919 pMessage = pConn->recvMessage(nMaxMS); 02920 02921 /* 02922 * If LLRP::CConnection::recvMessage() returns NULL then there was 02923 * an error. In that case we try to print the error details. 02924 */ 02925 if(NULL == pMessage) 02926 { 02927 const CErrorDetails * pError = pConn->getRecvError(); 02928 02929 /* don't warn on timeout since this is a polling example */ 02930 if(pError->m_eResultCode != RC_RecvTimeout) 02931 { 02932 printf("ERROR: recvMessage failed, %s\n", 02933 pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given"); 02934 } 02935 02936 if(NULL != pError->m_pRefType) 02937 { 02938 printf("ERROR: ... reference type %s\n", 02939 pError->m_pRefType->m_pName); 02940 } 02941 02942 if(NULL != pError->m_pRefField) 02943 { 02944 printf("ERROR: ... reference field %s\n", 02945 pError->m_pRefField->m_pName); 02946 } 02947 02948 return NULL; 02949 } 02950 02951 /* 02952 * Print the XML text for the inbound message if 02953 * verbosity is 2 or higher. 02954 */ 02955 if(1 < m_Verbose) 02956 { 02957 printf("\n===================================\n"); 02958 printf("INFO: Message received\n"); 02959 printXMLMessage(pMessage); 02960 } 02961 02962 return pMessage; 02963 } 02964 02965 02983 int 02984 CMyApplication::sendMessage ( 02985 CMessage * pSendMsg) 02986 { 02987 CConnection * pConn = m_pConnectionToReader; 02988 02989 /* 02990 * Print the XML text for the outbound message if 02991 * verbosity is 2 or higher. 02992 */ 02993 if(1 < m_Verbose) 02994 { 02995 printf("\n===================================\n"); 02996 printf("INFO: Sending\n"); 02997 printXMLMessage(pSendMsg); 02998 } 02999 03000 /* 03001 * If LLRP::CConnection::sendMessage() returns other than RC_OK 03002 * then there was an error. In that case we try to print 03003 * the error details. 03004 */ 03005 if(RC_OK != pConn->sendMessage(pSendMsg)) 03006 { 03007 const CErrorDetails * pError = pConn->getSendError(); 03008 03009 printf("ERROR: %s sendMessage failed, %s\n", 03010 pSendMsg->m_pType->m_pName, 03011 pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given"); 03012 03013 if(NULL != pError->m_pRefType) 03014 { 03015 printf("ERROR: ... reference type %s\n", 03016 pError->m_pRefType->m_pName); 03017 } 03018 03019 if(NULL != pError->m_pRefField) 03020 { 03021 printf("ERROR: ... reference field %s\n", 03022 pError->m_pRefField->m_pName); 03023 } 03024 03025 return -1; 03026 } 03027 03028 /* 03029 * Victory 03030 */ 03031 return 0; 03032 } 03033 03034 03048 void 03049 CMyApplication::printXMLMessage ( 03050 CMessage * pMessage) 03051 { 03052 char aBuf[100*1024]; 03053 03054 /* 03055 * Convert the message to an XML string. 03056 * This fills the buffer with either the XML string 03057 * or an error message. The return value could 03058 * be checked. 03059 */ 03060 03061 pMessage->toXMLString(aBuf, sizeof aBuf); 03062 03063 /* 03064 * Print the XML Text to the standard output. 03065 */ 03066 printf("%s", aBuf); 03067 }