LTKCPP-- LLRP Toolkit C Plus Plus Library
docsample2.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,2009. All rights reserved. *
12  * *
13  *****************************************************************************/
14 
51 #include <stdio.h>
52 #include "ltkcpp.h"
53 #include "impinj_ltkcpp.h"
54 #include "time.h"
55 
56 using namespace LLRP;
57 
58 /*
59 ** Sorry, we use this linux safe method
60 ** to print buffers. WIndows has the same
61 ** method, but by a different name
62 */
63 #if (WIN32)
64 #define snprintf _snprintf
65 #endif
66 
67 class CMyApplication
68 {
69 private:
70 
71  unsigned int m_PowerLevelIndex;
72  unsigned int m_hopTableID;
73  unsigned int m_channelIndex;
74  unsigned int m_modelNumber;
75  unsigned int m_messageID;
76 
77  public:
79  int m_Verbose;
80 
82  CConnection * m_pConnectionToReader;
83  CTypeRegistry * m_pTypeRegistry;
84 
85  inline
86  CMyApplication (void)
87  : m_Verbose(0), m_pConnectionToReader(NULL)
88  {
89  m_messageID = 0;
90  }
91 
92  int
93  run (
94  char * pReaderHostName);
95 
96  int
97  checkConnectionStatus (void);
98 
99  int
100  enableImpinjExtensions (void);
101 
102  int
103  resetConfigurationToFactoryDefaults (void);
104 
105  int
106  getReaderCapabilities(void);
107 
108  int
109  getReaderConfig(void);
110 
111  int
112  setImpinjReaderConfig(void);
113 
114  int
115  addROSpec (void);
116 
117  int
118  enableROSpec (void);
119 
120  int
121  startROSpec (void);
122 
123  int
124  stopROSpec (void);
125 
126  int
127  awaitAndPrintReport (int timeoutSec);
128 
129  void
130  printTagReportData (
131  CRO_ACCESS_REPORT * pRO_ACCESS_REPORT);
132 
133  void
134  printOneTagReportData (
135  CTagReportData * pTagReportData);
136 
137  void
138  formatOneEPC (
139  CParameter * pEpcParameter,
140  char * buf,
141  int buflen);
142 
143  void
144  handleReaderEventNotification (
145  CReaderEventNotificationData *pNtfData);
146 
147  void
148  handleAntennaEvent (
149  CAntennaEvent * pAntennaEvent);
150 
151  void
152  handleReaderExceptionEvent (
153  CReaderExceptionEvent * pReaderExceptionEvent);
154 
155  int
156  checkLLRPStatus (
157  CLLRPStatus * pLLRPStatus,
158  char * pWhatStr);
159 
160  CMessage *
161  transact (
162  CMessage * pSendMsg);
163 
164  CMessage *
165  recvMessage (
166  int nMaxMS);
167 
168  int
169  sendMessage (
170  CMessage * pSendMsg);
171 
172  void
173  printXMLMessage (
174  CMessage * pMessage);
175 };
176 
177 
178 /* BEGIN forward declarations */
179 int
180 main (
181  int ac,
182  char * av[]);
183 
184 void
185 usage (
186  char * pProgName);
187 /* END forward declarations */
188 
189 
205 int
207  int ac,
208  char * av[])
209 {
210  CMyApplication myApp;
211  char * pReaderHostName;
212  int rc;
213 
214  /*
215  * Process comand arguments, determine reader name
216  * and verbosity level.
217  */
218  if(ac == 2)
219  {
220  pReaderHostName = av[1];
221  }
222  else if(ac == 3)
223  {
224  char * p = av[1];
225 
226  while(*p)
227  {
228  switch(*p++)
229  {
230  case '-': /* linux conventional option warn char */
231  case '/': /* Windows/DOS conventional option warn char */
232  break;
233 
234  case 'v':
235  case 'V':
236  myApp.m_Verbose++;
237  break;
238 
239  default:
240  usage(av[0]);
241  /* no return */
242  break;
243  }
244  }
245 
246  pReaderHostName = av[2];
247  }
248  else
249  {
250  usage(av[0]);
251  /* no return */
252  }
253 
254  /*
255  * Run application, capture return value for exit status
256  */
257  rc = myApp.run(pReaderHostName);
258 
259  printf("INFO: Done\n");
260 
261  /*
262  * Exit with the right status.
263  */
264  if(0 == rc)
265  {
266  exit(0);
267  }
268  else
269  {
270  exit(2);
271  }
272  /*NOTREACHED*/
273 }
274 
275 
287 void
289  char * pProgName)
290 {
291 #ifdef linux
292  printf("Usage: %s [-v[v]] READERHOSTNAME\n", pProgName);
293  printf("\n");
294  printf("Each -v increases verbosity level\n");
295 #endif /* linux */
296 #ifdef WIN32
297  printf("Usage: %s [/v[v]] READERHOSTNAME\n", pProgName);
298  printf("\n");
299  printf("Each /v increases verbosity level\n");
300 #endif /* WIN32 */
301  exit(1);
302 }
303 
304 
346 int
347 CMyApplication::run (
348  char * pReaderHostName)
349 {
350  CConnection * pConn;
351  int rc;
352 
353  /*
354  * Allocate the type registry. This is needed
355  * by the connection to decode.
356  */
357  m_pTypeRegistry = getTheTypeRegistry();
358  if(NULL == m_pTypeRegistry)
359  {
360  printf("ERROR: getTheTypeRegistry failed\n");
361  return -1;
362  }
363 
364  /*
365  * Enroll impinj extension types into the
366  * type registry, in preparation for using
367  * Impinj extension params.
368  */
369  LLRP::enrollImpinjTypesIntoRegistry(m_pTypeRegistry);
370 
371  /*
372  * Construct a connection (LLRP::CConnection).
373  * Using a 32kb max frame size for send/recv.
374  * The connection object is ready for business
375  * but not actually connected to the reader yet.
376  */
377  pConn = new CConnection(m_pTypeRegistry, 32u*1024u);
378  if(NULL == pConn)
379  {
380  printf("ERROR: new CConnection failed\n");
381  return -2;
382  }
383 
384  /*
385  * Open the connection to the reader
386  */
387  if(m_Verbose)
388  {
389  printf("INFO: Connecting to %s....\n", pReaderHostName);
390  }
391 
392  rc = pConn->openConnectionToReader(pReaderHostName);
393  if(0 != rc)
394  {
395  printf("ERROR: connect: %s (%d)\n", pConn->getConnectError(), rc);
396  delete pConn;
397  return -3;
398  }
399 
400  /*
401  * Record the pointer to the connection object so other
402  * routines can use it.
403  */
404  m_pConnectionToReader = pConn;
405 
406  if(m_Verbose)
407  {
408  printf("INFO: Connected, checking status....\n");
409  }
410 
411  /*
412  * Commence the sequence and check for errors as we go.
413  * See comments for each routine for details.
414  * Each routine prints messages.
415  */
416  rc = 1;
417  if(0 == checkConnectionStatus())
418  {
419  rc = 2;
420  if(0 == enableImpinjExtensions())
421  {
422  rc = 3;
423  if(0 == resetConfigurationToFactoryDefaults())
424  {
425  rc = 4;
426  if(0 == getReaderCapabilities())
427  {
428  rc = 5;
429  if(0 == getReaderConfig())
430  {
431  rc = 6;
432  if(0 == setImpinjReaderConfig())
433  {
434  rc = 7;
435  if(0 == addROSpec())
436  {
437  rc = 8;
438  if(0 == enableROSpec())
439  {
440  rc = 9;
441  if(0 == startROSpec())
442  {
443  rc = 10;
444  if(0 == awaitAndPrintReport(60))
445  {
446  rc = 11;
447  if(0 == stopROSpec())
448  {
449  rc = 0;
450  }
451  }
452  }
453  }
454  }
455  }
456  }
457  }
458  }
459 
460  /*
461  * After we're done, try to leave the reader
462  * in a clean state for next use. This is best
463  * effort and no checking of the result is done.
464  */
465  if(m_Verbose)
466  {
467  printf("INFO: Clean up reader configuration...\n");
468  }
469  resetConfigurationToFactoryDefaults();
470  }
471  }
472 
473  if(m_Verbose)
474  {
475  printf("INFO: Finished\n");
476  }
477 
478  /*
479  * Close the connection and release its resources
480  */
481  pConn->closeConnectionToReader();
482  delete pConn;
483 
484  /*
485  * Done with the registry.
486  */
487  delete m_pTypeRegistry;
488 
489  /*
490  * When we get here all allocated memory should have been deallocated.
491  */
492  CXMLTextDecoder::cleanupParser();
493 
494  return rc;
495 }
496 
497 
528 int
529 CMyApplication::checkConnectionStatus (void)
530 {
531  CMessage * pMessage;
534  CConnectionAttemptEvent * pEvent;
535 
536  /*
537  * Expect the notification within 10 seconds.
538  * It is suppose to be the very first message sent.
539  */
540  pMessage = recvMessage(10000);
541 
542  /*
543  * recvMessage() returns NULL if something went wrong.
544  */
545  if(NULL == pMessage)
546  {
547  /* recvMessage already tattled */
548  goto fail;
549  }
550 
551  /*
552  * Check to make sure the message is of the right type.
553  * The type label (pointer) in the message should be
554  * the type descriptor for READER_EVENT_NOTIFICATION.
555  */
556  if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor != pMessage->m_pType)
557  {
558  goto fail;
559  }
560 
561  /*
562  * Now that we are sure it is a READER_EVENT_NOTIFICATION,
563  * traverse to the ReaderEventNotificationData parameter.
564  */
565  pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage;
566  pNtfData = pNtf->getReaderEventNotificationData();
567  if(NULL == pNtfData)
568  {
569  goto fail;
570  }
571 
572  /*
573  * The ConnectionAttemptEvent parameter must be present.
574  */
575  pEvent = pNtfData->getConnectionAttemptEvent();
576  if(NULL == pEvent)
577  {
578  goto fail;
579  }
580 
581  /*
582  * The status in the ConnectionAttemptEvent parameter
583  * must indicate connection success.
584  */
585  if(ConnectionAttemptStatusType_Success != pEvent->getStatus())
586  {
587  goto fail;
588  }
589 
590  /*
591  * Done with the message
592  */
593  delete pMessage;
594 
595  if(m_Verbose)
596  {
597  printf("INFO: Connection status OK\n");
598  }
599 
600  /*
601  * Victory.
602  */
603  return 0;
604 
605  fail:
606  /*
607  * Something went wrong. Tattle. Clean up. Return error.
608  */
609  printf("ERROR: checkConnectionStatus failed\n");
610  delete pMessage;
611  return -1;
612 }
613 
631 int
632 CMyApplication::enableImpinjExtensions (void)
633 {
635  CMessage * pRspMsg;
637 
638  /*
639  * Compose the command message
640  */
641  pCmd = new CIMPINJ_ENABLE_EXTENSIONS();
642  pCmd->setMessageID(m_messageID++);
643  /*
644  * Send the message, expect the response of certain type
645  */
646  pRspMsg = transact(pCmd);
647 
648  /*
649  * Done with the command message
650  */
651  delete pCmd;
652 
653  /*
654  * transact() returns NULL if something went wrong.
655  */
656  if(NULL == pRspMsg)
657  {
658  /* transact already tattled */
659  return -1;
660  }
661 
662  /*
663  * Cast to a CIMPINJ_ENABLE_EXTENSIONS_RESPONSE message.
664  */
665  pRsp = (CIMPINJ_ENABLE_EXTENSIONS_RESPONSE *) pRspMsg;
666 
667  /*
668  * Check the LLRPStatus parameter.
669  */
670  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
671  "enableImpinjExtensions"))
672  {
673  /* checkLLRPStatus already tattled */
674  delete pRspMsg;
675  return -1;
676  }
677 
678  /*
679  * Done with the response message.
680  */
681  delete pRspMsg;
682 
683  /*
684  * Tattle progress, maybe
685  */
686  if(m_Verbose)
687  {
688  printf("INFO: Impinj Extensions are enabled\n");
689  }
690 
691  /*
692  * Victory.
693  */
694  return 0;
695 }
696 
717 int
718 CMyApplication::resetConfigurationToFactoryDefaults (void)
719 {
720  CSET_READER_CONFIG * pCmd;
721  CMessage * pRspMsg;
723 
724  /*
725  * Compose the command message
726  */
727  pCmd = new CSET_READER_CONFIG();
728  pCmd->setMessageID(m_messageID++);
729  pCmd->setResetToFactoryDefault(1);
730 
731  /*
732  * Send the message, expect the response of certain type
733  */
734  pRspMsg = transact(pCmd);
735 
736  /*
737  * Done with the command message
738  */
739  delete pCmd;
740 
741  /*
742  * transact() returns NULL if something went wrong.
743  */
744  if(NULL == pRspMsg)
745  {
746  /* transact already tattled */
747  return -1;
748  }
749 
750  /*
751  * Cast to a SET_READER_CONFIG_RESPONSE message.
752  */
753  pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg;
754 
755  /*
756  * Check the LLRPStatus parameter.
757  */
758  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
759  "resetConfigurationToFactoryDefaults"))
760  {
761  /* checkLLRPStatus already tattled */
762  delete pRspMsg;
763  return -1;
764  }
765 
766  /*
767  * Done with the response message.
768  */
769  delete pRspMsg;
770 
771  /*
772  * Tattle progress, maybe
773  */
774  if(m_Verbose)
775  {
776  printf("INFO: Configuration reset to factory defaults\n");
777  }
778 
779  /*
780  * Victory.
781  */
782  return 0;
783 }
784 
802 int
803 CMyApplication::getReaderCapabilities(void)
804 {
806  CMessage * pRspMsg;
809  CUHFBandCapabilities *pUhf;
811  CGeneralDeviceCapabilities *pDeviceCap;
812  std::list<CTransmitPowerLevelTableEntry *>::iterator PwrLvl;
813 
814  /*
815  * Compose the command message
816  */
817  pCmd = new CGET_READER_CAPABILITIES();
818  pCmd->setMessageID(m_messageID++);
819  pCmd->setRequestedData(GetReaderCapabilitiesRequestedData_All);
820 
821  /*
822  * Send the message, expect the response of certain type
823  */
824  pRspMsg = transact(pCmd);
825 
826  /*
827  * Done with the command message
828  */
829  delete pCmd;
830 
831  /*
832  * transact() returns NULL if something went wrong.
833  */
834  if(NULL == pRspMsg)
835  {
836  /* transact already tattled */
837  return -1;
838  }
839 
840  /*
841  * Cast to a CGET_READER_CAPABILITIES_RESPONSE message.
842  */
843  pRsp = (CGET_READER_CAPABILITIES_RESPONSE *) pRspMsg;
844 
845  /*
846  * Check the LLRPStatus parameter.
847  */
848  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
849  "getReaderCapabilities"))
850  {
851  /* checkLLRPStatus already tattled */
852  delete pRspMsg;
853  return -1;
854  }
855 
856  /*
857  ** Get out the Regulatory Capabilities element
858  */
859  if(NULL == (pReg = pRsp->getRegulatoryCapabilities()))
860  {
861  delete pRspMsg;
862  return -1;
863  }
864 
865  /*
866  ** Get out the UHF Band Capabilities element
867  */
868  if(NULL == (pUhf = pReg->getUHFBandCapabilities()))
869  {
870  delete pRspMsg;
871  return -1;
872  }
873 
874  /* get the last power level in the table */
875  PwrLvl = pUhf->endTransmitPowerLevelTableEntry();
876  PwrLvl--;
877 
878  // store the index for use int the ROSpec.
879  pPwrLvl = *PwrLvl;
880  m_PowerLevelIndex = pPwrLvl->getIndex();
881 
882  if(1 < m_Verbose)
883  {
884  printf("INFO: Reader Max Power index %u, power %f\n",
885  pPwrLvl->getIndex(), (float)(float) pPwrLvl->getTransmitPowerValue()/100);
886  }
887 
888  /* if this parameter is missing, or if this is not an Impinj
889  ** reader, we can't determine its capabilities so we exit
890  ** Impinj Private Enterprise NUmber is 25882 */
891  if( (NULL == (pDeviceCap = pRsp->getGeneralDeviceCapabilities())) ||
892  (25882 != pDeviceCap->getDeviceManufacturerName()))
893  {
894  delete pRspMsg;
895  return -1;
896  }
897 
898  m_modelNumber = pDeviceCap->getModelName();
899 
900  if(1 < m_Verbose)
901  {
902  printf("INFO: Reader Model Name %u\n", m_modelNumber);
903  }
904 
905  /*
906  * Done with the response message.
907  */
908  delete pRspMsg;
909 
910  /*
911  * Tattle progress, maybe
912  */
913  if(m_Verbose)
914  {
915  printf("INFO: Found LLRP Capabilities \n");
916  }
917 
918  /*
919  * Victory.
920  */
921  return 0;
922 }
923 
924 
939 int
940 CMyApplication::getReaderConfig(void)
941 {
942  CGET_READER_CONFIG *pCmd;
943  CMessage * pRspMsg;
945  std::list<CAntennaConfiguration*>::iterator pAntCfg;
946  /*
947  * Compose the command message
948  */
949  pCmd = new CGET_READER_CONFIG();
950  pCmd->setMessageID(m_messageID++);
951  pCmd->setRequestedData(GetReaderConfigRequestedData_All);
952 
953  /*
954  * Send the message, expect the response of certain type
955  */
956  pRspMsg = transact(pCmd);
957 
958  /*
959  * Done with the command message
960  */
961  delete pCmd;
962 
963  /*
964  * transact() returns NULL if something went wrong.
965  */
966  if(NULL == pRspMsg)
967  {
968  /* transact already tattled */
969  return -1;
970  }
971 
972  /*
973  * Cast to a CGET_READER_CONFIG_RESPONSE message.
974  */
975  pRsp = (CGET_READER_CONFIG_RESPONSE *) pRspMsg;
976 
977  /*
978  * Check the LLRPStatus parameter.
979  */
980  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
981  "getReaderConfig"))
982  {
983  /* checkLLRPStatus already tattled */
984  delete pRspMsg;
985  return -1;
986  }
987 
988  /* just get the hop table and channel index out of
989  ** the first antenna configuration since they must all
990  ** be the same */
991  pAntCfg = pRsp->beginAntennaConfiguration();
992  if(pAntCfg != pRsp->endAntennaConfiguration())
993  {
994  CRFTransmitter *prfTx;
995  prfTx = (*pAntCfg)->getRFTransmitter();
996  m_hopTableID = prfTx->getHopTableID();
997  m_channelIndex = prfTx->getChannelIndex();
998  }
999  else
1000  {
1001  delete pRspMsg;
1002  return -1;
1003  }
1004 
1005  if(1 < m_Verbose)
1006  {
1007  printf("INFO: Reader hopTableID %u, ChannelIndex %u\n",
1008  m_hopTableID, m_channelIndex);
1009  }
1010 
1011  /*
1012  * Done with the response message.
1013  */
1014  delete pRspMsg;
1015 
1016  /*
1017  * Tattle progress, maybe
1018  */
1019  if(m_Verbose)
1020  {
1021  printf("INFO: Found LLRP Configuration \n");
1022  }
1023 
1024  /*
1025  * Victory.
1026  */
1027  return 0;
1028 }
1029 
1044 int
1045 CMyApplication::setImpinjReaderConfig(void)
1046 {
1047  CMessage * pCmdMsg;
1048  CSET_READER_CONFIG *pCmd;
1049  CMessage * pRspMsg;
1051  CXMLTextDecoder * pDecoder;
1052  std::list<CAntennaConfiguration *>::iterator Cur;
1053 
1054 
1055  /* Build a decoder to extract the message from XML */
1056  pDecoder = new CXMLTextDecoder(m_pTypeRegistry, "setReaderConfig.xml");
1057 
1058  if(NULL == pDecoder)
1059  {
1060  return -1;
1061  }
1062 
1063  pCmdMsg = pDecoder->decodeMessage();
1064 
1065  delete pDecoder;
1066 
1067  if(NULL == pCmdMsg)
1068  {
1069  return -2;
1070  }
1071 
1072  if(&CSET_READER_CONFIG::s_typeDescriptor != pCmdMsg->m_pType)
1073  {
1074  return -3;
1075  }
1076 
1077  /* get the message as a SET_READER_CONFIG */
1078  pCmd = (CSET_READER_CONFIG *) pCmdMsg;
1079 
1080 
1081  /* It's always a good idea to give it a unique message ID */
1082  pCmd->setMessageID(m_messageID++);
1083 
1084  /* at this point,we would be ready to send the message, but we need
1085  * to make a change to the transmit power for each enabled antenna.
1086  * Loop through */
1087  for(
1088  Cur = pCmd->beginAntennaConfiguration();
1089  Cur != pCmd->endAntennaConfiguration();
1090  Cur++)
1091  {
1092  CRFTransmitter *pRfTx = (*Cur)->getRFTransmitter();
1093 
1094  /* we already have this element in our sample XML file, but
1095  * we check here to create one if it doesn't exist to show
1096  * a more general usage */
1097  if(NULL == pRfTx)
1098  {
1099  pRfTx = new CRFTransmitter();
1100  (*Cur)->setRFTransmitter(pRfTx);
1101  }
1102  /*
1103  ** Set the max power that we retreived from the capabilities
1104  ** and the hopTableID and Channel index we got from the config
1105  */
1106  pRfTx->setChannelIndex(m_channelIndex);
1107  pRfTx->setHopTableID(m_hopTableID);
1108  pRfTx->setTransmitPower(m_PowerLevelIndex);
1109  }
1110 
1111  /*
1112  * Send the message, expect the response of certain type
1113  */
1114  pRspMsg = transact(pCmd);
1115 
1116  /*
1117  * Done with the command message
1118  */
1119  delete pCmd;
1120 
1121  /*
1122  * transact() returns NULL if something went wrong.
1123  */
1124  if(NULL == pRspMsg)
1125  {
1126  /* transact already tattled */
1127  return -1;
1128  }
1129 
1130  /*
1131  * Cast to a CSET_READER_CONFIG_RESPONSE message.
1132  */
1133  pRsp = (CSET_READER_CONFIG_RESPONSE *) pRspMsg;
1134 
1135  /*
1136  * Check the LLRPStatus parameter.
1137  */
1138  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(),
1139  "setImpinjReaderConfig"))
1140  {
1141  /* checkLLRPStatus already tattled */
1142  delete pRspMsg;
1143  return -1;
1144  }
1145 
1146  /*
1147  * Done with the response message.
1148  */
1149  delete pRspMsg;
1150 
1151  /*
1152  * Tattle progress, maybe
1153  */
1154  if(m_Verbose)
1155  {
1156  printf("INFO: Set Impinj Reader Configuration \n");
1157  }
1158 
1159  /*
1160  * Victory.
1161  */
1162  return 0;
1163 }
1164 
1213 int
1214 CMyApplication::addROSpec (void)
1215 {
1216  CROSpecStartTrigger * pROSpecStartTrigger =
1217  new CROSpecStartTrigger();
1218  pROSpecStartTrigger->setROSpecStartTriggerType(
1219  ROSpecStartTriggerType_Null);
1220 
1221  CROSpecStopTrigger * pROSpecStopTrigger = new CROSpecStopTrigger();
1222  pROSpecStopTrigger->setROSpecStopTriggerType(ROSpecStopTriggerType_Null);
1223  pROSpecStopTrigger->setDurationTriggerValue(0); /* n/a */
1224 
1225  CROBoundarySpec * pROBoundarySpec = new CROBoundarySpec();
1226  pROBoundarySpec->setROSpecStartTrigger(pROSpecStartTrigger);
1227  pROBoundarySpec->setROSpecStopTrigger(pROSpecStopTrigger);
1228 
1229  CAISpecStopTrigger * pAISpecStopTrigger = new CAISpecStopTrigger();
1230  pAISpecStopTrigger->setAISpecStopTriggerType(
1231  AISpecStopTriggerType_Null);
1232  pAISpecStopTrigger->setDurationTrigger(0);
1233 
1234  CInventoryParameterSpec * pInventoryParameterSpec =
1236  pInventoryParameterSpec->setInventoryParameterSpecID(1234);
1237  pInventoryParameterSpec->setProtocolID(AirProtocols_EPCGlobalClass1Gen2);
1238 
1239  /*
1240  ** configure to use two antennas
1241  */
1242  llrp_u16v_t AntennaIDs = llrp_u16v_t(2);
1243  AntennaIDs.m_pValue[0] = 1;
1244  AntennaIDs.m_pValue[1] = 2;
1245 
1246  CAISpec * pAISpec = new CAISpec();
1247  pAISpec->setAntennaIDs(AntennaIDs);
1248  pAISpec->setAISpecStopTrigger(pAISpecStopTrigger);
1249  pAISpec->addInventoryParameterSpec(pInventoryParameterSpec);
1250 
1251  CROSpec * pROSpec = new CROSpec();
1252  pROSpec->setROSpecID(1111);
1253  pROSpec->setPriority(0);
1254  pROSpec->setCurrentState(ROSpecState_Disabled);
1255  pROSpec->setROBoundarySpec(pROBoundarySpec);
1256  pROSpec->addSpecParameter(pAISpec);
1257 
1258  CADD_ROSPEC * pCmd;
1259  CMessage * pRspMsg;
1260  CADD_ROSPEC_RESPONSE * pRsp;
1261 
1262  /*
1263  * Compose the command message.
1264  * N.B.: After the message is composed, all the parameters
1265  * constructed, immediately above, are considered "owned"
1266  * by the command message. When it is destructed so
1267  * too will the parameters be.
1268  */
1269  pCmd = new CADD_ROSPEC();
1270  pCmd->setMessageID(m_messageID++);
1271  pCmd->setROSpec(pROSpec);
1272 
1273  /*
1274  * Send the message, expect the response of certain type
1275  */
1276  pRspMsg = transact(pCmd);
1277 
1278  /*
1279  * Done with the command message.
1280  * N.B.: And the parameters
1281  */
1282  delete pCmd;
1283 
1284  /*
1285  * transact() returns NULL if something went wrong.
1286  */
1287  if(NULL == pRspMsg)
1288  {
1289  /* transact already tattled */
1290  return -1;
1291  }
1292 
1293  /*
1294  * Cast to a ADD_ROSPEC_RESPONSE message.
1295  */
1296  pRsp = (CADD_ROSPEC_RESPONSE *) pRspMsg;
1297 
1298  /*
1299  * Check the LLRPStatus parameter.
1300  */
1301  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "addROSpec"))
1302  {
1303  /* checkLLRPStatus already tattled */
1304  delete pRspMsg;
1305  return -1;
1306  }
1307 
1308  /*
1309  * Done with the response message.
1310  */
1311  delete pRspMsg;
1312 
1313  /*
1314  * Tattle progress, maybe
1315  */
1316  if(m_Verbose)
1317  {
1318  printf("INFO: ROSpec added\n");
1319  }
1320 
1321  /*
1322  * Victory.
1323  */
1324  return 0;
1325 }
1326 
1327 
1345 int
1346 CMyApplication::enableROSpec (void)
1347 {
1348  CENABLE_ROSPEC * pCmd;
1349  CMessage * pRspMsg;
1350  CENABLE_ROSPEC_RESPONSE * pRsp;
1351 
1352  /*
1353  * Compose the command message
1354  */
1355  pCmd = new CENABLE_ROSPEC();
1356  pCmd->setMessageID(m_messageID++);
1357  pCmd->setROSpecID(1111);
1358 
1359  /*
1360  * Send the message, expect the response of certain type
1361  */
1362  pRspMsg = transact(pCmd);
1363 
1364  /*
1365  * Done with the command message
1366  */
1367  delete pCmd;
1368 
1369  /*
1370  * transact() returns NULL if something went wrong.
1371  */
1372  if(NULL == pRspMsg)
1373  {
1374  /* transact already tattled */
1375  return -1;
1376  }
1377 
1378  /*
1379  * Cast to a ENABLE_ROSPEC_RESPONSE message.
1380  */
1381  pRsp = (CENABLE_ROSPEC_RESPONSE *) pRspMsg;
1382 
1383  /*
1384  * Check the LLRPStatus parameter.
1385  */
1386  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "enableROSpec"))
1387  {
1388  /* checkLLRPStatus already tattled */
1389  delete pRspMsg;
1390  return -1;
1391  }
1392 
1393  /*
1394  * Done with the response message.
1395  */
1396  delete pRspMsg;
1397 
1398  /*
1399  * Tattle progress, maybe
1400  */
1401  if(m_Verbose)
1402  {
1403  printf("INFO: ROSpec enabled\n");
1404  }
1405 
1406  /*
1407  * Victory.
1408  */
1409  return 0;
1410 }
1411 
1412 
1430 int
1431 CMyApplication::startROSpec (void)
1432 {
1433  CSTART_ROSPEC * pCmd;
1434  CMessage * pRspMsg;
1435  CSTART_ROSPEC_RESPONSE * pRsp;
1436 
1437  /*
1438  * Compose the command message
1439  */
1440  pCmd = new CSTART_ROSPEC();
1441  pCmd->setMessageID(m_messageID++);
1442  pCmd->setROSpecID(1111);
1443 
1444  /*
1445  * Send the message, expect the response of certain type
1446  */
1447  pRspMsg = transact(pCmd);
1448 
1449  /*
1450  * Done with the command message
1451  */
1452  delete pCmd;
1453 
1454  /*
1455  * transact() returns NULL if something went wrong.
1456  */
1457  if(NULL == pRspMsg)
1458  {
1459  /* transact already tattled */
1460  return -1;
1461  }
1462 
1463  /*
1464  * Cast to a START_ROSPEC_RESPONSE message.
1465  */
1466  pRsp = (CSTART_ROSPEC_RESPONSE *) pRspMsg;
1467 
1468  /*
1469  * Check the LLRPStatus parameter.
1470  */
1471  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "startROSpec"))
1472  {
1473  /* checkLLRPStatus already tattled */
1474  delete pRspMsg;
1475  return -1;
1476  }
1477 
1478  /*
1479  * Done with the response message.
1480  */
1481  delete pRspMsg;
1482 
1483  /*
1484  * Tattle progress
1485  */
1486  if(m_Verbose)
1487  {
1488  printf("INFO: ROSpec started\n");
1489  }
1490 
1491  /*
1492  * Victory.
1493  */
1494  return 0;
1495 }
1496 
1514 int
1515 CMyApplication::stopROSpec (void)
1516 {
1517  CSTOP_ROSPEC * pCmd;
1518  CMessage * pRspMsg;
1519  CSTOP_ROSPEC_RESPONSE * pRsp;
1520 
1521  /*
1522  * Compose the command message
1523  */
1524  pCmd = new CSTOP_ROSPEC();
1525  pCmd->setMessageID(m_messageID++);
1526  pCmd->setROSpecID(1111);
1527 
1528  /*
1529  * Send the message, expect the response of certain type
1530  */
1531  pRspMsg = transact(pCmd);
1532 
1533  /*
1534  * Done with the command message
1535  */
1536  delete pCmd;
1537 
1538  /*
1539  * transact() returns NULL if something went wrong.
1540  */
1541  if(NULL == pRspMsg)
1542  {
1543  /* transact already tattled */
1544  return -1;
1545  }
1546 
1547  /*
1548  * Cast to a STOP_ROSPEC_RESPONSE message.
1549  */
1550  pRsp = (CSTOP_ROSPEC_RESPONSE *) pRspMsg;
1551 
1552  /*
1553  * Check the LLRPStatus parameter.
1554  */
1555  if(0 != checkLLRPStatus(pRsp->getLLRPStatus(), "stopROSpec"))
1556  {
1557  /* checkLLRPStatus already tattled */
1558  delete pRspMsg;
1559  return -1;
1560  }
1561 
1562  /*
1563  * Done with the response message.
1564  */
1565  delete pRspMsg;
1566 
1567  /*
1568  * Tattle progress
1569  */
1570  if(m_Verbose)
1571  {
1572  printf("INFO: ROSpec stopped\n");
1573  }
1574 
1575  /*
1576  * Victory.
1577  */
1578  return 0;
1579 }
1580 
1581 
1601 int
1602 CMyApplication::awaitAndPrintReport (int timeout)
1603 {
1604  int bDone = 0;
1605  int retVal = 0;
1606  time_t startTime = time(NULL);
1607  time_t tempTime;
1608  /*
1609  * Keep receiving messages until done or until
1610  * something bad happens.
1611  */
1612  while(!bDone)
1613  {
1614  CMessage * pMessage;
1615  const CTypeDescriptor * pType;
1616 
1617  /*
1618  * Wait up to 1 second for a report. Check
1619  * That way, we can check the timestamp even if
1620  * there are no reports coming in
1621  */
1622  pMessage = recvMessage(1000);
1623 
1624  /* validate the timestamp */
1625  tempTime = time(NULL);
1626  if(difftime(tempTime, startTime) > timeout)
1627  {
1628  bDone=1;
1629  }
1630 
1631  if(NULL == pMessage)
1632  {
1633  continue;
1634  }
1635 
1636  /*
1637  * What happens depends on what kind of message
1638  * received. Use the type label (m_pType) to
1639  * discriminate message types.
1640  */
1641  pType = pMessage->m_pType;
1642 
1643  /*
1644  * Is it a tag report? If so, print it out.
1645  */
1646  if(&CRO_ACCESS_REPORT::s_typeDescriptor == pType)
1647  {
1648  CRO_ACCESS_REPORT * pNtf;
1649 
1650  pNtf = (CRO_ACCESS_REPORT *) pMessage;
1651 
1652  printTagReportData(pNtf);
1653  }
1654 
1655  /*
1656  * Is it a reader event? This example only recognizes
1657  * AntennaEvents.
1658  */
1659  else if(&CREADER_EVENT_NOTIFICATION::s_typeDescriptor == pType)
1660  {
1662  CReaderEventNotificationData *pNtfData;
1663 
1664  pNtf = (CREADER_EVENT_NOTIFICATION *) pMessage;
1665 
1666  pNtfData = pNtf->getReaderEventNotificationData();
1667  if(NULL != pNtfData)
1668  {
1669  handleReaderEventNotification(pNtfData);
1670  }
1671  else
1672  {
1673  /*
1674  * This should never happen. Using continue
1675  * to keep indent depth down.
1676  */
1677  printf("WARNING: READER_EVENT_NOTIFICATION without data\n");
1678  }
1679  }
1680 
1681  /*
1682  * Hmmm. Something unexpected. Just tattle and keep going.
1683  */
1684  else
1685  {
1686  printf("WARNING: Ignored unexpected message during monitor: %s\n",
1687  pType->m_pName);
1688  }
1689 
1690  /*
1691  * Done with the received message
1692  */
1693  delete pMessage;
1694  }
1695 
1696  return retVal;
1697 }
1698 
1699 
1714 void
1715 CMyApplication::printTagReportData (
1716  CRO_ACCESS_REPORT * pRO_ACCESS_REPORT)
1717 {
1718  std::list<CTagReportData *>::iterator Cur;
1719  std::list<CParameter *>::iterator CustCur;
1720 
1721  unsigned int nEntry = 0;
1722 
1723  /*
1724  * Loop through and count the number of entries
1725  */
1726  for(
1727  Cur = pRO_ACCESS_REPORT->beginTagReportData();
1728  Cur != pRO_ACCESS_REPORT->endTagReportData();
1729  Cur++)
1730  {
1731  nEntry++;
1732  }
1733 
1734  if(m_Verbose)
1735  {
1736  printf("INFO: %u tag report entries\n", nEntry);
1737  }
1738 
1739  /*
1740  * Loop through again and print each entry.
1741  */
1742  for(
1743  Cur = pRO_ACCESS_REPORT->beginTagReportData();
1744  Cur != pRO_ACCESS_REPORT->endTagReportData();
1745  Cur++)
1746  {
1747  printOneTagReportData(*Cur);
1748  }
1749 }
1750 
1759 void
1760 CMyApplication::formatOneEPC (
1761  CParameter *pEPCParameter,
1762  char *buf,
1763  int buflen)
1764 {
1765  char * p = buf;
1766  int bufsize = buflen;
1767  int written = 0;
1768 
1769  if(NULL != pEPCParameter)
1770  {
1771  const CTypeDescriptor * pType;
1772  llrp_u96_t my_u96;
1773  llrp_u1v_t my_u1v;
1774  llrp_u8_t * pValue = NULL;
1775  unsigned int n, i;
1776 
1777  pType = pEPCParameter->m_pType;
1778  if(&CEPC_96::s_typeDescriptor == pType)
1779  {
1780  CEPC_96 *pEPC_96;
1781 
1782  pEPC_96 = (CEPC_96 *) pEPCParameter;
1783  my_u96 = pEPC_96->getEPC();
1784  pValue = my_u96.m_aValue;
1785  n = 12u;
1786  }
1787  else if(&CEPCData::s_typeDescriptor == pType)
1788  {
1789  CEPCData * pEPCData;
1790 
1791  pEPCData = (CEPCData *) pEPCParameter;
1792  my_u1v = pEPCData->getEPC();
1793  pValue = my_u1v.m_pValue;
1794  n = (my_u1v.m_nBit + 7u) / 8u;
1795  }
1796 
1797  if(NULL != pValue)
1798  {
1799  for(i = 0; i < n; i++)
1800  {
1801  if(0 < i && i%2 == 0 && 1 < bufsize)
1802  {
1803  *p++ = '-';
1804  bufsize--;
1805  }
1806  if(bufsize > 2)
1807  {
1808  written = snprintf(p, bufsize, "%02X", pValue[i]);
1809  bufsize -= written;
1810  p+= written;
1811  }
1812  }
1813  }
1814  else
1815  {
1816  written = snprintf(p, bufsize, "%s", "---unknown-epc-data-type---");
1817  bufsize -= written;
1818  p += written;
1819  }
1820  }
1821  else
1822  {
1823  written = snprintf(p, bufsize, "%s", "--null epc---");
1824  bufsize -= written;
1825  p += written;
1826  }
1827 
1828  // null terminate this for good practice
1829  buf[buflen-1] = '\0';
1830 
1831 }
1832 
1841 void
1842 CMyApplication::printOneTagReportData (
1843  CTagReportData * pTagReportData)
1844 {
1845  char aBuf[64];
1846 
1847  /*
1848  * Print the EPC. It could be an 96-bit EPC_96 parameter
1849  * or an variable length EPCData parameter.
1850  */
1851 
1852  CParameter * pEPCParameter =
1853  pTagReportData->getEPCParameter();
1854 
1855  formatOneEPC(pEPCParameter, aBuf, 64);
1856 
1857  /*
1858  * End of line
1859  */
1860  printf("EPC: %s\n", aBuf);
1861 }
1862 
1863 
1877 void
1878 CMyApplication::handleReaderEventNotification (
1879  CReaderEventNotificationData *pNtfData)
1880 {
1881  CAntennaEvent * pAntennaEvent;
1882  CReaderExceptionEvent * pReaderExceptionEvent;
1883  int nReported = 0;
1884 
1885  pAntennaEvent = pNtfData->getAntennaEvent();
1886  if(NULL != pAntennaEvent)
1887  {
1888  handleAntennaEvent(pAntennaEvent);
1889  nReported++;
1890  }
1891 
1892  pReaderExceptionEvent = pNtfData->getReaderExceptionEvent();
1893  if(NULL != pReaderExceptionEvent)
1894  {
1895  handleReaderExceptionEvent(pReaderExceptionEvent);
1896  nReported++;
1897  }
1898 
1899  /*
1900  * Similarly handle other events here:
1901  * HoppingEvent
1902  * GPIEvent
1903  * ROSpecEvent
1904  * ReportBufferLevelWarningEvent
1905  * ReportBufferOverflowErrorEvent
1906  * RFSurveyEvent
1907  * AISpecEvent
1908  * ConnectionAttemptEvent
1909  * ConnectionCloseEvent
1910  * Custom
1911  */
1912 
1913  if(0 == nReported)
1914  {
1915  printf("NOTICE: Unexpected (unhandled) ReaderEvent\n");
1916  }
1917 }
1918 
1919 
1931 void
1932 CMyApplication::handleAntennaEvent (
1933  CAntennaEvent * pAntennaEvent)
1934 {
1935  EAntennaEventType eEventType;
1936  llrp_u16_t AntennaID;
1937  char * pStateStr;
1938 
1939  eEventType = pAntennaEvent->getEventType();
1940  AntennaID = pAntennaEvent->getAntennaID();
1941 
1942  switch(eEventType)
1943  {
1944  case AntennaEventType_Antenna_Disconnected:
1945  pStateStr = "disconnected";
1946  break;
1947 
1948  case AntennaEventType_Antenna_Connected:
1949  pStateStr = "connected";
1950  break;
1951 
1952  default:
1953  pStateStr = "?unknown-event?";
1954  break;
1955  }
1956 
1957  printf("NOTICE: Antenna %d is %s\n", AntennaID, pStateStr);
1958 }
1959 
1960 
1973 void
1974 CMyApplication::handleReaderExceptionEvent (
1975  CReaderExceptionEvent * pReaderExceptionEvent)
1976 {
1977  llrp_utf8v_t Message;
1978 
1979  Message = pReaderExceptionEvent->getMessage();
1980 
1981  if(0 < Message.m_nValue && NULL != Message.m_pValue)
1982  {
1983  printf("NOTICE: ReaderException '%.*s'\n",
1984  Message.m_nValue, Message.m_pValue);
1985  }
1986  else
1987  {
1988  printf("NOTICE: ReaderException but no message\n");
1989  }
1990 }
1991 
1992 
2011 int
2012 CMyApplication::checkLLRPStatus (
2013  CLLRPStatus * pLLRPStatus,
2014  char * pWhatStr)
2015 {
2016  /*
2017  * The LLRPStatus parameter is mandatory in all responses.
2018  * If it is missing there should have been a decode error.
2019  * This just makes sure (remember, this program is a
2020  * diagnostic and suppose to catch LTKC mistakes).
2021  */
2022  if(NULL == pLLRPStatus)
2023  {
2024  printf("ERROR: %s missing LLRP status\n", pWhatStr);
2025  return -1;
2026  }
2027 
2028  /*
2029  * Make sure the status is M_Success.
2030  * If it isn't, print the error string if one.
2031  * This does not try to pretty-print the status
2032  * code. To get that, run this program with -vv
2033  * and examine the XML output.
2034  */
2035  if(StatusCode_M_Success != pLLRPStatus->getStatusCode())
2036  {
2037  llrp_utf8v_t ErrorDesc;
2038 
2039  ErrorDesc = pLLRPStatus->getErrorDescription();
2040 
2041  if(0 == ErrorDesc.m_nValue)
2042  {
2043  printf("ERROR: %s failed, no error description given\n",
2044  pWhatStr);
2045  }
2046  else
2047  {
2048  printf("ERROR: %s failed, %.*s\n",
2049  pWhatStr, ErrorDesc.m_nValue, ErrorDesc.m_pValue);
2050  }
2051  return -2;
2052  }
2053 
2054  /*
2055  * Victory. Everything is fine.
2056  */
2057  return 0;
2058 }
2059 
2060 
2084 CMessage *
2085 CMyApplication::transact (
2086  CMessage * pSendMsg)
2087 {
2088  CConnection * pConn = m_pConnectionToReader;
2089  CMessage * pRspMsg;
2090 
2091  /*
2092  * Print the XML text for the outbound message if
2093  * verbosity is 2 or higher.
2094  */
2095  if(1 < m_Verbose)
2096  {
2097  printf("\n===================================\n");
2098  printf("INFO: Transact sending\n");
2099  printXMLMessage(pSendMsg);
2100  }
2101 
2102  /*
2103  * Send the message, expect the response of certain type.
2104  * If LLRP::CConnection::transact() returns NULL then there was
2105  * an error. In that case we try to print the error details.
2106  */
2107  pRspMsg = pConn->transact(pSendMsg, 5000);
2108 
2109  if(NULL == pRspMsg)
2110  {
2111  const CErrorDetails * pError = pConn->getTransactError();
2112 
2113  printf("ERROR: %s transact failed, %s\n",
2114  pSendMsg->m_pType->m_pName,
2115  pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
2116 
2117  if(NULL != pError->m_pRefType)
2118  {
2119  printf("ERROR: ... reference type %s\n",
2120  pError->m_pRefType->m_pName);
2121  }
2122 
2123  if(NULL != pError->m_pRefField)
2124  {
2125  printf("ERROR: ... reference field %s\n",
2126  pError->m_pRefField->m_pName);
2127  }
2128 
2129  return NULL;
2130  }
2131 
2132  /*
2133  * Print the XML text for the inbound message if
2134  * verbosity is 2 or higher.
2135  */
2136  if(1 < m_Verbose)
2137  {
2138  printf("\n- - - - - - - - - - - - - - - - - -\n");
2139  printf("INFO: Transact received response\n");
2140  printXMLMessage(pRspMsg);
2141  }
2142 
2143  /*
2144  * If it is an ERROR_MESSAGE (response from reader
2145  * when it can't understand the request), tattle
2146  * and declare defeat.
2147  */
2148  if(&CERROR_MESSAGE::s_typeDescriptor == pRspMsg->m_pType)
2149  {
2150  const CTypeDescriptor * pResponseType;
2151 
2152  pResponseType = pSendMsg->m_pType->m_pResponseType;
2153 
2154  printf("ERROR: Received ERROR_MESSAGE instead of %s\n",
2155  pResponseType->m_pName);
2156  delete pRspMsg;
2157  pRspMsg = NULL;
2158  }
2159 
2160  return pRspMsg;
2161 }
2162 
2163 
2188 CMessage *
2189 CMyApplication::recvMessage (
2190  int nMaxMS)
2191 {
2192  CConnection * pConn = m_pConnectionToReader;
2193  CMessage * pMessage;
2194 
2195  /*
2196  * Receive the message subject to a time limit
2197  */
2198  pMessage = pConn->recvMessage(nMaxMS);
2199 
2200  /*
2201  * If LLRP::CConnection::recvMessage() returns NULL then there was
2202  * an error. In that case we try to print the error details.
2203  */
2204  if(NULL == pMessage)
2205  {
2206  const CErrorDetails * pError = pConn->getRecvError();
2207 
2208  /* don't warn on timeout since this is a polling example */
2209  if(pError->m_eResultCode != RC_RecvTimeout)
2210  {
2211  printf("ERROR: recvMessage failed, %s\n",
2212  pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
2213  }
2214 
2215  if(NULL != pError->m_pRefType)
2216  {
2217  printf("ERROR: ... reference type %s\n",
2218  pError->m_pRefType->m_pName);
2219  }
2220 
2221  if(NULL != pError->m_pRefField)
2222  {
2223  printf("ERROR: ... reference field %s\n",
2224  pError->m_pRefField->m_pName);
2225  }
2226 
2227  return NULL;
2228  }
2229 
2230  /*
2231  * Print the XML text for the inbound message if
2232  * verbosity is 2 or higher.
2233  */
2234  if(1 < m_Verbose)
2235  {
2236  printf("\n===================================\n");
2237  printf("INFO: Message received\n");
2238  printXMLMessage(pMessage);
2239  }
2240 
2241  return pMessage;
2242 }
2243 
2244 
2262 int
2263 CMyApplication::sendMessage (
2264  CMessage * pSendMsg)
2265 {
2266  CConnection * pConn = m_pConnectionToReader;
2267 
2268  /*
2269  * Print the XML text for the outbound message if
2270  * verbosity is 2 or higher.
2271  */
2272  if(1 < m_Verbose)
2273  {
2274  printf("\n===================================\n");
2275  printf("INFO: Sending\n");
2276  printXMLMessage(pSendMsg);
2277  }
2278 
2279  /*
2280  * If LLRP::CConnection::sendMessage() returns other than RC_OK
2281  * then there was an error. In that case we try to print
2282  * the error details.
2283  */
2284  if(RC_OK != pConn->sendMessage(pSendMsg))
2285  {
2286  const CErrorDetails * pError = pConn->getSendError();
2287 
2288  printf("ERROR: %s sendMessage failed, %s\n",
2289  pSendMsg->m_pType->m_pName,
2290  pError->m_pWhatStr ? pError->m_pWhatStr : "no reason given");
2291 
2292  if(NULL != pError->m_pRefType)
2293  {
2294  printf("ERROR: ... reference type %s\n",
2295  pError->m_pRefType->m_pName);
2296  }
2297 
2298  if(NULL != pError->m_pRefField)
2299  {
2300  printf("ERROR: ... reference field %s\n",
2301  pError->m_pRefField->m_pName);
2302  }
2303 
2304  return -1;
2305  }
2306 
2307  /*
2308  * Victory
2309  */
2310  return 0;
2311 }
2312 
2313 
2327 void
2328 CMyApplication::printXMLMessage (
2329  CMessage * pMessage)
2330 {
2331  char aBuf[100*1024];
2332 
2333  /*
2334  * Convert the message to an XML string.
2335  * This fills the buffer with either the XML string
2336  * or an error message. The return value could
2337  * be checked.
2338  */
2339 
2340  pMessage->toXMLString(aBuf, sizeof aBuf);
2341 
2342  /*
2343  * Print the XML Text to the standard output.
2344  */
2345  printf("%s", aBuf);
2346 }
llrp_utf8v_t getMessage(void)
Get accessor functions for the LLRP Message field.
void setRequestedData(EGetReaderConfigRequestedData value)
Set accessor functions for the LLRP RequestedData field.
void setROSpecID(llrp_u32_t value)
Set accessor functions for the LLRP ROSpecID field.
Class Definition CConnectionAttemptEvent for LLRP parameter ConnectionAttemptEvent.
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
std::list< CAntennaConfiguration * >::iterator beginAntennaConfiguration(void)
Returns the first element of the AntennaConfiguration sub-parameter list.
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
std::list< CTransmitPowerLevelTableEntry * >::iterator endTransmitPowerLevelTableEntry(void)
Returns the last element of the TransmitPowerLevelTableEntry sub-parameter list.
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...
Class Definition CTransmitPowerLevelTableEntry for LLRP parameter TransmitPowerLevelTableEntry.
std::list< CAntennaConfiguration * >::iterator endAntennaConfiguration(void)
Returns the last element of the AntennaConfiguration sub-parameter list.
void setDurationTrigger(llrp_u32_t value)
Set accessor functions for the LLRP DurationTrigger field.
Class Definition CSTART_ROSPEC_RESPONSE for LLRP message START_ROSPEC_RESPONSE.
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.
const CTypeDescriptor * m_pRefType
If non-NULL this is the type descriptors for the errored type.
Definition: ltkcpp_base.h:639
Class Definition CRegulatoryCapabilities for LLRP parameter RegulatoryCapabilities.
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.
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.
void setROSpecID(llrp_u32_t value)
Set accessor functions for the LLRP ROSpecID field.
llrp_u16_t getChannelIndex(void)
Get accessor functions for the LLRP ChannelIndex field.
EStatusCode getStatusCode(void)
Get accessor functions for the LLRP StatusCode field.
void setRequestedData(EGetReaderCapabilitiesRequestedData value)
Set accessor functions for the LLRP RequestedData field.
Class Definition CGET_READER_CONFIG for LLRP message GET_READER_CONFIG.
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.
CGeneralDeviceCapabilities * getGeneralDeviceCapabilities(void)
Get accessor functions for the LLRP GeneralDeviceCapabilities sub-parameter.
Class Definition CROSpecStartTrigger for LLRP parameter ROSpecStartTrigger.
llrp_s16_t getTransmitPowerValue(void)
Get accessor functions for the LLRP TransmitPowerValue field.
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.
std::list< CAntennaConfiguration * >::iterator endAntennaConfiguration(void)
Returns the last element of the AntennaConfiguration sub-parameter list.
EResultCode setROBoundarySpec(CROBoundarySpec *pValue)
Set accessor functions for the LLRP ROBoundarySpec sub-parameter.
Class Definition CRO_ACCESS_REPORT for LLRP message RO_ACCESS_REPORT.
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.
CUHFBandCapabilities * getUHFBandCapabilities(void)
Get accessor functions for the LLRP UHFBandCapabilities sub-parameter.
Class Definition CInventoryParameterSpec for LLRP parameter InventoryParameterSpec.
Class Definition CSET_READER_CONFIG_RESPONSE for LLRP message SET_READER_CONFIG_RESPONSE.
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
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.
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.
Class Definition CUHFBandCapabilities for LLRP parameter UHFBandCapabilities.
EResultCode setAISpecStopTrigger(CAISpecStopTrigger *pValue)
Set accessor functions for the LLRP AISpecStopTrigger sub-parameter.
File that includes all Impinj Custom extension classes and types.
void setROSpecStartTriggerType(EROSpecStartTriggerType value)
Set accessor functions for the LLRP ROSpecStartTriggerType 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.
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
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
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
llrp_u32_t getModelName(void)
Get accessor functions for the LLRP ModelName field.
llrp_u16_t getIndex(void)
Get accessor functions for the LLRP Index field.
void setProtocolID(EAirProtocols value)
Set accessor functions for the LLRP ProtocolID 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 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 CADD_ROSPEC for LLRP message ADD_ROSPEC.
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 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
Base Class for All LLRP LTK Parameters.
Definition: ltkcpp_base.h:1125
Base Class for All LLRP LTK Messages.
Definition: ltkcpp_base.h:1088
CLLRPStatus * getLLRPStatus(void)
Get accessor functions for the LLRP LLRPStatus sub-parameter.
Class Definition CADD_ROSPEC_RESPONSE for LLRP message ADD_ROSPEC_RESPONSE.
Class Definition CAISpecStopTrigger for LLRP parameter AISpecStopTrigger.
const char * getConnectError(void)
Get the string that explains openReaderConnection() error.
void setROSpecID(llrp_u32_t value)
Set accessor functions for the LLRP ROSpecID 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.
llrp_u16_t getHopTableID(void)
Get accessor functions for the LLRP HopTableID field.
Definition: ltkcpp.h:45
EResultCode setROSpecStartTrigger(CROSpecStartTrigger *pValue)
Set accessor functions for the LLRP ROSpecStartTrigger sub-parameter.
Class Definition CGET_READER_CONFIG_RESPONSE for LLRP message GET_READER_CONFIG_RESPONSE.
CRegulatoryCapabilities * getRegulatoryCapabilities(void)
Get accessor functions for the LLRP RegulatoryCapabilities sub-parameter.
std::list< CAntennaConfiguration * >::iterator beginAntennaConfiguration(void)
Returns the first element of the AntennaConfiguration sub-parameter list.
Class Definition CGET_READER_CAPABILITIES_RESPONSE for LLRP message GET_READER_CAPABILITIES_RESPONSE...
llrp_utf8v_t getErrorDescription(void)
Get accessor functions for the LLRP ErrorDescription 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.
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.