![]() |
RFID API Documentation
1.0
Reference guide for RFID API
|
The programmer's guide is divided into two parts:
The first part pertains to the Generic Reader Interface which covers the API and Usage supported by the reader. This interface is used for routine operations like Reading Tags (Inventory), Programming Tags (Tag Access Operations like Read, Write, Lock, Kill) and configuring the Reader.
The second part pertains to the Reader Management Interface which is used for managing the Reader (Software Update, Reset, Using Config Files, etc).
This section provides detailed information on how to develop RFID applications using RFID API generic interface. RFID API allows applications to talk to RFID Readers which support the LLRP Interface. LLRP is a standard specification for the network interface between the reader and its controlling software or hardware.
To develop applications using RFID API follow the steps beneath:
In general, if the function call succeeds, the function returns RFID_API_SUCCESS else it returns with specific Error code. The RFID_GetErrorDescription functions gets the error description string for the given status code. The RFID_GetLastErrorInfo can be called to find out the error information of the last called function. This function contains timestamp of the error, error description and additional vendor specific error messages if available.
This is the first step to talk to an RFID Reader over the Generic Reader Interface. An application must first acquire a Handle of type RFID_HANDLE32 to the RFID Reader by a call to RFID_Connect or RFID_AcceptConnection. A valid handle will be returned to the application if the function returns RFID_API_SUCCESS. The application can use this handle for all other functions.
The RFID_Connect function is to be used when the RFID Reader is configured in LLRP Server Mode. This function takes the hostname or IP address of the RFID-Reader to connect to, the port number and the response timeout. While connecting on Hand-Held or Device-based Readers, hostname shall be given as "NULL" or "localhost" or "127.0.0.1" so as to connect to the Reader within the device. For Host-based readers, hostname shall be the IP address of the RFID Reader.
The RFID_AcceptConnection function is to be used when the RFID Reader is configured in LLRP Client mode. The application shall create a socket using the win32 API, socket and listen and wait for incoming connection using the win32 API accept, the return value of which shall be passed as socket-handle to RFID_AcceptConnection API. The accept API returns when the connection is initiated from the RFID Reader.
The default LLRP port number is 5084 and the default response timeout is 5 seconds. Specifying zero for port number and timeout uses default values.
The timeout value is also used for configuring the Keep-Alive mechanism which helps in determining if the connection to the reader is alive or not. If the connection to the reader was inactive (i.e. no keep-alive message from the Reader) for a time greater than 10 times the timeout, DISCONNECTION_EVENT will be triggered to the application if the application has registered for the same.
Secure LLRP mode allows encrypted and optionally authenticated connection to use LLRP service on the reader using SSL/TLS. Please refer "Configure LLRP Settings" and "Certificates" chapter in Reader Integrator Guide for configuring reader in Secure LLRP mode.
RFID API can internally manage secure connection to LLRP service and clients using RFID API can enable secure connection by setting options in SEC_CONNECTION_INFO parameter of CONNECTION_INFO (or SERVER_INFO in case of server mode) parameter to RFID_Connect (or RFID_AcceptConnection call in case of server mode).
Please refer Reader Integrator Guide for documentation on generation of certificates for reader as well as client use.
The example below illustrates use of SEC_CONNECTION_INFO parameter in RFID_Connect to establish a secure to connection to a reader which is configured to operate in Secure LLRP mode.
#ifdef APP_HAS_OPENSSL_HEADERS
#include <openssl/err.h>
#endif
#define MAX_CERT_KEY_FILE_SIZE 4096
RFID_HANDLE32 readerHandle;
CONNECTION_INFO connInfo;
SEC_CONNECTION_INFO secConnInfoExt;
RFID_STATUS rfidStatus = RFID_API_SUCCESS;
BYTE g_clientCertContent[MAX_CERT_KEY_FILE_SIZE];
UINT32 clientCertSize = 0;
BYTE g_clientKeyContent[MAX_CERT_KEY_FILE_SIZE];
UINT32 clientKeySize = 0;
BYTE g_rootCertContent[MAX_CERT_KEY_FILE_SIZE];
UINT32 rootCertSize = 0;
BYTE g_password[MAX_PATH] = {0};
/* Read client certificate, client's private key file and root CA certificate file */
GetFileContent("client_crt.pem", &g_clientCertContent, &clientCertSize);
GetFileContent("client_key.pem", &g_clientKeyContent, &clientKeySize);
GetFileContent("cacert.pem", &g_rootCertContent, &rootCertSize);
/* Specify password for private key, if its encrypted (else should be null) */
strcpy(g_password, "abcd12345");
/* Setup secure connection info parameter */
secConnInfoExt.secureMode = true;
secConnInfoExt.validatePeerCert = false; // If true, make sure reader is updated
// with reader's certificate issued by
// the same CA that issued to this client
// (see Integrator Guide, "Certificates" chapter)
secConnInfoExt.sizeCertBuff = clientCertSize;
secConnInfoExt.clientCertBuff = g_clientCertContent;
secConnInfoExt.sizeKeyBuff = clientKeySize;
secConnInfoExt.clientKeyBuff = g_clientKeyContent;
secConnInfoExt.sizeRootCertBuff = rootCertSize;
secConnInfoExt.rootCertBuff = g_rootCertContent;
secConnInfoExt.sizePhraseBuff = strlen(g_password);
/* Setup connection info parameter */
connInfo.version = RFID_API3_5_5;
connInfo.lpSecConInfo = &secConnInfoExt;
EstablishSecureConnection()
{
rfidStatus = RFID_Connect(&readerHandle, TEXT("FX7500ABCDEF"), 0, 0, &connInfo);
if(RFID_API_SUCCESS == rfidStatus)
{
// Success... Use readerHandle for other API calls
// ...
// Disconnect after use
rfidStatus = RFID_Disconnect(readerHandle);
}
else
{
// Failed connection.
if (RFID_SECURE_CONNECTION_ERROR == rfidStatus)
{
// Show error
#ifdef APP_HAS_OPENSSL_HEADERS
char errStr[1024];
ERR_error_string(pSecConInfo->connStatus, errStr);
printf("Secure connection error. Error string: %d\n", errStr);
#else
printf("Secure connection error. Code: %d\n", secConnInfoExt.connStatus);
#endif
}
}
}
int GetFileContent(char* filePath, BYTE *pBuffer, int *pLen)
{
FILE * pFile;
size_t result;
File = fopen ( filePath , "r" );
if (pFile==NULL) return 0;
// obtain file size:
seek (pFile , 0 , SEEK_END);
pLen = ftell (pFile);
rewind (pFile);
// copy the file into the buffer:
result = fread (pBuffer, 1, *pLen, pFile);
pLen = result;
/* the whole file is now loaded in the memory buffer. */
// terminate
fclose (pFile);
return *pLen;
}
As new features are developed, reserved fields of existing structures are expanded. So as to ensure backward compatibility, the expanded reserved would not be used for applications compiled using older Dll versions. Applications that require using the new features shall mention the Dll version RFID_VERSION which is being used as part of CONNECTION_INFO or SERVER_INFO for the APIs RFID_Connect and RFID_AcceptConnection respectively.
Please note that when applications upgrade to higher version, it should ensure that those reserved fields in the data structures which have been expanded for use, shall be either NULL or a valid value so as to avoid exceptions due to accessing uninitialized memory.
List of versions versus the features supported
1.RFID_API3_5_0 - This is the basic version of RFID API3, and the Dll defaults to this version RFID_Connect is called with the last parameter LPCONNECTION_INFO as NULL.
2.RFID_API3_5_1 - Dll versions of 5.1.XXX supports the following additional features.
a. Generic Interface
Tag Event Reporting - TAG_EVENT_REPORT_INFO in TRIGGER_INFO
RSSI Filtering - RSSI_RANGE_FILTER in POST_FILTER and ACCESS_FILTER
NXP Tag Support
- RFID_NXPSetEAS
- RFID_NXPReadProtect
- RFID_NXPResetReadProtect
- RFID_PerformNXPEASScan
- RFID_StopNXPEASScan
- RFID_PerformInventory with NXP_EAS_SCAN
Selecting Tag Fields that is to be reported in TAG_DATA - tagFields in TAG_STORAGE_SETTINGS
Enabling Access reports (disabled by default) - enableAccessReports in TAG_STORAGE_SETTINGS
Reader Exception Event (READER_EXCEPTION_EVENT_DATA)
Truncate Action in Prefilters - TRUNCATE_ACTION in PRE_FILTER
Write Access operation to write to specific fields
b. RM Interface
RFID_GetReaderStats and RFID_ClearReaderStats.
Force login option in fixed readers
RFID_SetActiveProfile and RFID_DeleteProfile
Push model of Software Update in fixed readers
RFID_GetReaderInfo and RFID_SetReaderInfo
RFID_GetTimeZoneList and RFID_SetTimeZone
RFID_GetLocalTime and RFID_SetLocalTime
RFID_GetLLRPConnectionConfig, RFID_SetLLRPConnectionConfig, RFID_InitiateLLRPConnectionFromReader and RFID_DisconnectLLRPConnectionFromReader
3.RFID_API3_5_5 - Dll versions of 5.5.XXX supports the following additional features
a. Generic Interface
Set/Get Global Antenna Configuration
Call back Mechanism for reporting events
New Event added in RFID_EVENT_TYPE
- TEMPERATURE_ALARM_EVENT
- SLED_DISCONNECT_EVENT
- SLED_CONNECT_EVENT
New Enum added
Periodic Tag Report Duration
TAG_DATA is extended to report phaseInfo
Save LLRP Configuration
b. RM Interface
Idle Mode
User App Deployment
- RFID_InstallUserApp
- RFID_UninstallUserApp
- RFID_StartUserApp
- RFID_StopUserApp
- RFID_GetCurrentUserAppRunStatus
- RFID_ListUserApps
- RFID_SetUserAppAutoStart
Cable Loss Compensation
Region Configuration
- RFID_GetSupportedRegionList
- RFID_GetRegionStandardList
- RFID_SetActiveRegion
- RFID_SetFrequencySetting
- RFID_GetActiveRegionInfo
- RFID_GetActiveRegionStandardInfo
Power Negotiation
- RFID_GetPowerNegotiationState
- RFID_SetPowerNegotiationState
- RFID_GetPowerNegotiationStatus
- New Enum powersource added in READER_SYSTEM_INFO
User Management
4.RFID_API3_5_6 - Dll versions of 5.6.XXX supports the following additional features:
a. Generic Interface
NXP
Impinj
Tag Storage
RF Survey
b. RM Interface
Antenna Configuration
LLRP Config
Reader Config
Network
The capabilities (or Read-Only properties) of the Reader can be known using RFID_GetReaderCaps. The reader capabilities include the following:
General Capabilities
- Firmware Version
- Model Name
- Number of antennas supported
- Number of GPIs & GPOs
- UTC Clock supported
- Receive Sensitivity Table
- Tag Event Reporting Supported - Indicates the reader's ability to report tag visibility state changes(New Tag, Tag Invisible, or Tag Visibility Changed)
- RSSI Filter Supported - Indicates the reader's ability to report tags based on the signal strength of the back-scattered signal from the tag.
- NXP Commands Supported - Indicates whether the reader supports NXP commands like Change EAS,set Quiet, Reset Quiet,Calibrate
- Tag Locationing Supported - Indicates whether the reader supports Tag Locationing.
- Duty Cycle Table - if Reader supports setting of Duty Cycle from a list of values as indicated in this table.
Gen2 LLRP Capabilities
- Block Erase supported
- Block Write supported
- State Aware Singulation supported
- Maximum Number of Operation in Access Sequence
- Maximum Pre-filters allowable per antenna
- RF Modes
Regulatory Capabilities
- Country Code
- Communication Standard
UHF Band capabilities
- Transmit Power table
- Hopping enabled
- Frequency Hop table if hopping enabled, this table has the frequency information
- Fixed Frequency table if hopping not enabled, this table contains the frequency list used by the reader.The one-based position of a frequency in this list is its channel index.
The function RFID_ResetConfigToFactoryDefaults informs the reader to set all configurable values to factory defaults.
GPI (General Purpose Input) Port
The function RFID_GetGPIState is used to get the current configuration and state of the specified port number. The RFID_EnableGPIPort function enables the specified port number.It is possible to register for GPI Port state change notification. Before registering, the interested port must be enabled using this RFID_EnableGPIPort.
GPO (General Purpose Output) Port
The function RFID_GetGPOState gets the current state of the specified output port number.To change the state of the specified port, the RFID_SetGPOState can be used.
This is applicable only for hand held readers and FX7500. The function RFID_GetRadioPowerState gets the current power state of the RFID Radio Module whether it is turned ON or OFF. To modify the radio power state, the function RFID_SetRadioPowerState can be used.
This is applicable only for hand held readers. The function RFID_GetReaderCaps can be used to get the list of Duty Cycles supported by the reader in DUTY_CYCLE_TABLE.
The function RFID_GetReaderCaps helps to get the transmit power table. This table contains the list of transmit power level supported by the reader. To set appropriate transmit power level, find the power level at appropriate index from the Transmit Power Table and pass the index to the RFID_SetAntennaConfig API for corresponding antenna. The RFID_GetAntennaConfig gets the index of the transmit power level set.
Configuration
The function RFID_SetAntennaConfig is used to set the antenna configuration to individual antenna or all the antennas.
The antenna configuration comprises of Antenna ID, Receive Sensitivity Index, Transmit Power index, Transmit Frequency Index. These indexes are refers to the Receive Sensitivity table, Transmit Power table, Frequency Hop table or Fixed Frequency table respectively. These tables are available in Reader capabilities. If the antenna ID is specified by Zero (0), the configuration is applied to all the available antennas.
RF Configuration
The function RFID_SetAntennaRfConfig is added to configure antenna RF configuration to individual antenna or all the antennas. This function is similar like RFID_SetAntennaConfig but includes additional parameters specific pertaining to antenna.
The configuration includes Receive Sensitivity Index, Transmit Power index, Transmit Frequency Index, RF Mode Table index. These indexes are refers to the Receive Sensitivity table, Transmit Power table, Frequency Hop table or Fixed Frequency table, RF Mode table respectively. These tables are available in Reader capabilities. Also, includes tari, transmit port, receive port and Antenna Stop trigger condition. The stop condition can be 'n' number of attempts, duration based.
If the antenna ID is specified by Zero (0), the configuration is applied to all the available antennas.
Properties
The physical antenna properties of the individual antenna can be known by calling the function RFID_GetPhysicalAntennaProperties. The function gets the gain and the connectivity status of the specified antenna.
Singulation Control
The function RFID_GetSingulationControl retrieves the current settings of the singulation control from the reader for the given Antenna ID.
To set the singulation control settings, the RFID_SetSingulationControl function will be used. The following settings can be configured:
- Session: Session number to use for inventory operation
- Tag Population: An estimate of the tag population in view of the RF field of the antenna
- Tag Transit Time: An estimate of the time a tag will typically remain in the RF field
- State Aware singulation Action:The action includes the Inventory state and SL flag. The action can be used if only reader supports this capability. The function RFID_GetReaderCaps helps to determine whether state-aware singulation is supported or not.
This function allows setting to individual antenna or all the antennas by specifying the antenna ID as Zero (0).
RF Mode
The reader has one or more set of C1G2 RF mode that the reader is capable of operating. The supported RF mode can be retrieved from RF Mode table using RFID_GetReaderCaps function.
The function RFID_GetRFMode gets the current index to RF Mode table and the Tari from the reader. RFID_SetRFMode function shall be used to change the RF Mode settings in the reader.
The function RFID_GetSaveLlrpConfigStatus gets the current saved status of LLRP configurations. The RFID_SaveLlrpConfig function shall be used to save the LLRP configuration in the reader.
The Application can register for one or more events of the enumeration RFID_EVENT_TYPE so as to be notified of the same when it occurs:
| Events | Description |
|---|---|
| GPI_EVENT | A GPI event (state change from high to low, or low to high) has occurred on a GPI port. When this event is signaled, RFID_GetEventData can be called to know the GPI port and the event that has occurred. The Dll can store a maximum of 2000 GPI_EVENT_DATA, which if not retrieved using RFID_GetEventData, results in dropping of further events. |
| TAG_DATA_EVENT | Tag(s) are available for the Application to read. When this event is signaled RFID_GetReadTag can be called till all Tags are read from the Dll's Queue. The Dll can store a maximum of 4096 TAG_DATA by default, which if not retrieved using RFID_GetEventData, results in dropping of further events. The maximum Tag Storage count can be altered using the function RFID_SetTagStorageSettings. |
| BUFFER_FULL_WARNING_EVENT | When the internal buffers are 90% full, this event will be signaled. |
| ANTENNA_EVENT | A particular Antenna has been Connected/Disconnected. When this event is signaled, RFID_GetEventData can be called to know the Antenna and the Connection Status that has occurred. The Dll can store a maximum of 2000 ANTENNA_EVENT_DATA, which if not retrieved using RFID_GetEventData, results in dropping of further events. |
| INVENTORY_START_EVENT | Inventory Operation has started. In case of periodic trigger this event will be triggered for each period. |
| INVENTORY_STOP_EVENT | Inventory Operation has stopped. In case of periodic trigger this event will be triggered for each period. |
| ACCESS_START_EVENT | Access Operation has started. |
| ACCESS_STOP_EVENT | Access Operation has stopped. |
| DISCONNECTION_EVENT | Event notifying disconnection from the Reader. When this event is signaled, RFID_GetEventData can be called to know the reason for the disconnection. The Application can call RFID_Reconnect periodically to attempt re-connection or call RFID_Disconnect to cleanup and exit. |
| BUFFER_FULL_EVENT | When the internal buffers are 100% full, this event will be signaled and tags are discarded in FIFO manner. |
| NXP_EAS_ALARM_EVENT | This Event is generated when Reader finds a(NXP)tag with it's EAS System bit still set to true. |
| READER_EXCEPTION_EVENT | Event notifying that an exception has occured in the Reader. When this event is signaled, RFID_GetEventData can be called to know the reason for the exception. The Application can continue to use the connection if the reader renders is usable. |
| TEMPERATURE_ALARM_EVENT | When Temperature reaches Threshold level, this will be generated. RFID_GetEventData can be called to get the event details like source name (PA/Ambient), current Temperature and alarm Level (Low, High or Critical) |
The Application can use either win32 event based mechanism or call back mechanism to register for event notification.
Win32 Event Mechanism
The following steps have to be followed for getting event notifications:
1. The Application shall create an Event using the WIN32 API CreateEvent and pass it as the parameter for RFID_RegisterEventNotification. HANDLE hTagArrived = CreateEvent(NULL, FALSE, FALSE, NULL); rfidStatus = RFID_RegisterEventNotification(readerHandle, TAG_DATA_EVENT, hTagArrived); // Perform operations and wait for the Event to be signaled 2. Wait for the event to be notified or signaled. WaitForSingleObject(hTagArrived, INFINITE); 3. When the event is signaled, the Application shall call the function RFID_GetEventData to fetch the data associated with the respective event. 4. For de-registering an event, the Application shall call RFID_DeregisterEventNotification and close the event handle as follows: rfidStatus = RFID_DeregisterEventNotification(readerHandle, TAG_DATA_EVENT); CloseHandle(hTagArrived);
Call back Mechanism
This section describes new API that enable a Linux user to manage RFID events using a mechanism native to Linux, which is a Callback function.
The user can register a callback function for all the events he is interested in using the new API RFID_RegisterEventNotificationCallback.
1. Registering Event:
The application shall register the call back function along with interested events.
The call back function will be invoked when the event is raised.
RFID_EVENT_TYPE rfidEvents[12] =
{
GPI_EVENT, TAG_READ_EVENT, BUFFER_FULL_EVENT, BUFFER_FULL_WARNING_EVENT,ANTENNA_EVENT, DISCONNECTION_EVENT,
INVENTORY_START_EVENT, INVENTORY_STOP_EVENT, ACCESS_START_EVENT, ACCESS_STOP_EVENT, READER_EXCEPTION_EVENT
};
rfidStatus = RFID_RegisterEventNotificationCallback (readerHandle, rfidEvents, 12, (RfidEventCallbackFunction) rfidEventCallback, NULL, NULL);
2. De-register Event
The application shall call RFID_RegisterEventNotificationCallback with parameter pFnRfidEventCallbackFunction as NULL to de-register.
Call back Mechanism and win32 Event based event handlings are mutually exclusive. Hence application shall stick to one mechanism and not attempt combination of two event handling mechanisms.
Application needs to get the Tags from the Dll which are reported by Reader. Tags can be reported as part of an Inventory operation RFID_PerformInventory or a Read Access operation RFID_Read.
Starting from version RFID_API3_5_1 onwards, applications can configure to receive Tag reports that indicate the results of access operations as shown beneath.
TAG_STORAGE_SETTINGS tagStorageSettings; RFID_GetTagStorageSettings(readerHandle,&tagStorageSettings); tagStorageSettings.enableAccessReports = true; RFID_SetTagStorageSettings(readerHandle,&tagStorageSettings);
Each Tag has a set of associated information along with it. During Inventory operation the Reader reports the EPC-ID of the Tag, where as during Read-Access operation the requested Memory Bank Data is also reported apart from EPC-ID. In either case, there is additional information like PC-bits, RSSI, last time seen, tag seen count, etc that will be available for each Tag. This information is reported to the Application as TAG_DATA for each Tag reported by the Reader.
Applications can also choose to enable/disable reporting of certain fields in TAG_DATA. Disabling certain fields can sometimes improve the performance as the Reader and the Dll shall not be processing that information. It can also result in specific behavior. For e.g. disabling reporting of Antenna Id can result in application receiving as single unique tag even though they were multiple entries of the same tag reported from different Antennas. The following snippet shows enabling the reporting of PeakRSSI, Tag Seen count, PC and CRC only and disabling other fields like Antenna ID, time stamps and XPC.
TAG_STORAGE_SETTINGS tagStorageSettings; RFID_GetTagStorageSettings(readerHandle,&tagStorageSettings); tagStorageSettings.tagFields = (UINT16)(PEAK_RSSI | TAG_SEEN_COUNT | PC |CRC); RFID_SetTagStorageSettings(readerHandle,&tagStorageSettings);
Before the application can start getting/reading tags it has to allocate and initialize the memory for the Tag (EPC-ID and Memory-Bank) using the function RFID_AllocateTag. The Application can specify its customized memory bank data size using the function RFID_SetTagStorageSettings. The Application shall initialize the tag storage settings prior to allocating memory for TAG_DATA so that all Tag allocations reflect the applications customized memory requirement.
TAG_STORAGE_SETTINGS tagStorageSettings; LPTAG_DATA pTagData; tagStorageSettings.maxMemoryBankByteCount = 32; // for 256 bit Memory Bank Data tagStorageSettings.maxTagCount = 100; tagStorageSettings.maxTagIdByteCount = 12; // Default 96 bit EPC-Id rfidStatus = RFID_SetTagStorageSettings(readerHandle, &tagStorageSettings); pTagData = RFID_AllocateTag(readerHandle);
The applications can purge all tags present in Dll and Reader queues using the API RFID_PurgeTags.
Inventory operation: When RFID_PerformInventory is invoked, the application will get notified of TAG_DATA_EVENT if tags are reported back from the Reader. When notified of the same, application can call RFID_GetReadTag to fetch tags from the Dll one by one. The TAG_DATA will contain the EPC-ID (pTagID) and other information related to the tag; Being reported as part of an inventory operation, TAG_DATA's opCode will be ACCESS_OPERATION_NONE and opStatus to be ignored.
rfidStatus = RFID_PerformInventory(readerHandle, NULL, NULL, NULL, NULL);
// Lets wait for 3 seconds to see if a Tag arrives
if(WaitForSingleObject(hTagArrived, 3000) == WAIT_OBJECT_0)
{
// You can read Tag using RFID_GetEventData
while(RFID_API_SUCCESS == RFID_GetEventData(readerHandle, TAG_DATA_EVENT, pTagData))
printTagData(pTagData->pTagID, pTagData->tagIDLength);
}
rfidStatus = RFID_StopInventory(readerHandle);
Single Tag - Read Access: When the application calls the function RFID_Read to read data from a specific memory bank of a particular tag, the function returns the TAG_DATA as its out-parameter shown beneath. The TAG_DATA will contain the EPC-ID (pTagID) and its opStatus will indicate the status of Access operation; Access Operation for which the TAG_DATA pertains to is indicated by the opCode [ACCESS_OPERATION_READ for Read Access]. If opStatus is ACCESS_SUCCESS pMemoryBankData will have valid data, which is the requested Memory Bank data.
// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D};
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
READ_ACCESS_PARAMS readAccessParams;
LPTAG_DATA pTagData;
readAccessParams.accessPassword = 0; // Access Password for this memory bank is zero
readAccessParams.memoryBank = MEMORY_BANK_USER; // Read from User memory bank
readAccessParams.byteCount = 64; // Read 64 Bytes
readAccessParams.byteOffset = 0; // Start reading from Offset 0
pTagData = RFID_AllocateTag(readerHandle);
rfidStatus = RFID_Read(readerHandle, specificTag, specificTagIdLength, &readAccessParams, NULL, NULL, pTagData, NULL);
Multiple Tags : Read Access: When the application calls the function RFID_Read to read data from a specific memory bank of multiple tags, the function RFID_Read returns immediately, and reports the Tags asynchronously as done in Inventory operation. The TAG_DATA reported will contain the EPC-ID (pTagID) and its opStatus will indicate the status of Access operation [opCode will be ACCESS_OPERATION_READ for Read Access]. If opStatus is ACCESS_SUCCESS pMemoryBankData will have valid data, which is the requested Memory Bank data.
rfidStatus = RFID_Read(readerHandle, NULL, 0, &readAccessParams, NULL, NULL, NULL, NULL);
WaitForSingleObject(accessComplete, INFINITE);
// Fetch the tags
while(RFID_API_SUCCESS == RFID_GetReadTag(readerHandle, pTagData))
{
If(pTagData->opStatus == ACCESS_SUCCESS)
{
// print the Tag ID and Memory Bank
}
}
Access Operation Sequence : Read Access: When the application calls the function RFID_PerformAccessSequence further to adding operations for Read (using RFID_AddOperationToAccessSequence of type ACCESS_OPERATION_READ), the function RFID_PerformAccessSequence returns immediately, and reports tags asynchronously, as shown in use-case no 3.
It depends on the Application requirement to determine how many TAG_DATA needs to be allocated. A typical example of a simple UI application that just displays a list of inventoried tags would allocate one TAG_DATA and use it repeatedly in further calls to RFID_GetReadTag.
When the application is done with using the TAG_DATA allocated using RFID_AllocateTag, it shall call RFID_DeallocateTag. The Application shall not deallocate the TAG_DATA or its internal members (pTagID, pMemoryBankData) by itself, doing which shall result in unexpected behavior.
This section covers the basic/simple operations that an application would need to be performed on an RFID Reader which includes Inventory and single tag access operations.
A simple continuous inventory operation would read all tags in the field of view of all antennas of the connected RFID Reader. It will use NO filters (pre-filters or post-filters) and the start and stop trigger for the inventory would be default, i.e. start immediately when RFID_PerformInventory is called, and stop immediately when RFID_StopInventory is called.
rfidStatus = RFID_PerformInventory(readerHandle, NULL, NULL, NULL, NULL); // Wait as long as needed to perform a continuous inventory. // Keep getting tags using RFID_GetReadTag when TAG_DATA_EVENT is signaled. // getting Tags can also be done on a separate Read-Thread rfidStatus = RFID_StopInventory(readerHandle);
Tag Access operations can be performed on a specific tag or can be applied on tags that match a specific Access-Filter. If no Access-filter is specified the Access Operation will be performed on all Tags in the field of view of chosen Antennas.
This section covers simple tag access operation on a specific tag which could be in the field of view of any of the antenna of the connected RFID Reader.
Read
The application can call RFID_Read to read data from a specific memory bank.
// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D};
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
READ_ACCESS_PARAMS readAccessParams;
LPTAG_DATA pTagData;
readAccessParams.accessPassword = 0; // Access Password for accessing this memory bank is zero
readAccessParams.memoryBank = MEMORY_BANK_USER; // Read from User memory bank
readAccessParams.byteCount = 64; // Read 64 Bytes
readAccessParams.byteOffset = 0; // Start reading from Offset 0
pTagData = RFID_AllocateTag(readerHandle);
rfidStatus = RFID_Read(readerHandle, specificTag, specificTagIdLength, &readAccessParams, NULL, NULL, pTagData, NULL);
Write, Block-Write
The application can call RFID_Write or RFID_BlockWrite to write data to a specific memory bank.
// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D};
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
WRITE_ACCESS_PARAMS writeAccessParams;
UINT8 writeUserData[64];
writeAccessParams.accessPassword = 0; // Access Password for accessing this memory bank is zero
writeAccessParams.memoryBank = MEMORY_BANK_USER; // Write to User memory bank
writeAccessParams.byteOffset = 0; // Start writing from Offset 0
writeAccessParams.writeDataLength = 64; // Write 64 Bytes
//Fill in the Data to be written into writeUserData
writeAccessParams.pWriteData = writeUserData;
rfidStatus = RFID_Write(readerHandle, specificTag, specificTagIdLength, &writeAccessParams, NULL, NULL, NULL);
Lock
The application can call RFID_Lock to perform lock operation on one or more memory banks with specific privileges.
// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D};
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
LOCK_ACCESS_PARAMS lockAccessParams;
lockAccessParams.accessPassword = 0xAAAAAAAA; // Access Password to be applied.
lockAccessParams.privilege[LOCK_USER_MEMORY] = LOCK_PRIVILEGE_READ_WRITE;
lockAccessParams.privilege[LOCK_TID_MEMORY] = LOCK_PRIVILEGE_READ_WRITE;
rfidStatus = RFID_Lock(readerHandle, specificTag, specificTagIdLength, &lockAccessParams, &accessFilter, NULL, NULL);
Kill
The application can call RFID_Kill to kill a tag.
// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D};
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
KILL_ACCESS_PARAMS killAccessParams;
killAccessParams.killPassword = 0xAAAAAAAA;
rfidStatus = RFID_Kill(readerHandle, specificTag, specificTagIdLength,&killAccessParams, NULL, NULL, NULL);
Block-Erase
The application can call RFID_BlockErase to erase the contents of a tag.
// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D};
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
BLOCK_ERASE_ACCESS_PARAMS blockEraseAccessParams;
blockEraseAccessParams.accessPassword = 0;
blockEraseAccessParams.memoryBank = MEMORY_BANK_USER;
blockEraseAccessParams.byteCount = 100; // Number of bytes to be erased
blockEraseAccessParams.byteOffset = 0; // Start erasing from Offset 0
rfidStatus = RFID_BlockErase(readerHandle, specificTag, specificTagIdLength,&blockEraseAccessParams, NULL, NULL, NULL);
Block-Permalock
The application can call RFID_BlockPermalock to block permalock the contents of a tag. The TAG_DATA will contain the EPC-ID (pTagID) and its opStatus will indicate the status of Access operation; Access Operation for which the TAG_DATA pertains to is indicated by the opCode [ACCESS_OPERATION_BLOCK_PERMALOCK for BlockPermalock Access]. If opStatus is ACCESS_SUCCESS pMemoryBankData will have valid data, which is the Block-Permalock Mask Data.
// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D};
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
UINT8 lockMask[4] = {0xF0, 0x00, 0x00, 0x00};
BLOCK_PERMALOCK_ACCESS_PARAMS Block-PermalockAccessParams;
Block-PermalockAccessParams.accessPassword = 0xAAAAAAAA; // Access Password
Block-PermalockAccessParams.readLock = TRUE;
Block-PermalockAccessParams.memoryBank = MEMORY_BANK_USER
Block-PermalockAccessParams.byteOffset = 0;
Block-PermalockAccessParams.byteCount = 4;
Block-PermalockAccessParams.mask = lockMask;
Block-PermalockAccessParams.maskLength = 4;
rfidStatus = RFID_Block-Permalock(readerHandle, specificTag, specificTagIdLength, &Block-PermalockAccessParams, NULL, NULL, NULL, NULL);
Access Operations on specific memory field of Single Tag
The following functions are wrappers around RFID_Write API and assists in writing to specific memory fields of a specific Tag.
- RFID_WriteTagID - This function writes to TagID of a specific tag and adjusts the PC bits according to the length of the TagID. When the TagID is modified, this API ensures that the Tag shall subsequently backscatter the modified EPC, for which it also writes the length of the new or updated (PC + EPC) into the first 5 bits of the Tag's PC.
- RFID_WriteKillPassword - This function writes the kill password of a specific tag.
- RFID_WriteAccessPassword - This function writes the access password of the a specific tag.
This feature can be used to enable reporting tag visibility changes. If a reader supports this feature it reports the Reader Capability tagEventReportingSupported as true. The following code snippet enabled reporting tags when a Tag is visible/Gone out of Visibility/Back to visibility for at least 100 ms TRIGGER_INFO triggerInfo;
TAG_EVENT_REPORT_INFO tagEventReportInfo; triggerInfo.lpTagEventReportInfo = &tagEventReportInfo; triggerInfo.tagReportTrigger = 1; tagEventReportInfo.reportNewTagEvent = MODERATED; tagEventReportInfo.reportTagBackToVisibilityEvent = MODERATED; tagEventReportInfo.reportTagInvisibleEvent = MODERATED; tagEventReportInfo.newTagEventModeratedTimeoutMilliseconds = 100; tagEventReportInfo.tagBackToVisibilityModeratedTimeoutMilliseconds = 100; tagEventReportInfo.tagInvisibleEventModeratedTimeoutMilliseconds = 100; triggerInfo.startTrigger.type = START_TRIGGER_TYPE_IMMEDIATE; triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_IMMEDIATE; rfidStatus = RFID_PerformInventory(readerHandle, NULL, NULL, &triggerInfo, NULL);
TAG_EVENT reported as part of TAG_DATA indicates the visibility state of the Tag.
Pre-filters are same as the Select command of C1G2 specification. Once applied, pre-filters are applied prior to Inventory and Access operations.
Introduction
Singulation
Singulation refers to the method of identifying an individual Tag in a multiple-Tag environment. RFID Readers could support State-Aware or State-Unaware pre-filtering (or singulation) which is indicated by the boolean flag stateAwareSingulationSupported in the READER_CAPS and can be known using the function RFID_GetReaderCaps.
In order to filter tags that match a specific condition, it is necessary to use the tag-sessions and their states (setting the tags to different states based on match criteria- RFID_AddPreFilter) so that while performing inventory, tags can be instructed to participate (singulation - RFID_SetSingulationControl) or not participate in the inventory based on their states.
Sessions and Inventoried Flags
Tags provide 4 sessions (denoted S0, S1, S2, and S3) and maintain an independent inventoried flag for each session. Each of the four inventoried flags has two values, denoted A and B. These inventoried flag of each session can be set to A or B based on match criteria using function RFID_AddPreFilter.
Selected Flag
Tags provide a selected flag, SL, which can be asserted or deasserted based on match criteria using function RFID_AddPreFilter.
State-Unaware Singulation
In state-unaware singulation the Reader permits 6 options (as enumerated by STATE_UNAWARE_ACTION) of filtering tags. This is more simplified than state-aware singulation.
State-Aware Singulation
In state-aware singulation the Application can specify detailed controls for singulation: Action and Target. Action indicates whether matching Tags assert or deassert SL (Selected Flag), or set their inventoried flag to A or to B. Tags conforming to the match criteria specified using the function RFID_AddPreFilter are considered matching and the remaining are non-matching. Target indicates whether to modify a Tag's SL flag or its inventoried flag, and in the case of inventoried it further specifies one of four sessions.
Truncate Action
Truncate action specifies whether a Tag backscatters its entire EPC, or only that portion of the EPC immediately following Mask. During truncated replies a Tag substitutes 00000 for the PC bits. Truncated replies are always followed by the CRC-16 in EPC memory 00h to 0Fh; a Tag does not recompute this CRC for a truncated reply.
Applying Pre-Filters
The following are the steps to use pre-filters:
- Add pre-filters
- Set appropriate singulation controls
- Perform Inventory or Access operation
Add Pre-filters
Each RFID Reader supports a maximum number of Pre-Filters per Antenna as indicated by maxNumPreFilters in the READER_CAPS which can be known using the function RFID_GetReaderCaps. The application can set pre-filters using RFID_AddPreFilter and remove using RFID_DeletePreFilter. To set pre-filter for all antennas, use zero for antennaID.
State-Unaware Singulation
PRE_FILTER prefilter;
UINT8 tagMask[2] = {0x12, 0x11};
prefilter.filterAction = FILTER_ACTION_STATE_UNAWARE; // use state unaware singulation
//do not select tags that match the criteria in this pre-filter (Tags whose EPC-ID starts with 0x1211)
prefilter.filterActionParams.stateUnawareAction = STATE_UNAWARE_ACTION_UNSELECT;
prefilter.memoryBank = MEMORY_BANK_EPC;
prefilter.bitOffset = 32; // skip the PC bits
prefilter.tagPatternBitCount = 2 * 8;
prefilter.pTagPattern = tagMask; // Tags whose EPC-ID starts with 0x1211
//Set this filter for Antenna Number 3
rfidStatus = RFID_AddPreFilter(readerHandle, 3, &prefilter, &filterIndex); // filterIndex can be used later to Delete pre-filters
State-Aware Singulation
PRE_FILTER prefilter;
UINT8 tagMask[2] = {0x12, 0x11};
prefilter.filterAction = FILTER_ACTION_STATE_AWARE;
prefilter.filterActionParams.stateAwareParams.target = TARGET_INVENTORIED_STATE_S1;
prefilter.filterActionParams.stateAwareParams.stateAwareAction = STATE_AWARE_ACTION_INV_B;
// So as not to select tags that match the criteria in this pre-filter (Tags whose EPC-ID starts with 0x1211)
// lets put inventoried flag of session S1 of matching tags to B; We will also have to set appropriate singulation control
// not to get tags with inventoried flag B for session S1.
prefilter.memoryBank = MEMORY_BANK_EPC;
prefilter.bitOffset = 32; // skip the PC bits
prefilter.tagPatternBitCount = 2 * 8;
prefilter.pTagPattern = tagMask; // Tags whose EPC-ID starts with 0x1211
//Set this filter for Antenna Number 3
rfidStatus = RFID_AddPreFilter(readerHandle, 3, &prefilter, &filterIndex); // filterIndex can be used later to Delete pre-filters
Set appropriate Singulation Controls
Now that the pre-filters are set (i.e. Tags are classified into matching or non-matching criteria), the Application needs to specify which tags should participate in the Inventory using RFID_SetSingulationControl. Singulation Control also can be specified with respect to each Antenna like Pre-Filters. To set singulation for all antennas, use zero for antennaID.
State-Unaware Singulation
//Set all required values in Singualtion Control // Set Session to operate as S1. If not specified Reader uses its own way of implementing the State-unaware singulation. singulationControl.session = SESSION_S1; rfidStatus = RFID_SetSingulationControl(readerHandle, 3, &singulationControl);
State-Aware Singulation
//Set all required values in Singualtion Control singulationControl.session = SESSION_S1; singulationControl.stateAwareSingulationAction.perform = true; singulationControl.stateAwareSingulationAction.inventoryState = INVENTORY_STATE_B; singulationControl.stateAwareSingulationAction.slFlag = SL_FLAG_DEASSERTED; rfidStatus = RFID_SetSingulationControl(readerHandle, 3, &singulationControl);
Perform Inventory or Access Operation
Inventory or Access operation when performed after setting pre-filters, will use the tags filtered out of pre-filters for their operation.
Triggers are the conditions that should be satisfied in order to start or stop an operation (Inventory or AccessSequence). This information can be specified using TRIGGER_INFO. The application can also configure the Tag-Report trigger which indicates when to receive 'n' unique Tag-Reports from the Reader. Refer to TRIGGER_INFO for more information.
The following are some use-cases of using TRIGGER_INFO
GPI based Inventory - Start inventory when GPI port 'n' changes state to TRUE and stop inventory when GPI port n changes state to FALSE.
TRIGGER_INFO triggerInfo; triggerInfo.tagReportTrigger = 1; // Report back each tag report as and when its read by the reader triggerInfo.startTrigger.type = START_TRIGGER_TYPE_GPI; triggerInfo.startTrigger.value.gpi.eventInfo = TRUE; triggerInfo.startTrigger.value.gpi.portNumber = 1; triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_GPI_WITH_TIMEOUT; triggerInfo.stopTrigger.value.gpi.eventInfo = FALSE; triggerInfo.stopTrigger.value.gpi.portNumber = 1; triggerInfo.stopTrigger.value.gpi.timeoutMilliseconds = 1000;
Periodic Inventory - Start inventory at a specified time for a specified duration repeatedly.
// This trigger starts Inventory on 12th of this month, and 12AM, // and runs for 200 milliseconds every second. TRIGGER_INFO triggerInfo; triggerInfo.tagReportTrigger = 0; // Report back all read tags after completion of one round of inventory (i.e. one period). triggerInfo.startTrigger.type = START_TRIGGER_TYPE_PERIODIC; triggerInfo.startTrigger.value.periodic.periodMilliseconds = 1000; /*perform inventory for 1 sec*/ SYSTEMTIME startTime; GetSystemTime(&startTime); startTime.wDay = 12; startTime.wHour = 12; triggerInfo.startTrigger.value.periodic.startTime = &startTime; triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_DURATION; triggerInfo.stopTrigger.value.durationMilliseconds = 200;/*Stop after 200 milliseconds*/
Perform 'n' Rounds of Inventory with a timeout - Start condition could be any; Stop condition is to perform 'n' rounds of inventory and then stop or stop inventory after the specified timeout.
TRIGGER_INFO triggerInfo; triggerInfo.tagReportTrigger = 0; // Report back all read tags after 3 rounds of inventory). triggerInfo.startTrigger.type = START_TRIGGER_TYPE_IMMEDIATE; triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_N_ATTEMPTS_WITH_TIMEOUT; triggerInfo.stopTrigger.value.numAttempts.n = 3; // perform 3 rounds of inventory triggerInfo.stopTrigger.value.numAttempts.timeoutMilliseconds = 3000; // timeout after 3 seconds
Read 'n' Tags with a timeout - Start condition could be any; Stop condition is to stop after reading 'n' tags or stop inventory after the specified timeout.
TRIGGER_INFO triggerInfo; triggerInfo.tagReportTrigger = 100; // Report back all read tags after getting 100 unique tags or after 3 seconds). triggerInfo.startTrigger.type = START_TRIGGER_TYPE_IMMEDIATE; triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_TAG_OBSERVATION_WITH_TIMEOUT; triggerInfo.stopTrigger.value.tagObservation.n = 100; // Stop inventory after reading 100 Tags triggerInfo.stopTrigger.value.tagObservation.timeoutMilliseconds = 3000;
Inventory with Triggers
There are various situations that act as conditions (triggers) for performing inventory.
Refer section "Using Triggers" to configure Triggers.
The following shows an example of performing 1 round of Inventory on Antennas 1 and 3.
ANTENNA_INFO antennaInfo;
UINT16 antennaIDList[2] = {1,3};// Antennas for the operation are 1 and 3.
antennaInfo.pAntennaList = antennaIDList;
antennaInfo.length = 2;
TRIGGER_INFO triggerInfo;
triggerInfo.tagReportTrigger = 0; // Report back all read tags after 3 rounds of inventory).
triggerInfo.startTrigger.type = START_TRIGGER_TYPE_IMMEDIATE;
triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_N_ATTEMPTS_WITH_TIMEOUT;
triggerInfo.stopTrigger.value.numAttempts.n = 1; // perform 1 round of inventory
triggerInfo.stopTrigger.value.numAttempts.timeoutMilliseconds = 0; // Reader's default timeout
rfidStatus = RFID_PerformInventory(readerHandle, NULL, &antennaInfo, &triggerInfo, NULL);
Using Post-Filters
Post-filters are those filters which are applied on the Tags that the reader received after prefiltering (if any).
Post-filters allow the application to set one or two tag patterns and to specify a condition as a combination of the patterns.
The following snippet shows setting a post-filter that does not get tags starting with 0x1111 and 0x2222.
POST_FILTER postFilter;
TAG_PATTERN tagPatternA;
TAG_PATTERN tagPatternB;
UINT8 tagMask[64] = {0xFF};
UINT8 tagData[2];
/* Populate two post-filter patterns */
memset(tagMask, 0xFF, 64);
tagPatternA.memoryBank = MEMORY_BANK_EPC;
tagPatternA.bitOffset = 0x20;// Skip the PC bits
tagData[0] = tagData[1] = 0x11;
tagPatternA.pTagPattern = tagData;
tagPatternA.tagPatternBitCount = tagPatternA.tagMaskBitCount = 2 * 8;
tagPatternA.tagMaskBitCount = tagPatternA.tagPatternBitCount;
tagPatternA.pTagMask = tagMask;
tagPatternB.memoryBank = MEMORY_BANK_EPC;
tagPatternB.bitOffset = 0x20; // Skip the PC bits
tagData[0] = tagData[1] = 0x22;
tagPatternB.pTagPattern = tagData;
tagPatternB.tagPatternBitCount = tagPatternB.tagMaskBitCount = 2 * 8;
tagPatternB.tagMaskBitCount = tagPatternB.tagPatternBitCount;
tagPatternB.pTagMask = tagMask;
postFilter.lpTagPatternA = &tagPatternA;
postFilter.lpTagPatternB = &tagPatternB;
postFilter.matchPattern = NOTA_AND_NOTB;
RFID_API_SUCCESS == RFID_PerformInventory(readerHandle, &postFilter, NULL,NULL, NULL)
Using RSSI Filtering in Post Filters Starting from version RFID_API3_5_1 onwards, applications can use RSSI based filtering if supported by the reader. This is indicated by the field rssiFilterSupported of READER_CAPS. The following code snippet does filtering of tags which have RSSI value in range -40 to -10.
POST_FILTER postFilter; RSSI_RANGE_FILTER rssiRangeFilter; postFilter.lpTagPatternA = NULL; postFilter.lpTagPatternB = NULL; postFilter.lpRSSIRangeFilter = &rssiRangeFilter; rssiRangeFilter.peakRSSILowerLimit = -40; rssiRangeFilter.peakRSSIUpperLimit = -10; rssiRangeFilter.matchRange = WITHIN_RANGE; rfidStatus = RFID_PerformInventory(readerHandle, &postFilter, NULL, &triggerInfo, NULL);
Using Access-Filters
In order to perform an access operation on multiple tags, the Application can set ACCESS_FILTER to filter the required tags. If ACCESS_FILTER is not specified, the operation will be performed on all Tags. In any case, the PRE_FILTER(s) if any is set will apply prior to ACCESS_FILTER.
The following Access-filter gets all tags that have zeroed Reserved memory bank.
ACCESS_FILTER accessFilter; UINT8 tagData[8]; UINT8 tagMask[8]; memset(tagMask, 0xFF, 8); memset(tagData, 0, 8); tagPatternA.memoryBank = MEMORY_BANK_RESERVED; tagPatternA.bitOffset = 0; tagPatternA.pTagPattern = tagData; tagPatternA.tagPatternBitCount = tagPatternA.tagMaskBitCount = 8 * 8; tagPatternA.pTagMask = tagMask; accessFilter.lpTagPatternA = &tagPatternA; accessFilter.lpTagPatternB = NULL;
Access Operation on Multiple Tags
Performing a single Access operation on multiple tags is an asynchronous operation. The function issues the access-operation and returns. The Reader performs one round of inventory using pre-filters if any, and then applies the access-filters and the resultant tags are subject to the access-operation. When the access operation is complete, the Dll signals the event ACCESS_STOP_EVENT. The Application can call the function RFID_GetLastAccessResult to know the result. In case of Read access operation RFID_Read the event TAG_DATA_EVENT is signalled when Tags are reported.
The following snippet shows a sample write-access operation:
WRITE_ACCESS_PARAMS writeAccessParams;
UINT8 writeUserData[64];
UINT32 accessSuccessCount, accessFailureCount;
HANDLE accessComplete = CreateEvent(NULL, FALSE, FALSE, NULL);
RFID_RegisterEventNotification(readerHandle, ACCESS_STOP_EVENT, accessComplete);
writeAccessParams.accessPassword = 0;
writeAccessParams.memoryBank = MEMORY_BANK_USER;
writeAccessParams.byteOffset = 0;
writeAccessParams.writeDataLength = 64;
writeAccessParams.pWriteData = writeUserData;
memset(writeAccessParams.pWriteData, 0xAA, writeAccessParams.writeDataLength);
rfidStatus = RFID_Write(readerHandle, NULL, 0, &writeAccessParams, &accessFilter, NULL, NULL);
if(RFID_API_SUCCESS == rfidStatus)
{
accessSuccessCount = accessFailureCount = 0;
WaitForSingleObject(accessComplete, INFINITE);
rfidStatus = RFID_GetLastAccessResult(readerHandle,
&accessSuccessCount, &accessFailureCount);
}
The Application can issue multiple access operations on a single go using Access-Sequence API. This is useful when each tag from a set of (access-filtered) tags is to be subject to an order of access operations. The maximum number of access-operations that can be specified in an access sequence is specified in maxNumOperationsInAccessSequence of READER_CAPS. The Application shall first initialize the access-sequence using RFID_InitializeAccessSequence before adding operations to it using RFID_AddOperationToAccessSequence. The operations will be performed in the same order in which it is added to it sequence. An operation can be removed from the sequence using RFID_DeleteOperationFromAccessSequence and finally deinitialized if no more needed by calling the function RFID_DeinitializeAccessSequence.
rfidStatus = RFID_InitializeAccessSequence(readerHandle); UINT32 opCode = 0; readAccessParams.accessPassword = 0; readAccessParams.memoryBank = MEMORY_BANK_EPC; readAccessParams.byteCount = 6; readAccessParams.byteOffset = 4; opCodeParams.opCode = ACCESS_OPERATION_READ; opCodeParams.opParams = &readAccessParams; rfidStatus = RFID_AddOperationToAccessSequence(readerHandle, &opCodeParams, &opCode); // Add multiple access-operations. HANDLE accessStopped = CreateEvent(NULL, FALSE, FALSE, NULL); RFID_RegisterEventNotification(readerHandle, ACCESS_STOP_EVENT, accessStopped); status = RFID_PerformAccessSequence(readerHandle, NULL, NULL, &triggerInfo, NULL); DWORD thisEvent = WaitForSingleObject(accessStopped, INFINITE); // If the access operation is to be terminated without meeting // the stop trigger ( if specified), RFID_StopAccessSequence can be called. rfidStatus = RFID_StopAccessSequence(readerHandle);
Readers which support NXP commands report the same in the field NXPCommandsSupported of READER_CAPS as true. The following operations can be performed on NXPTags:
1) RFID_NXPSetEAS - This API can be used to set/reset the EAS (Electronic Article Surveillance) Bit. Tags can be monitored for EAS bit for the purpose of theft detection. For E.g Tags with EAS enabled moving out could be an indication of unbilled item or theft. The API RFID_NXPSetEAS lets you set or reset the EAS bits on one or more NXP tags. An NXP tag with EAS bit set will raise an NXP_EAS_ALARM_EVENT when running EAS SCAN NXP_EAS_SCAN on the reader.
2) RFID_NXPReadProtect and RFID_NXPResetReadProtect - The API RFID_NXPReadProtect sets the Quiet bit on one or more NXP tags. As a result, these tags trace-back a string of zeroes during Inventory and don't respond to access-operations, there by preventing unsecure access to Tag information. To put them back into normal mode, one has to call RFID_NXPResetReadProtect API.
3) Performing NXP Scan - To track NXP tags in which the EAS bit is set, an NXP_EAS_SCAN can be initiated on the reader by calling RFID_PerformNXPEASScan or RFID_PerformInventory API with its AntennaInfo parameter specifying NXP_EAS_SCAN as the OPERATION_QUALIFIER for at least one of the Antenna IDs in the AntennaList array.
4) Perform NXP BrandID check (supported only on NXP U-Code 8 and above tags that supports this functionality). Brand ID check can be initiated by API RFID_NXPBrandCheck. Reader performs an inventory operation with additional verification on whether or not tag inventoried matches the BrandID specified as parameter in RFID_NXPBrandCheck. Tags inventoried and matching the Brand ID will be reported with brandValid field of TAG_DATA for that tag set to 1 if there is a match else 0. Ongoing Brand ID check operation can be explicitly stopped using RFID_NXPStopBrandCheck.
Impinj's Monza 4, Monza 5, and Monza R6 tag chips offer a feature called TagFocus. This feature enables a reader to instruct tags to continue to refresh their A/B flag setting such that they remain in a non-responsive state. By instructing tags that have already been inventoried to remain silent while inventorying other tags, reader has a far greater chance of finding difficult-to-read tags. This feature can be enabled by configuring antenna's singulation settings and applying a pre-filter (same as the Select command of C1G2 specification) with specific parameter values. This feature can be disabled by deleting the pre-filter with specific parameter values from the API.
Note: This feature is applicable only for FX7500 ,FX9600 and RE40.
// Get the Reader Capability
READER_CAPS readerCaps;
RFID_GetReaderCaps(readerHandle, &readerCaps);
// configure antenna's singulation settings using Session 1 with Flag A
for(UINT16 nIndex = 1; nIndex <= readerCaps.numAntennas; nIndex++)
{
SINGULATION_CONTROL SingulationControl;
RFID_GetSingulationControl(readerHandle, nIndex, &SingulationControl);
SingulationControl.stateAwareSingulationAction.perform = true;
SingulationControl.session = SESSION_S1;
SingulationControl.stateAwareSingulationAction.inventoryState = INVENTORY_STATE_A;
SingulationControl.stateAwareSingulationAction.slFlag = SL_FLAG_DEASSERTED;
RFID_SetSingulationControl(readerHandle, nIndex, &SingulationControl);
}
//apply a pre-filter to the reader with specific parameter values
RFID_DeletePreFilter(readerHandle, 0, 0); // delete all existing pre-filters first
UINT32 tagFocusFilterIndex = 0;
PRE_FILTER tagFocusFilter;
UINT8 tagMask[3] = {0x80, 0x06, 0x00};
tagFocusFilter.bitOffset = 6;
tagFocusFilter.pTagPattern = tagMask;
tagFocusFilter.tagPatternBitCount = 20;
tagFocusFilter.memoryBank = MEMORY_BANK_TID;
tagFocusFilter.filterAction = FILTER_ACTION_STATE_AWARE;
tagFocusFilter.filterActionParams.stateAwareParams.target = TARGET_INVENTORIED_STATE_S1;
tagFocusFilter.filterActionParams.stateAwareParams.stateAwareAction = STATE_AWARE_ACTION_INV_B;
RFID_AddPreFilter(readerHandle, 0, &tagFocusFilter, &tagFocusFilterIndex);
//perform simple inventory
RFID_PerformInventory(readerHandle, NULL, NULL, NULL, NULL);
//disable TagFocus feature
RFID_DeletePreFilter(readerHandle, 0, tagFocusFilterIndex);
When the application is done with the connection and with the operations on the RFID-Reader, it shall call RFID_Disconnect to close the connection and to release and clean up the resources.
rfidStatus = RFID_Disconnect(readerHandle);
The reader allows set of reader management functionality via reader management interface. The reader requires login authentication prior to perform any other management functions. The management functions such as software/firmware upgrade, set the antenna mode, enable or disable the read point (Antenna) and set the radio power state can be performed through the management interface.
The RFID_Login function returns the handle to the reader management interface. The other functions must use this handle to perform the required operation.
After application is done with the reader management operations, the RFID_Logout function must be called for cleaning up the resources allocated during the RFID_Login function.
The RFID_Login must be called first to perform any reader management functions.
In case of fixed readers, the login information such as user name, password and secured mode are required for performing login operation. The secure mode parameter specifies that whether the mode of communication is HTTP or HTTPS. Based on this parameter, the internal communication between the client and the reader uses the specified transport interface. If supported by the Reader, there is an option to override an existing login session using the forceLogin option of LOGIN_INFO. This is currently supported on FX 7400 Version 1.1.0 and higher.
The login Info is not required for the Hand held readers. But it is must to call the RFID_Login function first prior to other reader management functions.
Fixed Reader
The reader allows to update software includes the OS, applications from the given FTP Server location. Starting from version RFID_API3_5_1 onwards, the API also supports the "push model" software update, which allows updating software from non-FTP locations (E.g. D:\NewSoftware) also. This is currently supported on FX 7400 Version 1.1.0 and higher.
The function RFID_UpdateSoftware helps to perform the software update functionality.
The function RFID_EnableReadPoint allows enabling or disabling the read point (Antenna) for the specified antenna ID.
To know the connection status of the antenna, the RFID_GetReadPointConnectStatus can be called.
The fixed reader supports the two modes of operation namely Mono-static and Bi-Static. The RFID_GetAntennaMode gets the current configured mode. The function RFID_SetAntennaMode allows changing the mode to either mono-static or bi-static.
The function RFID_GetSystemInfo helps to get the reader system information. This includes Radio Firmware version, FPGA version, Up time, reader name, location, RAM available & Flash memory available.
This API also gets the device Information which includes Hostname, Manufacturer, Model, Hardware version, Boot Loader version, and Number of Physical antennas supported.
The reader supports managing the reader configuration files, called profiles. The reader configuration is typically managed as XML files.
The list of configurations supported by a reader can be obtained from API RFID_GetProfileList. This API is supported only on FX SERIES.
The upload of configuration file can be performed using RRFID_ExportProfileToReader. The absolute file path of the source file must be specified. For example, "C:\Profiles"
The function RFID_DeleteProfile deletes the profile from the reader. To activate a profile in the reader, the function RFID_SetActiveProfile can be used.
The function RFID_SetSysLogServer allows to route the syslogs to remote syslog server. This API takes remote syslog server host name, port number & minimum severity as parameters. The API RFID_GetSysLogServer gets the current syslog configuration.
This function RFID_FactoryReset does the reset to factory defaults configuration. This wipes out region configuration, reader information, cable loss, Time related configuration and all other user configurations.
The RFID Reader can be configured in LLRP client or server mode using the function RFID_SetLLRPConnectionConfig and current setting can be retrieved using RFID_GetLLRPConnectionConfig. While acting in client mode, the function RFID_InitiateLLRPConnectionFromReader can be used to initiate an LLRP Connection from the reader to the port on the Server-IP as configured in LLRP_CONNECTION_CONFIG. RFID_DisconnectLLRPConnectionFromReader disconnects the current LLRP Connection from the reader.
The function RFID_GetLLRPConnectionStatus gets the current connected status of LLRP connection and the client IP address who is connected to LLRP server.
This feature is supported only on FX series readers. The FX Reader's USB connection can be configured to be either ActiveSync or Network. While in ActiveSync mode, the ActiveSync application running on host gets connected as soon as the USB cable connected to the Reader is plugged in to the host. While in Network mode, the Reader and the host gets connected as a network, reader being 169.254.10.1. This acts as a fallback mechanism to login to the Reader's web console to know its primary IP. The APIs RFID_GetUSBOperationMode and RFID_SetUSBOperationMode can be used for this.
This feature is supported only on FX series readers. The debounce time is used to filter out unwanted GPI signals. If the debounce time is greater than that GPI's on time, then the GPI will be ignored. If the debounce time is less that the GPI on time, then the GPI will be detected. The APIs RFID_GetGPIDebounceTime and RFID_SetGPIDebounceTime can be used for this.
API support for Getting and Setting the local time of the Reader is provided only on FX series readers. The APIs RFID_GetLocalTime and RFID_SetLocalTime can be used for this.
API support for this feature is supported only on FX series readers. Getting the Time zone list, current time zone and setting the time zone of the can be done using the APIs RFID_GetTimeZoneList and RFID_SetTimeZone.
This feature is supported only on FX series readers. The API support for getting and setting the Network settings such as DHCP or Static IP Address configuration for Ethernet, Wi-Fi and Bluetooth interface. The APIs RFID_GetNetworkInterfaceSettings and RFID_SetNetworkInterfaceSettings can be used for this.
For getting or setting NTP server, the APIs RFID_SetNTPServer and RFID_GetNTPServer can be used this. The reader time (UTC) is synchronized with the NTP Server configured.
To establish connection Wi-Fi access point, the API RFID_SetWirelessNetwork can be used to configure ESS ID, Passkey and auto connect on reboot. RFID_GetWirelessConfigParameters gets the current Wireless configuration.
Setting the user LED is supported only on FX series readers. The API RFID_SetUserLED can be used for this.
Getting per antenna Reader Statistics and clearing off the statistics is supported only on FX series readers. The API RFID_GetReaderStats and RFID_ClearReaderStats can be used for this. This API gets the inventory and access operation successful and failure counts. Also, includes Ambient/PA temperature critical, high & low alarm counts, forward/reverse power high, low alarm counts, echo threshold alarm counts, and GPIO information counts.
Getting the Reader's System Info like Firmware version, uptime, ram-available, flash-available, etc can be done using RFID_GetSystemInfo. Getting and Setting the Reader Information like name, description, location and contact information can be done using RFID_GetReaderInfo and RFID_SetReaderInfo.
This feature is supported only in FX7500 reader. The Idle Mode Timeout allows the reader to switch off the radio module power, after a specified timer interval elapsed only if reader is in idle state (Not performing any radio related operation like inventory or access). Radio will be powered on if any inventory/access operation is initiated from client application.
The APIs RFID_TurnOffRadioWhenIdle and RFID_GetRadioIdleTimeout can be used for this.
This feature is supported only in FX7500 reader. Typically RF power transmitted at the antenna is lesser than transmit power at the port due to loss in cable. Once the cable loss in dB per 100 feet and cable length in feet are configured per antenna, the reader sets new upper limit for the transmit power after accounting for the specified loss in cable.
The APIs RFID_SetCableLossCompensation and RFID_GetCableLossCompensation can be used for this.
This feature is supported only in FX7500 reader. The following functionalities are supported for facilitating embedded user application on the FX7500.
- Installation and un-installation of the user application
- Listing the set of currently installed user applications
- Starting and Stopping the user application
- Getting the current Run status
- Auto start of the upper application on reader reboot
The APIs that are exposed in RFID3 to support of deployment of user application are:
The following APIs are exposed to configure region:
This feature is supported only in FX7500 reader and applicable only when the reader is connected to LLDP enabled POE+ switch. This feature enables the reader to negotiate power with switch. On granting power, the reader power source switches to POE+ mode.
The following APIs are exposed:
The reader can be rebooted or restarted by calling the function RFID_Restart. This functionality is not supported on hand-held readers.
The RFID_Logout function does the clean-up activity for the reader management interface. This must be called once the application has done with Reader management functions.
The 64 bit Dll for RFID API is rfidapi32PC.dll. The name of the Dll is same as the 32-bit counterpart. 32-bit Applications can be recompiled to 64-bit applications as mentioned in section beneath.
Compiling EMDK Sample Applications for 64-bit support Existing RFID Samples (BasicRFIDHost1 & RFIDHostSample1) can be compiled for 64-bit machine by the following steps:
1) Ensure that Visual Studio 2005 or Visual Studio 2008 is installed for 64-bit support so that 64-bit applications can be compiled. 2) Open the solution file which is to be compiled. 3) Open Configuration Manager and add New Solution Platform and New Project Platform 'x64' if it is not present. 4) Set the active platform for the current project as 'x64'. 5) Add _WIN64 to the preprocessor definitions of the project to be compiled. 6) In the project properties, open Linker -> Advanced -> Target Machine. Set this as MachineX64 (/MACHINE:X64) 7) Now the environment is ready to build a 64-bit application.