LTKCPP-- LLRP Toolkit C Plus Plus Library
docsample7.cpp
1 
2 /*
3  *****************************************************************************
4  * *
5  * IMPINJ CONFIDENTIAL AND PROPRIETARY *
6  * *
7  * This source code is the sole property of Impinj, Inc. Reproduction or *
8  * utilization of this source code in whole or in part is forbidden without *
9  * the prior written consent of Impinj, Inc. *
10  * *
11  * (c) Copyright Impinj, Inc. 2007,2009. All rights reserved. *
12  * *
13  *****************************************************************************/
14 
44 #include <stdio.h>
45 #include "ltkcpp.h"
46 #include "impinj_ltkcpp.h"
47 #include "time.h"
48 
49 using namespace LLRP;
50 
51 /*
52 ** Sorry, we use this linux safe method
53 ** to print buffers. WIndows has the same
54 ** method, but by a different name
55 */
56 #if (WIN32)
57 #define snprintf _snprintf
58 #endif
59 
60 class CMyApplication
61 {
62  unsigned int m_messageID;
63 
64  public:
66  int m_Verbose;
67 
69  CConnection * m_pConnectionToReader;
70 
71  inline
72  CMyApplication (void)
73  : m_Verbose(0), m_pConnectionToReader(NULL)
74  {
75  m_messageID = 0;
76  }
77 
78  int
79  run (
80  char * pReaderHostName);
81 
82  int
83  checkConnectionStatus (void);
84 
85  int
86  enableImpinjExtensions (void);
87 
88  int
89  resetConfigurationToFactoryDefaults (void);
90 
91  int
92  addROSpec (void);
93 
94  int
95  enableROSpec (void);
96 
97  int
98  startROSpec (void);
99 
100  int
101  stopROSpec (void);
102 
103  int
104  awaitAndPrintReport (int timeoutSec);
105 
106  void
107  printTagReportData (
108  CRO_ACCESS_REPORT * pRO_ACCESS_REPORT);
109 
110  void
111  printOneTagReportData (
112  CTagReportData * pTagReportData);
113 
114  void
115  formatOneEPC (
116  CParameter * pEpcParameter,
117  char * buf,
118  int buflen);
119 
120  void
121  handleReaderEventNotification (
122  CReaderEventNotificationData *pNtfData);
123 
124  void
125  handleAntennaEvent (
126  CAntennaEvent * pAntennaEvent);
127 
128  void
129  handleReaderExceptionEvent (
130  CReaderExceptionEvent * pReaderExceptionEvent);
131 
132  int
133  checkLLRPStatus (
134  CLLRPStatus * pLLRPStatus,
135  char * pWhatStr);
136 
137  CMessage *
138  transact (
139  CMessage * pSendMsg);
140 
141  CMessage *
142  recvMessage (
143  int nMaxMS);
144 
145  int
146  sendMessage (
147  CMessage * pSendMsg);
148 
149  void
150  printXMLMessage (
151  CMessage * pMessage);
152 };
153 
154 
155 /* BEGIN forward declarations */
156 int
157 main (
158  int ac,
159  char * av[]);
160 
161 void
162 usage (
163  char * pProgName);
164 /* END forward declarations */
165 
166 
182 int
183 main (
184  int ac,
185  char * av[])
186 {
187  CMyApplication myApp;
188  char * pReaderHostName;
189  int rc;
190 
191  /*
192  * Process comand arguments, determine reader name
193  * and verbosity level.
194  */
195  if(ac == 2)
196  {
197  pReaderHostName = av[1];
198  }
199  else if(ac == 3)
200  {
201  char * p = av[1];
202 
203  while(*p)
204  {
205  switch(*p++)
206  {
207  case '-': /* linux conventional option warn char */
208  case '/': /* Windows/DOS conventional option warn char */
209  break;
210 
211  case 'v':
212  case 'V':
213  myApp.m_Verbose++;
214  break;
215 
216  default:
217  usage(av[0]);
218  /* no return */
219  break;
220  }
221  }
222 
223  pReaderHostName = av[2];
224  }
225  else
226  {
227  usage(av[0]);
228  /* no return */
229  }
230 
231  /*
232  * Run application, capture return value for exit status
233  */
234  rc = myApp.run(pReaderHostName);
235 
236  printf("INFO: Done\n");
237 
238  /*
239  * Exit with the right status.
240  */
241  if(0 == rc)
242  {
243  exit(0);
244  }
245  else
246  {
247  exit(2);
248  }
249  /*NOTREACHED*/
250 }
251 
252 
264 void
265 usage (
266  char * pProgName)
267 {
268 #ifdef linux
269  printf("Usage: %s [-v[v]] READERHOSTNAME\n", pProgName);
270  printf("\n");
271  printf("Each -v increases verbosity level\n");
272 #endif /* linux */
273 #ifdef WIN32
274  printf("Usage: %s [/v[v]] READERHOSTNAME\n", pProgName);
275  printf("\n");
276  printf("Each /v increases verbosity level\n");
277 #endif /* WIN32 */
278  exit(1);
279 }
280 
281 
315 int
316 CMyApplication::run (
317  char * pReaderHostName)
318 {
319  CTypeRegistry * pTypeRegistry;
320  CConnection * pConn;
321  int rc;
322 
323  /*
324  * Allocate the type registry. This is needed
325  * by the connection to decode.
326  */
327  pTypeRegistry = getTheTypeRegistry();
328  if(NULL == pTypeRegistry)
329  {
330  printf("ERROR: getTheTypeRegistry failed\n");
331  return -1;
332  }
333 
334  /*
335  * Enroll impinj extension types into the
336  * type registry, in preparation for using
337  * Impinj extension params.
338  */
340 
341  /*
342  * Construct a connection (LLRP::CConnection).
343  * Using a 32kb max frame size for send/recv.
344  * The connection object is ready for business
345  * but not actually connected to the reader yet.
346  */
347  pConn = new CConnection(pTypeRegistry, 32u*1024u);
348  if(NULL == pConn)
349  {
350  printf("ERROR: new CConnection failed\n");
351  return -2;
352  }
353 
354  /*
355  * Open the connection to the reader
356  */
357  if(m_Verbose)
358  {
359  printf("INFO: Connecting to %s....\n", pReaderHostName);
360  }
361 
362  rc = pConn->openConnectionToReader(pReaderHostName);
363  if(0 != rc)
364  {
365  printf("ERROR: connect: %s (%d)\n", pConn->getConnectError(), rc);
366  delete pConn;
367  return -3;
368  }
369 
370  /*
371  * Record the pointer to the connection object so other
372  * routines can use it.
373  */
374  m_pConnectionToReader = pConn;
375 
376  if(m_Verbose)
377  {
378  printf("INFO: Connected, checking status....\n");
379  }
380 
381  /*
382  * Commence the sequence and check for errors as we go.
383  * See comments for each routine for details.
384  * Each routine prints messages.
385  */
386  rc = 1;
387  if(0 == checkConnectionStatus())
388  {
389  rc = 2;
390  if(0 == enableImpinjExtensions())
391  {
392  rc = 3;
393  if(0 == resetConfigurationToFactoryDefaults())
394  {
395  rc = 4;
396  if(0 == addROSpec())
397  {
398  rc = 5;
399  if(0 == enableROSpec())
400  {
401  //rc = 6;
402  //if(0 == startROSpec())
403  //{
404  rc = 7;
405  if(0 == awaitAndPrintReport(10))
406  {
407  rc = 8;
408  if(0 == stopROSpec())
409  {
410  rc = 0;
411  }
412  }
413  //}
414  }
415  }
416  }
417 
418  /*
419  * After we're done, try to leave the reader
420  * in a clean state for next use. This is best
421  * effort and no checking of the result is done.
422  */
423  if(m_Verbose)
424  {
425  printf("INFO: Clean up reader configuration...\n");
426  }
427  resetConfigurationToFactoryDefaults();
428  }
429  }
430 
431  if(m_Verbose)
432  {
433  printf("INFO: Finished\n");
434  }
435 
436  /*
437  * Close the connection and release its resources
438  */
439  pConn->closeConnectionToReader();
440  delete pConn;
441 
442  /*
443  * Done with the registry.
444  */
445  delete pTypeRegistry;
446 
447  /*
448  * When we get here all allocated memory should have been deallocated.
449  */
450 
451  return rc;
452 }
453 
454 
485 int
486 CMyApplication::checkConnectionStatus (void)
487 {
488  CMessage * pMessage;
491  CConnectionAttemptEvent * pEvent;
492 
493  /*
494  * Expect the notification within 10 seconds.
495  * It is suppose to be the very first message sent.
496  */
497  pMessage = recvMessage(10000);
498 
499  /*
500  * recvMessage() returns NULL if something went wrong.
501  */
502  if(NULL == pMessage)
503  {
504  /* recvMessage already tattled */
505  goto fail;
506  }
507 
508  /*
509  * Check to make sure the message is of the right type.
510  * The type label (pointer) in the message should be
511  * the type descriptor for READER_EVENT_NOTIFICATION.
512  */
513  if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor != pMessage->m_pType)
514  {
515  goto fail;
516  }
517 
518  /*
519  * Now that we are sure it is a READER_EVENT_NOTIFICATION,
520  * traverse to the ReaderEventNotificationData parameter.
521  */
522  pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage;
523  pNtfData = pNtf->getReaderEventNotificationData();
524  if(NULL == pNtfData)
525  {
526  goto fail;
527  }
528 
529  /*
530  * The ConnectionAttemptEvent parameter must be present.
531  */
532  pEvent = pNtfData->getConnectionAttemptEvent();
533  if(NULL == pEvent)
534  {
535  goto fail;
536  }
537 
538  /*
539  * The status in the ConnectionAttemptEvent parameter
540  * must indicate connection success.
541  */
542  if(ConnectionAttemptStatusType_Success != pEvent->getStatus())
543  {
544  goto fail;
545  }
546 
547  /*
548  * Done with the message
549  */
550  delete pMessage;
551 
552  if(m_Verbose)
553  {
554  printf("INFO: Connection status OK\n");
555  }
556 
557  /*
558  * Victory.
559  */
560  return 0;
561 
562  fail:
563  /*
564  * Something went wrong. Tattle. Clean up. Return error.
565  */
566  printf("ERROR: checkConnectionStatus failed\n");
567  delete pMessage;
568  return -1;
569 }
570 
588 int
589 CMyApplication::enableImpinjExtensions (void)
590 {
592  CMessage * pRspMsg;
594 
595  /*
596  * Compose the command message
597  */
598  pCmd = new CIMPINJ_ENABLE_EXTENSIONS();
599  pCmd->setMessageID(m_messageID++);
600  /*
601  * Send the message, expect the response of certain type
602  */
603  pRspMsg = transact(pCmd);
604 
605  /*
606  * Done with the command message
607  */
608  delete pCmd;
609 
610  /*
611  * transact() returns NULL if something went wrong.
612  */
613  if(NULL == pRspMsg)
614  {
615  /* transact already tattled */
616  return -1;
617  }
618 
619  /*
620  * Cast to a CIMPINJ_ENABLE_EXTENSIONS_RESPONSE message.
621  */
622  pRsp = (CIMPINJ_ENABLE_EXTENSIONS_RESPONSE *) pRspMsg;
623 
624  /*
625  * Check the LLRPStatus parameter.
626  */
627  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
628  "enableImpinjExtensions"))
629  {
630  /* checkLLRPStatus already tattled */
631  delete pRspMsg;
632  return -1;
633  }
634 
635  /*
636  * Done with the response message.
637  */
638  delete pRspMsg;
639 
640  /*
641  * Tattle progress, maybe
642  */
643  if(m_Verbose)
644  {
645  printf("INFO: Impinj Extensions are enabled\n");
646  }
647 
648  /*
649  * Victory.
650  */
651  return 0;
652 }
653 
674 int
675 CMyApplication::resetConfigurationToFactoryDefaults (void)
676 {
677  CSET_READER_CONFIG * pCmd;
678  CMessage * pRspMsg;
680 
681  /*
682  * Compose the command message
683  */
684  pCmd = new CSET_READER_CONFIG();
685  pCmd->setMessageID(m_messageID++);
686  pCmd->setResetToFactoryDefault(1);
687 
688  /*
689  * Send the message, expect the response of certain type
690  */
691  pRspMsg = transact(pCmd);
692 
693  /*
694  * Done with the command message
695  */
696  delete pCmd;
697 
698  /*
699  * transact() returns NULL if something went wrong.
700  */
701  if(NULL == pRspMsg)
702  {
703  /* transact already tattled */
704  return -1;
705  }
706 
707  /*
708  * Cast to a SET_READER_CONFIG_RESPONSE message.
709  */
710  pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg;
711 
712  /*
713  * Check the LLRPStatus parameter.
714  */
715  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
716  "resetConfigurationToFactoryDefaults"))
717  {
718  /* checkLLRPStatus already tattled */
719  delete pRspMsg;
720  return -1;
721  }
722 
723  /*
724  * Done with the response message.
725  */
726  delete pRspMsg;
727 
728  /*
729  * Tattle progress, maybe
730  */
731  if(m_Verbose)
732  {
733  printf("INFO: Configuration reset to factory defaults\n");
734  }
735 
736  /*
737  * Victory.
738  */
739  return 0;
740 }
741 
742 
790 int
791 CMyApplication::addROSpec (void)
792 {
793  CROSpecStartTrigger * pROSpecStartTrigger =
794  new CROSpecStartTrigger();
795  pROSpecStartTrigger->setROSpecStartTriggerType(
796  ROSpecStartTriggerType_Immediate);
797 
798  CROSpecStopTrigger * pROSpecStopTrigger = new CROSpecStopTrigger();
799  pROSpecStopTrigger->setROSpecStopTriggerType(ROSpecStopTriggerType_Null);
800  pROSpecStopTrigger->setDurationTriggerValue(0); /* n/a */
801 
802  CROBoundarySpec * pROBoundarySpec = new CROBoundarySpec();
803  pROBoundarySpec->setROSpecStartTrigger(pROSpecStartTrigger);
804  pROBoundarySpec->setROSpecStopTrigger(pROSpecStopTrigger);
805 
806  CAISpecStopTrigger * pAISpecStopTrigger = new CAISpecStopTrigger();
807  pAISpecStopTrigger->setAISpecStopTriggerType(
808  AISpecStopTriggerType_Tag_Observation);
809  pAISpecStopTrigger->setDurationTrigger(0);
810 
811  CTagObservationTrigger * pAISpecTagObsvTrigger = new CTagObservationTrigger();
812  pAISpecTagObsvTrigger->setTriggerType(TagObservationTriggerType_Upon_Seeing_N_Tags_Or_Timeout);
813  pAISpecTagObsvTrigger->setNumberOfTags(100);
814  pAISpecTagObsvTrigger->setNumberOfAttempts(0);
815  pAISpecTagObsvTrigger->setT(0);
816  pAISpecTagObsvTrigger->setTimeout(500);
817 
818  pAISpecStopTrigger->setTagObservationTrigger(pAISpecTagObsvTrigger);
819 
820 
822 
823 
824  CInventoryParameterSpec * pInventoryParameterSpec =
826  pInventoryParameterSpec->setInventoryParameterSpecID(1234);
827  pInventoryParameterSpec->setProtocolID(AirProtocols_EPCGlobalClass1Gen2);
828 
829  CAntennaConfiguration * pAntennaConfig = new CAntennaConfiguration();
830  pAntennaConfig->setAntennaID(1);
831 
832  CRFTransmitter * pRFTransmitter = new CRFTransmitter();
833  pRFTransmitter->setHopTableID(1);
834  pRFTransmitter->setChannelIndex(0);
835  pRFTransmitter->setTransmitPower(81);
836  pAntennaConfig->setRFTransmitter(pRFTransmitter);
837 
838  CC1G2InventoryCommand * pC1G2InventoryCmd = new CC1G2InventoryCommand();
839  pC1G2InventoryCmd->setTagInventoryStateAware(1);
840 
841 // Filter 1
842  CC1G2Filter * pC1G2Filter1 = new CC1G2Filter();
843  pC1G2Filter1->setT(C1G2TruncateAction_Do_Not_Truncate);
844 
845  CC1G2TagInventoryMask * pC1G2TagInvMask1 = new CC1G2TagInventoryMask();
846  pC1G2TagInvMask1->setMB(2);
847  pC1G2TagInvMask1->setPointer(0);
848 
849  llrp_u1v_t tagMask1 = llrp_u1v_t(15);
850  tagMask1.m_nBit = 15;
851  tagMask1.m_pValue[0] = 0xE2;
852  tagMask1.m_pValue[1] = 0x00;
853  pC1G2TagInvMask1->setTagMask(tagMask1);
854 
855  pC1G2Filter1->setC1G2TagInventoryMask(pC1G2TagInvMask1);
856 
857  CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction1 = new CC1G2TagInventoryStateAwareFilterAction();
858  pC1G2TagInvStateAwareFilterAction1->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S3);
859  pC1G2TagInvStateAwareFilterAction1->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB);
860 
861  pC1G2Filter1->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction1);
862 
863  pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter1);
864 
865  // Filter 2
866  CC1G2Filter * pC1G2Filter2 = new CC1G2Filter();
867  pC1G2Filter2->setT(C1G2TruncateAction_Do_Not_Truncate);
868 
869  CC1G2TagInventoryMask * pC1G2TagInvMask2 = new CC1G2TagInventoryMask();
870  pC1G2TagInvMask2->setMB(1);
871  pC1G2TagInvMask2->setPointer(0);
872 
873  llrp_u1v_t tagMask2 = llrp_u1v_t(16);
874  tagMask2.m_nBit = 16;
875  tagMask2.m_pValue[0] = 0xE2;
876  tagMask2.m_pValue[1] = 0x00;
877  pC1G2TagInvMask2->setTagMask(tagMask2);
878 
879  pC1G2Filter2->setC1G2TagInventoryMask(pC1G2TagInvMask2);
880 
881  CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction2 = new CC1G2TagInventoryStateAwareFilterAction();
882  pC1G2TagInvStateAwareFilterAction2->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S2);
883  pC1G2TagInvStateAwareFilterAction2->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB);
884 
885  pC1G2Filter2->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction2);
886 
887  pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter2);
888 
889 // Filter 3
890  CC1G2Filter * pC1G2Filter3 = new CC1G2Filter();
891  pC1G2Filter3->setT(C1G2TruncateAction_Do_Not_Truncate);
892 
893  CC1G2TagInventoryMask * pC1G2TagInvMask3 = new CC1G2TagInventoryMask();
894  pC1G2TagInvMask3->setMB(3);
895  pC1G2TagInvMask3->setPointer(0);
896 
897  llrp_u1v_t tagMask3 = llrp_u1v_t(32);
898  tagMask3.m_nBit = 32;
899  tagMask3.m_pValue[0] = 0xFF;
900  tagMask3.m_pValue[1] = 0xFF;
901  tagMask3.m_pValue[2] = 0xE2;
902  tagMask3.m_pValue[3] = 0x00;
903  pC1G2TagInvMask3->setTagMask(tagMask3);
904 
905  pC1G2Filter3->setC1G2TagInventoryMask(pC1G2TagInvMask3);
906 
907  CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction3 = new CC1G2TagInventoryStateAwareFilterAction();
908  pC1G2TagInvStateAwareFilterAction3->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S1);
909  pC1G2TagInvStateAwareFilterAction3->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB);
910 
911  pC1G2Filter3->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction3);
912 
913  pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter3);
914 
915 // Filter 4
916  CC1G2Filter * pC1G2Filter4 = new CC1G2Filter();
917  pC1G2Filter4->setT(C1G2TruncateAction_Do_Not_Truncate);
918 
919  CC1G2TagInventoryMask * pC1G2TagInvMask4 = new CC1G2TagInventoryMask();
920  pC1G2TagInvMask4->setMB(2);
921  pC1G2TagInvMask4->setPointer(0);
922 
923  llrp_u1v_t tagMask4 = llrp_u1v_t(8);
924  tagMask4.m_nBit = 8;
925  tagMask4.m_pValue[0] = 0xAA;
926  pC1G2TagInvMask4->setTagMask(tagMask4);
927 
928  pC1G2Filter4->setC1G2TagInventoryMask(pC1G2TagInvMask4);
929 
930  CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction4 = new CC1G2TagInventoryStateAwareFilterAction();
931  pC1G2TagInvStateAwareFilterAction4->setTarget(C1G2StateAwareTarget_Inventoried_State_For_Session_S0);
932  pC1G2TagInvStateAwareFilterAction4->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB);
933 
934  pC1G2Filter4->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction4);
935 
936  pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter4);
937 
938 // Filter 5
939  CC1G2Filter * pC1G2Filter5 = new CC1G2Filter();
940  pC1G2Filter5->setT(C1G2TruncateAction_Do_Not_Truncate);
941 
942  CC1G2TagInventoryMask * pC1G2TagInvMask5 = new CC1G2TagInventoryMask();
943  pC1G2TagInvMask5->setMB(1);
944  pC1G2TagInvMask5->setPointer(0);
945 
946  llrp_u1v_t tagMask5 = llrp_u1v_t(16);
947  tagMask5.m_nBit = 16;
948  tagMask5.m_pValue[0] = 0xFF;
949  tagMask5.m_pValue[1] = 0xFF;
950  pC1G2TagInvMask5->setTagMask(tagMask5);
951 
952  pC1G2Filter5->setC1G2TagInventoryMask(pC1G2TagInvMask5);
953 
954  CC1G2TagInventoryStateAwareFilterAction * pC1G2TagInvStateAwareFilterAction5 = new CC1G2TagInventoryStateAwareFilterAction();
955  pC1G2TagInvStateAwareFilterAction5->setTarget(C1G2StateAwareTarget_SL);
956  pC1G2TagInvStateAwareFilterAction5->setAction(C1G2StateAwareAction_AssertSLOrA_DeassertSLOrB);
957 
958  pC1G2Filter5->setC1G2TagInventoryStateAwareFilterAction(pC1G2TagInvStateAwareFilterAction5);
959 
960  pC1G2InventoryCmd->addC1G2Filter(pC1G2Filter5);
961 
962 //
963 
964 
965  CC1G2SingulationControl * pC1G2SingulationControl = new CC1G2SingulationControl();
966  pC1G2SingulationControl->setSession(1);
967  pC1G2SingulationControl->setTagPopulation(32);
968  pC1G2SingulationControl->setTagTransitTime(0);
969 
971  pC1G2TagInvStateAwareSingAction->setI(C1G2TagInventoryStateAwareI_State_B);
972  pC1G2TagInvStateAwareSingAction->setS(C1G2TagInventoryStateAwareS_SL);
973 
974  pC1G2SingulationControl->setC1G2TagInventoryStateAwareSingulationAction(pC1G2TagInvStateAwareSingAction);
975 
976  pC1G2InventoryCmd->setC1G2SingulationControl(pC1G2SingulationControl);
977 
978  pAntennaConfig->addAirProtocolInventoryCommandSettings(pC1G2InventoryCmd);
979 
980  pInventoryParameterSpec->addAntennaConfiguration(pAntennaConfig);
981 
983  llrp_u16v_t AntennaIDs = llrp_u16v_t(1);
984  AntennaIDs.m_pValue[0] = 1;
985 
986  CAISpec * pAISpec = new CAISpec();
987  pAISpec->setAntennaIDs(AntennaIDs);
988  pAISpec->setAISpecStopTrigger(pAISpecStopTrigger);
989  pAISpec->addInventoryParameterSpec(pInventoryParameterSpec);
990 
991 
993  CROReportSpec * pROReportSpec = new CROReportSpec();
994  pROReportSpec->setROReportTrigger(ROReportTriggerType_Upon_N_Tags_Or_End_Of_AISpec);
995  pROReportSpec->setN(1000);
996 
997  CTagReportContentSelector * pTagRptContentSelector = new CTagReportContentSelector();
998  pTagRptContentSelector->setEnableROSpecID(1);
999  pTagRptContentSelector->setEnableSpecIndex(1);
1000  pTagRptContentSelector->setEnableInventoryParameterSpecID(1);
1001  pTagRptContentSelector->setEnableAntennaID(1);
1002  pTagRptContentSelector->setEnableChannelIndex(1);
1003  pTagRptContentSelector->setEnablePeakRSSI(1);
1004  pTagRptContentSelector->setEnableFirstSeenTimestamp(1);
1005  pTagRptContentSelector->setEnableLastSeenTimestamp(1);
1006  pTagRptContentSelector->setEnableTagSeenCount(1);
1007  pTagRptContentSelector->setEnableAccessSpecID(1);
1008 
1009  pROReportSpec->setTagReportContentSelector(pTagRptContentSelector);
1011 
1012 
1013  CROSpec * pROSpec = new CROSpec();
1014  pROSpec->setROSpecID(1);
1015  pROSpec->setPriority(0);
1016  pROSpec->setCurrentState(ROSpecState_Disabled);
1017  pROSpec->setROBoundarySpec(pROBoundarySpec);
1018  pROSpec->addSpecParameter(pAISpec);
1019  pROSpec->setROReportSpec(pROReportSpec);
1020 
1021  CADD_ROSPEC * pCmd;
1022  CMessage * pRspMsg;
1023  CADD_ROSPEC_RESPONSE * pRsp;
1024 
1025  /*
1026  * Compose the command message.
1027  * N.B.: After the message is composed, all the parameters
1028  * constructed, immediately above, are considered "owned"
1029  * by the command message. When it is destructed so
1030  * too will the parameters be.
1031  */
1032  pCmd = new CADD_ROSPEC();
1033  pCmd->setMessageID(m_messageID++);
1034  pCmd->setROSpec(pROSpec);
1035 
1036  /*
1037  * Send the message, expect the response of certain type
1038  */
1039  pRspMsg = transact(pCmd);
1040 
1041  /*
1042  * Done with the command message.
1043  * N.B.: And the parameters
1044  */
1045  delete pCmd;
1046 
1047  /*
1048  * transact() returns NULL if something went wrong.
1049  */
1050  if(NULL == pRspMsg)
1051  {
1052  /* transact already tattled */
1053  return -1;
1054  }
1055 
1056  /*
1057  * Cast to a ADD_ROSPEC_RESPONSE message.
1058  */
1059  pRsp = (CADD_ROSPEC_RESPONSE *) pRspMsg;
1060 
1061  /*
1062  * Check the LLRPStatus parameter.
1063  */
1064  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "addROSpec"))
1065  {
1066  /* checkLLRPStatus already tattled */
1067  delete pRspMsg;
1068  return -1;
1069  }
1070 
1071  /*
1072  * Done with the response message.
1073  */
1074  delete pRspMsg;
1075 
1076  /*
1077  * Tattle progress, maybe
1078  */
1079  if(m_Verbose)
1080  {
1081  printf("INFO: ROSpec added\n");
1082  }
1083 
1084  /*
1085  * Victory.
1086  */
1087  return 0;
1088 }
1089 
1090 
1108 int
1109 CMyApplication::enableROSpec (void)
1110 {
1111  CENABLE_ROSPEC * pCmd;
1112  CMessage * pRspMsg;
1113  CENABLE_ROSPEC_RESPONSE * pRsp;
1114 
1115  /*
1116  * Compose the command message
1117  */
1118  pCmd = new CENABLE_ROSPEC();
1119  pCmd->setMessageID(m_messageID++);
1120  pCmd->setROSpecID(1);
1121 
1122  /*
1123  * Send the message, expect the response of certain type
1124  */
1125  pRspMsg = transact(pCmd);
1126 
1127  /*
1128  * Done with the command message
1129  */
1130  delete pCmd;
1131 
1132  /*
1133  * transact() returns NULL if something went wrong.
1134  */
1135  if(NULL == pRspMsg)
1136  {
1137  /* transact already tattled */
1138  return -1;
1139  }
1140 
1141  /*
1142  * Cast to a ENABLE_ROSPEC_RESPONSE message.
1143  */
1144  pRsp = (CENABLE_ROSPEC_RESPONSE *) pRspMsg;
1145 
1146  /*
1147  * Check the LLRPStatus parameter.
1148  */
1149  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "enableROSpec"))
1150  {
1151  /* checkLLRPStatus already tattled */
1152  delete pRspMsg;
1153  return -1;
1154  }
1155 
1156  /*
1157  * Done with the response message.
1158  */
1159  delete pRspMsg;
1160 
1161  /*
1162  * Tattle progress, maybe
1163  */
1164  if(m_Verbose)
1165  {
1166  printf("INFO: ROSpec enabled\n");
1167  }
1168 
1169  /*
1170  * Victory.
1171  */
1172  return 0;
1173 }
1174 
1175 
1193 int
1194 CMyApplication::startROSpec (void)
1195 {
1196  CSTART_ROSPEC * pCmd;
1197  CMessage * pRspMsg;
1198  CSTART_ROSPEC_RESPONSE * pRsp;
1199 
1200  /*
1201  * Compose the command message
1202  */
1203  pCmd = new CSTART_ROSPEC();
1204  pCmd->setMessageID(m_messageID++);
1205  pCmd->setROSpecID(1);
1206 
1207  /*
1208  * Send the message, expect the response of certain type
1209  */
1210  pRspMsg = transact(pCmd);
1211 
1212  /*
1213  * Done with the command message
1214  */
1215  delete pCmd;
1216 
1217  /*
1218  * transact() returns NULL if something went wrong.
1219  */
1220  if(NULL == pRspMsg)
1221  {
1222  /* transact already tattled */
1223  return -1;
1224  }
1225 
1226  /*
1227  * Cast to a START_ROSPEC_RESPONSE message.
1228  */
1229  pRsp = (CSTART_ROSPEC_RESPONSE *) pRspMsg;
1230 
1231  /*
1232  * Check the LLRPStatus parameter.
1233  */
1234  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "startROSpec"))
1235  {
1236  /* checkLLRPStatus already tattled */
1237  delete pRspMsg;
1238  return -1;
1239  }
1240 
1241  /*
1242  * Done with the response message.
1243  */
1244  delete pRspMsg;
1245 
1246  /*
1247  * Tattle progress
1248  */
1249  if(m_Verbose)
1250  {
1251  printf("INFO: ROSpec started\n");
1252  }
1253 
1254  /*
1255  * Victory.
1256  */
1257  return 0;
1258 }
1259 
1277 int
1278 CMyApplication::stopROSpec (void)
1279 {
1280  CSTOP_ROSPEC * pCmd;
1281  CMessage * pRspMsg;
1282  CSTOP_ROSPEC_RESPONSE * pRsp;
1283 
1284  /*
1285  * Compose the command message
1286  */
1287  pCmd = new CSTOP_ROSPEC();
1288  pCmd->setMessageID(m_messageID++);
1289  pCmd->setROSpecID(1);
1290 
1291  /*
1292  * Send the message, expect the response of certain type
1293  */
1294  pRspMsg = transact(pCmd);
1295 
1296  /*
1297  * Done with the command message
1298  */
1299  delete pCmd;
1300 
1301  /*
1302  * transact() returns NULL if something went wrong.
1303  */
1304  if(NULL == pRspMsg)
1305  {
1306  /* transact already tattled */
1307  return -1;
1308  }
1309 
1310  /*
1311  * Cast to a STOP_ROSPEC_RESPONSE message.
1312  */
1313  pRsp = (CSTOP_ROSPEC_RESPONSE *) pRspMsg;
1314 
1315  /*
1316  * Check the LLRPStatus parameter.
1317  */
1318  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "stopROSpec"))
1319  {
1320  /* checkLLRPStatus already tattled */
1321  delete pRspMsg;
1322  return -1;
1323  }
1324 
1325  /*
1326  * Done with the response message.
1327  */
1328  delete pRspMsg;
1329 
1330  /*
1331  * Tattle progress
1332  */
1333  if(m_Verbose)
1334  {
1335  printf("INFO: ROSpec stopped\n");
1336  }
1337 
1338  /*
1339  * Victory.
1340  */
1341  return 0;
1342 }
1343 
1344 
1364 int
1365 CMyApplication::awaitAndPrintReport (int timeout)
1366 {
1367  int bDone = 0;
1368  int retVal = 0;
1369  time_t startTime = time(NULL);
1370  time_t tempTime;
1371  /*
1372  * Keep receiving messages until done or until
1373  * something bad happens.
1374  */
1375  while(!bDone)
1376  {
1377  CMessage * pMessage;
1378  const CTypeDescriptor * pType;
1379 
1380  /*
1381  * Wait up to 1 second for a report. Check
1382  * That way, we can check the timestamp even if
1383  * there are no reports coming in
1384  */
1385  pMessage = recvMessage(1000);
1386 
1387  /* validate the timestamp */
1388  tempTime = time(NULL);
1389  if(difftime(tempTime, startTime) > timeout)
1390  {
1391  bDone=1;
1392  }
1393 
1394  if(NULL == pMessage)
1395  {
1396  continue;
1397  }
1398 
1399  /*
1400  * What happens depends on what kind of message
1401  * received. Use the type label (m_pType) to
1402  * discriminate message types.
1403  */
1404  pType = pMessage->m_pType;
1405 
1406  /*
1407  * Is it a tag report? If so, print it out.
1408  */
1409  if(&CRO_ACCESS_REPORT::s_typeDescriptor == pType)
1410  {
1411  CRO_ACCESS_REPORT * pNtf;
1412 
1413  pNtf = (CRO_ACCESS_REPORT *) pMessage;
1414 
1415  printTagReportData(pNtf);
1416  }
1417 
1418  /*
1419  * Is it a reader event? This example only recognizes
1420  * AntennaEvents.
1421  */
1422  else if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor == pType)
1423  {
1425  CReaderEventNotificationData *pNtfData;
1426 
1427  pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage;
1428 
1429  pNtfData = pNtf->getReaderEventNotificationData();
1430  if(NULL != pNtfData)
1431  {
1432  handleReaderEventNotification(pNtfData);
1433  }
1434  else
1435  {
1436  /*
1437  * This should never happen. Using continue
1438  * to keep indent depth down.
1439  */
1440  printf("WARNING: READER_EVENT_NOTIFICATION without data\n");
1441  }
1442  }
1443 
1444  /*
1445  * Hmmm. Something unexpected. Just tattle and keep going.
1446  */
1447  else
1448  {
1449  printf("WARNING: Ignored unexpected message during monitor: %s\n",
1450  pType->m_pName);
1451  }
1452 
1453  /*
1454  * Done with the received message
1455  */
1456  delete pMessage;
1457  }
1458 
1459  return retVal;
1460 }
1461 
1462 
1477 void
1478 CMyApplication::printTagReportData (
1479  CRO_ACCESS_REPORT * pRO_ACCESS_REPORT)
1480 {
1481  std::list<CTagReportData *>::iterator Cur;
1482 
1483  unsigned int nEntry = 0;
1484 
1485  /*
1486  * Loop through and count the number of entries
1487  */
1488  for(
1489  Cur = pRO_ACCESS_REPORT->beginTagReportData();
1490  Cur != pRO_ACCESS_REPORT->endTagReportData();
1491  Cur++)
1492  {
1493  nEntry++;
1494  }
1495 
1496  if(m_Verbose)
1497  {
1498  printf("INFO: %u tag report entries\n", nEntry);
1499  }
1500 
1501  /*
1502  * Loop through again and print each entry.
1503  */
1504  for(
1505  Cur = pRO_ACCESS_REPORT->beginTagReportData();
1506  Cur != pRO_ACCESS_REPORT->endTagReportData();
1507  Cur++)
1508  {
1509  printOneTagReportData(*Cur);
1510  }
1511 }
1512 
1513 
1522 void
1523 CMyApplication::formatOneEPC (
1524  CParameter *pEPCParameter,
1525  char *buf,
1526  int buflen)
1527 {
1528  char * p = buf;
1529  int bufsize = buflen;
1530  int written = 0;
1531 
1532  if(NULL != pEPCParameter)
1533  {
1534  const CTypeDescriptor * pType;
1535  llrp_u96_t my_u96;
1536  llrp_u1v_t my_u1v;
1537  llrp_u8_t * pValue = NULL;
1538  unsigned int n, i;
1539 
1540  pType = pEPCParameter->m_pType;
1541  if(&CEPC_96::s_typeDescriptor == pType)
1542  {
1543  CEPC_96 *pEPC_96;
1544 
1545  pEPC_96 = (CEPC_96 *) pEPCParameter;
1546  my_u96 = pEPC_96->getEPC();
1547  pValue = my_u96.m_aValue;
1548  n = 12u;
1549  }
1550  else if(&CEPCData::s_typeDescriptor == pType)
1551  {
1552  CEPCData * pEPCData;
1553 
1554  pEPCData = (CEPCData *) pEPCParameter;
1555  my_u1v = pEPCData->getEPC();
1556  pValue = my_u1v.m_pValue;
1557  n = (my_u1v.m_nBit + 7u) / 8u;
1558  }
1559 
1560  if(NULL != pValue)
1561  {
1562  for(i = 0; i < n; i++)
1563  {
1564  if(0 < i && i%2 == 0 && 1 < bufsize)
1565  {
1566  *p++ = '-';
1567  bufsize--;
1568  }
1569  if(bufsize > 2)
1570  {
1571  written = snprintf(p, bufsize, "%02X", pValue[i]);
1572  bufsize -= written;
1573  p+= written;
1574  }
1575  }
1576  }
1577  else
1578  {
1579  written = snprintf(p, bufsize, "%s", "---unknown-epc-data-type---");
1580  bufsize -= written;
1581  p += written;
1582  }
1583  }
1584  else
1585  {
1586  written = snprintf(p, bufsize, "%s", "--null epc---");
1587  bufsize -= written;
1588  p += written;
1589  }
1590 
1591  // null terminate this for good practice
1592  buf[buflen-1] = '\0';
1593 
1594 }
1595 
1604 void
1605 CMyApplication::printOneTagReportData (
1606  CTagReportData * pTagReportData)
1607 {
1608  char aBuf[64];
1609 
1610  /*
1611  * Print the EPC. It could be an 96-bit EPC_96 parameter
1612  * or an variable length EPCData parameter.
1613  */
1614 
1615  CParameter * pEPCParameter =
1616  pTagReportData->getEPCParameter();
1617 
1618  formatOneEPC(pEPCParameter, aBuf, 64);
1619 
1620  /*
1621  * End of line
1622  */
1623  printf("EPC: %s\n", aBuf);
1624 }
1625 
1626 
1640 void
1641 CMyApplication::handleReaderEventNotification (
1642  CReaderEventNotificationData *pNtfData)
1643 {
1644  CAntennaEvent * pAntennaEvent;
1645  CReaderExceptionEvent * pReaderExceptionEvent;
1646  int nReported = 0;
1647 
1648  pAntennaEvent = pNtfData->getAntennaEvent();
1649  if(NULL != pAntennaEvent)
1650  {
1651  handleAntennaEvent(pAntennaEvent);
1652  nReported++;
1653  }
1654 
1655  pReaderExceptionEvent = pNtfData->getReaderExceptionEvent();
1656  if(NULL != pReaderExceptionEvent)
1657  {
1658  handleReaderExceptionEvent(pReaderExceptionEvent);
1659  nReported++;
1660  }
1661 
1662  /*
1663  * Similarly handle other events here:
1664  * HoppingEvent
1665  * GPIEvent
1666  * ROSpecEvent
1667  * ReportBufferLevelWarningEvent
1668  * ReportBufferOverflowErrorEvent
1669  * RFSurveyEvent
1670  * AISpecEvent
1671  * ConnectionAttemptEvent
1672  * ConnectionCloseEvent
1673  * Custom
1674  */
1675 
1676  if(0 == nReported)
1677  {
1678  printf("NOTICE: Unexpected (unhandled) ReaderEvent\n");
1679  }
1680 }
1681 
1682 
1694 void
1695 CMyApplication::handleAntennaEvent (
1696  CAntennaEvent * pAntennaEvent)
1697 {
1698  EAntennaEventType eEventType;
1699  llrp_u16_t AntennaID;
1700  char * pStateStr;
1701 
1702  eEventType = pAntennaEvent->getEventType();
1703  AntennaID = pAntennaEvent->getAntennaID();
1704 
1705  switch(eEventType)
1706  {
1707  case AntennaEventType_Antenna_Disconnected:
1708  pStateStr = "disconnected";
1709  break;
1710 
1711  case AntennaEventType_Antenna_Connected:
1712  pStateStr = "connected";
1713  break;
1714 
1715  default:
1716  pStateStr = "?unknown-event?";
1717  break;
1718  }
1719 
1720  printf("NOTICE: Antenna %d is %s\n", AntennaID, pStateStr);
1721 }
1722 
1723 
1736 void
1737 CMyApplication::handleReaderExceptionEvent (
1738  CReaderExceptionEvent * pReaderExceptionEvent)
1739 {
1740  llrp_utf8v_t Message;
1741 
1742  Message = pReaderExceptionEvent->getMessage();
1743 
1744  if(0 < Message.m_nValue && NULL != Message.m_pValue)
1745  {
1746  printf("NOTICE: ReaderException '%.*s'\n",
1747  Message.m_nValue, Message.m_pValue);
1748  }
1749  else
1750  {
1751  printf("NOTICE: ReaderException but no message\n");
1752  }
1753 }
1754 
1755 
1774 int
1775 CMyApplication::checkLLRPStatus (
1776  CLLRPStatus * pLLRPStatus,
1777  char * pWhatStr)
1778 {
1779  /*
1780  * The LLRPStatus parameter is mandatory in all responses.
1781  * If it is missing there should have been a decode error.
1782  * This just makes sure (remember, this program is a
1783  * diagnostic and suppose to catch LTKC mistakes).
1784  */
1785  if(NULL == pLLRPStatus)
1786  {
1787  printf("ERROR: %s missing LLRP status\n", pWhatStr);
1788  return -1;
1789  }
1790 
1791  /*
1792  * Make sure the status is M_Success.
1793  * If it isn't, print the error string if one.
1794  * This does not try to pretty-print the status
1795  * code. To get that, run this program with -vv
1796  * and examine the XML output.
1797  */
1798  if(StatusCode_M_Success != pLLRPStatus->getStatusCode())
1799  {
1800  llrp_utf8v_t ErrorDesc;
1801 
1802  ErrorDesc = pLLRPStatus->getErrorDescription();
1803 
1804  if(0 == ErrorDesc.m_nValue)
1805  {
1806  printf("ERROR: %s failed, no error description given\n",
1807  pWhatStr);
1808  }
1809  else
1810  {
1811  printf("ERROR: %s failed, %.*s\n",
1812  pWhatStr, ErrorDesc.m_nValue, ErrorDesc.m_pValue);
1813  }
1814  return -2;
1815  }
1816 
1817  /*
1818  * Victory. Everything is fine.
1819  */
1820  return 0;
1821 }
1822 
1823 
1847 CMessage *
1848 CMyApplication::transact (
1849  CMessage * pSendMsg)
1850 {
1851  CConnection * pConn = m_pConnectionToReader;
1852  CMessage * pRspMsg;
1853 
1854  /*
1855  * Print the XML text for the outbound message if
1856  * verbosity is 2 or higher.
1857  */
1858  if(1 < m_Verbose)
1859  {
1860  printf("\n===================================\n");
1861  printf("INFO: Transact sending\n");
1862  printXMLMessage(pSendMsg);
1863  }
1864 
1865  /*
1866  * Send the message, expect the response of certain type.
1867  * If LLRP::CConnection::transact() returns NULL then there was
1868  * an error. In that case we try to print the error details.
1869  */
1870  pRspMsg = pConn->transact(pSendMsg, 5000);
1871 
1872  if(NULL == pRspMsg)
1873  {
1874  const CErrorDetails * pError = pConn->getTransactError();
1875 
1876  printf("ERROR: %s transact failed, %s\n",
1877  pSendMsg->m_pType->m_pName,
1878  pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
1879 
1880  if(NULL != pError->m_pRefType)
1881  {
1882  printf("ERROR: ... reference type %s\n",
1883  pError->m_pRefType->m_pName);
1884  }
1885 
1886  if(NULL != pError->m_pRefField)
1887  {
1888  printf("ERROR: ... reference field %s\n",
1889  pError->m_pRefField->m_pName);
1890  }
1891 
1892  return NULL;
1893  }
1894 
1895  /*
1896  * Print the XML text for the inbound message if
1897  * verbosity is 2 or higher.
1898  */
1899  if(1 < m_Verbose)
1900  {
1901  printf("\n- - - - - - - - - - - - - - - - - -\n");
1902  printf("INFO: Transact received response\n");
1903  printXMLMessage(pRspMsg);
1904  }
1905 
1906  /*
1907  * If it is an ERROR_MESSAGE (response from reader
1908  * when it can't understand the request), tattle
1909  * and declare defeat.
1910  */
1911  if(&CERROR_MESSAGE::s_typeDescriptor == pRspMsg->m_pType)
1912  {
1913  const CTypeDescriptor * pResponseType;
1914 
1915  pResponseType = pSendMsg->m_pType->m_pResponseType;
1916 
1917  printf("ERROR: Received ERROR_MESSAGE instead of %s\n",
1918  pResponseType->m_pName);
1919  delete pRspMsg;
1920  pRspMsg = NULL;
1921  }
1922 
1923  return pRspMsg;
1924 }
1925 
1926 
1951 CMessage *
1952 CMyApplication::recvMessage (
1953  int nMaxMS)
1954 {
1955  CConnection * pConn = m_pConnectionToReader;
1956  CMessage * pMessage;
1957 
1958  /*
1959  * Receive the message subject to a time limit
1960  */
1961  pMessage = pConn->recvMessage(nMaxMS);
1962 
1963  /*
1964  * If LLRP::CConnection::recvMessage() returns NULL then there was
1965  * an error. In that case we try to print the error details.
1966  */
1967  if(NULL == pMessage)
1968  {
1969  const CErrorDetails * pError = pConn->getRecvError();
1970 
1971  /* don't warn on timeout since this is a polling example */
1972  if(pError->m_eResultCode != RC_RecvTimeout)
1973  {
1974  printf("ERROR: recvMessage failed, %s\n",
1975  pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
1976  }
1977 
1978  if(NULL != pError->m_pRefType)
1979  {
1980  printf("ERROR: ... reference type %s\n",
1981  pError->m_pRefType->m_pName);
1982  }
1983 
1984  if(NULL != pError->m_pRefField)
1985  {
1986  printf("ERROR: ... reference field %s\n",
1987  pError->m_pRefField->m_pName);
1988  }
1989 
1990  return NULL;
1991  }
1992 
1993  /*
1994  * Print the XML text for the inbound message if
1995  * verbosity is 2 or higher.
1996  */
1997  if(1 < m_Verbose)
1998  {
1999  printf("\n===================================\n");
2000  printf("INFO: Message received\n");
2001  printXMLMessage(pMessage);
2002  }
2003 
2004  return pMessage;
2005 }
2006 
2007 
2025 int
2026 CMyApplication::sendMessage (
2027  CMessage * pSendMsg)
2028 {
2029  CConnection * pConn = m_pConnectionToReader;
2030 
2031  /*
2032  * Print the XML text for the outbound message if
2033  * verbosity is 2 or higher.
2034  */
2035  if(1 < m_Verbose)
2036  {
2037  printf("\n===================================\n");
2038  printf("INFO: Sending\n");
2039  printXMLMessage(pSendMsg);
2040  }
2041 
2042  /*
2043  * If LLRP::CConnection::sendMessage() returns other than RC_OK
2044  * then there was an error. In that case we try to print
2045  * the error details.
2046  */
2047  if(RC_OK != pConn->sendMessage(pSendMsg))
2048  {
2049  const CErrorDetails * pError = pConn->getSendError();
2050 
2051  printf("ERROR: %s sendMessage failed, %s\n",
2052  pSendMsg->m_pType->m_pName,
2053  pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
2054 
2055  if(NULL != pError->m_pRefType)
2056  {
2057  printf("ERROR: ... reference type %s\n",
2058  pError->m_pRefType->m_pName);
2059  }
2060 
2061  if(NULL != pError->m_pRefField)
2062  {
2063  printf("ERROR: ... reference field %s\n",
2064  pError->m_pRefField->m_pName);
2065  }
2066 
2067  return -1;
2068  }
2069 
2070  /*
2071  * Victory
2072  */
2073  return 0;
2074 }
2075 
2076 
2090 void
2091 CMyApplication::printXMLMessage (
2092  CMessage * pMessage)
2093 {
2094  char aBuf[100*1024];
2095 
2096  /*
2097  * Convert the message to an XML string.
2098  * This fills the buffer with either the XML string
2099  * or an error message. The return value could
2100  * be checked.
2101  */
2102 
2103  pMessage->toXMLString(aBuf, sizeof aBuf);
2104 
2105  /*
2106  * Print the XML Text to the standard output.
2107  */
2108  printf("%s", aBuf);
2109 }
void setEnableFirstSeenTimestamp(llrp_u1_t value)
Set accessor functions for the LLRP EnableFirstSeenTimestamp field.
llrp_utf8v_t getMessage(void)
Get accessor functions for the LLRP Message field.
void setROSpecID(llrp_u32_t value)
Set accessor functions for the LLRP ROSpecID field.
Class Definition CConnectionAttemptEvent for LLRP parameter ConnectionAttemptEvent.
EResultCode setTagObservationTrigger(CTagObservationTrigger *pValue)
Set accessor functions for the LLRP TagObservationTrigger sub-parameter.
EResultCode setC1G2TagInventoryStateAwareFilterAction(CC1G2TagInventoryStateAwareFilterAction *pValue)
Set accessor functions for the LLRP C1G2TagInventoryStateAwareFilterAction sub-parameter.
EResultCode setC1G2SingulationControl(CC1G2SingulationControl *pValue)
Set accessor functions for the LLRP C1G2SingulationControl sub-parameter.
EResultCode setRFTransmitter(CRFTransmitter *pValue)
Set accessor functions for the LLRP RFTransmitter sub-parameter.
char * m_pName
String name of field (e.g. "ROSpecID")
Definition: ltkcpp_base.h:840
const CTypeDescriptor * m_pType
The type descriptor desribing this element.
Definition: ltkcpp_base.h:972
Class Definition CC1G2TagInventoryStateAwareSingulationAction for LLRP parameter C1G2TagInventoryStat...
Class Definition CEPC_96 for LLRP parameter EPC_96.
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
llrp_u8_t * m_pValue
Pointer to the first array element.
Definition: ltkcpp_base.h:443
Class Definition CTagObservationTrigger for LLRP parameter TagObservationTrigger. ...
Class for LLRP basic type u16v (List of unsigned 16-bit values)
Definition: ltkcpp_base.h:179
Class Definition CIMPINJ_ENABLE_EXTENSIONS_RESPONSE for LLRP message IMPINJ_ENABLE_EXTENSIONS_RESPONS...
void setDurationTrigger(llrp_u32_t value)
Set accessor functions for the LLRP DurationTrigger field.
void setEnablePeakRSSI(llrp_u1_t value)
Set accessor functions for the LLRP EnablePeakRSSI field.
Class Definition CSTART_ROSPEC_RESPONSE for LLRP message START_ROSPEC_RESPONSE.
Class Definition CC1G2SingulationControl for LLRP parameter C1G2SingulationControl.
void usage(char *pProgName)
Print usage message and exit.
Definition: docsample2.cpp:288
Class Definition CRFTransmitter for LLRP parameter RFTransmitter.
const CFieldDescriptor * m_pRefField
If non-NULL this is the field descriptors for the errored field.
Definition: ltkcpp_base.h:641
void setDurationTriggerValue(llrp_u32_t value)
Set accessor functions for the LLRP DurationTriggerValue field.
Class Definition CENABLE_ROSPEC for LLRP message ENABLE_ROSPEC.
void setEnableLastSeenTimestamp(llrp_u1_t value)
Set accessor functions for the LLRP EnableLastSeenTimestamp field.
const CTypeDescriptor * m_pRefType
If non-NULL this is the type descriptors for the errored type.
Definition: ltkcpp_base.h:639
Class Definition CC1G2TagInventoryMask for LLRP parameter C1G2TagInventoryMask.
void setROReportTrigger(EROReportTriggerType value)
Set accessor functions for the LLRP ROReportTrigger field.
Class Definition CC1G2TagInventoryStateAwareFilterAction for LLRP parameter C1G2TagInventoryStateAwar...
CParameter * getEPCParameter(void)
Get accessor functions for the LLRP EPCParameter sub-parameter.
EResultCode m_eResultCode
Result code from operation.
Definition: ltkcpp_base.h:635
Class for LLRP basic type u96 (96-bit value)
Definition: ltkcpp_base.h:566
Class Definition CAntennaEvent for LLRP parameter AntennaEvent.
Class Definition CSTOP_ROSPEC_RESPONSE for LLRP message STOP_ROSPEC_RESPONSE.
void setAISpecStopTriggerType(EAISpecStopTriggerType value)
Set accessor functions for the LLRP AISpecStopTriggerType field.
void setPointer(llrp_u16_t value)
Set accessor functions for the LLRP Pointer field.
void enrollImpinjTypesIntoRegistry(CTypeRegistry *pTypeRegistry)
Enrolls the types for Impinj into the LTKCPP registry.
llrp_u96_t getEPC(void)
Get accessor functions for the LLRP EPC field.
const char * m_pWhatStr
Descriptive printable error string.
Definition: ltkcpp_base.h:637
EResultCode toXMLString(char *pBuffer, int nBuffer)
A wrapper around LLRP::toXMLString()
void setROSpecID(llrp_u32_t value)
Set accessor functions for the LLRP ROSpecID field.
void setS(EC1G2TagInventoryStateAwareS value)
Set accessor functions for the LLRP S field.
Class Definition CROReportSpec for LLRP parameter ROReportSpec.
EStatusCode getStatusCode(void)
Get accessor functions for the LLRP StatusCode field.
llrp_u16_t m_nValue
The number of arrray elements.
Definition: ltkcpp_base.h:484
int closeConnectionToReader(void)
Close connection to reader, allow reuse of instance.
Class Definition CROSpecStartTrigger for LLRP parameter ROSpecStartTrigger.
EAntennaEventType getEventType(void)
Get accessor functions for the LLRP EventType field.
A collection of pointers to CTypeDescriptors.
Definition: ltkcpp_base.h:885
CAntennaEvent * getAntennaEvent(void)
Get accessor functions for the LLRP AntennaEvent sub-parameter.
const CErrorDetails * getTransactError(void)
Get the details that explains transact() error.
EResultCode setROBoundarySpec(CROBoundarySpec *pValue)
Set accessor functions for the LLRP ROBoundarySpec sub-parameter.
Class Definition CRO_ACCESS_REPORT for LLRP message RO_ACCESS_REPORT.
void setEnableAccessSpecID(llrp_u1_t value)
Set accessor functions for the LLRP EnableAccessSpecID field.
Class Definition CAISpec for LLRP parameter AISpec.
void setHopTableID(llrp_u16_t value)
Set accessor functions for the LLRP HopTableID field.
Class Definition CROSpec for LLRP parameter ROSpec.
void setChannelIndex(llrp_u16_t value)
Set accessor functions for the LLRP ChannelIndex field.
void setROSpecID(llrp_u32_t value)
Set accessor functions for the LLRP ROSpecID field.
void setTimeout(llrp_u32_t value)
Set accessor functions for the LLRP Timeout field.
Class Definition CInventoryParameterSpec for LLRP parameter InventoryParameterSpec.
void setTriggerType(ETagObservationTriggerType value)
Set accessor functions for the LLRP TriggerType field.
Class Definition CSET_READER_CONFIG_RESPONSE for LLRP message SET_READER_CONFIG_RESPONSE.
void setEnableTagSeenCount(llrp_u1_t value)
Set accessor functions for the LLRP EnableTagSeenCount field.
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
CReaderExceptionEvent * getReaderExceptionEvent(void)
Get accessor functions for the LLRP ReaderExceptionEvent sub-parameter.
void setT(llrp_u16_t value)
Set accessor functions for the LLRP T field.
Class Definition CReaderExceptionEvent for LLRP parameter ReaderExceptionEvent.
Class Definition CLLRPStatus for LLRP parameter LLRPStatus.
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
EResultCode addSpecParameter(CParameter *pValue)
Add a SpecParameter to the LLRP sub-parameter list.
Class Definition CEPCData for LLRP parameter EPCData.
Class Definition CREADER_EVENT_NOTIFICATION for LLRP message READER_EVENT_NOTIFICATION.
CMessage * recvMessage(int nMaxMS)
Receive a message from a connection.
std::list< CTagReportData * >::iterator beginTagReportData(void)
Returns the first element of the TagReportData sub-parameter list.
void setTagInventoryStateAware(llrp_u1_t value)
Set accessor functions for the LLRP TagInventoryStateAware field.
EResultCode setAISpecStopTrigger(CAISpecStopTrigger *pValue)
Set accessor functions for the LLRP AISpecStopTrigger sub-parameter.
EResultCode setTagReportContentSelector(CTagReportContentSelector *pValue)
Set accessor functions for the LLRP TagReportContentSelector sub-parameter.
File that includes all Impinj Custom extension classes and types.
void setEnableChannelIndex(llrp_u1_t value)
Set accessor functions for the LLRP EnableChannelIndex field.
void setROSpecStartTriggerType(EROSpecStartTriggerType value)
Set accessor functions for the LLRP ROSpecStartTriggerType field.
void setNumberOfAttempts(llrp_u16_t value)
Set accessor functions for the LLRP NumberOfAttempts field.
llrp_u1v_t getEPC(void)
Get accessor functions for the LLRP EPC field.
Class Definition CSET_READER_CONFIG for LLRP message SET_READER_CONFIG.
CMessage * transact(CMessage *pSendMessage, int nMaxMS)
Transact a LLRP request and response to a connection.
void setI(EC1G2TagInventoryStateAwareI value)
Set accessor functions for the LLRP I field.
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
const CErrorDetails * getRecvError(void)
Get the details that explains recvMessage() or recvResponse() error.
Class for LLRP basic type utf8v (vector of utf-8 encoded characters)
Definition: ltkcpp_base.h:480
llrp_u16_t m_nBit
The number of arrray elements.
Definition: ltkcpp_base.h:441
void setTagMask(llrp_u1v_t value)
Set accessor functions for the LLRP TagMask field.
Class for LLRP basic type u1v (vector of unsigned 1-bit values)
Definition: ltkcpp_base.h:437
void setTarget(EC1G2StateAwareTarget value)
Set accessor functions for the LLRP Target field.
void setAntennaIDs(llrp_u16v_t value)
Set accessor functions for the LLRP AntennaIDs field.
EResultCode addAntennaConfiguration(CAntennaConfiguration *pValue)
Add a AntennaConfiguration to the LLRP sub-parameter list.
int openConnectionToReader(const char *pReaderHostName)
Open a connection to the reader over an unencrypted socket.
void setT(EC1G2TruncateAction value)
Set accessor functions for the LLRP T field.
Class Definition CENABLE_ROSPEC_RESPONSE for LLRP message ENABLE_ROSPEC_RESPONSE. ...
const CTypeDescriptor * m_pResponseType
For messages (bIsMessage==TRUE), this is the type descriptor for the corresponding response...
Definition: ltkcpp_base.h:776
void setTagPopulation(llrp_u16_t value)
Set accessor functions for the LLRP TagPopulation field.
void setProtocolID(EAirProtocols value)
Set accessor functions for the LLRP ProtocolID field.
void setMB(llrp_u2_t value)
Set accessor functions for the LLRP MB field.
int main(int ac, char *av[])
Command main routine.
Definition: docsample2.cpp:206
EResultCode sendMessage(CMessage *pMessage)
Send a LLRP message to a connection.
std::list< CTagReportData * >::iterator endTagReportData(void)
Returns the last element of the TagReportData sub-parameter list.
Class to return error details in LTKCPP operations.
Definition: ltkcpp_base.h:631
void setN(llrp_u16_t value)
Set accessor functions for the LLRP N field.
void setTransmitPower(llrp_u16_t value)
Set accessor functions for the LLRP TransmitPower field.
Class Definition CTagReportData for LLRP parameter TagReportData.
char * m_pName
String name of parameter/message type (e.g. "ROSpec")
Definition: ltkcpp_base.h:762
EResultCode setROSpec(CROSpec *pValue)
Set accessor functions for the LLRP ROSpec sub-parameter.
llrp_u16_t getAntennaID(void)
Get accessor functions for the LLRP AntennaID field.
File that includes all LLRP classes and types.
Class Definition CC1G2InventoryCommand for LLRP parameter C1G2InventoryCommand.
Class Definition CADD_ROSPEC for LLRP message ADD_ROSPEC.
void setAntennaID(llrp_u16_t value)
Set accessor functions for the LLRP AntennaID field.
Class Definition CSTART_ROSPEC for LLRP message START_ROSPEC.
void setROSpecStopTriggerType(EROSpecStopTriggerType value)
Set accessor functions for the LLRP ROSpecStopTriggerType field.
Class Definition CIMPINJ_ENABLE_EXTENSIONS for LLRP message IMPINJ_ENABLE_EXTENSIONS.
EResultCode setROSpecStopTrigger(CROSpecStopTrigger *pValue)
Set accessor functions for the LLRP ROSpecStopTrigger sub-parameter.
Class Definition CAntennaConfiguration for LLRP parameter AntennaConfiguration.
Class Definition CROSpecStopTrigger for LLRP parameter ROSpecStopTrigger.
EResultCode addC1G2Filter(CC1G2Filter *pValue)
Add a C1G2Filter to the LLRP sub-parameter list.
void setInventoryParameterSpecID(llrp_u16_t value)
Set accessor functions for the LLRP InventoryParameterSpecID field.
llrp_u16_t * m_pValue
Pointer to the first array element.
Definition: ltkcpp_base.h:185
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
llrp_u8_t m_aValue[12]
Simple array of basic type llrp_u8_t.
Definition: ltkcpp_base.h:570
EResultCode setC1G2TagInventoryStateAwareSingulationAction(CC1G2TagInventoryStateAwareSingulationAction *pValue)
Set accessor functions for the LLRP C1G2TagInventoryStateAwareSingulationAction sub-parameter.
void setAction(EC1G2StateAwareAction value)
Set accessor functions for the LLRP Action field.
Base Class for All LLRP LTK Parameters.
Definition: ltkcpp_base.h:1125
Base Class for All LLRP LTK Messages.
Definition: ltkcpp_base.h:1088
EResultCode setROReportSpec(CROReportSpec *pValue)
Set accessor functions for the LLRP ROReportSpec sub-parameter.
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
Class Definition CADD_ROSPEC_RESPONSE for LLRP message ADD_ROSPEC_RESPONSE.
EResultCode addAirProtocolInventoryCommandSettings(CParameter *pValue)
Add a AirProtocolInventoryCommandSettings to the LLRP sub-parameter list.
Class Definition CAISpecStopTrigger for LLRP parameter AISpecStopTrigger.
const char * getConnectError(void)
Get the string that explains openReaderConnection() error.
void setEnableInventoryParameterSpecID(llrp_u1_t value)
Set accessor functions for the LLRP EnableInventoryParameterSpecID field.
void setROSpecID(llrp_u32_t value)
Set accessor functions for the LLRP ROSpecID field.
void setEnableAntennaID(llrp_u1_t value)
Set accessor functions for the LLRP EnableAntennaID field.
CReaderEventNotificationData * getReaderEventNotificationData(void)
Get accessor functions for the LLRP ReaderEventNotificationData sub-parameter.
void setResetToFactoryDefault(llrp_u1_t value)
Set accessor functions for the LLRP ResetToFactoryDefault field.
Definition: ltkcpp.h:45
void setNumberOfTags(llrp_u16_t value)
Set accessor functions for the LLRP NumberOfTags field.
EResultCode setROSpecStartTrigger(CROSpecStartTrigger *pValue)
Set accessor functions for the LLRP ROSpecStartTrigger sub-parameter.
void setEnableSpecIndex(llrp_u1_t value)
Set accessor functions for the LLRP EnableSpecIndex field.
EResultCode setC1G2TagInventoryMask(CC1G2TagInventoryMask *pValue)
Set accessor functions for the LLRP C1G2TagInventoryMask sub-parameter.
llrp_utf8v_t getErrorDescription(void)
Get accessor functions for the LLRP ErrorDescription field.
void setTagTransitTime(llrp_u32_t value)
Set accessor functions for the LLRP TagTransitTime field.
Class Definition CTagReportContentSelector for LLRP parameter TagReportContentSelector.
void setSession(llrp_u2_t value)
Set accessor functions for the LLRP Session field.
Class Definition CSTOP_ROSPEC for LLRP message STOP_ROSPEC.
LLRP connection class.
void setCurrentState(EROSpecState value)
Set accessor functions for the LLRP CurrentState field.
Class Definition CC1G2Filter for LLRP parameter C1G2Filter.
void setEnableROSpecID(llrp_u1_t value)
Set accessor functions for the LLRP EnableROSpecID field.
llrp_utf8_t * m_pValue
Pointer to the first array element.
Definition: ltkcpp_base.h:486
EResultCode addInventoryParameterSpec(CInventoryParameterSpec *pValue)
Add a InventoryParameterSpec to the LLRP sub-parameter list.
void setPriority(llrp_u8_t value)
Set accessor functions for the LLRP Priority field.
Class Definition CROBoundarySpec for LLRP parameter ROBoundarySpec.
CConnectionAttemptEvent * getConnectionAttemptEvent(void)
Get accessor functions for the LLRP ConnectionAttemptEvent sub-parameter.
Describes a message or parameter type.
Definition: ltkcpp_base.h:755
const CErrorDetails * getSendError(void)
Get the details that explains sendMessage() error.
EConnectionAttemptStatusType getStatus(void)
Get accessor functions for the LLRP Status field.
Class Definition CReaderEventNotificationData for LLRP parameter ReaderEventNotificationData.