Overview
This chapter provides detailed information about how to use various basic and advanced functionality to develop an Android application using the Zebra RFID SDK for Android.
Create The Project
- Start by creating a new project in Android Studio. For help, see the Android Studio tutorial.
- Refer Hello RFID to prepare basic setup to work with RFID Reader and then follow this guide
Details
The Zebra RFID SDK for Android provides the ability to manage RFID readers’ connections, perform various operations with connected RFID readers, configure connected RFID readers and knowing other information related to connected RFID readers. All available APIs are defined under the com.zebra.rfid.api3 package. RFIDReader is the root Java class in the SDK. The application uses a single instance of an RFIDReader object to interact with a particular reader. Use available readers and the RFIDReader object to register for events, connect with readers, and after successful connection, perform required operations such as inventory, access and locate. It is recommended that all API calls should be made using Android ‘AsyncTask’ so that operations are performed in the background thread keeping the UI thread free. If the API call fails, the API throws an exception. The application should call all APIs in try-catch block for handling exceptions.
Connection Management
Connect to an RFID Reader
Please refer Connect to RFID reader
Region Is Not Configured
If the region is not configured, then exception gives RFID_READER_REGION_NOT_CONFIGURED result the caller then gets supported regions and chooses operation regulatory region from list. Set region with required configurations
if (ex.getResults() == RFIDResults.RFID_READER_REGION_NOT_CONFIGURED) {
// Get and Set regulatory configuration settings
// RegulatoryConfig regulatoryConfig = rfidReader.Config.getRegulatoryConfig();
// RegionInfo regionInfo =
rfidReader.ReaderCapabilities.SupportedRegions.getRegionInfo(1);
// regulatoryConfig.setRegion(regionInfo.getRegionCode());
// rfidReader.Config.setRegulatoryConfig(regulatoryConfig);
}
Reader Requires Bluetooth (BT )Password (RFD8500 only)
If the BT connection password is configured for connection, a direct call to the connection results with an exception pointing that the BT password is required. Set the password in the RFIDReader instance and then call connect again.
if (ex.getResults() == RFIDResults.RFID_CONNECTION_PASSWORD_ERROR) {
// get password showPasswordDialog();
rfidReader.setPassword(password);
rfidReader.connect();
}
Reader Is Running In Batch Mode (RFD8500 only)
If the reader is configured with auto or batch mode enabled, the reader continues performing the inventory operation even it is not connected to an Android device. If, at that time, there is a connection made to a specific RFID reader, then the connection API throws the following exception. Then the application should stop the operation as required by usage
if (ex.getResults() == RFIDResults.RFID_BATCHMODE_IN_PROGRESS) {
// handle batch mode related stuff
}
Note that as the batch operation runs on the reader, the reader related information cannot be autonomously retrieved by the SDK. It is the responsibility of the application to retrieve/update reader related information using the following API once the BATCH operation is stopped before any other use
rfidReader.PostConnectReaderUpdate();
Knowing the Reader Capabilities
The capabilities (or Read-Only properties) of the reader are known using the ReaderCapabilites class. The reader capabilities include the following:
General Capabilities
- Model Name
- Number of antennas supported
- 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 such as Change
- NXP Commands Supported - Indicates whether the reader supports NXP commands such as Change EAS, set Quiet, Reset Quiet, Calibrate.
- Tag LocationingSupported - Indicates the reader’s ability to locate a tag
- DutyCycleValues - List of DutyCycle percentages supported by the reader.
Gen2 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 tabl
- Hopping enabled
- Frequency Hop table - If hopping is enabled, this table has the frequency information.
- Fixed Frequency table - If hopping is 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
Reader-identification
Reader ID and Reader ID Type (the reader identification can be MAC or EPC)Reader ID and Reader ID Type (the reader identification can be MAC or EPC)
System.out.println("\nReader ID: " + reader.ReaderCapabilities.ReaderID.getID());
System.out.println("\nModelName: " + reader.ReaderCapabilities.getModelName());
System.out.println("\nCommunication Standard: " +
reader.ReaderCapabilities.getCommunicationStandard().toString());
System.out.println("\nCountry Code: " + reader.ReaderCapabilities.getCountryCode());
System.out.println("\nRSSI Filter: " + reader.ReaderCapabilities.isRSSIFilterSupported());
System.out.println("\nTag Event Reporting: " +
reader.ReaderCapabilities.isTagEventReportingSupported());
System.out.println("\nTag
Locating Reporting: " + reader.ReaderCapabilities.isTagLocationingSupported());
System.out.println("\nNXP Command Support: " +
reader.ReaderCapabilities.isNXPCommandSupported());
System.out.println("\nBlockEraseSupport: " +
reader.ReaderCapabilities.isBlockEraseSupported());
System.out.println("\nBlockWriteSupport: " +
reader.ReaderCapabilities.isBlockWriteSupported());
System.out.println("\nBlockPermalockSupport:
" + reader.ReaderCapabilities.isBlockPermalockSupported());
System.out.println("\nRecommisionSupport: " +
reader.ReaderCapabilities.isRecommisionSupported());
System.out.println("\nWriteWMISupport:
" + reader.ReaderCapabilities.isWriteUMISupported());
System.out.println("\nRadioPowerControlSupport: " +
reader.ReaderCapabilities.isRadioPowerControlSupported());System.out.println("\nHoppingEn
abled: " + reader.ReaderCapabilities.isHoppingEnabled());
System.out.println("\nStateAwareSingulationCapable: " +
reader.ReaderCapabilities.isTagInventoryStateAwareSingulationSupported());
System.out.println("\nUTCClockCapable: " +
reader.ReaderCapabilities.isUTCClockSupported());System.out.println("\nNumOperationsInAccessSequence: " +
reader.ReaderCapabilities.getMaxNumOperationsInAccessSequence());
System.out.println("\nNumPreFilters: " + reader.ReaderCapabilities.getMaxNumPreFilters());
System.out.println("\nNumAntennaSupported: " +
reader.ReaderCapabilities.getNumAntennaSupported())
Configuring the Reader
RF-Mode
The reader has one or more sets of C1G2 RF Mode that the reader is capable of operating. The supported RF mode is retrieved from the RF Mode table using the ReaderCapabilities class.
The API GetRFModeTableInfo
in reader capabilities.RFModes gets the RF Mode table from the
reader. The getLinkedProfiles function described below populates the RFModeTable into an
List
// The rfModeTable is populated by the GetRFModeTableInfo function
public RFModeTable rfModeTable = Reader.ReaderCapabilities.RFModes.GetRFModeTableInfo(0);
// The linked profiles are added to an list
private void getLinkedProfiles(List linkedProfiles)
{
RFModeTableEntry rfModeTableEntry = null;
for (int i = 0; i < rfModeTable.Length(); i++)
{
rfModeTableEntry = rfModeTable.GetRFModeTableEntryInfo(i);
linkedProfiles.Add(rfModeTableEntry.BdrValue + " " +
rfModeTableEntry.Modulation + " " + rfModeTableEntry.PieValue + " " +
rfModeTableEntry.MaxTariValue + " " +
rfModeTableEntry.MaxTariValue + " " +
rfModeTableEntry.StepTariValue);
}
}
Antenna specific configurations
Antenna configurations
Please refer Antenna configurationsSingulation Control
Please refer Singulation ControlTag report configuration
The SDK provides an ability to configure a set of fields to be reported in a response to an operation by a specific active RFID reader.Supported fields that might be reported include the following:
- First seen time
- Last seen time
- PC value
- RSSI value
- Phase value
- Channel index
- Tag seen count
The function getTagStorageSettings retrieves the tag report parameters from the reader for the given Antenna ID. To set the Tag report parameters, the setTagStorageSettings method is used. The following settings can be configured
// Get tag storage settings from the reader
TagStorageSettings tagStorageSettings = reader.Config.getTagStorageSettings();
// set tag storage settings on the reader with all fields
tagStorageSettings.setTagFields(TAG_FIELD.ALL_TAG_FIELDS);
reader.Config.setTagStorageSettings(tagStorageSettings);
Regulatory Configuration
Please refer Region setting guideSaving Configuration
Various parameters of a specific RFID reader configured via SDK are lost after the next power down. The SDK provides an ability to save a persistent configuration of RFID reader. The saveConfig API function can be used to make the current configuration persistent over power down and power up cycles. The following example demonstrates utilization of mentioned API functions
reader.Config.saveConfig();
Reset Configuration to Factory Defaults
The SDK provides a way to reset the RFID reader to the factory default settings. The resetFactoryDefaults API can be used to attain this functionality. Once this method is called, all the reader settings like events, singulation control, etc will be lost and the RFID reader reboots. A connected application shall lose connectivity to the reader and must connect back again and is required to redo the basic steps for initializing the reader. The following example demonstrates utilization of mentioned API function.reader.Config.resetFactoryDefaults();
Managing Events
Please refer Event handlingBasic operations
Tag storage settings
This section covers the basic operations that an application needs to perform on an RFID reader which includes inventory and single tag access operations
The application needs to get the tags from the dll which are reported by the reader. Tags can be reported as part of an Inventory operation (Reader.Actions.Inventory.Perform) or a Read Access operation (Reader.Actions.TagAccess.ReadEvent or Reader.Actions.TagAccess.ReadWait).
Applications can also configure to receive tag reports that indicate the results of access operations as shown below.
TagStorageSettings tagStorageSettings = reader.Config.getTagStorageSettings();
reader.Config.setTagStorageSettings(tagStorageSettings)
Each tag has a set of associated information along with it. During the Inventory operation, the reader reports theEPC-ID of the tag, where as during the Read-Access operation the requested Memory Bank Data is also reportedapart from EPC-ID. In either case, there is additional information such as PC-bits, RSSI, last time seen, tag seen count, etc. that is available for each tag. This information is reported to the application as TagData for each tagreported by the reader.
Applications can also choose to enable/disable reporting certain fields in TAG_DATA. Disabling certain fields cansometimes improve the performance as the reader and the sdk are not processing that information. It can also resultin specific behavior. For example, disabling reporting an Antenna Id can result in the application receiving a single unique tag even though they were multiple entries of the same tag reported from different antennas. The following demonstrates enabling the reporting of PeakRSSI, Tag Seen Count, PC and CRC only and disabling other fields such as Antenna ID, Time Stamps, and XPC.
TagStorageSettings tagStorageSettings = reader.Config.getTagStorageSettings();
TAG_FIELD[] tagField = new TAG_FIELD[4];
tagField[0] = TAG_FIELD.PC; tagField[1] =
TAG_FIELD.PEAK_RSSI; tagField[2] =
TAG_FIELD.TAG_SEEN_COUNT; tagField[3] =
TAG_FIELD.CRC;
tagStorageSettings.setTagFields(tagField);
reader.Config.setTagStorageSettings(tagStorageSettings);
Tag storage usecases
Inventory
Please refer Inventory
Read
Please refer read
-
Write
Please refer write
-
Block Erase
The application calls RFID_BlockErase to erase the contents of a tag.
// Block Erase TagData tagData = new TagData (); String tagId = "1234ABCD00000000000025B1"; TagAccess.BlockEraseAccessParams blockEraseAccessParams = tagAccess.new BlockEraseAccessParams(); blockEraseAccessParams.setAccessPassword(0); blockEraseAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_USER); // user memory bank blockEraseAccessParams.setOffset(0); // start erasing from word offset 0 blockEraseAccessParams.setCount(8); // number of words to erase mConnectedReader.Actions.TagAccess.blockEraseWait(tagId, blockEraseAccessParams, null,tagData);
-
Block-Permalock
The application calls method Reader.Actions.TagAccess.blockPermalockWait to block a permalock tag. Tags reported as part of Block-Permalock access operation have TagData.getOpCode as ACCESS_OPERATION_BLOCK_PERMALOCK and TagData.getOpStatus indicating the result of the operation; if TagData.OpStatus is ACCESS_SUCCESS, TagData.getMemoryBankData contains the Block-Permalock Mask Data.
// Block-Perma Lock the tag String tagId = "1234ABCD00000000000025B1"; TagAccess tagAccess = new TagAccess(); TagAccess.BlockPermalockAccessParams blockPermalockAccessParams = tagAccess.new BlockPermalockAccessParams(); byte[] permalockMask = new byte[] {(byte)0xF0, 0x00}; blockPermalockAccessParams.setReadLock(true); blockPermalockAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_USER); blockPermalockAccessParams.setOffset(0); // start BlockPermalock from word offset 0 blockPermalockAccessParams.setCount(1); // start BlockPermalock from word offset 0 blockPermalockAccessParams.setMask(permalockMask); blockPermalockAccessParams.setMaskLength(2); reader.Actions.TagAccess.blockPermalockWait(tagId, blockPermalockAccessParams, null);
Lock
The application calls method reader.Actions.TagAccess.lockWait to perform a lock operation on one or more memory banks with specific privileges
// Lock the tag
String tagId = "1234ABCD00000000000025B1";
TagAccess tagAccess = new TagAccess();
TagAccess.LockAccessParams lockAccessParams = tagAccess.new
LockAccessParams();
/* lock now */
lockAccessParams.setLockPrivilege(LOCK_DATA_FIELD.LOCK_USER_MEMORY,
LOCK_PRIVILEGE.LOCK_PRIVILEGE_READ_WRITE);
lockAccessParams.setAccessPassword(0);
reader.Actions.TagAccess.lockWait(tagId, lockAccessParams, null);
Kill
The application calls method reader.Actions.TagAccess.killWait
to kill a tag
// Kill the tag
String tagId = "1234ABCD00000000000025B1";
TagAccess tagAccess = new TagAccess();
TagAccess.KillAccessParams killAccessParams = tagAccess.new KillAccessParams();
killAccessParams.setKillPassword(0);
reader.Actions.TagAccess.killWait(tagId, killAccessParams,null);
Synchronous Access Operation API Updates
All synchronous access operation APIs have been overloaded with new parameters for prefilter support.
APIs: readWait, writeWait, killWait, lockWait, blockWriteWait, blockEraseWait and blockPermalockWait
public TagData readWait(java.lang.String tagID, TagAccess.ReadAccessParams readAccessParams, AntennaInfo antennaInfo, boolean bPrefilter, boolean bTIDPrefilter)
Example
reader.Actions.TagAccess.readWait("2F2203447334C3100002EA55", readAccessParams, null,true);
Apply TID memory bank as prefilter:
reader.Actions.TagAccess.writeWait(tagId, writeAccessParams, null, tagData, true, true);
Provision of TID memory bank as prefilter and giving number of retries will help doing retries on partial writes of EPC memory bank.
Note - Using TID memory bank as prefilter will result in longer time of write, as SDK internally retrieves TID memory bank of tag.
Note - When prefilter is enabled, SDK does access operation in session S0 and uses
INV_B_NOT_INV_A_OR_DSRT_SL_NOT_ASRT_SL with INV_B inventory state
TagAccess.WriteAccessParams
have additional parameter to define number of retries.
void setWriteRetries(int writeRetries)
Number of retries to be performed for write access operation.
In case of failure SDK retries to perform write operation from data offset from last successful number of words written.
API to configure access operation time out via Config class
Earlier version of SDK has hardcoded timeout of five seconds which results in longer wait for operation result to come if tag is not found in FOV or other reasons (not singulated). By this application can shorten wait time and quickly retry in failure cases.
void setAccessOperationWaitTimeout(int timeout)
Method to set access operation timeout for all synchronous tag access operations APIs.
Example:reader.Config.setAccessOperationWaitTimeout(1000);
Advanced operations
Using Prefilters
Please refer Prefilters Tutorial
Singulation
Please refer Singulation
Using Triggers
>Triggers are the conditions that are satisfied in order to start or stop an operation (Inventory or Access Sequence). This information can be specified using TriggerInfo class. The application can also configure the Tag-Report trigger which indicates when to receive ‘n’ unique Tag-Reports from the Reader.
We have to use Config.setStartTrigger
and Config.setStopTrigger
APIs to set triggers on the reader.
The following are some use-cases of using TRIGGER_INFO:
-
Periodic Inventory: Start inventory at a specified time for a specified duration repeatedly
TriggerInfo triggerInfo = new TriggerInfo(); // start inventory at every 2 seconds triggerInfo.StartTrigger.setTriggerType(START_TRIGGER_TYPE.START_TRIGGER_TYPE_PERIODIC); triggerInfo.StartTrigger.Periodic.setPeriod(2000); // perform inventory for 2 seconds // stop trigger triggerInfo.StopTrigger.setTriggerType(STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_DURATION); triggerInfo.StopTrigger.setDurationMilliSeconds(200); // stop after 200 milliseconds
-
Perform ‘n’ Rounds of Inventory with a timeout: Start condition can be any; Stop condition is to perform ‘n’
rounds of inventory and then stop or stop inventory after the specified timeout
TriggerInfo triggerInfo = new TriggerInfo(); // start inventory immediate triggerInfo.StartTrigger.setTriggerType(START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE); // stop trigger triggerInfo.StopTrigger.setTriggerType(STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_N_ATTEMPTS_WITH_TIMEOUT); triggerInfo.StopTrigger.NumAttempts.setN((short)3); // perform 3 rounds of inventory triggerInfo.StopTrigger.NumAttempts.setTimeout(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
TriggerInfo triggerInfo = new TriggerInfo(); // start inventory immediate triggerInfo.StartTrigger.setTriggerType(START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE); // stop trigger triggerInfo.StopTrigger.setTriggerType(STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_TAG_OBSERVATION_WITH_TIMEOUT); triggerInfo.StopTrigger.TagObservation.setN((short)100); // stop inventory after reading 100 tags triggerInfo.StopTrigger.TagObservation.setTimeout(3000); // timeout after 3 seconds // report back all read tags after getting 100 unique tags or after 3 seconds
-
Inventory based on hand-held trigger: Start inventory when the hand-held gun/button trigger is pulled, and stop inventory when the hand-held gun/button trigger is released or subject to timeout
TriggerInfo triggerInfo = new TriggerInfo(); triggerInfo.StartTrigger.setTriggerType(START_TRIGGER_TYPE.START_TRIGGER_TYPE_HANDHELD); // Start Inventory when the Handheld trigger is pressed triggerInfo.StartTrigger.Handheld.setHandheldTriggerEvent(HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_PRESSED); triggerInfo.StopTrigger.setTriggerType(STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_HANDHELD_WITH_TIMEOUT); // Stop Inventory when the Handheld trigger is released triggerInfo.StopTrigger.Handheld.setHandheldTriggerEvent(HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_RELEASED); triggerInfo.StopTrigger.Handheld.setHandheldTriggerTimeout(0);
-
Set the trigger using the following APIs, perform inventory and other operations which are using above set start and stop triggers.
reader.Config.setStartTrigger(triggerInfo.StartTrigger); reader.Config.setStopTrigger(triggerInfo.StopTrigger); reader.Actions.Inventory.perform();
Access
-
Using Access-Filter
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 is performed on all tags. In any case, the PRE_FILTER(s) (if any is set) applies prior to ACCESS_FILTER.The following access-filter gets all tags that have zeroed reserved memory bank
AccessFilter accessFilter = new AccessFilter(); byte[] tagMask = new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }; // Tag Pattern A accessFilter.TagPatternA.setMemoryBank(MEMORY_BANK.MEMORY_BANK_RESERVED); accessFilter.TagPatternA.setTagPattern(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); accessFilter.TagPatternA.setTagPatternBitCount(8 * 8); accessFilter.TagPatternA.setBitOffset(0); accessFilter.TagPatternA.setTagMask(tagMask); accessFilter.TagPatternA.setTagMaskBitCount(tagMask.length * 8); accessFilter.setAccessFilterMatchPattern(FILTER_MATCH_PATTERN.A);
-
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 SDK signals the eventStatusNotify event with event data as INVENTORY_STOP_EVENT/.
In case of Read access operation (
reader.Actions.TagAccess.readEvent/
) the event eventReadNotify is signaled when tags are reported.The following demonstrates a sample write-access operation:
// Create Event to signify access operation complete reader.Events.setInventoryStartEvent(true); reader.Events.setInventoryStopEvent(true); // Data Read Notification from the reader class EventHandler implements RfidEventsListener { // Read Event Notification public void eventReadNotify(RfidReadEvents e){ TagData tag = e.getReadEventData().tagData; System.out.println("Tag ID " + tag.getTagID()); if (tag.getOpCode() == ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ && tag.getOpStatus() == ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) { if (tag.getMemoryBankData().length() > 0) { System.out.println(" Mem Bank Data " + tag.getMemoryBankData()); } } } // Status Event Notification public void eventStatusNotify(RfidStatusEvents e) { if (e.StatusEventData.getStatusEventType() == STATUS_EVENT_TYPE.INVENTORY_START_EVENT) { // Access operation started } else if(e.StatusEventData.getStatusEventType() == STATUS_EVENT_TYPE.INVENTORY_STOP_EVENT) { // Access operation stopped - Can be used to signal waiting thread } } } // Access Filter - EPC ID starting with 0x1122 AccessFilter accessFilter = new AccessFilter(); byte[] tagMask = new byte[] { 0xff, 0xff }; // Tag Pattern A accessFilter.TagPatternA.setMemoryBank(MEMORY_BANK.MEMORY_BANK_EPC); accessFilter.TagPatternA.setTagPattern(new byte[] { 0x11, 0x22}); accessFilter.TagPatternA.setTagPatternBitCount(2 * 8); accessFilter.TagPatternA.setBitOffset(0); accessFilter.TagPatternA.setTagMask(tagMask); accessFilter.TagPatternA.setTagMaskBitCount(tagMask.length * 8); accessFilter.setAccessFilterMatchPattern(FILTER_MATCH_PATTERN.A); // Write user memory bank data TagAccess tagAccess = new TagAccess(); TagAccess.WriteAccessParams writeAccessParams = tagAccess.new WriteAccessParams(); String writeData = “ABCDABCD” writeAccessParams.setAccessPassword(0); writeAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_USER); writeAccessParams.setOffset(0); // start writing from word offset 0 writeAccessParams.setWriteData(writeData); // Asynchronous write operation reader.Actions.TagAccess.writeEvent(writeAccessParams, accessFilter, null); // wait for access operation to complete (INVENTORY_STOP_EVENT is signaled after completing //the access operation in the eventStatusNotify)
-
Using Access Sequence
The application issues 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 available in
reader.ReaderCapabilities.getMaxNumOperationsInAccessSequence
of ReaderCapabilities class.The operations are performed in the same order in which it is added to it sequence. An operation can be removed from the sequence using
reader.Actions.TagAccess.OperationSequence.delete
and finally de-initialized if no longer needed by calling the function.Sample 1:
reader.Actions.TagAccess.OperationSequence.deleteAll(); // add Write Access operation - Write to User memory TagAccess tagAccess = new TagAccess(); TagAccess.Sequence opSequence = tagAccess.new Sequence(tagAccess); TagAccess.Sequence.Operation op1 = opSequence.new Operation(); op1.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE); op1.WriteAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_USER); op1.WriteAccessParams.setAccessPassword(0); op1.WriteAccessParams.setOffset(0); op1.WriteAccessParams.setWriteData("55667788"); op1.WriteAccessParams.setWriteDataLength(4); reader.Actions.TagAccess.OperationSequence.add(op1); // add Write Access operation - Write to Reserved memory bank TagAccess.Sequence.Operation op2 = opSequence.new Operation(); op2.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE); op2.WriteAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_USER); op2.WriteAccessParams.setAccessPassword(0); op2.WriteAccessParams.setOffset(0); op2.WriteAccessParams.setWriteData("BBBBCCCC"); op2.WriteAccessParams.setWriteDataLength(4); reader.Actions.TagAccess.OperationSequence.add(op2); // perform access sequence reader.Actions.TagAccess.OperationSequence.performSequence(); // if the access operation is to be terminated without meeting stop trigger (ifspecified), // stopSequence method can be called reader.Actions.TagAccess.OperationSequence.stopSequence();
Sample 2:
// RFID Reader private static Readers readers; private static ArrayList
availableRFIDReaderList; private static ReaderDevice readerDevice; private static RFIDReader reader; private EventHandler eventHandler; synchronized void performAccessSequence() { // check reader connection if (!isReaderConnected()) return; Log.d(TAG, "Start RfidAccessSequenceStart ..."); new RfidAccessSequenceStart().execute(); } public class RfidAccessSequenceStart extends AsyncTask { @Override protected Void doInBackground(Void... params) { try { addOperationSequenceRead(0, 64, MEMORY_BANK.MEMORY_BANK_USER); addOperationSequenceRead(64, 64, MEMORY_BANK.MEMORY_BANK_USER); addOperationSequenceRead(128, 64, MEMORY_BANK.MEMORY_BANK_USER); } catch (Exception ex) { Log.d("ECRT", "UI Input Paramaters Exception=" + ex.getMessage()); } try { Log.d("ECRT", "Start OperationSequence.performSequence..."); reader.Actions.TagAccess.OperationSequence.performSequence(); } catch (InvalidUsageException e) { e.printStackTrace(); } catch (OperationFailureException e) { e.printStackTrace(); } return null; } } boolean addOperationSequenceRead(int iWordOffset, int iWordCount, MEMORY_BANK memory_bank) { boolean bResult = false; TagAccess tagAccess = new TagAccess(); TagAccess.Sequence sequence = tagAccess.new Sequence(tagAccess); TagAccess.Sequence.Operation operation = sequence.new Operation(); operation.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ); operation.ReadAccessParams.setMemoryBank(memory_bank); operation.ReadAccessParams.setAccessPassword(0); operation.ReadAccessParams.setCount(iWordCount); operation.ReadAccessParams.setOffset(iWordOffset); try { reader.Actions.TagAccess.OperationSequence.add(operation); bResult = true; } catch (InvalidUsageException e) { e.printStackTrace(); } catch (OperationFailureException e) { e.printStackTrace(); } return bResult; } boolean addOperationSequenceWrite(int iWordOffset, int iWordCount, MEMORY_BANK memory_bank, String toWriteData) { boolean bResult = false; TagAccess tagAccess = new TagAccess(); TagAccess.Sequence sequence = tagAccess.new Sequence(tagAccess); TagAccess.Sequence.Operation operation = sequence.new Operation(); operation.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE); operation.WriteAccessParams.setMemoryBank(memory_bank); operation.WriteAccessParams.setAccessPassword(0); operation.WriteAccessParams.setWriteData(toWriteData); operation.WriteAccessParams.setOffset(iWordOffset); try { reader.Actions.TagAccess.OperationSequence.add(operation); bResult = true; } catch (InvalidUsageException e) { e.printStackTrace(); } catch (OperationFailureException e) { e.printStackTrace(); } return bResult; } synchronized void performAccessSequence() { // check reader connection if (!isReaderConnected()) return; Log.d(TAG, "Start RfidAccessSequenceStart ..."); new RfidAccessSequenceStart().execute(); } synchronized void stopInventory() { // check reader connection if (!isReaderConnected()) return; try { reader.Actions.Inventory.stop(); } catch (InvalidUsageException e) { e.printStackTrace(); } catch (OperationFailureException e) { e.printStackTrace(); } } //Decode the access sequence response and stop public class EventHandler implements RfidEventsListener { // Read Event Notification public void eventReadNotify(RfidReadEvents e) { // Recommended to use new method getReadTagsEx for better performance in case of large tag population TagData[] myTags = reader.Actions.getReadTags(100); if (myTags != null) { for (int index = 0; index < myTags.length; index++) { final String epc = myTags[index].getTagID(); Log.d(TAG, "EPC = " + epc); if (myTags[index].getOpCode() == ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ && myTags[index].getOpStatus() == ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) { if (myTags[index].getMemoryBankData().length() > 0) { Log.d(TAG, "Sequence=" + index + " ,Mem Bank Data " + myTags[index].getMemoryBankData()); if( index==2){ //stop for three access sequence Index: 0, 1 and 2 //if(epc.equals("AA55AA55AA55AA55AA55AA55AA55AA11")) { stopInventory(); Log.d(TAG, "Stop... "); } } } } } } // Status Event Notification public void eventStatusNotify(RfidStatusEvents rfidStatusEvents) { } }
Gen2v2 Operations
Please refer G2v2
Resetting the Reader
The RFID SDK supports performing soft-reset of the reader. A connected application shall lose connectivity to the reader, must connect back again, and is required to redo the basic steps for initializing the reader. The following example demonstrates utilization of then API function.
reader.Actions.reset();
Tag Locationing
Readers that support the Tag Locationing feature report the same in the field isTagLocationingSupported of ReaderCapabilities as true. This feature is supported only on hand-held readers and is useful to locate a specific tag in the field of view of the reader’s antenna. The default locationing algorithm supported on the reader can perform locationing only on a single antenna. reader.Actions.TagLocationing.Perform can be used to start locating a tag, and reader.Actions.TagLocationing.Stop to stop the locationing operation. The result of locationing of a tag is reported as LocationInfo in TagData and is present in TagData if tagData isContainsLocationInfo is true. tagData.LocationInfo.getRelativeDistance gives the relative distance of the tag from the reader antenna.
Performing Tag Locationing on a particular tag ID
reader.Actions.TagLocationing.Perform("E2002849491502421020B330",null);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
reader.Actions.Inventory.stop();
//The response of the tag locationing comes through eventReadNotify in the following Event Handler.
public class EventHandler implements RfidEventsListener {
// Read Event Notification
public void eventReadNotify(RfidReadEvents e) {
TagData[] myTags = reader.Actions.getReadTags(100);
if (myTags != null) {
for (int index = 0; index < myTags.length; index++) {
System.out.println("Tag ID " + myTags[index].getTagID());
if (myTags[index].isContainsLocationInfo()) {
int tag = index;
System.out.println("Tag locationing distance " +
myTags[tag].LocationInfo.getRelativeDistance());
}
}
}
}
}