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

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

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