Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

example1.cpp

Go to the documentation of this file.
00001 
00002 /*
00003  ***************************************************************************
00004  *  Copyright 2007,2008 Impinj, Inc.
00005  *
00006  *  Licensed under the Apache License, Version 2.0 (the "License");
00007  *  you may not use this file except in compliance with the License.
00008  *  You may obtain a copy of the License at
00009  *
00010  *      http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  *  Unless required by applicable law or agreed to in writing, software
00013  *  distributed under the License is distributed on an "AS IS" BASIS,
00014  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  *  See the License for the specific language governing permissions and
00016  *  limitations under the License.
00017  *
00018  ***************************************************************************
00019  */
00020 
00051 #include <stdio.h>
00052 
00053 #include "ltkcpp.h"
00054 
00055 using namespace LLRP;
00056 
00057 
00058 class CMyApplication
00059 {
00060   public:
00062     int                         m_Verbose;
00063 
00065     CConnection *               m_pConnectionToReader;
00066 
00067     inline
00068     CMyApplication (void)
00069      : m_Verbose(0), m_pConnectionToReader(NULL)
00070     {}
00071 
00072     int
00073     run (
00074       char *                    pReaderHostName);
00075 
00076     int
00077     checkConnectionStatus (void);
00078 
00079     int
00080     scrubConfiguration (void);
00081 
00082     int
00083     resetConfigurationToFactoryDefaults (void);
00084 
00085     int
00086     deleteAllROSpecs (void);
00087 
00088     int
00089     addROSpec (void);
00090 
00091     int
00092     enableROSpec (void);
00093 
00094     int
00095     startROSpec (void);
00096 
00097     int
00098     awaitAndPrintReport (void);
00099 
00100     void
00101     printTagReportData (
00102       CRO_ACCESS_REPORT *       pRO_ACCESS_REPORT);
00103 
00104     void
00105     printOneTagReportData (
00106       CTagReportData *          pTagReportData);
00107 
00108     void
00109     handleReaderEventNotification (
00110       CReaderEventNotificationData *pNtfData);
00111 
00112     void
00113     handleAntennaEvent (
00114       CAntennaEvent *           pAntennaEvent);
00115 
00116     void
00117     handleReaderExceptionEvent (
00118       CReaderExceptionEvent *   pReaderExceptionEvent);
00119 
00120     int
00121     checkLLRPStatus (
00122       CLLRPStatus *             pLLRPStatus,
00123       char *                    pWhatStr);
00124 
00125     CMessage *
00126     transact (
00127       CMessage *                pSendMsg);
00128 
00129     CMessage *
00130     recvMessage (
00131       int                       nMaxMS);
00132 
00133     int
00134     sendMessage (
00135       CMessage *                pSendMsg);
00136 
00137     void
00138     printXMLMessage (
00139       CMessage *                pMessage);
00140 };
00141 
00142 
00143 /* BEGIN forward declarations */
00144 int
00145 main (
00146   int                           ac,
00147   char *                        av[]);
00148 
00149 void
00150 usage (
00151   char *                        pProgName);
00152 /* END forward declarations */
00153 
00154 
00170 int
00171 main (
00172   int                           ac,
00173   char *                        av[])
00174 {
00175     CMyApplication              myApp;
00176     char *                      pReaderHostName;
00177     int                         rc;
00178 
00179     /*
00180      * Process comand arguments, determine reader name
00181      * and verbosity level.
00182      */
00183     if(ac == 2)
00184     {
00185         pReaderHostName = av[1];
00186     }
00187     else if(ac == 3)
00188     {
00189         char *                  p = av[1];
00190 
00191         while(*p)
00192         {
00193             switch(*p++)
00194             {
00195             case '-':   /* linux conventional option warn char */
00196             case '/':   /* Windows/DOS conventional option warn char */
00197                 break;
00198 
00199             case 'v':
00200             case 'V':
00201                 myApp.m_Verbose++;
00202                 break;
00203 
00204             default:
00205                 usage(av[0]);
00206                 /* no return */
00207                 break;
00208             }
00209         }
00210 
00211         pReaderHostName = av[2];
00212     }
00213     else
00214     {
00215         usage(av[0]);
00216         /* no return */
00217     }
00218 
00219     /*
00220      * Run application, capture return value for exit status
00221      */
00222     rc = myApp.run(pReaderHostName);
00223 
00224     printf("INFO: Done\n");
00225 
00226     /*
00227      * Exit with the right status.
00228      */
00229     if(0 == rc)
00230     {
00231         exit(0);
00232     }
00233     else
00234     {
00235         exit(2);
00236     }
00237     /*NOTREACHED*/
00238 }
00239 
00240 
00252 void
00253 usage (
00254   char *                        pProgName)
00255 {
00256 #ifdef linux
00257     printf("Usage: %s [-v[v]] READERHOSTNAME\n", pProgName);
00258     printf("\n");
00259     printf("Each -v increases verbosity level\n");
00260 #endif /* linux */
00261 #ifdef WIN32
00262     printf("Usage: %s [/v[v]] READERHOSTNAME\n", pProgName);
00263     printf("\n");
00264     printf("Each /v increases verbosity level\n");
00265 #endif /* WIN32 */
00266     exit(1);
00267 }
00268 
00269 
00300 int
00301 CMyApplication::run (
00302   char *                        pReaderHostName)
00303 {
00304     CTypeRegistry *             pTypeRegistry;
00305     CConnection *               pConn;
00306     int                         rc;
00307 
00308     /*
00309      * Allocate the type registry. This is needed
00310      * by the connection to decode.
00311      */
00312     pTypeRegistry = getTheTypeRegistry();
00313     if(NULL == pTypeRegistry)
00314     {
00315         printf("ERROR: getTheTypeRegistry failed\n");
00316         return -1;
00317     }
00318 
00319     /*
00320      * Construct a connection (LLRP::CConnection).
00321      * Using a 32kb max frame size for send/recv.
00322      * The connection object is ready for business
00323      * but not actually connected to the reader yet.
00324      */
00325     pConn = new CConnection(pTypeRegistry, 32u*1024u);
00326     if(NULL == pConn)
00327     {
00328         printf("ERROR: new CConnection failed\n");
00329         return -2;
00330     }
00331 
00332     /*
00333      * Open the connection to the reader
00334      */
00335     if(m_Verbose)
00336     {
00337         printf("INFO: Connecting to %s....\n", pReaderHostName);
00338     }
00339 
00340     rc = pConn->openConnectionToReader(pReaderHostName);
00341     if(0 != rc)
00342     {
00343         printf("ERROR: connect: %s (%d)\n", pConn->getConnectError(), rc);
00344         delete pConn;
00345         return -3;
00346     }
00347 
00348     /*
00349      * Record the pointer to the connection object so other
00350      * routines can use it.
00351      */
00352     m_pConnectionToReader = pConn;
00353 
00354     if(m_Verbose)
00355     {
00356         printf("INFO: Connected, checking status....\n");
00357     }
00358 
00359     /*
00360      * Commence the sequence and check for errors as we go.
00361      * See comments for each routine for details.
00362      * Each routine prints messages.
00363      */
00364     rc = 1;
00365     if(0 == checkConnectionStatus())
00366     {
00367         rc = 2;
00368         if(0 == scrubConfiguration())
00369         {
00370             rc = 3;
00371             if(0 == addROSpec())
00372             {
00373                 rc = 4;
00374                 if(0 == enableROSpec())
00375                 {
00376                     int         i;
00377 
00378                     rc = 5;
00379 
00380                     for(i = 1; i <= 5; i++)
00381                     {
00382                         printf("INFO: Starting run %d ================\n", i);
00383                         if(0 != startROSpec())
00384                         {
00385                             /* already tattled */
00386                             break;
00387                         }
00388                         if(0 != awaitAndPrintReport())
00389                         {
00390                             /* already tattled */
00391                             break;
00392                         }
00393                     }
00394 
00395                     if(5 == i)
00396                     {
00397                         rc = 0;
00398                     }
00399                 }
00400             }
00401 
00402             /*
00403              * After we're done, try to leave the reader
00404              * in a clean state for next use. This is best
00405              * effort and no checking of the result is done.
00406              */
00407             if(m_Verbose)
00408             {
00409                 printf("INFO: Clean up reader configuration...\n");
00410             }
00411             scrubConfiguration();
00412         }
00413     }
00414 
00415     if(m_Verbose)
00416     {
00417         printf("INFO: Finished\n");
00418     }
00419 
00420     /*
00421      * Close the connection and release its resources
00422      */
00423     pConn->closeConnectionToReader();
00424     delete pConn;
00425 
00426     /*
00427      * Done with the registry.
00428      */
00429     delete pTypeRegistry;
00430 
00431     /*
00432      * When we get here all allocated memory should have been deallocated.
00433      */
00434 
00435     return rc;
00436 }
00437 
00438 
00469 int
00470 CMyApplication::checkConnectionStatus (void)
00471 {
00472     CMessage *                  pMessage;
00473     CREADER_EVENT_NOTIFICATION *pNtf;
00474     CReaderEventNotificationData *pNtfData;
00475     CConnectionAttemptEvent *   pEvent;
00476 
00477     /*
00478      * Expect the notification within 10 seconds.
00479      * It is suppose to be the very first message sent.
00480      */
00481     pMessage = recvMessage(10000);
00482 
00483     /*
00484      * recvMessage() returns NULL if something went wrong.
00485      */
00486     if(NULL == pMessage)
00487     {
00488         /* recvMessage already tattled */
00489         goto fail;
00490     }
00491 
00492     /*
00493      * Check to make sure the message is of the right type.
00494      * The type label (pointer) in the message should be
00495      * the type descriptor for READER_EVENT_NOTIFICATION.
00496      */
00497     if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor != pMessage->m_pType)
00498     {
00499         goto fail;
00500     }
00501 
00502     /*
00503      * Now that we are sure it is a READER_EVENT_NOTIFICATION,
00504      * traverse to the ReaderEventNotificationData parameter.
00505      */
00506     pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage;
00507     pNtfData = pNtf->getReaderEventNotificationData();
00508     if(NULL == pNtfData)
00509     {
00510         goto fail;
00511     }
00512 
00513     /*
00514      * The ConnectionAttemptEvent parameter must be present.
00515      */
00516     pEvent = pNtfData->getConnectionAttemptEvent();
00517     if(NULL == pEvent)
00518     {
00519         goto fail;
00520     }
00521 
00522     /*
00523      * The status in the ConnectionAttemptEvent parameter
00524      * must indicate connection success.
00525      */
00526     if(ConnectionAttemptStatusType_Success != pEvent->getStatus())
00527     {
00528         goto fail;
00529     }
00530 
00531     /*
00532      * Done with the message
00533      */
00534     delete pMessage;
00535 
00536     if(m_Verbose)
00537     {
00538         printf("INFO: Connection status OK\n");
00539     }
00540 
00541     /*
00542      * Victory.
00543      */
00544     return 0;
00545 
00546   fail:
00547     /*
00548      * Something went wrong. Tattle. Clean up. Return error.
00549      */
00550     printf("ERROR: checkConnectionStatus failed\n");
00551     delete pMessage;
00552     return -1;
00553 }
00554 
00555 
00572 int
00573 CMyApplication::scrubConfiguration (void)
00574 {
00575     if(0 != resetConfigurationToFactoryDefaults())
00576     {
00577         return -1;
00578     }
00579 
00580     if(0 != deleteAllROSpecs())
00581     {
00582         return -2;
00583     }
00584 
00585     return 0;
00586 }
00587 
00588 
00609 int
00610 CMyApplication::resetConfigurationToFactoryDefaults (void)
00611 {
00612     CSET_READER_CONFIG *        pCmd;
00613     CMessage *                  pRspMsg;
00614     CSET_READER_CONFIG_RESPONSE *pRsp;
00615 
00616     /*
00617      * Compose the command message
00618      */
00619     pCmd = new CSET_READER_CONFIG();
00620     pCmd->setMessageID(101);
00621     pCmd->setResetToFactoryDefault(1);
00622 
00623     /*
00624      * Send the message, expect the response of certain type
00625      */
00626     pRspMsg = transact(pCmd);
00627 
00628     /*
00629      * Done with the command message
00630      */
00631     delete pCmd;
00632 
00633     /*
00634      * transact() returns NULL if something went wrong.
00635      */
00636     if(NULL == pRspMsg)
00637     {
00638         /* transact already tattled */
00639         return -1;
00640     }
00641 
00642     /*
00643      * Cast to a SET_READER_CONFIG_RESPONSE message.
00644      */
00645     pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg;
00646 
00647     /*
00648      * Check the LLRPStatus parameter.
00649      */
00650     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
00651                         "resetConfigurationToFactoryDefaults"))
00652     {
00653         /* checkLLRPStatus already tattled */
00654         delete pRspMsg;
00655         return -1;
00656     }
00657 
00658     /*
00659      * Done with the response message.
00660      */
00661     delete pRspMsg;
00662 
00663     /*
00664      * Tattle progress, maybe
00665      */
00666     if(m_Verbose)
00667     {
00668         printf("INFO: Configuration reset to factory defaults\n");
00669     }
00670 
00671     /*
00672      * Victory.
00673      */
00674     return 0;
00675 }
00676 
00677 
00697 int
00698 CMyApplication::deleteAllROSpecs (void)
00699 {
00700     CDELETE_ROSPEC *            pCmd;
00701     CMessage *                  pRspMsg;
00702     CDELETE_ROSPEC_RESPONSE *   pRsp;
00703 
00704     /*
00705      * Compose the command message
00706      */
00707     pCmd = new CDELETE_ROSPEC();
00708     pCmd->setMessageID(102);
00709     pCmd->setROSpecID(0);               /* All */
00710 
00711     /*
00712      * Send the message, expect the response of certain type
00713      */
00714     pRspMsg = transact(pCmd);
00715 
00716     /*
00717      * Done with the command message
00718      */
00719     delete pCmd;
00720 
00721     /*
00722      * transact() returns NULL if something went wrong.
00723      */
00724     if(NULL == pRspMsg)
00725     {
00726         /* transact already tattled */
00727         return -1;
00728     }
00729 
00730     /*
00731      * Cast to a DELETE_ROSPEC_RESPONSE message.
00732      */
00733     pRsp = (CDELETE_ROSPEC_RESPONSE *) pRspMsg;
00734 
00735     /*
00736      * Check the LLRPStatus parameter.
00737      */
00738     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "deleteAllROSpecs"))
00739     {
00740         /* checkLLRPStatus already tattled */
00741         delete pRspMsg;
00742         return -1;
00743     }
00744 
00745     /*
00746      * Done with the response message.
00747      */
00748     delete pRspMsg;
00749 
00750     /*
00751      * Tattle progress, maybe
00752      */
00753     if(m_Verbose)
00754     {
00755         printf("INFO: All ROSpecs are deleted\n");
00756     }
00757 
00758     /*
00759      * Victory.
00760      */
00761     return 0;
00762 }
00763 
00764 
00836 int
00837 CMyApplication::addROSpec (void)
00838 {
00839     CROSpecStartTrigger *       pROSpecStartTrigger =
00840                                     new CROSpecStartTrigger();
00841     pROSpecStartTrigger->setROSpecStartTriggerType(
00842                                 ROSpecStartTriggerType_Null);
00843 
00844     CROSpecStopTrigger *        pROSpecStopTrigger = new CROSpecStopTrigger();
00845     pROSpecStopTrigger->setROSpecStopTriggerType(ROSpecStopTriggerType_Null);
00846     pROSpecStopTrigger->setDurationTriggerValue(0);     /* n/a */
00847 
00848     CROBoundarySpec *           pROBoundarySpec = new CROBoundarySpec();
00849     pROBoundarySpec->setROSpecStartTrigger(pROSpecStartTrigger);
00850     pROBoundarySpec->setROSpecStopTrigger(pROSpecStopTrigger);
00851 
00852     CAISpecStopTrigger *        pAISpecStopTrigger = new CAISpecStopTrigger();
00853     pAISpecStopTrigger->setAISpecStopTriggerType(
00854             AISpecStopTriggerType_Duration);
00855     pAISpecStopTrigger->setDurationTrigger(5000);
00856 
00857     CInventoryParameterSpec *   pInventoryParameterSpec =
00858                                     new CInventoryParameterSpec();
00859     pInventoryParameterSpec->setInventoryParameterSpecID(1234);
00860     pInventoryParameterSpec->setProtocolID(AirProtocols_EPCGlobalClass1Gen2);
00861 
00862     llrp_u16v_t                 AntennaIDs = llrp_u16v_t(1);
00863     AntennaIDs.m_pValue[0] = 0;         /* All */
00864 
00865     CAISpec *                   pAISpec = new CAISpec();
00866     pAISpec->setAntennaIDs(AntennaIDs);
00867     pAISpec->setAISpecStopTrigger(pAISpecStopTrigger);
00868     pAISpec->addInventoryParameterSpec(pInventoryParameterSpec);
00869 
00870     CTagReportContentSelector * pTagReportContentSelector =
00871                                     new CTagReportContentSelector();
00872     pTagReportContentSelector->setEnableROSpecID(FALSE);
00873     pTagReportContentSelector->setEnableSpecIndex(FALSE);
00874     pTagReportContentSelector->setEnableInventoryParameterSpecID(FALSE);
00875     pTagReportContentSelector->setEnableAntennaID(FALSE);
00876     pTagReportContentSelector->setEnableChannelIndex(FALSE);
00877     pTagReportContentSelector->setEnablePeakRSSI(FALSE);
00878     pTagReportContentSelector->setEnableFirstSeenTimestamp(FALSE);
00879     pTagReportContentSelector->setEnableLastSeenTimestamp(FALSE);
00880     pTagReportContentSelector->setEnableTagSeenCount(FALSE);
00881     pTagReportContentSelector->setEnableAccessSpecID(FALSE);
00882 
00883     CROReportSpec *             pROReportSpec = new CROReportSpec();
00884     pROReportSpec->setROReportTrigger(
00885             ROReportTriggerType_Upon_N_Tags_Or_End_Of_ROSpec);
00886     pROReportSpec->setN(0);         /* Unlimited */
00887     pROReportSpec->setTagReportContentSelector(pTagReportContentSelector);
00888 
00889     CROSpec *                   pROSpec = new CROSpec();
00890     pROSpec->setROSpecID(123);
00891     pROSpec->setPriority(0);
00892     pROSpec->setCurrentState(ROSpecState_Disabled);
00893     pROSpec->setROBoundarySpec(pROBoundarySpec);
00894     pROSpec->addSpecParameter(pAISpec);
00895     pROSpec->setROReportSpec(pROReportSpec);
00896 
00897     CADD_ROSPEC *               pCmd;
00898     CMessage *                  pRspMsg;
00899     CADD_ROSPEC_RESPONSE *      pRsp;
00900 
00901     /*
00902      * Compose the command message.
00903      * N.B.: After the message is composed, all the parameters
00904      *       constructed, immediately above, are considered "owned"
00905      *       by the command message. When it is destructed so
00906      *       too will the parameters be.
00907      */
00908     pCmd = new CADD_ROSPEC();
00909     pCmd->setMessageID(201);
00910     pCmd->setROSpec(pROSpec);
00911 
00912     /*
00913      * Send the message, expect the response of certain type
00914      */
00915     pRspMsg = transact(pCmd);
00916 
00917     /*
00918      * Done with the command message.
00919      * N.B.: And the parameters
00920      */
00921     delete pCmd;
00922 
00923     /*
00924      * transact() returns NULL if something went wrong.
00925      */
00926     if(NULL == pRspMsg)
00927     {
00928         /* transact already tattled */
00929         return -1;
00930     }
00931 
00932     /*
00933      * Cast to a ADD_ROSPEC_RESPONSE message.
00934      */
00935     pRsp = (CADD_ROSPEC_RESPONSE *) pRspMsg;
00936 
00937     /*
00938      * Check the LLRPStatus parameter.
00939      */
00940     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "addROSpec"))
00941     {
00942         /* checkLLRPStatus already tattled */
00943         delete pRspMsg;
00944         return -1;
00945     }
00946 
00947     /*
00948      * Done with the response message.
00949      */
00950     delete pRspMsg;
00951 
00952     /*
00953      * Tattle progress, maybe
00954      */
00955     if(m_Verbose)
00956     {
00957         printf("INFO: ROSpec added\n");
00958     }
00959 
00960     /*
00961      * Victory.
00962      */
00963     return 0;
00964 }
00965 
00966 
00984 int
00985 CMyApplication::enableROSpec (void)
00986 {
00987     CENABLE_ROSPEC *            pCmd;
00988     CMessage *                  pRspMsg;
00989     CENABLE_ROSPEC_RESPONSE *   pRsp;
00990 
00991     /*
00992      * Compose the command message
00993      */
00994     pCmd = new CENABLE_ROSPEC();
00995     pCmd->setMessageID(202);
00996     pCmd->setROSpecID(123);
00997 
00998     /*
00999      * Send the message, expect the response of certain type
01000      */
01001     pRspMsg = transact(pCmd);
01002 
01003     /*
01004      * Done with the command message
01005      */
01006     delete pCmd;
01007 
01008     /*
01009      * transact() returns NULL if something went wrong.
01010      */
01011     if(NULL == pRspMsg)
01012     {
01013         /* transact already tattled */
01014         return -1;
01015     }
01016 
01017     /*
01018      * Cast to a ENABLE_ROSPEC_RESPONSE message.
01019      */
01020     pRsp = (CENABLE_ROSPEC_RESPONSE *) pRspMsg;
01021 
01022     /*
01023      * Check the LLRPStatus parameter.
01024      */
01025     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "enableROSpec"))
01026     {
01027         /* checkLLRPStatus already tattled */
01028         delete pRspMsg;
01029         return -1;
01030     }
01031 
01032     /*
01033      * Done with the response message.
01034      */
01035     delete pRspMsg;
01036 
01037     /*
01038      * Tattle progress, maybe
01039      */
01040     if(m_Verbose)
01041     {
01042         printf("INFO: ROSpec enabled\n");
01043     }
01044 
01045     /*
01046      * Victory.
01047      */
01048     return 0;
01049 }
01050 
01051 
01069 int
01070 CMyApplication::startROSpec (void)
01071 {
01072     CSTART_ROSPEC *             pCmd;
01073     CMessage *                  pRspMsg;
01074     CSTART_ROSPEC_RESPONSE *    pRsp;
01075 
01076     /*
01077      * Compose the command message
01078      */
01079     pCmd = new CSTART_ROSPEC();
01080     pCmd->setMessageID(202);
01081     pCmd->setROSpecID(123);
01082 
01083     /*
01084      * Send the message, expect the response of certain type
01085      */
01086     pRspMsg = transact(pCmd);
01087 
01088     /*
01089      * Done with the command message
01090      */
01091     delete pCmd;
01092 
01093     /*
01094      * transact() returns NULL if something went wrong.
01095      */
01096     if(NULL == pRspMsg)
01097     {
01098         /* transact already tattled */
01099         return -1;
01100     }
01101 
01102     /*
01103      * Cast to a START_ROSPEC_RESPONSE message.
01104      */
01105     pRsp = (CSTART_ROSPEC_RESPONSE *) pRspMsg;
01106 
01107     /*
01108      * Check the LLRPStatus parameter.
01109      */
01110     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "startROSpec"))
01111     {
01112         /* checkLLRPStatus already tattled */
01113         delete pRspMsg;
01114         return -1;
01115     }
01116 
01117     /*
01118      * Done with the response message.
01119      */
01120     delete pRspMsg;
01121 
01122     /*
01123      * Tattle progress
01124      */
01125     if(m_Verbose)
01126     {
01127         printf("INFO: ROSpec started\n");
01128     }
01129 
01130     /*
01131      * Victory.
01132      */
01133     return 0;
01134 }
01135 
01136 
01152 int
01153 CMyApplication::awaitAndPrintReport (void)
01154 {
01155     int                         bDone = 0;
01156     int                         retVal = 0;
01157 
01158     /*
01159      * Keep receiving messages until done or until
01160      * something bad happens.
01161      */
01162     while(!bDone)
01163     {
01164         CMessage *              pMessage;
01165         const CTypeDescriptor * pType;
01166 
01167         /*
01168          * Wait up to 7 seconds for a message. The report
01169          * should occur within 5 seconds.
01170          */
01171         pMessage = recvMessage(7000);
01172         if(NULL == pMessage)
01173         {
01174             /*
01175              * Did not receive a message within a reasonable
01176              * amount of time. recvMessage() already tattled
01177              */
01178             retVal = -2;
01179             bDone = 1;
01180             continue;
01181         }
01182 
01183         /*
01184          * What happens depends on what kind of message
01185          * received. Use the type label (m_pType) to
01186          * discriminate message types.
01187          */
01188         pType = pMessage->m_pType;
01189 
01190         /*
01191          * Is it a tag report? If so, print it out.
01192          */
01193         if(&CRO_ACCESS_REPORT::s_typeDescriptor == pType)
01194         {
01195             CRO_ACCESS_REPORT * pNtf;
01196 
01197             pNtf = (CRO_ACCESS_REPORT *) pMessage;
01198 
01199             printTagReportData(pNtf);
01200             bDone = 1;
01201             retVal = 0;
01202         }
01203 
01204         /*
01205          * Is it a reader event? This example only recognizes
01206          * AntennaEvents.
01207          */
01208         else if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor == pType)
01209         {
01210             CREADER_EVENT_NOTIFICATION *pNtf;
01211             CReaderEventNotificationData *pNtfData;
01212 
01213             pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage;
01214 
01215             pNtfData = pNtf->getReaderEventNotificationData();
01216             if(NULL != pNtfData)
01217             {
01218                 handleReaderEventNotification(pNtfData);
01219             }
01220             else
01221             {
01222                 /*
01223                  * This should never happen. Using continue
01224                  * to keep indent depth down.
01225                  */
01226                 printf("WARNING: READER_EVENT_NOTIFICATION without data\n");
01227             }
01228         }
01229 
01230         /*
01231          * Hmmm. Something unexpected. Just tattle and keep going.
01232          */
01233         else
01234         {
01235             printf("WARNING: Ignored unexpected message during monitor: %s\n",
01236                 pType->m_pName);
01237         }
01238 
01239         /*
01240          * Done with the received message
01241          */
01242         delete pMessage;
01243     }
01244 
01245     return retVal;
01246 }
01247 
01248 
01263 void
01264 CMyApplication::printTagReportData (
01265   CRO_ACCESS_REPORT *           pRO_ACCESS_REPORT)
01266 {
01267     std::list<CTagReportData *>::iterator Cur;
01268     unsigned int                nEntry = 0;
01269 
01270     /*
01271      * Loop through and count the number of entries
01272      */
01273     for(
01274         Cur = pRO_ACCESS_REPORT->beginTagReportData();
01275         Cur != pRO_ACCESS_REPORT->endTagReportData();
01276         Cur++)
01277     {
01278         nEntry++;
01279     }
01280 
01281     printf("INFO: %u tag report entries\n", nEntry);
01282 
01283     /*
01284      * Loop through again and print each entry.
01285      */
01286     for(
01287         Cur = pRO_ACCESS_REPORT->beginTagReportData();
01288         Cur != pRO_ACCESS_REPORT->endTagReportData();
01289         Cur++)
01290     {
01291         printOneTagReportData(*Cur);
01292     }
01293 }
01294 
01295 
01305 void
01306 CMyApplication::printOneTagReportData (
01307   CTagReportData *              pTagReportData)
01308 {
01309     const CTypeDescriptor *     pType;
01310     char                        aBuf[64];
01311 
01312     /*
01313      * Print the EPC. It could be an 96-bit EPC_96 parameter
01314      * or an variable length EPCData parameter.
01315      */
01316 
01317     CParameter *                pEPCParameter =
01318                                     pTagReportData->getEPCParameter();
01319 
01320     if(NULL != pEPCParameter)
01321     {
01322         char *              p = aBuf;
01323         llrp_u96_t          my_u96;
01324         llrp_u1v_t          my_u1v;
01325         llrp_u8_t *         pValue = NULL;
01326         unsigned int        n, i;
01327 
01328         pType = pEPCParameter->m_pType;
01329         if(&CEPC_96::s_typeDescriptor == pType)
01330         {
01331             CEPC_96             *pEPC_96;
01332 
01333             pEPC_96 = (CEPC_96 *) pEPCParameter;
01334             my_u96 = pEPC_96->getEPC();
01335             pValue = my_u96.m_aValue;
01336             n = 12u;
01337         }
01338         else if(&CEPCData::s_typeDescriptor == pType)
01339         {
01340             CEPCData *          pEPCData;
01341 
01342             pEPCData = (CEPCData *) pEPCParameter;
01343             my_u1v = pEPCData->getEPC();
01344             pValue = my_u1v.m_pValue;
01345             n = (my_u1v.m_nBit + 7u) / 8u;
01346         }
01347 
01348         if(NULL != pValue)
01349         {
01350             for(i = 0; i < n; i++)
01351             {
01352                 if(0 < i && i%2 == 0)
01353                 {
01354                     *p++ = '-';
01355                 }
01356                 sprintf(p, "%02X", pValue[i]);
01357                 while(*p) p++;
01358             }
01359         }
01360         else
01361         {
01362             strcpy(aBuf, "---unknown-epc-data-type---");
01363         }
01364     }
01365     else
01366     {
01367         strcpy(aBuf, "---missing-epc-data---");
01368     }
01369     printf("%-32s", aBuf);
01370 
01371     /*
01372      * End of line
01373      */
01374     printf("\n");
01375 }
01376 
01377 
01391 void
01392 CMyApplication::handleReaderEventNotification (
01393   CReaderEventNotificationData *pNtfData)
01394 {
01395     CAntennaEvent *             pAntennaEvent;
01396     CReaderExceptionEvent *     pReaderExceptionEvent;
01397     int                         nReported = 0;
01398 
01399     pAntennaEvent = pNtfData->getAntennaEvent();
01400     if(NULL != pAntennaEvent)
01401     {
01402         handleAntennaEvent(pAntennaEvent);
01403         nReported++;
01404     }
01405 
01406     pReaderExceptionEvent = pNtfData->getReaderExceptionEvent();
01407     if(NULL != pReaderExceptionEvent)
01408     {
01409         handleReaderExceptionEvent(pReaderExceptionEvent);
01410         nReported++;
01411     }
01412 
01413     /*
01414      * Similarly handle other events here:
01415      *      HoppingEvent
01416      *      GPIEvent
01417      *      ROSpecEvent
01418      *      ReportBufferLevelWarningEvent
01419      *      ReportBufferOverflowErrorEvent
01420      *      RFSurveyEvent
01421      *      AISpecEvent
01422      *      ConnectionAttemptEvent
01423      *      ConnectionCloseEvent
01424      *      Custom
01425      */
01426 
01427     if(0 == nReported)
01428     {
01429         printf("NOTICE: Unexpected (unhandled) ReaderEvent\n");
01430     }
01431 }
01432 
01433 
01445 void
01446 CMyApplication::handleAntennaEvent (
01447   CAntennaEvent *               pAntennaEvent)
01448 {
01449     EAntennaEventType           eEventType;
01450     llrp_u16_t                  AntennaID;
01451     char *                      pStateStr;
01452 
01453     eEventType = pAntennaEvent->getEventType();
01454     AntennaID = pAntennaEvent->getAntennaID();
01455 
01456     switch(eEventType)
01457     {
01458     case AntennaEventType_Antenna_Disconnected:
01459         pStateStr = "disconnected";
01460         break;
01461 
01462     case AntennaEventType_Antenna_Connected:
01463         pStateStr = "connected";
01464         break;
01465 
01466     default:
01467         pStateStr = "?unknown-event?";
01468         break;
01469     }
01470 
01471     printf("NOTICE: Antenna %d is %s\n", AntennaID, pStateStr);
01472 }
01473 
01474 
01487 void
01488 CMyApplication::handleReaderExceptionEvent (
01489   CReaderExceptionEvent *       pReaderExceptionEvent)
01490 {
01491     llrp_utf8v_t                Message;
01492 
01493     Message = pReaderExceptionEvent->getMessage();
01494 
01495     if(0 < Message.m_nValue && NULL != Message.m_pValue)
01496     {
01497         printf("NOTICE: ReaderException '%.*s'\n",
01498              Message.m_nValue, Message.m_pValue);
01499     }
01500     else
01501     {
01502         printf("NOTICE: ReaderException but no message\n");
01503     }
01504 }
01505 
01506 
01525 int
01526 CMyApplication::checkLLRPStatus (
01527   CLLRPStatus *                 pLLRPStatus,
01528   char *                        pWhatStr)
01529 {
01530     /*
01531      * The LLRPStatus parameter is mandatory in all responses.
01532      * If it is missing there should have been a decode error.
01533      * This just makes sure (remember, this program is a
01534      * diagnostic and suppose to catch LTKC mistakes).
01535      */
01536     if(NULL == pLLRPStatus)
01537     {
01538         printf("ERROR: %s missing LLRP status\n", pWhatStr);
01539         return -1;
01540     }
01541 
01542     /*
01543      * Make sure the status is M_Success.
01544      * If it isn't, print the error string if one.
01545      * This does not try to pretty-print the status
01546      * code. To get that, run this program with -vv
01547      * and examine the XML output.
01548      */
01549     if(StatusCode_M_Success != pLLRPStatus->getStatusCode())
01550     {
01551         llrp_utf8v_t            ErrorDesc;
01552 
01553         ErrorDesc = pLLRPStatus->getErrorDescription();
01554 
01555         if(0 == ErrorDesc.m_nValue)
01556         {
01557             printf("ERROR: %s failed, no error description given\n",
01558                 pWhatStr);
01559         }
01560         else
01561         {
01562             printf("ERROR: %s failed, %.*s\n",
01563                 pWhatStr, ErrorDesc.m_nValue, ErrorDesc.m_pValue);
01564         }
01565         return -2;
01566     }
01567 
01568     /*
01569      * Victory. Everything is fine.
01570      */
01571     return 0;
01572 }
01573 
01574 
01598 CMessage *
01599 CMyApplication::transact (
01600   CMessage *                    pSendMsg)
01601 {
01602     CConnection *               pConn = m_pConnectionToReader;
01603     CMessage *                  pRspMsg;
01604 
01605     /*
01606      * Print the XML text for the outbound message if
01607      * verbosity is 2 or higher.
01608      */
01609     if(1 < m_Verbose)
01610     {
01611         printf("\n===================================\n");
01612         printf("INFO: Transact sending\n");
01613         printXMLMessage(pSendMsg);
01614     }
01615 
01616     /*
01617      * Send the message, expect the response of certain type.
01618      * If LLRP::CConnection::transact() returns NULL then there was
01619      * an error. In that case we try to print the error details.
01620      */
01621     pRspMsg = pConn->transact(pSendMsg, 5000);
01622 
01623     if(NULL == pRspMsg)
01624     {
01625         const CErrorDetails *   pError = pConn->getTransactError();
01626 
01627         printf("ERROR: %s transact failed, %s\n",
01628             pSendMsg->m_pType->m_pName,
01629             pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
01630 
01631         if(NULL != pError->m_pRefType)
01632         {
01633             printf("ERROR: ... reference type %s\n",
01634                 pError->m_pRefType->m_pName);
01635         }
01636 
01637         if(NULL != pError->m_pRefField)
01638         {
01639             printf("ERROR: ... reference field %s\n",
01640                 pError->m_pRefField->m_pName);
01641         }
01642 
01643         return NULL;
01644     }
01645 
01646     /*
01647      * Print the XML text for the inbound message if
01648      * verbosity is 2 or higher.
01649      */
01650     if(1 < m_Verbose)
01651     {
01652         printf("\n- - - - - - - - - - - - - - - - - -\n");
01653         printf("INFO: Transact received response\n");
01654         printXMLMessage(pRspMsg);
01655     }
01656 
01657     /*
01658      * If it is an ERROR_MESSAGE (response from reader
01659      * when it can't understand the request), tattle
01660      * and declare defeat.
01661      */
01662     if(&CERROR_MESSAGE::s_typeDescriptor == pRspMsg->m_pType)
01663     {
01664         const CTypeDescriptor * pResponseType;
01665 
01666         pResponseType = pSendMsg->m_pType->m_pResponseType;
01667 
01668         printf("ERROR: Received ERROR_MESSAGE instead of %s\n",
01669             pResponseType->m_pName);
01670         delete pRspMsg;
01671         pRspMsg = NULL;
01672     }
01673 
01674     return pRspMsg;
01675 }
01676 
01677 
01702 CMessage *
01703 CMyApplication::recvMessage (
01704   int                           nMaxMS)
01705 {
01706     CConnection *               pConn = m_pConnectionToReader;
01707     CMessage *                  pMessage;
01708 
01709     /*
01710      * Receive the message subject to a time limit
01711      */
01712     pMessage = pConn->recvMessage(nMaxMS);
01713 
01714     /*
01715      * If LLRP::CConnection::recvMessage() returns NULL then there was
01716      * an error. In that case we try to print the error details.
01717      */
01718     if(NULL == pMessage)
01719     {
01720         const CErrorDetails *   pError = pConn->getRecvError();
01721 
01722         printf("ERROR: recvMessage failed, %s\n",
01723             pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
01724 
01725         if(NULL != pError->m_pRefType)
01726         {
01727             printf("ERROR: ... reference type %s\n",
01728                 pError->m_pRefType->m_pName);
01729         }
01730 
01731         if(NULL != pError->m_pRefField)
01732         {
01733             printf("ERROR: ... reference field %s\n",
01734                 pError->m_pRefField->m_pName);
01735         }
01736 
01737         return NULL;
01738     }
01739 
01740     /*
01741      * Print the XML text for the inbound message if
01742      * verbosity is 2 or higher.
01743      */
01744     if(1 < m_Verbose)
01745     {
01746         printf("\n===================================\n");
01747         printf("INFO: Message received\n");
01748         printXMLMessage(pMessage);
01749     }
01750 
01751     return pMessage;
01752 }
01753 
01754 
01772 int
01773 CMyApplication::sendMessage (
01774   CMessage *                    pSendMsg)
01775 {
01776     CConnection *               pConn = m_pConnectionToReader;
01777 
01778     /*
01779      * Print the XML text for the outbound message if
01780      * verbosity is 2 or higher.
01781      */
01782     if(1 < m_Verbose)
01783     {
01784         printf("\n===================================\n");
01785         printf("INFO: Sending\n");
01786         printXMLMessage(pSendMsg);
01787     }
01788 
01789     /*
01790      * If LLRP::CConnection::sendMessage() returns other than RC_OK
01791      * then there was an error. In that case we try to print
01792      * the error details.
01793      */
01794     if(RC_OK != pConn->sendMessage(pSendMsg))
01795     {
01796         const CErrorDetails *   pError = pConn->getSendError();
01797 
01798         printf("ERROR: %s sendMessage failed, %s\n",
01799             pSendMsg->m_pType->m_pName,
01800             pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
01801 
01802         if(NULL != pError->m_pRefType)
01803         {
01804             printf("ERROR: ... reference type %s\n",
01805                 pError->m_pRefType->m_pName);
01806         }
01807 
01808         if(NULL != pError->m_pRefField)
01809         {
01810             printf("ERROR: ... reference field %s\n",
01811                 pError->m_pRefField->m_pName);
01812         }
01813 
01814         return -1;
01815     }
01816 
01817     /*
01818      * Victory
01819      */
01820     return 0;
01821 }
01822 
01823 
01837 void
01838 CMyApplication::printXMLMessage (
01839   CMessage *                    pMessage)
01840 {
01841     char                        aBuf[100*1024];
01842 
01843     /*
01844      * Convert the message to an XML string.
01845      * This fills the buffer with either the XML string
01846      * or an error message. The return value could
01847      * be checked.
01848      */
01849 
01850     pMessage->toXMLString(aBuf, sizeof aBuf);
01851 
01852     /*
01853      * Print the XML Text to the standard output.
01854      */
01855     printf("%s", aBuf);
01856 }

Generated on Wed Nov 26 12:27:44 2008 for LTKCPP-- LLRP Toolkit C Plus Plus Library by  doxygen 1.3.9.1