dx201.cpp

Go to the documentation of this file.
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,2008. All rights reserved.                *
00012  *                                                                           *
00013  *****************************************************************************/
00014 
00050 #include <stdio.h>
00051 #ifdef linux
00052 #include <unistd.h>
00053 #endif
00054 
00055 #include "ltkcpp.h"
00056 
00057 using namespace LLRP;
00058 
00059 
00060 class CMyApplication
00061 {
00062   public:
00064     int                         m_Verbose;
00065 
00068     int                         m_ModeIndex;
00070     int                         m_Quiet;
00072     int                         m_nTagReport;
00073 
00075     CConnection *               m_pConnectionToReader;
00076 
00077     inline
00078     CMyApplication (void)
00079      : m_Verbose(0), m_ModeIndex(-1), m_Quiet(0),
00080        m_nTagReport(0), m_pConnectionToReader(NULL)
00081     {}
00082 
00083     int
00084     run (
00085       char *                    pReaderHostName);
00086 
00087     int
00088     checkConnectionStatus (void);
00089 
00090     int
00091     scrubConfiguration (void);
00092 
00093     int
00094     resetConfigurationToFactoryDefaults (void);
00095 
00096     int
00097     deleteAllROSpecs (void);
00098 
00099     int
00100     deleteAllAccessSpecs (void);
00101 
00102     int
00103     prepareReader(void);
00104 
00105     int
00106     getAllCapabilities (void);
00107 
00108     int
00109     getAllConfiguration (void);
00110 
00111     int
00112     configureNotificationStates (void);
00113 
00114     int
00115     addROSpec (void);
00116 
00117     int
00118     enableROSpec (void);
00119 
00120     int
00121     startAndMonitorOperation (void);
00122 
00123     void
00124     printTagReportData (
00125       CRO_ACCESS_REPORT *       pRO_ACCESS_REPORT);
00126 
00127     void
00128     printOneTagReportData (
00129       CTagReportData *          pTagReportData);
00130 
00131     int
00132     checkLLRPStatus (
00133       CLLRPStatus *             pLLRPStatus,
00134       char *                    pWhatStr);
00135 
00136     CMessage *
00137     transact (
00138       CMessage *                pSendMsg);
00139 
00140     CMessage *
00141     recvMessage (
00142       int                       nMaxMS);
00143 
00144     int
00145     sendMessage (
00146       CMessage *                pSendMsg);
00147 
00148     void
00149     printXMLMessage (
00150       CMessage *                pMessage);
00151 };
00152 
00153 
00154 /* BEGIN forward declarations */
00155 int
00156 main (
00157   int                           ac,
00158   char *                        av[]);
00159 
00160 void
00161 usage (
00162   char *                        pProgName);
00163 /* END forward declarations */
00164 
00165 
00187 int
00188 main (
00189   int                           ac,
00190   char *                        av[])
00191 {
00192     CMyApplication              myApp;
00193     char *                      pReaderHostName;
00194     int                         rc;
00195 #ifdef linux
00196     char *                      pMemHiwatAtStart = (char*)sbrk(0);
00197 #endif
00198 
00199     /*
00200      * Process comand arguments, determine reader name
00201      * and verbosity level.
00202      */
00203     if(ac == 2)
00204     {
00205         pReaderHostName = av[1];
00206     }
00207     else if(ac == 3)
00208     {
00209         char *                  p = av[1];
00210 
00211         while(*p)
00212         {
00213             switch(*p++)
00214             {
00215             case '-':   /* linux conventional option warn char */
00216             case '/':   /* Windows/DOS conventional option warn char */
00217                 break;
00218 
00219             case 'v':
00220             case 'V':
00221                 myApp.m_Verbose++;
00222                 break;
00223 
00224             case 'q':
00225             case 'Q':
00226                 myApp.m_Quiet++;
00227                 break;
00228 
00229             case '0': case '1': case '2': case '3': case '4': case '5':
00230                 myApp.m_ModeIndex = p[-1] - '0';
00231                 break;
00232 
00233             default:
00234                 usage(av[0]);
00235                 /* no return */
00236                 break;
00237             }
00238         }
00239 
00240         pReaderHostName = av[2];
00241     }
00242     else
00243     {
00244         usage(av[0]);
00245         /* no return */
00246     }
00247 
00248     /*
00249      * Run application, capture return value for exit status
00250      */
00251     rc = myApp.run(pReaderHostName);
00252 
00253     printf("INFO: Done\n");
00254 
00255 #ifdef linux
00256     {
00257         char *              pMemHiwatAtEnd = (char*)sbrk(0);
00258 
00259         printf("INFO: Needed %d bytes of heap\n",
00260             pMemHiwatAtEnd - pMemHiwatAtStart);
00261     }
00262 #endif
00263 
00264     /*
00265      * Exit with the right status.
00266      */
00267     if(0 == rc)
00268     {
00269         exit(0);
00270     }
00271     else
00272     {
00273         exit(2);
00274     }
00275     /*NOTREACHED*/
00276 }
00277 
00278 
00290 void
00291 usage (
00292   char *                        pProgName)
00293 {
00294 #ifdef linux
00295     printf("Usage: %s [-v[v]] READERHOSTNAME\n", pProgName);
00296     printf("\n");
00297     printf("Each -v increases verbosity level\n");
00298 #endif /* linux */
00299 #ifdef WIN32
00300     printf("Usage: %s [/v[v]] READERHOSTNAME\n", pProgName);
00301     printf("\n");
00302     printf("Each /v increases verbosity level\n");
00303 #endif /* WIN32 */
00304     exit(1);
00305 }
00306 
00307 
00337 int
00338 CMyApplication::run (
00339   char *                        pReaderHostName)
00340 {
00341     CTypeRegistry *             pTypeRegistry;
00342     CConnection *               pConn;
00343     int                         rc;
00344 
00345     /*
00346      * Allocate the type registry. This is needed
00347      * by the connection to decode.
00348      */
00349     pTypeRegistry = getTheTypeRegistry();
00350     if(NULL == pTypeRegistry)
00351     {
00352         printf("ERROR: getTheTypeRegistry failed\n");
00353         return -1;
00354     }
00355 
00356     /*
00357      * Construct a connection (LLRP::CConnection).
00358      * Using a 32kb max frame size for send/recv.
00359      * The connection object is ready for business
00360      * but not actually connected to the reader yet.
00361      */
00362     pConn = new CConnection(pTypeRegistry, 32u*1024u);
00363     if(NULL == pConn)
00364     {
00365         printf("ERROR: new CConnection failed\n");
00366         return -2;
00367     }
00368 
00369     /*
00370      * Open the connection to the reader
00371      */
00372     if(m_Verbose)
00373     {
00374         printf ("INFO: Connecting to %s....\n", pReaderHostName);
00375     }
00376 
00377     rc = pConn->openConnectionToReader(pReaderHostName);
00378     if(0 != rc)
00379     {
00380         printf("ERROR: connect: %s (%d)\n", pConn->getConnectError(), rc);
00381         delete pConn;
00382         return -3;
00383     }
00384 
00385     /*
00386      * Record the pointer to the connection object so other
00387      * routines can use it.
00388      */
00389     m_pConnectionToReader = pConn;
00390 
00391     if(m_Verbose)
00392     {
00393         printf ("INFO: Connected, checking status....\n");
00394     }
00395 
00396     /*
00397      * Commence the sequence and check for errors as we go.
00398      * See comments for each routine for details.
00399      * Each routine prints messages per verbose level.
00400      */
00401     rc = 1;
00402     if(0 == checkConnectionStatus())
00403     {
00404         rc = 2;
00405         if(0 == scrubConfiguration())
00406         {
00407             rc = 3;
00408             if(0 == prepareReader())
00409             {
00410                 rc = 4;
00411                 if(0 == startAndMonitorOperation())
00412                 {
00413                     rc = 0;
00414                 }
00415             }
00416 
00417             /*
00418              * After we're done, try to leave the reader
00419              * in a clean state for next use. This is best
00420              * effort and no checking of the result is done.
00421              */
00422             if(m_Verbose)
00423             {
00424                 printf("INFO: Clean up reader configuration...\n");
00425             }
00426             scrubConfiguration();
00427         }
00428     }
00429 
00430     if(m_Verbose)
00431     {
00432         printf ("INFO: Finished\n");
00433     }
00434 
00435     /*
00436      * Close the connection and release its resources
00437      */
00438     pConn->closeConnectionToReader();
00439     delete pConn;
00440 
00441     /*
00442      * Done with the registry.
00443      */
00444     delete pTypeRegistry;
00445 
00446     /*
00447      * Maybe tattle on the number of tags. Normally tags are reported.
00448      * The -q command option prevents that and instead asks for just a
00449      * total. With the -v command option we're probably reporting tags
00450      * and a final count.
00451      */
00452     if(m_Verbose || m_Quiet)
00453     {
00454         printf("INFO: %d Tag reports\n", m_nTagReport);
00455     }
00456 
00457     /*
00458      * When we get here all allocated memory should have been deallocated.
00459      */
00460 
00461     return rc;
00462 }
00463 
00464 
00495 int
00496 CMyApplication::checkConnectionStatus (void)
00497 {
00498     CMessage *                  pMessage;
00499     CREADER_EVENT_NOTIFICATION *pNtf;
00500     CReaderEventNotificationData *pNtfData;
00501     CConnectionAttemptEvent *   pEvent;
00502 
00503     /*
00504      * Expect the notification within 10 seconds.
00505      * It is suppose to be the very first message sent.
00506      */
00507     pMessage = recvMessage(10000);
00508 
00509     /*
00510      * recvMessage() returns NULL if something went wrong.
00511      */
00512     if(NULL == pMessage)
00513     {
00514         /* recvMessage already tattled */
00515         goto fail;
00516     }
00517 
00518     /*
00519      * Check to make sure the message is of the right type.
00520      * The type label (pointer) in the message should be
00521      * the type descriptor for READER_EVENT_NOTIFICATION.
00522      */
00523     if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor != pMessage->m_pType)
00524     {
00525         goto fail;
00526     }
00527 
00528     /*
00529      * Now that we are sure it is a READER_EVENT_NOTIFICATION,
00530      * traverse to the ReaderEventNotificationData parameter.
00531      */
00532     pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage;
00533     pNtfData = pNtf->getReaderEventNotificationData();
00534     if(NULL == pNtfData)
00535     {
00536         goto fail;
00537     }
00538 
00539     /*
00540      * The ConnectionAttemptEvent parameter must be present.
00541      */
00542     pEvent = pNtfData->getConnectionAttemptEvent();
00543     if(NULL == pEvent)
00544     {
00545         goto fail;
00546     }
00547 
00548     /*
00549      * The status in the ConnectionAttemptEvent parameter
00550      * must indicate connection success.
00551      */
00552     if(ConnectionAttemptStatusType_Success != pEvent->getStatus())
00553     {
00554         goto fail;
00555     }
00556 
00557     /*
00558      * Done with the message
00559      */
00560     delete pMessage;
00561 
00562     if(m_Verbose)
00563     {
00564         printf("INFO: Connection status OK\n");
00565     }
00566 
00567     /*
00568      * Victory.
00569      */
00570     return 0;
00571 
00572   fail:
00573     /*
00574      * Something went wrong. Tattle. Clean up. Return error.
00575      */
00576     printf("ERROR: checkConnectionStatus failed\n");
00577     delete pMessage;
00578     return -1;
00579 }
00580 
00581 
00605 int
00606 CMyApplication::scrubConfiguration (void)
00607 {
00608     if(0 != resetConfigurationToFactoryDefaults())
00609     {
00610         return -1;
00611     }
00612 
00613     if(0 != deleteAllROSpecs())
00614     {
00615         return -2;
00616     }
00617 
00618     if(0 != deleteAllAccessSpecs())
00619     {
00620         return -3;
00621     }
00622 
00623     return 0;
00624 }
00625 
00626 
00647 int
00648 CMyApplication::resetConfigurationToFactoryDefaults (void)
00649 {
00650     CSET_READER_CONFIG *        pCmd;
00651     CMessage *                  pRspMsg;
00652     CSET_READER_CONFIG_RESPONSE *pRsp;
00653 
00654     /*
00655      * Compose the command message
00656      */
00657     pCmd = new CSET_READER_CONFIG();
00658     pCmd->setMessageID(101);
00659     pCmd->setResetToFactoryDefault(1);
00660 
00661     /*
00662      * Send the message, expect the response of certain type
00663      */
00664     pRspMsg = transact(pCmd);
00665 
00666     /*
00667      * Done with the command message
00668      */
00669     delete pCmd;
00670 
00671     /*
00672      * transact() returns NULL if something went wrong.
00673      */
00674     if(NULL == pRspMsg)
00675     {
00676         /* transact already tattled */
00677         return -1;
00678     }
00679 
00680     /*
00681      * Cast to a SET_READER_CONFIG_RESPONSE message.
00682      */
00683     pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg;
00684 
00685     /*
00686      * Check the LLRPStatus parameter.
00687      */
00688     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
00689                         "resetConfigurationToFactoryDefaults"))
00690     {
00691         /* checkLLRPStatus already tattled */
00692         delete pRspMsg;
00693         return -1;
00694     }
00695 
00696     /*
00697      * Done with the response message.
00698      */
00699     delete pRspMsg;
00700 
00701     /*
00702      * Tattle progress, maybe
00703      */
00704     if(m_Verbose)
00705     {
00706         printf("INFO: Configuration reset to factory defaults\n");
00707     }
00708 
00709     /*
00710      * Victory.
00711      */
00712     return 0;
00713 }
00714 
00715 
00735 int
00736 CMyApplication::deleteAllROSpecs (void)
00737 {
00738     CDELETE_ROSPEC *            pCmd;
00739     CMessage *                  pRspMsg;
00740     CDELETE_ROSPEC_RESPONSE *   pRsp;
00741 
00742     /*
00743      * Compose the command message
00744      */
00745     pCmd = new CDELETE_ROSPEC();
00746     pCmd->setMessageID(102);
00747     pCmd->setROSpecID(0);               /* All */
00748 
00749     /*
00750      * Send the message, expect the response of certain type
00751      */
00752     pRspMsg = transact(pCmd);
00753 
00754     /*
00755      * Done with the command message
00756      */
00757     delete pCmd;
00758 
00759     /*
00760      * transact() returns NULL if something went wrong.
00761      */
00762     if(NULL == pRspMsg)
00763     {
00764         /* transact already tattled */
00765         return -1;
00766     }
00767 
00768     /*
00769      * Cast to a DELETE_ROSPEC_RESPONSE message.
00770      */
00771     pRsp = (CDELETE_ROSPEC_RESPONSE *) pRspMsg;
00772 
00773     /*
00774      * Check the LLRPStatus parameter.
00775      */
00776     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "deleteAllROSpecs"))
00777     {
00778         /* checkLLRPStatus already tattled */
00779         delete pRspMsg;
00780         return -1;
00781     }
00782 
00783     /*
00784      * Done with the response message.
00785      */
00786     delete pRspMsg;
00787 
00788     /*
00789      * Tattle progress, maybe
00790      */
00791     if(m_Verbose)
00792     {
00793         printf("INFO: All ROSpecs are deleted\n");
00794     }
00795 
00796     /*
00797      * Victory.
00798      */
00799     return 0;
00800 }
00801 
00802 
00822 int
00823 CMyApplication::deleteAllAccessSpecs (void)
00824 {
00825     CDELETE_ACCESSSPEC *        pCmd;
00826     CMessage *                  pRspMsg;
00827     CDELETE_ACCESSSPEC_RESPONSE *pRsp;
00828 
00829     /*
00830      * Compose the command message
00831      */
00832     pCmd = new CDELETE_ACCESSSPEC();
00833     pCmd->setMessageID(103);
00834     pCmd->setAccessSpecID(0);           /* All */
00835 
00836     /*
00837      * Send the message, expect the response of certain type
00838      */
00839     pRspMsg = transact(pCmd);
00840 
00841     /*
00842      * Done with the command message
00843      */
00844     delete pCmd;
00845 
00846     /*
00847      * transact() returns NULL if something went wrong.
00848      */
00849     if(NULL == pRspMsg)
00850     {
00851         /* transact already tattled */
00852         return -1;
00853     }
00854 
00855     /*
00856      * Cast to a DELETE_ACCESSSPEC_RESPONSE message.
00857      */
00858     pRsp = (CDELETE_ACCESSSPEC_RESPONSE *) pRspMsg;
00859 
00860     /*
00861      * Check the LLRPStatus parameter.
00862      */
00863     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "deleteAllAccessSpecs"))
00864     {
00865         /* checkLLRPStatus already tattled */
00866         delete pRspMsg;
00867         return -1;
00868     }
00869 
00870     /*
00871      * Done with the response message.
00872      */
00873     delete pRspMsg;
00874 
00875     /*
00876      * Tattle progress, maybe
00877      */
00878     if(m_Verbose)
00879     {
00880         printf("INFO: All AccessSpecs are deleted\n");
00881     }
00882 
00883     /*
00884      * Victory.
00885      */
00886     return 0;
00887 }
00888 
00889 
00918 int
00919 CMyApplication::prepareReader(void)
00920 {
00921     if(0 != getAllCapabilities())
00922     {
00923         return -1;
00924     }
00925 
00926     if(0 != getAllConfiguration())
00927     {
00928         return -2;
00929     }
00930 
00931     if(0 != configureNotificationStates())
00932     {
00933         return -3;
00934     }
00935 
00936     if(0 != getAllConfiguration())
00937     {
00938         return -4;
00939     }
00940 
00941     if(0 != addROSpec())
00942     {
00943         return -5;
00944     }
00945 
00946     if(0 != enableROSpec())
00947     {
00948         return -6;
00949     }
00950 
00951     return 0;
00952 }
00953 
00954 
00977 int
00978 CMyApplication::getAllCapabilities (void)
00979 {
00980     CGET_READER_CAPABILITIES *  pCmd;
00981     CMessage *                  pRspMsg;
00982     CGET_READER_CAPABILITIES_RESPONSE *pRsp;
00983 
00984     /*
00985      * Compose the command message
00986      */
00987     pCmd = new CGET_READER_CAPABILITIES();
00988     pCmd->setMessageID(120);
00989     pCmd->setRequestedData(GetReaderCapabilitiesRequestedData_All);
00990 
00991     /*
00992      * Send the message, expect the response of certain type
00993      */
00994     pRspMsg = transact(pCmd);
00995 
00996     /*
00997      * Done with the command message
00998      */
00999     delete pCmd;
01000 
01001     /*
01002      * transact() returns NULL if something went wrong.
01003      */
01004     if(NULL == pRspMsg)
01005     {
01006         /* transact already tattled */
01007         return -1;
01008     }
01009 
01010     /*
01011      * Cast to a GET_READER_CAPABILITIES_RESPONSE message.
01012      */
01013     pRsp = (CGET_READER_CAPABILITIES_RESPONSE *) pRspMsg;
01014 
01015     /*
01016      * Check the LLRPStatus parameter.
01017      */
01018     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "getAllCapabilities"))
01019     {
01020         /* checkLLRPStatus already tattled */
01021         delete pRspMsg;
01022         return -1;
01023     }
01024 
01025     /*
01026      * Done with the response message.
01027      */
01028     delete pRspMsg;
01029 
01030     /*
01031      * Tattle progress, maybe
01032      */
01033     if(m_Verbose)
01034     {
01035         printf("INFO: Got capabilities\n");
01036     }
01037 
01038     /*
01039      * Victory.
01040      */
01041     return 0;
01042 }
01043 
01044 
01067 int
01068 CMyApplication::getAllConfiguration (void)
01069 {
01070     CGET_READER_CONFIG *        pCmd;
01071     CMessage *                  pRspMsg;
01072     CGET_READER_CONFIG_RESPONSE *pRsp;
01073 
01074     /*
01075      * Compose the command message
01076      */
01077     pCmd = new CGET_READER_CONFIG();
01078     pCmd->setMessageID(121);
01079     pCmd->setRequestedData(GetReaderConfigRequestedData_All);
01080 
01081     /*
01082      * Send the message, expect the response of certain type
01083      */
01084     pRspMsg = transact(pCmd);
01085 
01086     /*
01087      * Done with the command message
01088      */
01089     delete pCmd;
01090 
01091     /*
01092      * transact() returns NULL if something went wrong.
01093      */
01094     if(NULL == pRspMsg)
01095     {
01096         /* transact already tattled */
01097         return -1;
01098     }
01099 
01100     /*
01101      * Cast to a GET_READER_CONFIG_RESPONSE message.
01102      */
01103     pRsp = (CGET_READER_CONFIG_RESPONSE *) pRspMsg;
01104 
01105     /*
01106      * Check the LLRPStatus parameter.
01107      */
01108     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "getAllConfiguration"))
01109     {
01110         /* checkLLRPStatus already tattled */
01111         delete pRspMsg;
01112         return -1;
01113     }
01114 
01115     /*
01116      * Done with the response message.
01117      */
01118     delete pRspMsg;
01119 
01120     /*
01121      * Tattle progress, maybe
01122      */
01123     if(m_Verbose)
01124     {
01125         printf("INFO: Got configuration\n");
01126     }
01127 
01128     /*
01129      * Victory.
01130      */
01131     return 0;
01132 }
01133 
01134 
01199 int
01200 CMyApplication::configureNotificationStates (void)
01201 {
01202     CEventNotificationState *   pENHop = new CEventNotificationState();
01203     pENHop->setEventType(NotificationEventType_Upon_Hopping_To_Next_Channel);
01204     pENHop->setNotificationState(TRUE);
01205 
01206     CEventNotificationState *   pENGPI = new CEventNotificationState();
01207     pENGPI->setEventType(NotificationEventType_GPI_Event);
01208     pENGPI->setNotificationState(FALSE);
01209 
01210     CEventNotificationState *   pENROSpec = new CEventNotificationState();
01211     pENROSpec->setEventType(NotificationEventType_ROSpec_Event);
01212     pENROSpec->setNotificationState(TRUE);
01213 
01214     CEventNotificationState *   pENBufWarn = new CEventNotificationState();
01215     pENBufWarn->setEventType(NotificationEventType_Report_Buffer_Fill_Warning);
01216     pENBufWarn->setNotificationState(TRUE);
01217 
01218     CEventNotificationState *   pENExcept = new CEventNotificationState();
01219     pENExcept->setEventType(NotificationEventType_Reader_Exception_Event);
01220     pENExcept->setNotificationState(TRUE);
01221 
01222     CEventNotificationState *   pENSurvey = new CEventNotificationState();
01223     pENSurvey->setEventType(NotificationEventType_RFSurvey_Event);
01224     pENSurvey->setNotificationState(FALSE);
01225 
01226     CEventNotificationState *   pENAISpec = new CEventNotificationState();
01227     pENAISpec->setEventType(NotificationEventType_AISpec_Event);
01228     pENAISpec->setNotificationState(TRUE);
01229 
01230     CEventNotificationState *   pENAISpecDetails
01231                                     = new CEventNotificationState();
01232     pENAISpecDetails->setEventType(
01233             NotificationEventType_AISpec_Event_With_Details);
01234     pENAISpecDetails->setNotificationState(FALSE);
01235 
01236     CEventNotificationState *   pENAnt = new CEventNotificationState();
01237     pENAnt->setEventType(NotificationEventType_Antenna_Event);
01238     pENAnt->setNotificationState(TRUE);
01239 
01240     CReaderEventNotificationSpec * pReaderEventNotificationSpec;
01241 
01242     pReaderEventNotificationSpec = new CReaderEventNotificationSpec;
01243 
01244     pReaderEventNotificationSpec->addEventNotificationState(pENHop);
01245     pReaderEventNotificationSpec->addEventNotificationState(pENGPI);
01246     pReaderEventNotificationSpec->addEventNotificationState(pENROSpec);
01247     pReaderEventNotificationSpec->addEventNotificationState(pENBufWarn);
01248     pReaderEventNotificationSpec->addEventNotificationState(pENExcept);
01249     pReaderEventNotificationSpec->addEventNotificationState(pENSurvey);
01250     pReaderEventNotificationSpec->addEventNotificationState(pENAISpec);
01251     pReaderEventNotificationSpec->addEventNotificationState(
01252                 pENAISpecDetails);
01253     pReaderEventNotificationSpec->addEventNotificationState(pENAnt);
01254 
01255     CSET_READER_CONFIG *        pCmd;
01256     CMessage *                  pRspMsg;
01257     CSET_READER_CONFIG_RESPONSE *pRsp;
01258 
01259     /*
01260      * Compose the command message.
01261      * N.B.: After the message is composed, all the parameters
01262      *       constructed, immediately above, are considered "owned"
01263      *       by the command message. When it is destructed so
01264      *       too will the parameters be.
01265      */
01266     pCmd = new CSET_READER_CONFIG();
01267     pCmd->setMessageID(150);
01268     pCmd->setReaderEventNotificationSpec(pReaderEventNotificationSpec);
01269 
01270     /*
01271      * Send the message, expect the response of certain type
01272      */
01273     pRspMsg = transact(pCmd);
01274 
01275     /*
01276      * Done with the command message.
01277      * N.B.: And the parameters
01278      */
01279     delete pCmd;
01280 
01281     /*
01282      * transact() returns NULL if something went wrong.
01283      */
01284     if(NULL == pRspMsg)
01285     {
01286         /* transact already tattled */
01287         return -1;
01288     }
01289 
01290     /*
01291      * Cast to a SET_READER_CONFIG_RESPONSE message.
01292      */
01293     pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg;
01294 
01295     /*
01296      * Check the LLRPStatus parameter.
01297      */
01298     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
01299                     "configureNotificationStates"))
01300     {
01301         delete pRspMsg;
01302         return -1;
01303     }
01304 
01305     /*
01306      * Done with the response message.
01307      */
01308     delete pRspMsg;
01309 
01310     /*
01311      * Tattle progress, maybe
01312      */
01313     if(m_Verbose)
01314     {
01315         printf("INFO: Notifications are configured\n");
01316     }
01317 
01318     /*
01319      * Victory.
01320      */
01321     return 0;
01322 }
01323 
01324 
01415 int
01416 CMyApplication::addROSpec (void)
01417 {
01418     CROSpecStartTrigger *       pROSpecStartTrigger =
01419                                     new CROSpecStartTrigger();
01420     pROSpecStartTrigger->setROSpecStartTriggerType(
01421                                 ROSpecStartTriggerType_Null);
01422 
01423     CROSpecStopTrigger *        pROSpecStopTrigger = new CROSpecStopTrigger();
01424     pROSpecStopTrigger->setROSpecStopTriggerType(ROSpecStopTriggerType_Null);
01425     pROSpecStopTrigger->setDurationTriggerValue(0);     /* n/a */
01426 
01427     CROBoundarySpec *           pROBoundarySpec = new CROBoundarySpec();
01428     pROBoundarySpec->setROSpecStartTrigger(pROSpecStartTrigger);
01429     pROBoundarySpec->setROSpecStopTrigger(pROSpecStopTrigger);
01430 
01431 #if 1
01432     CAISpecStopTrigger *        pAISpecStopTrigger = new CAISpecStopTrigger();
01433     pAISpecStopTrigger->setAISpecStopTriggerType(
01434                             AISpecStopTriggerType_Duration);
01435     pAISpecStopTrigger->setDurationTrigger(30000);
01436 #else
01437     CTagObservationTrigger *    pTagObservationTrigger =
01438                                     new CTagObservationTrigger();
01439     pTagObservationTrigger->setTriggerType (
01440  TagObservationTriggerType_Upon_Seeing_No_More_New_Tags_For_Tms_Or_Timeout);
01441     pTagObservationTrigger->setNumberOfTags(0);         /* unlimited */
01442     pTagObservationTrigger->setNumberOfAttempts(0);     /* n/a */
01443     pTagObservationTrigger->setT(3500);                 /* 3.5 sec */
01444     pTagObservationTrigger->setTimeout(12500);          /* 12.5 sec */
01445 
01446     CAISpecStopTrigger *        pAISpecStopTrigger = new CAISpecStopTrigger();
01447     pAISpecStopTrigger->setAISpecStopTriggerType(
01448                             AISpecStopTriggerType_Tag_Observation);
01449     pAISpecStopTrigger->setDurationTrigger(0);
01450     pAISpecStopTrigger->setTagObservationTrigger(pTagObservationTrigger);
01451 #endif
01452 
01453     CC1G2SingulationControl *   pC1G2SingulationControl =
01454                                     new CC1G2SingulationControl();
01455     pC1G2SingulationControl->setSession(2);
01456     pC1G2SingulationControl->setTagPopulation(32);
01457 
01458     CC1G2InventoryCommand *     pC1G2InventoryCommand =
01459                                     new CC1G2InventoryCommand();
01460     pC1G2InventoryCommand->setC1G2SingulationControl(
01461                                         pC1G2SingulationControl);
01462     /*
01463      * C1G2RFControl might be set below if a m_ModeIndex was
01464      * given on the command line.
01465      */
01466     CAntennaConfiguration *     pAntennaConfiguration =
01467                                     new CAntennaConfiguration();
01468     pAntennaConfiguration->addAirProtocolInventoryCommandSettings (
01469                                         pC1G2InventoryCommand);
01470 
01471     CInventoryParameterSpec *   pInventoryParameterSpec =
01472                                     new CInventoryParameterSpec();
01473     pInventoryParameterSpec->setInventoryParameterSpecID(1234);
01474     pInventoryParameterSpec->setProtocolID(AirProtocols_EPCGlobalClass1Gen2);
01475     pInventoryParameterSpec->addAntennaConfiguration (
01476                                         pAntennaConfiguration);
01477 
01478     llrp_u16v_t                 AntennaIDs = llrp_u16v_t(1);
01479     AntennaIDs.m_pValue[0] = 0;         /* All */
01480 
01481     CAISpec *                   pAISpec = new CAISpec();
01482     pAISpec->setAntennaIDs(AntennaIDs);
01483     pAISpec->setAISpecStopTrigger(pAISpecStopTrigger);
01484     pAISpec->addInventoryParameterSpec(pInventoryParameterSpec);
01485 
01486     CTagReportContentSelector * pTagReportContentSelector =
01487                                     new CTagReportContentSelector();
01488     pTagReportContentSelector->setEnableROSpecID(FALSE);
01489     pTagReportContentSelector->setEnableSpecIndex(FALSE);
01490     pTagReportContentSelector->setEnableInventoryParameterSpecID(FALSE);
01491     pTagReportContentSelector->setEnableAntennaID(TRUE);
01492     pTagReportContentSelector->setEnableChannelIndex(FALSE);
01493     pTagReportContentSelector->setEnablePeakRSSI(TRUE);
01494     pTagReportContentSelector->setEnableFirstSeenTimestamp(TRUE);
01495     pTagReportContentSelector->setEnableLastSeenTimestamp(TRUE);
01496     pTagReportContentSelector->setEnableTagSeenCount(TRUE);
01497     pTagReportContentSelector->setEnableAccessSpecID(FALSE);
01498 
01499     CROReportSpec *             pROReportSpec = new CROReportSpec();
01500     pROReportSpec->setROReportTrigger(
01501             ROReportTriggerType_Upon_N_Tags_Or_End_Of_ROSpec);
01502     pROReportSpec->setN(1);         /* Report every singulation */
01503     pROReportSpec->setTagReportContentSelector(pTagReportContentSelector);
01504 
01505     CROSpec *                   pROSpec = new CROSpec();
01506     pROSpec->setROSpecID(123);
01507     pROSpec->setPriority(0);
01508     pROSpec->setCurrentState(ROSpecState_Disabled);
01509     pROSpec->setROBoundarySpec(pROBoundarySpec);
01510     pROSpec->addSpecParameter(pAISpec);
01511     pROSpec->setROReportSpec(pROReportSpec);
01512 
01513     CADD_ROSPEC *               pCmd;
01514     CMessage *                  pRspMsg;
01515     CADD_ROSPEC_RESPONSE *      pRsp;
01516 
01517     /*
01518      * Compose the command message.
01519      * N.B.: After the message is composed, all the parameters
01520      *       constructed, immediately above, are considered "owned"
01521      *       by the command message. When it is destructed so
01522      *       too will the parameters be.
01523      */
01524     pCmd = new CADD_ROSPEC();
01525     pCmd->setMessageID(201);
01526     pCmd->setROSpec(pROSpec);
01527 
01528     /*
01529      * If the mode was specified link in the AntennaConfiguration
01530      * that was prepared, above. The absence of the AntennaConfiguration
01531      * tells the reader to use the default mode.
01532      */
01533     if(0 <= m_ModeIndex)
01534     {
01535         CC1G2RFControl *        pC1G2RFControl =
01536                                     new CC1G2RFControl();
01537 
01538         pC1G2RFControl->setModeIndex(m_ModeIndex);
01539         pC1G2InventoryCommand->setC1G2RFControl(pC1G2RFControl);
01540     }
01541 
01542     /*
01543      * Send the message, expect the response of certain type
01544      */
01545     pRspMsg = transact(pCmd);
01546 
01547     /*
01548      * Done with the command message.
01549      * N.B.: And the parameters
01550      */
01551     delete pCmd;
01552 
01553     /*
01554      * transact() returns NULL if something went wrong.
01555      */
01556     if(NULL == pRspMsg)
01557     {
01558         /* transact already tattled */
01559         return -1;
01560     }
01561 
01562     /*
01563      * Cast to a ADD_ROSPEC_RESPONSE message.
01564      */
01565     pRsp = (CADD_ROSPEC_RESPONSE *) pRspMsg;
01566 
01567     /*
01568      * Check the LLRPStatus parameter.
01569      */
01570     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "addROSpec"))
01571     {
01572         /* checkLLRPStatus already tattled */
01573         delete pRspMsg;
01574         return -1;
01575     }
01576 
01577     /*
01578      * Done with the response message.
01579      */
01580     delete pRspMsg;
01581 
01582     /*
01583      * Tattle progress, maybe
01584      */
01585     if(m_Verbose)
01586     {
01587         printf("INFO: ROSpec added\n");
01588     }
01589 
01590     /*
01591      * Victory.
01592      */
01593     return 0;
01594 }
01595 
01596 
01614 int
01615 CMyApplication::enableROSpec (void)
01616 {
01617     CENABLE_ROSPEC *            pCmd;
01618     CMessage *                  pRspMsg;
01619     CENABLE_ROSPEC_RESPONSE *   pRsp;
01620 
01621     /*
01622      * Compose the command message
01623      */
01624     pCmd = new CENABLE_ROSPEC();
01625     pCmd->setMessageID(202);
01626     pCmd->setROSpecID(123);
01627 
01628     /*
01629      * Send the message, expect the response of certain type
01630      */
01631     pRspMsg = transact(pCmd);
01632 
01633     /*
01634      * Done with the command message
01635      */
01636     delete pCmd;
01637 
01638     /*
01639      * transact() returns NULL if something went wrong.
01640      */
01641     if(NULL == pRspMsg)
01642     {
01643         /* transact already tattled */
01644         return -1;
01645     }
01646 
01647     /*
01648      * Cast to a ENABLE_ROSPEC_RESPONSE message.
01649      */
01650     pRsp = (CENABLE_ROSPEC_RESPONSE *) pRspMsg;
01651 
01652     /*
01653      * Check the LLRPStatus parameter.
01654      */
01655     if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "enableROSpec"))
01656     {
01657         /* checkLLRPStatus already tattled */
01658         delete pRspMsg;
01659         return -1;
01660     }
01661 
01662     /*
01663      * Done with the response message.
01664      */
01665     delete pRspMsg;
01666 
01667     /*
01668      * Tattle progress, maybe
01669      */
01670     if(m_Verbose)
01671     {
01672         printf("INFO: ROSpec enabled\n");
01673     }
01674 
01675     /*
01676      * Victory.
01677      */
01678     return 0;
01679 }
01680 
01681 
01724 int
01725 CMyApplication::startAndMonitorOperation (void)
01726 {
01727     CSTART_ROSPEC *             pCmd;
01728     int                         bDone = 0;
01729     int                         RetVal = 0;
01730 
01731     /*
01732      * Tattle as we start.
01733      */
01734     printf("INFO: Inventory operation starting\n");
01735 
01736     /*
01737      * Compose the command message
01738      */
01739     pCmd = new CSTART_ROSPEC();
01740     pCmd->setMessageID(203);
01741     pCmd->setROSpecID(123);
01742 
01743     /*
01744      * Just send the START_ROSPEC message, do not wait for the resposne.
01745      */
01746     if(0 != sendMessage(pCmd))
01747     {
01748         /* sendMessage already tattled */
01749         return -1;
01750     }
01751 
01752     /*
01753      * Done with the command message
01754      */
01755     delete pCmd;
01756 
01757     /*
01758      * Keep receiving messages until done or until
01759      * something bad happens.
01760      */
01761     while(!bDone)
01762     {
01763         CMessage *              pMessage;
01764         const CTypeDescriptor * pType;
01765 
01766         /*
01767          * Wait up to 20 seconds for a message. They should
01768          * be much more frequent because there will be several
01769          * hopping events per second.
01770          */
01771         pMessage = recvMessage(20000);
01772         if(NULL == pMessage)
01773         {
01774             /*
01775              * Did not receive a message within a reasonable
01776              * amount of time. recvMessage() already tattled
01777              */
01778             RetVal = -2;
01779             bDone = 1;
01780             continue;
01781         }
01782 
01783         /*
01784          * What happens depends on what kind of message
01785          * received. Use the type label (m_pType) to
01786          * discriminate message types.
01787          */
01788         pType = pMessage->m_pType;
01789 
01790         /*
01791          * Is it the response from the START_ROSPEC?
01792          * If so, just make sure the status is good.
01793          * If the status is not good there is no
01794          * ROSpec running and things are done.
01795          */
01796         if(&CSTART_ROSPEC_RESPONSE::s_typeDescriptor == pType)
01797         {
01798             CSTART_ROSPEC_RESPONSE *pRsp;
01799 
01800             /*
01801              * Cast to a START_ROSPEC_RESPONSE message.
01802              */
01803             pRsp = (CSTART_ROSPEC_RESPONSE *) pMessage;
01804 
01805             /*
01806              * Check the LLRPStatus parameter.
01807              */
01808             if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "startROSpec"))
01809             {
01810                 /* checkLLRPStatus already tattled */
01811                 RetVal = -3;
01812                 bDone = 1;
01813             }
01814             else
01815             {
01816                 /* Good start. Tattle, maybe. */
01817                 if(m_Verbose)
01818                 {
01819                     printf("INFO: Start command acknowledged\n");
01820                 }
01821             }
01822         }
01823 
01824         /*
01825          * Is it a reader event? If so, which ones?
01826          */
01827         else if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor == pType)
01828         {
01829             CREADER_EVENT_NOTIFICATION *pNtf;
01830             CReaderEventNotificationData *pNtfData;
01831 
01832             pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage;
01833             pNtfData = pNtf->getReaderEventNotificationData();
01834 
01835             /*
01836              * Is there an ROSpecEvent? These tell use when the ROSpec
01837              * starts and stops. When it stops things are done.
01838              */
01839             if(NULL != pNtfData->getROSpecEvent())
01840             {
01841                 CROSpecEvent *    pROEvent;
01842 
01843                 pROEvent = pNtfData->getROSpecEvent();
01844                 switch(pROEvent->getEventType())
01845                 {
01846                 default:
01847                     printf("ERROR: Unknown RO event type\n");
01848                     RetVal = -4;
01849                     bDone = 1;
01850                     break;
01851 
01852                 case ROSpecEventType_Start_Of_ROSpec:
01853                     if(m_Verbose)
01854                     {
01855                         printf("INFO: RO running\n");
01856                     }
01857                     break;
01858 
01859                 case ROSpecEventType_End_Of_ROSpec:
01860                     if(m_Verbose)
01861                     {
01862                         printf("INFO: RO stopped\n");
01863                     }
01864                     RetVal = 0;
01865                     bDone = 1;
01866                     break;
01867                 }
01868             }
01869 
01870             /*
01871              * Other reader events may be present.
01872              * Notifications enabled include AISpec events,
01873              * antenna events, and hopping events.
01874              * Run this programs with -vv to see the
01875              * XML for the other events.
01876              *
01877              * For this example we just ignore them.
01878              */
01879         }
01880 
01881         /*
01882          * Is it a tag report? If so, print it out.
01883          */
01884         else if(&CRO_ACCESS_REPORT::s_typeDescriptor == pType)
01885         {
01886             CRO_ACCESS_REPORT * pNtf;
01887 
01888             pNtf = (CRO_ACCESS_REPORT *) pMessage;
01889 
01890             printTagReportData(pNtf);
01891         }
01892 
01893         /*
01894          * Hmmm. Something unexpected. Just tattle and keep going.
01895          */
01896         else
01897         {
01898             printf("WARNING: Ignored unexpected message during monitor: %s\n",
01899                 pType->m_pName);
01900         }
01901 
01902         /*
01903          * Done with the received message
01904          */
01905         delete pMessage;
01906     }
01907 
01908     /*
01909      * Tattle about how things turned out.
01910      */
01911     if(RetVal != 0)
01912     {
01913         printf("ERROR: Inventory operation terminated (%d)\n", RetVal);
01914     }
01915     else if(m_Verbose)
01916     {
01917         printf("INFO: Inventory operation finished\n");
01918     }
01919 
01920     return RetVal;
01921 }
01922 
01923 
01938 void
01939 CMyApplication::printTagReportData (
01940   CRO_ACCESS_REPORT *           pRO_ACCESS_REPORT)
01941 {
01942     std::list<CTagReportData *>::iterator Cur;
01943     unsigned int                nEntry = 0;
01944 
01945     /*
01946      * Count the number of tag reports.
01947      */
01948     m_nTagReport++;
01949 
01950     /*
01951      * If individual tag reports are not wanted, just return.
01952      */
01953     if(m_Quiet)
01954     {
01955         return;
01956     }
01957 
01958     /*
01959      * Loop through and count the number of entries
01960      */
01961     for (
01962         Cur = pRO_ACCESS_REPORT->beginTagReportData();
01963         Cur != pRO_ACCESS_REPORT->endTagReportData();
01964         Cur++)
01965     {
01966         nEntry++;
01967     }
01968 
01969     printf("INFO: %u tag report entries\n", nEntry);
01970 
01971     /*
01972      * Loop through again and print each entry.
01973      */
01974     for (
01975         Cur = pRO_ACCESS_REPORT->beginTagReportData();
01976         Cur != pRO_ACCESS_REPORT->endTagReportData();
01977         Cur++)
01978     {
01979         printOneTagReportData (*Cur);
01980     }
01981 }
01982 
01983 
01997 void
01998 CMyApplication::printOneTagReportData (
01999   CTagReportData *              pTagReportData)
02000 {
02001     const CTypeDescriptor *     pType;
02002     char                        aBuf[64];
02003 
02004     /*
02005      * Print the EPC. It could be an 96-bit EPC_96 parameter
02006      * or an variable length EPCData parameter.
02007      */
02008 
02009     CParameter *                pEPCParameter =
02010                                     pTagReportData->getEPCParameter();
02011 
02012     if(NULL != pEPCParameter)
02013     {
02014         char *              p = aBuf;
02015         llrp_u96_t          my_u96;
02016         llrp_u1v_t          my_u1v;
02017         llrp_u8_t *         pValue = NULL;
02018         unsigned int        n, i;
02019 
02020         pType = pEPCParameter->m_pType;
02021         if(&CEPC_96::s_typeDescriptor == pType)
02022         {
02023             CEPC_96             *pEPC_96;
02024 
02025             pEPC_96 = (CEPC_96 *) pEPCParameter;
02026             my_u96 = pEPC_96->getEPC();
02027             pValue = my_u96.m_aValue;
02028             n = 12u;
02029         }
02030         else if(&CEPCData::s_typeDescriptor == pType)
02031         {
02032             CEPCData *          pEPCData;
02033 
02034             pEPCData = (CEPCData *) pEPCParameter;
02035             my_u1v = pEPCData->getEPC();
02036             pValue = my_u1v.m_pValue;
02037             n = (my_u1v.m_nBit + 7u) / 8u;
02038         }
02039 
02040         if(NULL != pValue)
02041         {
02042             for(i = 0; i < n; i++)
02043             {
02044                 if(0 < i && i%2 == 0)
02045                 {
02046                     *p++ = '-';
02047                 }
02048                 sprintf(p, "%02X", pValue[i]);
02049                 while(*p) p++;
02050             }
02051         }
02052         else
02053         {
02054             strcpy(aBuf, "---unknown-epc-data-type---");
02055         }
02056     }
02057     else
02058     {
02059         strcpy(aBuf, "---missing-epc-data---");
02060     }
02061     printf("%-32s", aBuf);
02062 
02063     /*
02064      * Print the antenna ID number
02065      */
02066     if(NULL != pTagReportData->getAntennaID())
02067     {
02068         sprintf(aBuf, "ant%d",
02069             pTagReportData->getAntennaID()->getAntennaID());
02070     }
02071     else
02072     {
02073         sprintf(aBuf, "ant?");
02074     }
02075     printf(" %-5s", aBuf);
02076 
02077     /*
02078      * Print the peak RSSI
02079      */
02080     if(NULL != pTagReportData->getPeakRSSI())
02081     {
02082         sprintf(aBuf, "%3ddBm",
02083             pTagReportData->getPeakRSSI()->getPeakRSSI());
02084     }
02085     else
02086     {
02087         sprintf(aBuf, "  ?dBm");
02088     }
02089     printf(" %-7s", aBuf);
02090 
02091     /*
02092      * Print the number of times the tag was seen
02093      */
02094     if(NULL != pTagReportData->getTagSeenCount())
02095     {
02096         sprintf(aBuf, "%4dseen",
02097             pTagReportData->getTagSeenCount()->getTagCount());
02098     }
02099     else
02100     {
02101         sprintf(aBuf, "   ?seen");
02102     }
02103     printf(" %-8s", aBuf);
02104 
02105     /*
02106      * End of line
02107      */
02108     printf("\n");
02109 }
02110 
02111 
02130 int
02131 CMyApplication::checkLLRPStatus (
02132   CLLRPStatus *                 pLLRPStatus,
02133   char *                        pWhatStr)
02134 {
02135     /*
02136      * The LLRPStatus parameter is mandatory in all responses.
02137      * If it is missing there should have been a decode error.
02138      * This just makes sure (remember, this program is a
02139      * diagnostic and suppose to catch LTKC mistakes).
02140      */
02141     if(NULL == pLLRPStatus)
02142     {
02143         printf("ERROR: %s missing LLRP status\n", pWhatStr);
02144         return -1;
02145     }
02146 
02147     /*
02148      * Make sure the status is M_Success.
02149      * If it isn't, print the error string if one.
02150      * This does not try to pretty-print the status
02151      * code. To get that, run this program with -vv
02152      * and examine the XML output.
02153      */
02154     if(StatusCode_M_Success != pLLRPStatus->getStatusCode())
02155     {
02156         llrp_utf8v_t            ErrorDesc;
02157 
02158         ErrorDesc = pLLRPStatus->getErrorDescription();
02159 
02160         if(0 == ErrorDesc.m_nValue)
02161         {
02162             printf("ERROR: %s failed, no error description given\n",
02163                 pWhatStr);
02164         }
02165         else
02166         {
02167             printf("ERROR: %s failed, %.*s\n",
02168                 pWhatStr, ErrorDesc.m_nValue, ErrorDesc.m_pValue);
02169         }
02170         return -2;
02171     }
02172 
02173     /*
02174      * Victory. Everything is fine.
02175      */
02176     return 0;
02177 }
02178 
02179 
02203 CMessage *
02204 CMyApplication::transact (
02205   CMessage *                    pSendMsg)
02206 {
02207     CConnection *               pConn = m_pConnectionToReader;
02208     CMessage *                  pRspMsg;
02209 
02210     /*
02211      * Print the XML text for the outbound message if
02212      * verbosity is 2 or higher.
02213      */
02214     if(1 < m_Verbose)
02215     {
02216         /* If -qq command option, do XML encode but don't actually print */
02217         if(2 > m_Quiet)
02218         {
02219             printf("\n===================================\n");
02220             printf("INFO: Transact sending\n");
02221         }
02222         printXMLMessage(pSendMsg);
02223     }
02224 
02225     /*
02226      * Send the message, expect the response of certain type.
02227      * If LLRP::CConnection::transact() returns NULL then there was
02228      * an error. In that case we try to print the error details.
02229      */
02230     pRspMsg = pConn->transact(pSendMsg, 5000);
02231 
02232     if(NULL == pRspMsg)
02233     {
02234         const CErrorDetails *   pError = pConn->getTransactError();
02235 
02236         printf("ERROR: %s transact failed, %s\n",
02237             pSendMsg->m_pType->m_pName,
02238             pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
02239 
02240         if(NULL != pError->m_pRefType)
02241         {
02242             printf("ERROR: ... reference type %s\n",
02243                 pError->m_pRefType->m_pName);
02244         }
02245 
02246         if(NULL != pError->m_pRefField)
02247         {
02248             printf("ERROR: ... reference field %s\n",
02249                 pError->m_pRefField->m_pName);
02250         }
02251 
02252         return NULL;
02253     }
02254 
02255     /*
02256      * Print the XML text for the inbound message if
02257      * verbosity is 2 or higher.
02258      */
02259     if(1 < m_Verbose)
02260     {
02261         /* If -qq command option, do XML encode but don't actually print */
02262         if(2 > m_Quiet)
02263         {
02264             printf("\n- - - - - - - - - - - - - - - - - -\n");
02265             printf("INFO: Transact received response\n");
02266         }
02267         printXMLMessage(pRspMsg);
02268     }
02269 
02270     /*
02271      * If it is an ERROR_MESSAGE (response from reader
02272      * when it can't understand the request), tattle
02273      * and declare defeat.
02274      */
02275     if(&CERROR_MESSAGE::s_typeDescriptor == pRspMsg->m_pType)
02276     {
02277         const CTypeDescriptor * pResponseType;
02278 
02279         pResponseType = pSendMsg->m_pType->m_pResponseType;
02280 
02281         printf("ERROR: Received ERROR_MESSAGE instead of %s\n",
02282             pResponseType->m_pName);
02283         delete pRspMsg;
02284         pRspMsg = NULL;
02285     }
02286 
02287     return pRspMsg;
02288 }
02289 
02290 
02315 CMessage *
02316 CMyApplication::recvMessage (
02317   int                           nMaxMS)
02318 {
02319     CConnection *               pConn = m_pConnectionToReader;
02320     CMessage *                  pMessage;
02321 
02322     /*
02323      * Receive the message subject to a time limit
02324      */
02325     pMessage = pConn->recvMessage(nMaxMS);
02326 
02327     /*
02328      * If LLRP::CConnection::recvMessage() returns NULL then there was
02329      * an error. In that case we try to print the error details.
02330      */
02331     if(NULL == pMessage)
02332     {
02333         const CErrorDetails *   pError = pConn->getRecvError();
02334 
02335         printf("ERROR: recvMessage failed, %s\n",
02336             pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
02337 
02338         if(NULL != pError->m_pRefType)
02339         {
02340             printf("ERROR: ... reference type %s\n",
02341                 pError->m_pRefType->m_pName);
02342         }
02343 
02344         if(NULL != pError->m_pRefField)
02345         {
02346             printf("ERROR: ... reference field %s\n",
02347                 pError->m_pRefField->m_pName);
02348         }
02349 
02350         return NULL;
02351     }
02352 
02353     /*
02354      * Print the XML text for the inbound message if
02355      * verbosity is 2 or higher.
02356      */
02357     if(1 < m_Verbose)
02358     {
02359         /* If -qq command option, do XML encode but don't actually print */
02360         if(2 > m_Quiet)
02361         {
02362             printf("\n===================================\n");
02363             printf("INFO: Message received\n");
02364         }
02365         printXMLMessage(pMessage);
02366     }
02367 
02368     return pMessage;
02369 }
02370 
02371 
02389 int
02390 CMyApplication::sendMessage (
02391   CMessage *                    pSendMsg)
02392 {
02393     CConnection *               pConn = m_pConnectionToReader;
02394 
02395     /*
02396      * Print the XML text for the outbound message if
02397      * verbosity is 2 or higher.
02398      */
02399     if(1 < m_Verbose)
02400     {
02401         /* If -qq command option, do XML encode but don't actually print */
02402         if(2 > m_Quiet)
02403         {
02404             printf("\n===================================\n");
02405             printf("INFO: Sending\n");
02406         }
02407         printXMLMessage(pSendMsg);
02408     }
02409 
02410     /*
02411      * If LLRP::CConnection::sendMessage() returns other than RC_OK
02412      * then there was an error. In that case we try to print
02413      * the error details.
02414      */
02415     if(RC_OK != pConn->sendMessage(pSendMsg))
02416     {
02417         const CErrorDetails *   pError = pConn->getSendError();
02418 
02419         printf("ERROR: %s sendMessage failed, %s\n",
02420             pSendMsg->m_pType->m_pName,
02421             pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
02422 
02423         if(NULL != pError->m_pRefType)
02424         {
02425             printf("ERROR: ... reference type %s\n",
02426                 pError->m_pRefType->m_pName);
02427         }
02428 
02429         if(NULL != pError->m_pRefField)
02430         {
02431             printf("ERROR: ... reference field %s\n",
02432                 pError->m_pRefField->m_pName);
02433         }
02434 
02435         return -1;
02436     }
02437 
02438     /*
02439      * Victory
02440      */
02441     return 0;
02442 }
02443 
02444 
02458 void
02459 CMyApplication::printXMLMessage (
02460   CMessage *                    pMessage)
02461 {
02462     char                        aBuf[100*1024];
02463 
02464     /*
02465      * Convert the message to an XML string.
02466      * This fills the buffer with either the XML string
02467      * or an error message. The return value could
02468      * be checked.
02469      */
02470 
02471     pMessage->toXMLString(aBuf, sizeof aBuf);
02472 
02473     /*
02474      * Print the XML Text to the standard output.
02475      * For characterization, command line option -qq
02476      * prevents the XML text actually being printed and
02477      * so the CPU utilization of XMLTextEncoder can be measured
02478      * without the noise.
02479      */
02480     if(2 > m_Quiet)
02481     {
02482         printf("%s", aBuf);
02483     }
02484 }

Generated on Wed Jun 6 11:55:49 2012 for LTKCPP-- LLRP Toolkit C Plus Plus Library by  doxygen 1.5.9