LTKCPP-- LLRP Toolkit C Plus Plus Library
docsample4.cpp
Go to the documentation of this file.
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,2010. All rights reserved. *
12  * *
13  *****************************************************************************/
14 
29 #include <stdio.h>
30 #include "ltkcpp.h"
31 #include "impinj_ltkcpp.h"
32 #include "time.h"
33 
34 using namespace LLRP;
35 
36 /*
37 ** Sorry, we use this linux safe method
38 ** to print buffers. WIndows has the same
39 ** method, but by a different name
40 */
41 #if (WIN32)
42 #define snprintf _snprintf
43 #endif
44 
45 class CMyApplication
46 {
47 private:
48 
49  unsigned int m_modelNumber;
50  unsigned int m_messageID;
51 
52  public:
54  int m_Verbose;
55 
57  CConnection * m_pConnectionToReader;
58 
59  inline
60  CMyApplication (void)
61  : m_Verbose(0), m_pConnectionToReader(NULL)
62  {
63  m_messageID = 0;
64  }
65 
66  int
67  run (
68  char * pReaderHostName);
69 
70  int
71  checkConnectionStatus (void);
72 
73  int
74  enableImpinjExtensions (void);
75 
76  int
77  resetConfigurationToFactoryDefaults (void);
78 
79  int
80  getReaderCapabilities(void);
81 
82  int
83  setImpinjReaderConfig(void);
84 
85  int
86  addROSpec (void);
87 
88  int
89  enableROSpec (void);
90 
91  int
92  startROSpec (void);
93 
94  int
95  stopROSpec (void);
96 
97  int
98  awaitAndPrintReport (int timeoutSec);
99 
100  void
101  printTagReportData (
102  CRO_ACCESS_REPORT * pRO_ACCESS_REPORT);
103 
104  void
105  printOneTagReportData (
106  CTagReportData * pTagReportData);
107 
108  int
109  formatOneEPC (
110  CParameter * pEpcParameter,
111  char * buf,
112  int buflen,
113  char * startStr);
114 
115  int getOnePhaseAngle(
116  CImpinjRFPhaseAngle *pRfPhase,
117  double *out);
118 
119  int
120  getOnePeakRSSI (
121  CImpinjPeakRSSI *pPeakRSSI,
122  double *out);
123 
124  int
125  getOneTimestamp (
126  CParameter *pTimestamp,
127  unsigned long long *out);
128 
129  int
130  getOneAntenna (
131  CAntennaID *pAntenna,
132  unsigned short *out);
133 
134  int
135  getOneChannelIndex (
136  CChannelIndex *pChannelIndex,
137  unsigned short *out);
138 
139  int
140  estimateVelocity(
141  char * epcStr,
142  double rssi,
143  double phase,
144  unsigned short channelIndex,
145  unsigned short antenna,
146  unsigned long long time,
147  double *outVelocity);
148 
149  void
150  handleReaderEventNotification (
151  CReaderEventNotificationData *pNtfData);
152 
153  void
154  handleAntennaEvent (
155  CAntennaEvent * pAntennaEvent);
156 
157  void
158  handleReaderExceptionEvent (
159  CReaderExceptionEvent * pReaderExceptionEvent);
160 
161  int
162  checkLLRPStatus (
163  CLLRPStatus * pLLRPStatus,
164  char * pWhatStr);
165 
166  CMessage *
167  transact (
168  CMessage * pSendMsg);
169 
170  CMessage *
171  recvMessage (
172  int nMaxMS);
173 
174  int
175  sendMessage (
176  CMessage * pSendMsg);
177 
178  void
179  printXMLMessage (
180  CMessage * pMessage);
181 };
182 
183 
184 /* BEGIN forward declarations */
185 int
186 main (
187  int ac,
188  char * av[]);
189 
190 void
191 usage (
192  char * pProgName);
193 /* END forward declarations */
194 
195 
211 int
213  int ac,
214  char * av[])
215 {
216  CMyApplication myApp;
217  char * pReaderHostName;
218  int rc;
219 
220  /*
221  * Process comand arguments, determine reader name
222  * and verbosity level.
223  */
224  if(ac == 2)
225  {
226  pReaderHostName = av[1];
227  }
228  else if(ac == 3)
229  {
230  char * p = av[1];
231 
232  while(*p)
233  {
234  switch(*p++)
235  {
236  case '-': /* linux conventional option warn char */
237  case '/': /* Windows/DOS conventional option warn char */
238  break;
239 
240  case 'v':
241  case 'V':
242  myApp.m_Verbose++;
243  break;
244 
245  default:
246  usage(av[0]);
247  /* no return */
248  break;
249  }
250  }
251 
252  pReaderHostName = av[2];
253  }
254  else
255  {
256  usage(av[0]);
257  /* no return */
258  }
259 
260  /*
261  * Run application, capture return value for exit status
262  */
263  rc = myApp.run(pReaderHostName);
264 
265  printf("INFO: Done\n");
266 
267  /*
268  * Exit with the right status.
269  */
270  if(0 == rc)
271  {
272  exit(0);
273  }
274  else
275  {
276  exit(2);
277  }
278  /*NOTREACHED*/
279 }
280 
281 
293 void
295  char * pProgName)
296 {
297 #ifdef linux
298  printf("Usage: %s [-v[v]] READERHOSTNAME\n", pProgName);
299  printf("\n");
300  printf("Each -v increases verbosity level\n");
301 #endif /* linux */
302 #ifdef WIN32
303  printf("Usage: %s [/v[v]] READERHOSTNAME\n", pProgName);
304  printf("\n");
305  printf("Each /v increases verbosity level\n");
306 #endif /* WIN32 */
307  exit(1);
308 }
309 
310 
352 int
353 CMyApplication::run (
354  char * pReaderHostName)
355 {
356  CTypeRegistry * pTypeRegistry;
357  CConnection * pConn;
358  int rc;
359 
360  /*
361  * Allocate the type registry. This is needed
362  * by the connection to decode.
363  */
364  pTypeRegistry = getTheTypeRegistry();
365  if(NULL == pTypeRegistry)
366  {
367  printf("ERROR: getTheTypeRegistry failed\n");
368  return -1;
369  }
370 
371  /*
372  * Enroll impinj extension types into the
373  * type registry, in preparation for using
374  * Impinj extension params.
375  */
377 
378  /*
379  * Construct a connection (LLRP::CConnection).
380  * Using a 32kb max frame size for send/recv.
381  * The connection object is ready for business
382  * but not actually connected to the reader yet.
383  */
384  pConn = new CConnection(pTypeRegistry, 32u*1024u);
385  if(NULL == pConn)
386  {
387  printf("ERROR: new CConnection failed\n");
388  return -2;
389  }
390 
391  /*
392  * Open the connection to the reader
393  */
394  if(m_Verbose)
395  {
396  printf("INFO: Connecting to %s....\n", pReaderHostName);
397  }
398 
399  rc = pConn->openConnectionToReader(pReaderHostName);
400  if(0 != rc)
401  {
402  printf("ERROR: connect: %s (%d)\n", pConn->getConnectError(), rc);
403  delete pConn;
404  return -3;
405  }
406 
407  /*
408  * Record the pointer to the connection object so other
409  * routines can use it.
410  */
411  m_pConnectionToReader = pConn;
412 
413  if(m_Verbose)
414  {
415  printf("INFO: Connected, checking status....\n");
416  }
417 
418  /*
419  * Commence the sequence and check for errors as we go.
420  * See comments for each routine for details.
421  * Each routine prints messages.
422  */
423  rc = 1;
424  if(0 == checkConnectionStatus())
425  {
426  rc = 2;
427  if(0 == enableImpinjExtensions())
428  {
429  rc = 3;
430  if(0 == resetConfigurationToFactoryDefaults())
431  {
432  rc = 4;
433  if(0 == getReaderCapabilities())
434  {
435  rc = 6;
436  if(0 == setImpinjReaderConfig())
437  {
438  rc = 7;
439  if(0 == addROSpec())
440  {
441  rc = 8;
442  if(0 == enableROSpec())
443  {
444  rc = 9;
445  if(0 == startROSpec())
446  {
447  rc = 10;
448  if(0 == awaitAndPrintReport(60))
449  {
450  rc = 11;
451  if(0 == stopROSpec())
452  {
453  rc = 0;
454  }
455  }
456  }
457  }
458  }
459  }
460  }
461  }
462 
463  /*
464  * After we're done, try to leave the reader
465  * in a clean state for next use. This is best
466  * effort and no checking of the result is done.
467  */
468  if(m_Verbose)
469  {
470  printf("INFO: Clean up reader configuration...\n");
471  }
472  resetConfigurationToFactoryDefaults();
473  }
474  }
475 
476  if(m_Verbose)
477  {
478  printf("INFO: Finished\n");
479  }
480 
481  /*
482  * Close the connection and release its resources
483  */
484  pConn->closeConnectionToReader();
485  delete pConn;
486 
487  /*
488  * Done with the registry.
489  */
490  delete pTypeRegistry;
491 
492  /*
493  * When we get here all allocated memory should have been deallocated.
494  */
495 
496  return rc;
497 }
498 
499 
530 int
531 CMyApplication::checkConnectionStatus (void)
532 {
533  CMessage * pMessage;
536  CConnectionAttemptEvent * pEvent;
537 
538  /*
539  * Expect the notification within 10 seconds.
540  * It is suppose to be the very first message sent.
541  */
542  pMessage = recvMessage(10000);
543 
544  /*
545  * recvMessage() returns NULL if something went wrong.
546  */
547  if(NULL == pMessage)
548  {
549  /* recvMessage already tattled */
550  goto fail;
551  }
552 
553  /*
554  * Check to make sure the message is of the right type.
555  * The type label (pointer) in the message should be
556  * the type descriptor for READER_EVENT_NOTIFICATION.
557  */
558  if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor != pMessage->m_pType)
559  {
560  goto fail;
561  }
562 
563  /*
564  * Now that we are sure it is a READER_EVENT_NOTIFICATION,
565  * traverse to the ReaderEventNotificationData parameter.
566  */
567  pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage;
568  pNtfData = pNtf->getReaderEventNotificationData();
569  if(NULL == pNtfData)
570  {
571  goto fail;
572  }
573 
574  /*
575  * The ConnectionAttemptEvent parameter must be present.
576  */
577  pEvent = pNtfData->getConnectionAttemptEvent();
578  if(NULL == pEvent)
579  {
580  goto fail;
581  }
582 
583  /*
584  * The status in the ConnectionAttemptEvent parameter
585  * must indicate connection success.
586  */
587  if(ConnectionAttemptStatusType_Success != pEvent->getStatus())
588  {
589  goto fail;
590  }
591 
592  /*
593  * Done with the message
594  */
595  delete pMessage;
596 
597  if(m_Verbose)
598  {
599  printf("INFO: Connection status OK\n");
600  }
601 
602  /*
603  * Victory.
604  */
605  return 0;
606 
607  fail:
608  /*
609  * Something went wrong. Tattle. Clean up. Return error.
610  */
611  printf("ERROR: checkConnectionStatus failed\n");
612  delete pMessage;
613  return -1;
614 }
615 
633 int
634 CMyApplication::enableImpinjExtensions (void)
635 {
637  CMessage * pRspMsg;
639 
640  /*
641  * Compose the command message
642  */
643  pCmd = new CIMPINJ_ENABLE_EXTENSIONS();
644  pCmd->setMessageID(m_messageID++);
645  /*
646  * Send the message, expect the response of certain type
647  */
648  pRspMsg = transact(pCmd);
649 
650  /*
651  * Done with the command message
652  */
653  delete pCmd;
654 
655  /*
656  * transact() returns NULL if something went wrong.
657  */
658  if(NULL == pRspMsg)
659  {
660  /* transact already tattled */
661  return -1;
662  }
663 
664  /*
665  * Cast to a CIMPINJ_ENABLE_EXTENSIONS_RESPONSE message.
666  */
667  pRsp = (CIMPINJ_ENABLE_EXTENSIONS_RESPONSE *) pRspMsg;
668 
669  /*
670  * Check the LLRPStatus parameter.
671  */
672  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
673  "enableImpinjExtensions"))
674  {
675  /* checkLLRPStatus already tattled */
676  delete pRspMsg;
677  return -1;
678  }
679 
680  /*
681  * Done with the response message.
682  */
683  delete pRspMsg;
684 
685  /*
686  * Tattle progress, maybe
687  */
688  if(m_Verbose)
689  {
690  printf("INFO: Impinj Extensions are enabled\n");
691  }
692 
693  /*
694  * Victory.
695  */
696  return 0;
697 }
698 
719 int
720 CMyApplication::resetConfigurationToFactoryDefaults (void)
721 {
722  CSET_READER_CONFIG * pCmd;
723  CMessage * pRspMsg;
725 
726  /*
727  * Compose the command message
728  */
729  pCmd = new CSET_READER_CONFIG();
730  pCmd->setMessageID(m_messageID++);
731  pCmd->setResetToFactoryDefault(1);
732 
733  /*
734  * Send the message, expect the response of certain type
735  */
736  pRspMsg = transact(pCmd);
737 
738  /*
739  * Done with the command message
740  */
741  delete pCmd;
742 
743  /*
744  * transact() returns NULL if something went wrong.
745  */
746  if(NULL == pRspMsg)
747  {
748  /* transact already tattled */
749  return -1;
750  }
751 
752  /*
753  * Cast to a SET_READER_CONFIG_RESPONSE message.
754  */
755  pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg;
756 
757  /*
758  * Check the LLRPStatus parameter.
759  */
760  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
761  "resetConfigurationToFactoryDefaults"))
762  {
763  /* checkLLRPStatus already tattled */
764  delete pRspMsg;
765  return -1;
766  }
767 
768  /*
769  * Done with the response message.
770  */
771  delete pRspMsg;
772 
773  /*
774  * Tattle progress, maybe
775  */
776  if(m_Verbose)
777  {
778  printf("INFO: Configuration reset to factory defaults\n");
779  }
780 
781  /*
782  * Victory.
783  */
784  return 0;
785 }
786 
803 int
804 CMyApplication::getReaderCapabilities(void)
805 {
807  CMessage * pRspMsg;
809  CGeneralDeviceCapabilities *pDeviceCap;
810  std::list<CTransmitPowerLevelTableEntry *>::iterator PwrLvl;
811  unsigned int bMajorVersion, bMinorVersion, bDevVersion, bBuildVersion = 0;
812 
813  /*
814  * Compose the command message
815  */
816  pCmd = new CGET_READER_CAPABILITIES();
817  pCmd->setMessageID(m_messageID++);
818  pCmd->setRequestedData(GetReaderCapabilitiesRequestedData_All);
819 
820  /*
821  * Send the message, expect the response of certain type
822  */
823  pRspMsg = transact(pCmd);
824 
825  /*
826  * Done with the command message
827  */
828  delete pCmd;
829 
830  /*
831  * transact() returns NULL if something went wrong.
832  */
833  if(NULL == pRspMsg)
834  {
835  /* transact already tattled */
836  return -1;
837  }
838 
839  /*
840  * Cast to a CGET_READER_CAPABILITIES_RESPONSE message.
841  */
842  pRsp = (CGET_READER_CAPABILITIES_RESPONSE *) pRspMsg;
843 
844  /*
845  * Check the LLRPStatus parameter.
846  */
847  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
848  "getReaderCapabilities"))
849  {
850  /* checkLLRPStatus already tattled */
851  delete pRspMsg;
852  return -1;
853  }
854 
855  /* if this parameter is missing, or if this is not an Impinj
856  ** reader, we can't determine its capabilities so we exit
857  ** Impinj Private Enterprise NUmber is 25882 */
858  if( (NULL == (pDeviceCap = pRsp->getGeneralDeviceCapabilities())) ||
859  (25882 != pDeviceCap->getDeviceManufacturerName()))
860  {
861  delete pRspMsg;
862  return -1;
863  }
864 
865 
866  /*
867  * Get the version information from the reader and make sure we are 4.4 or better.
868  */
869  if ( pDeviceCap->getReaderFirmwareVersion().m_nValue < 3)
870  {
871  printf("ERROR: Must have Firmware 4.4 or later for low level data example \n");
872  delete pRspMsg;
873  return -1;
874  }
875 
876  /*
877  * Parse to make sure it is really 4.4 or better
878  */
879  sscanf((char *) pDeviceCap->getReaderFirmwareVersion().m_pValue, "%u.%u.%u.%u", &bMajorVersion, &bMinorVersion, &bDevVersion, &bBuildVersion);
880 
881  if( (bMajorVersion < 4) && (bMinorVersion < 4) )
882  {
883  printf("ERROR: Must have Firmware 4.4 or later for low level data example \n");
884  delete pRspMsg;
885  return -1;
886  }
887 
888  if(1 < m_Verbose)
889  {
890  printf("INFO: Reader Model Name %u\n", m_modelNumber);
891  }
892 
893  /*
894  * Done with the response message.
895  */
896  delete pRspMsg;
897 
898  /*
899  * Tattle progress, maybe
900  */
901  if(m_Verbose)
902  {
903  printf("INFO: Found LLRP Capabilities \n");
904  }
905 
906  /*
907  * Victory.
908  */
909  return 0;
910 }
911 
991 int
992 CMyApplication::setImpinjReaderConfig(void)
993 {
994  CSET_READER_CONFIG *pCmd;
995  CMessage * pRspMsg;
997 
998  /*
999  * Compose the command message
1000  */
1001  pCmd = new CSET_READER_CONFIG();
1002  pCmd->setMessageID(m_messageID++);
1003 
1005 
1006  /*
1007  ** Apply this configuration to all antennas
1008  */
1009  pAnt->setAntennaID(0);
1010 
1011 
1012  CC1G2InventoryCommand *pC1G2Inv = new CC1G2InventoryCommand();
1013 
1014  /* set the mode to auto-set max throughput */
1015  CC1G2RFControl *pC1G2Rf = new CC1G2RFControl();
1016  pC1G2Rf->setModeIndex(1002);
1017  pC1G2Rf->setTari(0); /* tari is ignored by the reader */
1018  pC1G2Inv->setC1G2RFControl(pC1G2Rf);
1019 
1021  pC1G2Sing->setSession(2);
1022  pC1G2Sing->setTagPopulation(1);
1023  pC1G2Sing->setTagTransitTime(0);
1024  pC1G2Inv->setC1G2SingulationControl(pC1G2Sing);
1025 
1026  pC1G2Inv->setTagInventoryStateAware(false);
1027 
1028  /* set the Impinj Inventory search mode as per the use case */
1030  pImpIsm->setInventorySearchMode(ImpinjInventorySearchType_Dual_Target);
1031  pC1G2Inv->addCustom(pImpIsm);
1032 
1033  /* set the Impinj Low Duty Cycle mode as per the use case */
1034  CImpinjLowDutyCycle *pImpLdc = new CImpinjLowDutyCycle();
1035  pImpLdc->setEmptyFieldTimeout(10000);
1036  pImpLdc->setFieldPingInterval(200);
1037  pImpLdc->setLowDutyCycleMode(ImpinjLowDutyCycleMode_Enabled);
1038  pC1G2Inv->addCustom(pImpLdc);
1039 
1041  pCmd->addAntennaConfiguration(pAnt);
1042 
1043  /* report every tag (N=1) since that is required for tag direction */
1044  CROReportSpec *pROrs = new CROReportSpec();
1045  pROrs->setROReportTrigger(ROReportTriggerType_Upon_N_Tags_Or_End_Of_ROSpec);
1046  pROrs->setN(1);
1047 
1048  /* lets turn off off report data that we don't need since our use
1049  ** case suggests we are bandwidth constrained */
1051  pROcontent->setEnableAccessSpecID(false);
1052 
1053  /* these are very handy to have with low level data */
1054  pROcontent->setEnableAntennaID(true);
1055  pROcontent->setEnableChannelIndex(true);
1056  pROcontent->setEnableFirstSeenTimestamp(true);
1057 
1058  pROcontent->setEnableInventoryParameterSpecID(false);
1059  pROcontent->setEnableLastSeenTimestamp(false);
1060  pROcontent->setEnablePeakRSSI(false);
1061  pROcontent->setEnableROSpecID(false);
1062  pROcontent->setEnableSpecIndex(false);
1063  pROcontent->setEnableTagSeenCount(false);
1065  pC1G2Mem->setEnableCRC(false);
1066  pC1G2Mem->setEnablePCBits(false);
1067  pROcontent->addAirProtocolEPCMemorySelector(pC1G2Mem);
1068 
1069  pROrs->setTagReportContentSelector(pROcontent);
1070 
1071  /* Turn on the low level phase data in the ImpinjTagContentSelector*/
1073 
1074  CImpinjEnableRFPhaseAngle * pEnableRfPhase = new CImpinjEnableRFPhaseAngle();
1075  pEnableRfPhase->setRFPhaseAngleMode(ImpinjRFPhaseAngleMode_Enabled);
1076  pImpTagCnt->setImpinjEnableRFPhaseAngle(pEnableRfPhase);
1077 
1078  CImpinjEnablePeakRSSI * pEnablePeakRssi = new CImpinjEnablePeakRSSI();
1079  pEnablePeakRssi->setPeakRSSIMode(ImpinjPeakRSSIMode_Enabled);
1080  pImpTagCnt->setImpinjEnablePeakRSSI(pEnablePeakRssi);
1081 
1082  CImpinjEnableSerializedTID * pEnableSerializedTID = new CImpinjEnableSerializedTID();
1083  pEnableSerializedTID->setSerializedTIDMode(ImpinjSerializedTIDMode_Disabled);
1084  pImpTagCnt->setImpinjEnableSerializedTID(pEnableSerializedTID);
1085 
1086  pROrs->addCustom(pImpTagCnt);
1087 
1088  pCmd->setROReportSpec(pROrs);
1089 
1090  /*
1091  * Send the message, expect the response of certain type
1092  */
1093  pRspMsg = transact(pCmd);
1094 
1095  /*
1096  * Done with the command message
1097  */
1098  delete pCmd;
1099 
1100  /*
1101  * transact() returns NULL if something went wrong.
1102  */
1103  if(NULL == pRspMsg)
1104  {
1105  /* transact already tattled */
1106  return -1;
1107  }
1108 
1109  /*
1110  * Cast to a CSET_READER_CONFIG_RESPONSE message.
1111  */
1112  pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg;
1113 
1114  /*
1115  * Check the LLRPStatus parameter.
1116  */
1117  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
1118  "setImpinjReaderConfig"))
1119  {
1120  /* checkLLRPStatus already tattled */
1121  delete pRspMsg;
1122  return -1;
1123  }
1124 
1125  /*
1126  * Done with the response message.
1127  */
1128  delete pRspMsg;
1129 
1130  /*
1131  * Tattle progress, maybe
1132  */
1133  if(m_Verbose)
1134  {
1135  printf("INFO: Set Impinj Reader Configuration \n");
1136  }
1137 
1138  /*
1139  * Victory.
1140  */
1141  return 0;
1142 }
1143 
1193 int
1194 CMyApplication::addROSpec (void)
1195 {
1196  CROSpecStartTrigger * pROSpecStartTrigger =
1197  new CROSpecStartTrigger();
1198  pROSpecStartTrigger->setROSpecStartTriggerType(
1199  ROSpecStartTriggerType_Null);
1200 
1201  CROSpecStopTrigger * pROSpecStopTrigger = new CROSpecStopTrigger();
1202  pROSpecStopTrigger->setROSpecStopTriggerType(ROSpecStopTriggerType_Null);
1203  pROSpecStopTrigger->setDurationTriggerValue(0); /* n/a */
1204 
1205  CROBoundarySpec * pROBoundarySpec = new CROBoundarySpec();
1206  pROBoundarySpec->setROSpecStartTrigger(pROSpecStartTrigger);
1207  pROBoundarySpec->setROSpecStopTrigger(pROSpecStopTrigger);
1208 
1209  CAISpecStopTrigger * pAISpecStopTrigger = new CAISpecStopTrigger();
1210  pAISpecStopTrigger->setAISpecStopTriggerType(
1211  AISpecStopTriggerType_Null);
1212  pAISpecStopTrigger->setDurationTrigger(0);
1213 
1214  CInventoryParameterSpec * pInventoryParameterSpec =
1216  pInventoryParameterSpec->setInventoryParameterSpecID(1234);
1217  pInventoryParameterSpec->setProtocolID(AirProtocols_EPCGlobalClass1Gen2);
1218 
1219  /*
1220  ** configure to use two antennas to be compatible with
1221  ** our tag direction settings
1222  */
1223  llrp_u16v_t AntennaIDs = llrp_u16v_t(1);
1224  AntennaIDs.m_pValue[0] = 2;
1225 
1226  CAISpec * pAISpec = new CAISpec();
1227  pAISpec->setAntennaIDs(AntennaIDs);
1228  pAISpec->setAISpecStopTrigger(pAISpecStopTrigger);
1229  pAISpec->addInventoryParameterSpec(pInventoryParameterSpec);
1230 
1231  CROSpec * pROSpec = new CROSpec();
1232  pROSpec->setROSpecID(1111);
1233  pROSpec->setPriority(0);
1234  pROSpec->setCurrentState(ROSpecState_Disabled);
1235  pROSpec->setROBoundarySpec(pROBoundarySpec);
1236  pROSpec->addSpecParameter(pAISpec);
1237 
1238  CADD_ROSPEC * pCmd;
1239  CMessage * pRspMsg;
1240  CADD_ROSPEC_RESPONSE * pRsp;
1241 
1242  /*
1243  * Compose the command message.
1244  * N.B.: After the message is composed, all the parameters
1245  * constructed, immediately above, are considered "owned"
1246  * by the command message. When it is destructed so
1247  * too will the parameters be.
1248  */
1249  pCmd = new CADD_ROSPEC();
1250  pCmd->setMessageID(m_messageID++);
1251  pCmd->setROSpec(pROSpec);
1252 
1253  /*
1254  * Send the message, expect the response of certain type
1255  */
1256  pRspMsg = transact(pCmd);
1257 
1258  /*
1259  * Done with the command message.
1260  * N.B.: And the parameters
1261  */
1262  delete pCmd;
1263 
1264  /*
1265  * transact() returns NULL if something went wrong.
1266  */
1267  if(NULL == pRspMsg)
1268  {
1269  /* transact already tattled */
1270  return -1;
1271  }
1272 
1273  /*
1274  * Cast to a ADD_ROSPEC_RESPONSE message.
1275  */
1276  pRsp = (CADD_ROSPEC_RESPONSE *) pRspMsg;
1277 
1278  /*
1279  * Check the LLRPStatus parameter.
1280  */
1281  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "addROSpec"))
1282  {
1283  /* checkLLRPStatus already tattled */
1284  delete pRspMsg;
1285  return -1;
1286  }
1287 
1288  /*
1289  * Done with the response message.
1290  */
1291  delete pRspMsg;
1292 
1293  /*
1294  * Tattle progress, maybe
1295  */
1296  if(m_Verbose)
1297  {
1298  printf("INFO: ROSpec added\n");
1299  }
1300 
1301  /*
1302  * Victory.
1303  */
1304  return 0;
1305 }
1306 
1307 
1325 int
1326 CMyApplication::enableROSpec (void)
1327 {
1328  CENABLE_ROSPEC * pCmd;
1329  CMessage * pRspMsg;
1330  CENABLE_ROSPEC_RESPONSE * pRsp;
1331 
1332  /*
1333  * Compose the command message
1334  */
1335  pCmd = new CENABLE_ROSPEC();
1336  pCmd->setMessageID(m_messageID++);
1337  pCmd->setROSpecID(1111);
1338 
1339  /*
1340  * Send the message, expect the response of certain type
1341  */
1342  pRspMsg = transact(pCmd);
1343 
1344  /*
1345  * Done with the command message
1346  */
1347  delete pCmd;
1348 
1349  /*
1350  * transact() returns NULL if something went wrong.
1351  */
1352  if(NULL == pRspMsg)
1353  {
1354  /* transact already tattled */
1355  return -1;
1356  }
1357 
1358  /*
1359  * Cast to a ENABLE_ROSPEC_RESPONSE message.
1360  */
1361  pRsp = (CENABLE_ROSPEC_RESPONSE *) pRspMsg;
1362 
1363  /*
1364  * Check the LLRPStatus parameter.
1365  */
1366  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "enableROSpec"))
1367  {
1368  /* checkLLRPStatus already tattled */
1369  delete pRspMsg;
1370  return -1;
1371  }
1372 
1373  /*
1374  * Done with the response message.
1375  */
1376  delete pRspMsg;
1377 
1378  /*
1379  * Tattle progress, maybe
1380  */
1381  if(m_Verbose)
1382  {
1383  printf("INFO: ROSpec enabled\n");
1384  }
1385 
1386  /*
1387  * Victory.
1388  */
1389  return 0;
1390 }
1391 
1392 
1410 int
1411 CMyApplication::startROSpec (void)
1412 {
1413  CSTART_ROSPEC * pCmd;
1414  CMessage * pRspMsg;
1415  CSTART_ROSPEC_RESPONSE * pRsp;
1416 
1417  /*
1418  * Compose the command message
1419  */
1420  pCmd = new CSTART_ROSPEC();
1421  pCmd->setMessageID(m_messageID++);
1422  pCmd->setROSpecID(1111);
1423 
1424  /*
1425  * Send the message, expect the response of certain type
1426  */
1427  pRspMsg = transact(pCmd);
1428 
1429  /*
1430  * Done with the command message
1431  */
1432  delete pCmd;
1433 
1434  /*
1435  * transact() returns NULL if something went wrong.
1436  */
1437  if(NULL == pRspMsg)
1438  {
1439  /* transact already tattled */
1440  return -1;
1441  }
1442 
1443  /*
1444  * Cast to a START_ROSPEC_RESPONSE message.
1445  */
1446  pRsp = (CSTART_ROSPEC_RESPONSE *) pRspMsg;
1447 
1448  /*
1449  * Check the LLRPStatus parameter.
1450  */
1451  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "startROSpec"))
1452  {
1453  /* checkLLRPStatus already tattled */
1454  delete pRspMsg;
1455  return -1;
1456  }
1457 
1458  /*
1459  * Done with the response message.
1460  */
1461  delete pRspMsg;
1462 
1463  /*
1464  * Tattle progress
1465  */
1466  if(m_Verbose)
1467  {
1468  printf("INFO: ROSpec started\n");
1469  }
1470 
1471  /*
1472  * Victory.
1473  */
1474  return 0;
1475 }
1476 
1494 int
1495 CMyApplication::stopROSpec (void)
1496 {
1497  CSTOP_ROSPEC * pCmd;
1498  CMessage * pRspMsg;
1499  CSTOP_ROSPEC_RESPONSE * pRsp;
1500 
1501  /*
1502  * Compose the command message
1503  */
1504  pCmd = new CSTOP_ROSPEC();
1505  pCmd->setMessageID(m_messageID++);
1506  pCmd->setROSpecID(1111);
1507 
1508  /*
1509  * Send the message, expect the response of certain type
1510  */
1511  pRspMsg = transact(pCmd);
1512 
1513  /*
1514  * Done with the command message
1515  */
1516  delete pCmd;
1517 
1518  /*
1519  * transact() returns NULL if something went wrong.
1520  */
1521  if(NULL == pRspMsg)
1522  {
1523  /* transact already tattled */
1524  return -1;
1525  }
1526 
1527  /*
1528  * Cast to a STOP_ROSPEC_RESPONSE message.
1529  */
1530  pRsp = (CSTOP_ROSPEC_RESPONSE *) pRspMsg;
1531 
1532  /*
1533  * Check the LLRPStatus parameter.
1534  */
1535  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "stopROSpec"))
1536  {
1537  /* checkLLRPStatus already tattled */
1538  delete pRspMsg;
1539  return -1;
1540  }
1541 
1542  /*
1543  * Done with the response message.
1544  */
1545  delete pRspMsg;
1546 
1547  /*
1548  * Tattle progress
1549  */
1550  if(m_Verbose)
1551  {
1552  printf("INFO: ROSpec stopped\n");
1553  }
1554 
1555  /*
1556  * Victory.
1557  */
1558  return 0;
1559 }
1560 
1561 
1581 int
1582 CMyApplication::awaitAndPrintReport (int timeout)
1583 {
1584  int bDone = 0;
1585  int retVal = 0;
1586  time_t startTime = time(NULL);
1587  time_t tempTime;
1588  /*
1589  * Keep receiving messages until done or until
1590  * something bad happens.
1591  */
1592  while(!bDone)
1593  {
1594  CMessage * pMessage;
1595  const CTypeDescriptor * pType;
1596 
1597  /*
1598  * Wait up to 1 second for a report. Check
1599  * That way, we can check the timestamp even if
1600  * there are no reports coming in
1601  */
1602  pMessage = recvMessage(1000);
1603 
1604  /* validate the timestamp */
1605  tempTime = time(NULL);
1606  if(difftime(tempTime, startTime) > timeout)
1607  {
1608  bDone=1;
1609  }
1610 
1611  if(NULL == pMessage)
1612  {
1613  continue;
1614  }
1615 
1616  /*
1617  * What happens depends on what kind of message
1618  * received. Use the type label (m_pType) to
1619  * discriminate message types.
1620  */
1621  pType = pMessage->m_pType;
1622 
1623  /*
1624  * Is it a tag report? If so, print it out.
1625  */
1626  if(&CRO_ACCESS_REPORT::s_typeDescriptor == pType)
1627  {
1628  CRO_ACCESS_REPORT * pNtf;
1629 
1630  pNtf = (CRO_ACCESS_REPORT *) pMessage;
1631 
1632  printTagReportData(pNtf);
1633  }
1634 
1635  /*
1636  * Is it a reader event? This example only recognizes
1637  * AntennaEvents.
1638  */
1639  else if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor == pType)
1640  {
1642  CReaderEventNotificationData *pNtfData;
1643 
1644  pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage;
1645 
1646  pNtfData = pNtf->getReaderEventNotificationData();
1647  if(NULL != pNtfData)
1648  {
1649  handleReaderEventNotification(pNtfData);
1650  }
1651  else
1652  {
1653  /*
1654  * This should never happen. Using continue
1655  * to keep indent depth down.
1656  */
1657  printf("WARNING: READER_EVENT_NOTIFICATION without data\n");
1658  }
1659  }
1660 
1661  /*
1662  * Hmmm. Something unexpected. Just tattle and keep going.
1663  */
1664  else
1665  {
1666  printf("WARNING: Ignored unexpected message during monitor: %s\n",
1667  pType->m_pName);
1668  }
1669 
1670  /*
1671  * Done with the received message
1672  */
1673  delete pMessage;
1674  }
1675 
1676  return retVal;
1677 }
1678 
1679 
1694 void
1695 CMyApplication::printTagReportData (
1696  CRO_ACCESS_REPORT * pRO_ACCESS_REPORT)
1697 {
1698  std::list<CTagReportData *>::iterator Cur;
1699  std::list<CParameter *>::iterator CustCur;
1700 
1701  unsigned int nEntry = 0;
1702 
1703  /*
1704  * Loop through and count the number of entries
1705  */
1706  for(
1707  Cur = pRO_ACCESS_REPORT->beginTagReportData();
1708  Cur != pRO_ACCESS_REPORT->endTagReportData();
1709  Cur++)
1710  {
1711  nEntry++;
1712  }
1713 
1714  if(m_Verbose)
1715  {
1716  printf("INFO: %u tag report entries\n", nEntry);
1717  }
1718 
1719  /*
1720  * Loop through again and print each entry.
1721  */
1722  for(
1723  Cur = pRO_ACCESS_REPORT->beginTagReportData();
1724  Cur != pRO_ACCESS_REPORT->endTagReportData();
1725  Cur++)
1726  {
1727  printOneTagReportData(*Cur);
1728  }
1729 }
1730 
1739 int
1740 CMyApplication::formatOneEPC (
1741  CParameter *pEPCParameter,
1742  char *buf,
1743  int buflen,
1744  char * startStr)
1745 {
1746  char * p = buf;
1747  int bufsize = buflen;
1748  int written = 0;
1749 
1750  written = snprintf(p, bufsize, "%s", startStr);
1751  bufsize -= written;
1752  p += written;
1753 
1754  if(NULL != pEPCParameter)
1755  {
1756  const CTypeDescriptor * pType;
1757  llrp_u96_t my_u96;
1758  llrp_u1v_t my_u1v;
1759  llrp_u8_t * pValue = NULL;
1760  unsigned int n, i;
1761 
1762  pType = pEPCParameter->m_pType;
1763  if(&CEPC_96::s_typeDescriptor == pType)
1764  {
1765  CEPC_96 *pEPC_96;
1766 
1767  pEPC_96 = (CEPC_96 *) pEPCParameter;
1768  my_u96 = pEPC_96->getEPC();
1769  pValue = my_u96.m_aValue;
1770  n = 12u;
1771  }
1772  else if(&CEPCData::s_typeDescriptor == pType)
1773  {
1774  CEPCData * pEPCData;
1775 
1776  pEPCData = (CEPCData *) pEPCParameter;
1777  my_u1v = pEPCData->getEPC();
1778  pValue = my_u1v.m_pValue;
1779  n = (my_u1v.m_nBit + 7u) / 8u;
1780  }
1781 
1782  if(NULL != pValue)
1783  {
1784  for(i = 0; i < n; i++)
1785  {
1786  if(0 < i && i%2 == 0 && 1 < bufsize)
1787  {
1788  *p++ = '-';
1789  bufsize--;
1790  }
1791  if(bufsize > 2)
1792  {
1793  written = snprintf(p, bufsize, "%02X", pValue[i]);
1794  bufsize -= written;
1795  p+= written;
1796  }
1797  }
1798  }
1799  else
1800  {
1801  written = snprintf(p, bufsize, "%s", "---unknown-epc-data-type---");
1802  bufsize -= written;
1803  p += written;
1804  }
1805  }
1806  else
1807  {
1808  written = snprintf(p, bufsize, "%s", "--null epc---");
1809  bufsize -= written;
1810  p += written;
1811  }
1812 
1813  // null terminate this for good practice
1814  buf[buflen-1] = '\0';
1815 
1816  return buflen - bufsize;
1817 }
1818 
1819 
1828 int
1829 CMyApplication::getOnePhaseAngle(
1830  CImpinjRFPhaseAngle *pRfPhase,
1831  double *out)
1832 {
1833  if(NULL != pRfPhase)
1834  {
1835  llrp_u16_t phase = pRfPhase->getPhaseAngle();
1836  *out = ((double) phase * 360)/4096;
1837  return 1;
1838  }
1839  return 0;
1840 }
1841 
1850 int
1851 CMyApplication::getOnePeakRSSI (
1852  CImpinjPeakRSSI *pPeakRSSI,
1853  double *out)
1854 {
1855  if(NULL != pPeakRSSI)
1856  {
1857  llrp_s16_t rssival = pPeakRSSI->getRSSI();
1858  *out = ((double) rssival / 100);
1859  return 1;
1860  }
1861  return 0;
1862 }
1863 
1872 int
1873 CMyApplication::getOneTimestamp (
1874  CParameter *pTimestamp,
1875  unsigned long long *out)
1876 {
1877  llrp_u64_t ttime;
1878 
1879  if(NULL == pTimestamp)
1880  {
1881  return 0;
1882  }
1883 
1884  if(&CFirstSeenTimestampUTC::s_typeDescriptor == pTimestamp->m_pType)
1885  {
1886  CFirstSeenTimestampUTC *pftutc = (CFirstSeenTimestampUTC*) pTimestamp;
1887  ttime = pftutc->getMicroseconds();
1888  } else if (&CFirstSeenTimestampUptime::s_typeDescriptor == pTimestamp->m_pType)
1889  {
1891  ttime = pftup->getMicroseconds();
1892  } else if(&CLastSeenTimestampUTC::s_typeDescriptor == pTimestamp->m_pType)
1893  {
1894  CLastSeenTimestampUTC *pltutc = (CLastSeenTimestampUTC*) pTimestamp;
1895  ttime = pltutc->getMicroseconds();
1896  } else if (&CLastSeenTimestampUTC::s_typeDescriptor == pTimestamp->m_pType)
1897  {
1898  CLastSeenTimestampUptime *pltup = (CLastSeenTimestampUptime*) pTimestamp;
1899  ttime = pltup->getMicroseconds();
1900  }
1901 
1902  *out = ttime;
1903  return 1;
1904 }
1905 
1914 int
1915 CMyApplication::getOneAntenna (
1916  CAntennaID *pAntenna,
1917  unsigned short *out)
1918 {
1919  if(NULL != pAntenna)
1920  {
1921  *out = pAntenna->getAntennaID();
1922  return 1;
1923  }
1924  return 0;
1925 }
1926 
1935 int
1936 CMyApplication::getOneChannelIndex (
1937  CChannelIndex *pChannelIndex,
1938  unsigned short *out)
1939 {
1940  if(NULL != pChannelIndex)
1941  {
1942 
1943  *out = pChannelIndex->getChannelIndex();
1944  return 1;
1945  }
1946  return 0;
1947 }
1948 
1957 int
1958 CMyApplication::estimateVelocity(
1959  char * epcStr,
1960  double rssi,
1961  double phase,
1962  unsigned short channelIndex,
1963  unsigned short antenna,
1964  unsigned long long time,
1965  double *outVelocity)
1966  {
1967  int retVal = 0;
1968  static char lastEpcStr[128];
1969  static double lastrssi = 0;
1970  static double lastphase = 0;
1971  static unsigned short lastchannelindex = 0;
1972  static unsigned short lastantenna = 0;
1973  static unsigned long long lasttime = 0;
1974 
1975  /* only collect a velocity sample if we have
1976  ** been on the same EPC, antenna and channel. It's best
1977  ** to run this example with only one EPC */
1978  if((0 == strcmp(epcStr, lastEpcStr)) &&
1979  (lastantenna == antenna) &&
1980  (lastchannelindex == channelIndex))
1981  {
1982  /* positive velocity is moving towards the antenna */
1983  double phaseChangeDegrees = (phase - lastphase);
1984  double timeChangeUsec = (double) (time - lasttime);
1985 
1986  /* always wrap the phase to between -180 and 180 */
1987  while( phaseChangeDegrees < -180)
1988  phaseChangeDegrees += 360;
1989  while( phaseChangeDegrees > 180)
1990  phaseChangeDegrees -= 360;
1991 
1992  /* if our phase changes close to 180 degrees, you can see we
1993  ** have an ambiguity of whether the phase advanced or retarded by
1994  ** 180 degrees (or slightly over). There is no way to tell unless
1995  ** you use more advanced techiques with multiple channels. So just
1996  ** ignore any samples where phase change is > 90 */
1997 
1998  if( abs((int) phaseChangeDegrees) <= 90)
1999  {
2000  /* We can divide these two to get degrees/usec, but it would be more
2001  ** convenient to have this in a common unit like meters/second.
2002  ** Here's a straightforward conversion. NOTE: to be exact here, we
2003  ** should use the channel index to find the channel frequency/wavelength.
2004  ** For now, I'll just assume the wavelength corresponds to mid-band at
2005  ** 0.32786885245901635 meters. The formula below eports meters per second.
2006  ** Note that 360 degrees equals only 1/2 a wavelength of motion because
2007  ** we are computing the round trip phase change.
2008  **
2009  ** phaseChange (degrees) 1/2 wavelength 0.327 meter 1000000 usec
2010  ** --------------------- * -------------- * ---------------- * ------------
2011  ** timeChange (usec) 360 degrees 1 wavelength 1 second
2012  **
2013  ** which should net out to estimated tag velocity in meters/second */
2014 
2015  *outVelocity = ((phaseChangeDegrees * 0.5 * 0.327868852 * 1000000)/(360 * timeChangeUsec ));
2016 
2017  retVal = 1;
2018  }
2019  }
2020 
2021  /* record these for next time */
2022  strcpy(lastEpcStr, epcStr);
2023  lastrssi = rssi;
2024  lastphase = phase;
2025  lastchannelindex = channelIndex;
2026  lastantenna = antenna;
2027  lasttime = time;
2028 
2029  return retVal;
2030  }
2031 
2040 void
2041 CMyApplication::printOneTagReportData (
2042  CTagReportData * pTagReportData)
2043 {
2044  char epcBuf[128];
2045  char aBuf[128];
2046  char *ptr = aBuf;
2047  int len = 128;
2048  int written;
2049  unsigned long long time;
2050  unsigned short antenna, channelIndex;
2051  double rssi, phase, velocityInst;
2052 
2053  /* this is static to keep a moving average of velocity */
2054  static double velocity = 0;
2055  std::list<CParameter *>::iterator Cur;
2056  /*
2057  * Print the EPC. It could be an 96-bit EPC_96 parameter
2058  * or an variable length EPCData parameter.
2059  */
2060 
2061  CParameter * pEPCParameter =
2062  pTagReportData->getEPCParameter();
2063 
2064  /* save a copy of the EPC */
2065  memset(epcBuf, 0x00, sizeof(epcBuf));
2066  formatOneEPC(pEPCParameter, epcBuf, 128, "");
2067 
2068  written = snprintf(ptr, len, " epc=%s", epcBuf);
2069  ptr += written;
2070  len -= written;
2071 
2072  if(getOneTimestamp(pTagReportData->getFirstSeenTimestampUTC(), &time))
2073  {
2074  written = snprintf(ptr, len, " tm=%010u", time);
2075  ptr += written;
2076  len -= written;
2077  }
2078 
2079  if(getOneChannelIndex(pTagReportData->getChannelIndex(), &channelIndex))
2080  {
2081  written = snprintf(ptr, len, " idx=%02u", channelIndex);
2082  ptr += written;
2083  len -= written;
2084  }
2085 
2086  if(getOneAntenna(pTagReportData->getAntennaID(), &antenna))
2087  {
2088  written = snprintf(ptr, len, " ant=%01u", antenna);
2089  ptr += written;
2090  len -= written;
2091  }
2092 
2093  for(
2094  Cur = pTagReportData->beginCustom();
2095  Cur != pTagReportData->endCustom();
2096  Cur++)
2097  {
2098  /* look for our special Impinj Tag Report Data */
2099  if(&CImpinjRFPhaseAngle::s_typeDescriptor == (*Cur)->m_pType)
2100  {
2101  if(getOnePhaseAngle((CImpinjRFPhaseAngle*) *Cur, &phase))
2102  {
2103  written = snprintf(ptr, len, " ph=%+04d", (int) phase);
2104  ptr += written;
2105  len -= written;
2106  }
2107  } else if (&CImpinjPeakRSSI::s_typeDescriptor == (*Cur)->m_pType)
2108  {
2109  if (getOnePeakRSSI((CImpinjPeakRSSI*) *Cur, &rssi))
2110  {
2111  written = snprintf(ptr, len, " rs=%+3.2f", rssi);
2112  ptr += written;
2113  len -= written;
2114  }
2115  }
2116  }
2117 
2118  /* Pauls Test code for looking at low level data */
2119 
2120  if(estimateVelocity(&epcBuf[0], rssi, phase, channelIndex, antenna, time, &velocityInst))
2121  {
2122  /* keep a filtered value. Use a 1 pole IIR here for simplicity */
2123  velocity = (6*velocity + 4*velocityInst)/10.0;
2124 
2125  char *str = " - ";
2126  if (velocity > 0.25)
2127  str = "---->";
2128  if (velocity < -0.25)
2129  str = "<----";
2130 
2131  written =snprintf(ptr, len, " vel=%+2.2f filt=%+2.2f %s",
2132  velocityInst, velocity, str);
2133  ptr += written;
2134  len -= written;
2135 
2136  /*
2137  * Only print if we have a velocity estimate
2138  */
2139  printf("%s\n", aBuf);
2140  }
2141 }
2142 
2143 
2157 void
2158 CMyApplication::handleReaderEventNotification (
2159  CReaderEventNotificationData *pNtfData)
2160 {
2161  CAntennaEvent * pAntennaEvent;
2162  CReaderExceptionEvent * pReaderExceptionEvent;
2163  int nReported = 0;
2164 
2165  pAntennaEvent = pNtfData->getAntennaEvent();
2166  if(NULL != pAntennaEvent)
2167  {
2168  handleAntennaEvent(pAntennaEvent);
2169  nReported++;
2170  }
2171 
2172  pReaderExceptionEvent = pNtfData->getReaderExceptionEvent();
2173  if(NULL != pReaderExceptionEvent)
2174  {
2175  handleReaderExceptionEvent(pReaderExceptionEvent);
2176  nReported++;
2177  }
2178 
2179  /*
2180  * Similarly handle other events here:
2181  * HoppingEvent
2182  * GPIEvent
2183  * ROSpecEvent
2184  * ReportBufferLevelWarningEvent
2185  * ReportBufferOverflowErrorEvent
2186  * RFSurveyEvent
2187  * AISpecEvent
2188  * ConnectionAttemptEvent
2189  * ConnectionCloseEvent
2190  * Custom
2191  */
2192 
2193  if(0 == nReported)
2194  {
2195  printf("NOTICE: Unexpected (unhandled) ReaderEvent\n");
2196  }
2197 }
2198 
2199 
2211 void
2212 CMyApplication::handleAntennaEvent (
2213  CAntennaEvent * pAntennaEvent)
2214 {
2215  EAntennaEventType eEventType;
2216  llrp_u16_t AntennaID;
2217  char * pStateStr;
2218 
2219  eEventType = pAntennaEvent->getEventType();
2220  AntennaID = pAntennaEvent->getAntennaID();
2221 
2222  switch(eEventType)
2223  {
2224  case AntennaEventType_Antenna_Disconnected:
2225  pStateStr = "disconnected";
2226  break;
2227 
2228  case AntennaEventType_Antenna_Connected:
2229  pStateStr = "connected";
2230  break;
2231 
2232  default:
2233  pStateStr = "?unknown-event?";
2234  break;
2235  }
2236 
2237  printf("NOTICE: Antenna %d is %s\n", AntennaID, pStateStr);
2238 }
2239 
2240 
2253 void
2254 CMyApplication::handleReaderExceptionEvent (
2255  CReaderExceptionEvent * pReaderExceptionEvent)
2256 {
2257  llrp_utf8v_t Message;
2258 
2259  Message = pReaderExceptionEvent->getMessage();
2260 
2261  if(0 < Message.m_nValue && NULL != Message.m_pValue)
2262  {
2263  printf("NOTICE: ReaderException '%.*s'\n",
2264  Message.m_nValue, Message.m_pValue);
2265  }
2266  else
2267  {
2268  printf("NOTICE: ReaderException but no message\n");
2269  }
2270 }
2271 
2272 
2291 int
2292 CMyApplication::checkLLRPStatus (
2293  CLLRPStatus * pLLRPStatus,
2294  char * pWhatStr)
2295 {
2296  /*
2297  * The LLRPStatus parameter is mandatory in all responses.
2298  * If it is missing there should have been a decode error.
2299  * This just makes sure (remember, this program is a
2300  * diagnostic and suppose to catch LTKC mistakes).
2301  */
2302  if(NULL == pLLRPStatus)
2303  {
2304  printf("ERROR: %s missing LLRP status\n", pWhatStr);
2305  return -1;
2306 
2307  }
2308 
2309  /*
2310  * Make sure the status is M_Success.
2311  * If it isn't, print the error string if one.
2312  * This does not try to pretty-print the status
2313  * code. To get that, run this program with -vv
2314  * and examine the XML output.
2315  */
2316  if(StatusCode_M_Success != pLLRPStatus->getStatusCode())
2317  {
2318  llrp_utf8v_t ErrorDesc;
2319 
2320  ErrorDesc = pLLRPStatus->getErrorDescription();
2321 
2322  if(0 == ErrorDesc.m_nValue)
2323  {
2324  printf("ERROR: %s failed, no error description given\n",
2325  pWhatStr);
2326  }
2327  else
2328  {
2329  printf("ERROR: %s failed, %.*s\n",
2330  pWhatStr, ErrorDesc.m_nValue, ErrorDesc.m_pValue);
2331  }
2332  return -2;
2333  }
2334 
2335  /*
2336  * Victory. Everything is fine.
2337  */
2338  return 0;
2339 }
2340 
2341 
2365 CMessage *
2366 CMyApplication::transact (
2367  CMessage * pSendMsg)
2368 {
2369  CConnection * pConn = m_pConnectionToReader;
2370  CMessage * pRspMsg;
2371 
2372  /*
2373  * Print the XML text for the outbound message if
2374  * verbosity is 2 or higher.
2375  */
2376  if(1 < m_Verbose)
2377  {
2378  printf("\n===================================\n");
2379  printf("INFO: Transact sending\n");
2380  printXMLMessage(pSendMsg);
2381  }
2382 
2383  /*
2384  * Send the message, expect the response of certain type.
2385  * If LLRP::CConnection::transact() returns NULL then there was
2386  * an error. In that case we try to print the error details.
2387  */
2388  pRspMsg = pConn->transact(pSendMsg, 5000);
2389 
2390  if(NULL == pRspMsg)
2391  {
2392  const CErrorDetails * pError = pConn->getTransactError();
2393 
2394  printf("ERROR: %s transact failed, %s\n",
2395  pSendMsg->m_pType->m_pName,
2396  pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
2397 
2398  if(NULL != pError->m_pRefType)
2399  {
2400  printf("ERROR: ... reference type %s\n",
2401  pError->m_pRefType->m_pName);
2402  }
2403 
2404  if(NULL != pError->m_pRefField)
2405  {
2406  printf("ERROR: ... reference field %s\n",
2407  pError->m_pRefField->m_pName);
2408  }
2409 
2410  return NULL;
2411  }
2412 
2413  /*
2414  * Print the XML text for the inbound message if
2415  * verbosity is 2 or higher.
2416  */
2417  if(1 < m_Verbose)
2418  {
2419  printf("\n- - - - - - - - - - - - - - - - - -\n");
2420  printf("INFO: Transact received response\n");
2421  printXMLMessage(pRspMsg);
2422  }
2423 
2424  /*
2425  * If it is an ERROR_MESSAGE (response from reader
2426  * when it can't understand the request), tattle
2427  * and declare defeat.
2428  */
2429  if(&CERROR_MESSAGE::s_typeDescriptor == pRspMsg->m_pType)
2430  {
2431  const CTypeDescriptor * pResponseType;
2432 
2433  pResponseType = pSendMsg->m_pType->m_pResponseType;
2434 
2435  printf("ERROR: Received ERROR_MESSAGE instead of %s\n",
2436  pResponseType->m_pName);
2437  delete pRspMsg;
2438  pRspMsg = NULL;
2439  }
2440 
2441  return pRspMsg;
2442 }
2443 
2444 
2469 CMessage *
2470 CMyApplication::recvMessage (
2471  int nMaxMS)
2472 {
2473  CConnection * pConn = m_pConnectionToReader;
2474  CMessage * pMessage;
2475 
2476  /*
2477  * Receive the message subject to a time limit
2478  */
2479  pMessage = pConn->recvMessage(nMaxMS);
2480 
2481  /*
2482  * If LLRP::CConnection::recvMessage() returns NULL then there was
2483  * an error. In that case we try to print the error details.
2484  */
2485  if(NULL == pMessage)
2486  {
2487  const CErrorDetails * pError = pConn->getRecvError();
2488 
2489  /* don't warn on timeout since this is a polling example */
2490  if(pError->m_eResultCode != RC_RecvTimeout)
2491  {
2492  printf("ERROR: recvMessage failed, %s\n",
2493  pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
2494  }
2495 
2496  if(NULL != pError->m_pRefType)
2497  {
2498  printf("ERROR: ... reference type %s\n",
2499  pError->m_pRefType->m_pName);
2500  }
2501 
2502  if(NULL != pError->m_pRefField)
2503  {
2504  printf("ERROR: ... reference field %s\n",
2505  pError->m_pRefField->m_pName);
2506  }
2507 
2508  return NULL;
2509  }
2510 
2511  /*
2512  * Print the XML text for the inbound message if
2513  * verbosity is 2 or higher.
2514  */
2515  if(1 < m_Verbose)
2516  {
2517  printf("\n===================================\n");
2518  printf("INFO: Message received\n");
2519  printXMLMessage(pMessage);
2520  }
2521 
2522  return pMessage;
2523 }
2524 
2525 
2543 int
2544 CMyApplication::sendMessage (
2545  CMessage * pSendMsg)
2546 {
2547  CConnection * pConn = m_pConnectionToReader;
2548 
2549  /*
2550  * Print the XML text for the outbound message if
2551  * verbosity is 2 or higher.
2552  */
2553  if(1 < m_Verbose)
2554  {
2555  printf("\n===================================\n");
2556  printf("INFO: Sending\n");
2557  printXMLMessage(pSendMsg);
2558  }
2559 
2560  /*
2561  * If LLRP::CConnection::sendMessage() returns other than RC_OK
2562  * then there was an error. In that case we try to print
2563  * the error details.
2564  */
2565  if(RC_OK != pConn->sendMessage(pSendMsg))
2566  {
2567  const CErrorDetails * pError = pConn->getSendError();
2568 
2569  printf("ERROR: %s sendMessage failed, %s\n",
2570  pSendMsg->m_pType->m_pName,
2571  pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
2572 
2573  if(NULL != pError->m_pRefType)
2574  {
2575  printf("ERROR: ... reference type %s\n",
2576  pError->m_pRefType->m_pName);
2577  }
2578 
2579  if(NULL != pError->m_pRefField)
2580  {
2581  printf("ERROR: ... reference field %s\n",
2582  pError->m_pRefField->m_pName);
2583  }
2584 
2585  return -1;
2586  }
2587 
2588  /*
2589  * Victory
2590  */
2591  return 0;
2592 }
2593 
2594 
2608 void
2609 CMyApplication::printXMLMessage (
2610  CMessage * pMessage)
2611 {
2612  char aBuf[100*1024];
2613 
2614  /*
2615  * Convert the message to an XML string.
2616  * This fills the buffer with either the XML string
2617  * or an error message. The return value could
2618  * be checked.
2619  */
2620 
2621  pMessage->toXMLString(aBuf, sizeof aBuf);
2622 
2623  /*
2624  * Print the XML Text to the standard output.
2625  */
2626  printf("%s", aBuf);
2627 }
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.
Class Definition CImpinjTagReportContentSelector for LLRP parameter ImpinjTagReportContentSelector.
void setEnableCRC(llrp_u1_t value)
Set accessor functions for the LLRP EnableCRC field.
Class Definition CFirstSeenTimestampUTC for LLRP parameter FirstSeenTimestampUTC. ...
Class Definition CLastSeenTimestampUptime for LLRP parameter LastSeenTimestampUptime.
EResultCode setC1G2SingulationControl(CC1G2SingulationControl *pValue)
Set accessor functions for the LLRP C1G2SingulationControl sub-parameter.
EResultCode addCustom(CParameter *pValue)
Add a Custom to the LLRP sub-parameter list.
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
llrp_u16_t getChannelIndex(void)
Get accessor functions for the LLRP ChannelIndex field.
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 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.
Class Definition CFirstSeenTimestampUptime for LLRP parameter FirstSeenTimestampUptime.
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.
const CFieldDescriptor * m_pRefField
If non-NULL this is the field descriptors for the errored field.
Definition: ltkcpp_base.h:641
void setTari(llrp_u16_t value)
Set accessor functions for the LLRP Tari field.
void setDurationTriggerValue(llrp_u32_t value)
Set accessor functions for the LLRP DurationTriggerValue field.
Class Definition CENABLE_ROSPEC for LLRP message ENABLE_ROSPEC.
void usage(char *pProgName)
Print usage message and exit.
Definition: docsample4.cpp:294
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
void setROReportTrigger(EROReportTriggerType value)
Set accessor functions for the LLRP ROReportTrigger field.
EResultCode addAirProtocolEPCMemorySelector(CParameter *pValue)
Add a AirProtocolEPCMemorySelector to the LLRP sub-parameter list.
void setSerializedTIDMode(EImpinjSerializedTIDMode value)
Set accessor functions for the LLRP SerializedTIDMode field.
void setFieldPingInterval(llrp_u16_t value)
Set accessor functions for the LLRP FieldPingInterval field.
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.
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
llrp_u64_t getMicroseconds(void)
Get accessor functions for the LLRP Microseconds 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()
Class Definition CGeneralDeviceCapabilities for LLRP parameter GeneralDeviceCapabilities.
EResultCode setImpinjEnableSerializedTID(CImpinjEnableSerializedTID *pValue)
Set accessor functions for the LLRP ImpinjEnableSerializedTID sub-parameter.
void setROSpecID(llrp_u32_t value)
Set accessor functions for the LLRP ROSpecID field.
Class Definition CImpinjLowDutyCycle for LLRP parameter ImpinjLowDutyCycle.
llrp_utf8v_t getReaderFirmwareVersion(void)
Get accessor functions for the LLRP ReaderFirmwareVersion field.
Class Definition CImpinjPeakRSSI for LLRP parameter ImpinjPeakRSSI.
void setModeIndex(llrp_u16_t value)
Set accessor functions for the LLRP ModeIndex field.
Class Definition CROReportSpec for LLRP parameter ROReportSpec.
EStatusCode getStatusCode(void)
Get accessor functions for the LLRP StatusCode field.
Class Definition CChannelIndex for LLRP parameter ChannelIndex.
void setRequestedData(EGetReaderCapabilitiesRequestedData value)
Set accessor functions for the LLRP RequestedData field.
llrp_u16_t m_nValue
The number of arrray elements.
Definition: ltkcpp_base.h:484
Class Definition CImpinjRFPhaseAngle for LLRP parameter ImpinjRFPhaseAngle.
int closeConnectionToReader(void)
Close connection to reader, allow reuse of instance.
CGeneralDeviceCapabilities * getGeneralDeviceCapabilities(void)
Get accessor functions for the LLRP GeneralDeviceCapabilities sub-parameter.
EResultCode setC1G2RFControl(CC1G2RFControl *pValue)
Set accessor functions for the LLRP C1G2RFControl sub-parameter.
void setRFPhaseAngleMode(EImpinjRFPhaseAngleMode value)
Set accessor functions for the LLRP RFPhaseAngleMode field.
Class Definition CROSpecStartTrigger for LLRP parameter ROSpecStartTrigger.
Class Definition CImpinjEnablePeakRSSI for LLRP parameter ImpinjEnablePeakRSSI.
EResultCode setImpinjEnablePeakRSSI(CImpinjEnablePeakRSSI *pValue)
Set accessor functions for the LLRP ImpinjEnablePeakRSSI sub-parameter.
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.
llrp_u32_t getDeviceManufacturerName(void)
Get accessor functions for the LLRP DeviceManufacturerName field.
const CErrorDetails * getTransactError(void)
Get the details that explains transact() error.
EResultCode setROBoundarySpec(CROBoundarySpec *pValue)
Set accessor functions for the LLRP ROBoundarySpec sub-parameter.
void setLowDutyCycleMode(EImpinjLowDutyCycleMode value)
Set accessor functions for the LLRP LowDutyCycleMode field.
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.
Class Definition CROSpec for LLRP parameter ROSpec.
std::list< CParameter * >::iterator endCustom(void)
Returns the last element of the Custom sub-parameter list.
void setROSpecID(llrp_u32_t value)
Set accessor functions for the LLRP ROSpecID field.
Class Definition CImpinjInventorySearchMode for LLRP parameter ImpinjInventorySearchMode.
Class Definition CC1G2RFControl for LLRP parameter C1G2RFControl.
Class Definition CInventoryParameterSpec for LLRP parameter InventoryParameterSpec.
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.
void setInventorySearchMode(EImpinjInventorySearchType value)
Set accessor functions for the LLRP InventorySearchMode field.
CReaderExceptionEvent * getReaderExceptionEvent(void)
Get accessor functions for the LLRP ReaderExceptionEvent sub-parameter.
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.
CAntennaID * getAntennaID(void)
Get accessor functions for the LLRP AntennaID sub-parameter.
EResultCode addSpecParameter(CParameter *pValue)
Add a SpecParameter to the LLRP sub-parameter list.
Class Definition CEPCData for LLRP parameter EPCData.
llrp_u64_t getMicroseconds(void)
Get accessor functions for the LLRP Microseconds field.
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.
Class Definition CImpinjEnableSerializedTID for LLRP parameter ImpinjEnableSerializedTID.
llrp_u1v_t getEPC(void)
Get accessor functions for the LLRP EPC field.
Class Definition CSET_READER_CONFIG for LLRP message SET_READER_CONFIG.
llrp_u16_t getPhaseAngle(void)
Get accessor functions for the LLRP PhaseAngle field.
CChannelIndex * getChannelIndex(void)
Get accessor functions for the LLRP ChannelIndex sub-parameter.
std::list< CParameter * >::iterator beginCustom(void)
Returns the first element of the Custom sub-parameter list.
CMessage * transact(CMessage *pSendMessage, int nMaxMS)
Transact a LLRP request and response to a connection.
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
void setEnablePCBits(llrp_u1_t value)
Set accessor functions for the LLRP EnablePCBits field.
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
Class for LLRP basic type u1v (vector of unsigned 1-bit values)
Definition: ltkcpp_base.h:437
void setAntennaIDs(llrp_u16v_t value)
Set accessor functions for the LLRP AntennaIDs field.
int openConnectionToReader(const char *pReaderHostName)
Open a connection to the reader over an unencrypted socket.
Class Definition CENABLE_ROSPEC_RESPONSE for LLRP message ENABLE_ROSPEC_RESPONSE. ...
Class Definition CGET_READER_CAPABILITIES for LLRP message GET_READER_CAPABILITIES.
const CTypeDescriptor * m_pResponseType
For messages (bIsMessage==TRUE), this is the type descriptor for the corresponding response...
Definition: ltkcpp_base.h:776
EResultCode addCustom(CParameter *pValue)
Add a Custom to the LLRP sub-parameter list.
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.
llrp_u16_t getAntennaID(void)
Get accessor functions for the LLRP AntennaID field.
Class Definition CAntennaID for LLRP parameter AntennaID.
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.
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.
int main(int ac, char *av[])
Command main routine.
Definition: docsample4.cpp:212
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.
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
Class Definition CLastSeenTimestampUTC for LLRP parameter LastSeenTimestampUTC.
Base Class for All LLRP LTK Parameters.
Definition: ltkcpp_base.h:1125
Base Class for All LLRP LTK Messages.
Definition: ltkcpp_base.h:1088
Class Definition CImpinjEnableRFPhaseAngle for LLRP parameter ImpinjEnableRFPhaseAngle.
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
EResultCode setROSpecStartTrigger(CROSpecStartTrigger *pValue)
Set accessor functions for the LLRP ROSpecStartTrigger sub-parameter.
EResultCode addAntennaConfiguration(CAntennaConfiguration *pValue)
Add a AntennaConfiguration to the LLRP sub-parameter list.
Class Definition CC1G2EPCMemorySelector for LLRP parameter C1G2EPCMemorySelector. ...
void setEnableSpecIndex(llrp_u1_t value)
Set accessor functions for the LLRP EnableSpecIndex field.
llrp_s16_t getRSSI(void)
Get accessor functions for the LLRP RSSI field.
Class Definition CGET_READER_CAPABILITIES_RESPONSE for LLRP message GET_READER_CAPABILITIES_RESPONSE...
llrp_u64_t getMicroseconds(void)
Get accessor functions for the LLRP Microseconds field.
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.
CFirstSeenTimestampUTC * getFirstSeenTimestampUTC(void)
Get accessor functions for the LLRP FirstSeenTimestampUTC sub-parameter.
void setCurrentState(EROSpecState value)
Set accessor functions for the LLRP CurrentState field.
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 setPeakRSSIMode(EImpinjPeakRSSIMode value)
Set accessor functions for the LLRP PeakRSSIMode field.
llrp_u64_t getMicroseconds(void)
Get accessor functions for the LLRP Microseconds field.
void setPriority(llrp_u8_t value)
Set accessor functions for the LLRP Priority field.
EResultCode setImpinjEnableRFPhaseAngle(CImpinjEnableRFPhaseAngle *pValue)
Set accessor functions for the LLRP ImpinjEnableRFPhaseAngle sub-parameter.
Class Definition CROBoundarySpec for LLRP parameter ROBoundarySpec.
void setEmptyFieldTimeout(llrp_u16_t value)
Set accessor functions for the LLRP EmptyFieldTimeout field.
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.