RFID developers guide for Xamarin Android

Applicable Devices : HandHeld readers

Overview

This chapter provides detailed information about how to use various basic and advanced functionality to develop an Xamarin Android application using the Zebra RFID SDK for Xamarin Android.

Create The Project

  • Start by creating a new project in Visual Studio. For help, see the Create Project.
  • Refer Hello RFID to prepare basic setup to work with RFID Reader and then follow this guide

Details

Zebra RFID Xamarin consists of library in dll format that should be linked with an external Xamarin application. All available APIs are defined under the Com.Zebra.Rfid.Api3 namespace. RFIDReader is the root 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 are made using Xamarin ThreadPool.QueueUserWorkItem 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 calls all APIs in try-catch block for handling exceptions

Connection Management

Connect to an RFID Reader

Connection is the first step to talk to an RFID reader. Importing package is the first step to use any API. Import the package as follows:

using Com.Zebra.Rfid.Api3;

As first step create instance of Readers class with passing activity context as first parameter and enum value ServiceSerial as second parameter

readers = new Readers(this.context, ENUM_TRANSPORT.ServiceSerial);

The Readers class instance gives a list of all available/paired RFID readers with an Android device. Readers list is in the form of ReaderDevice class.

IList readersList = readers.AvailableRFIDReaderList; ReaderDevice readerDevice = readersList[0];

ReaderDevice class includes instance of RFIDReader class; which is root class to interface and performing all operations with RFID reader.

rfidReader.Connect();

In addition, the application can implement Readers.IRFIDReaderEventHandler in the following way to get notified for RFID reader getting attached (added) / detached (removal)

 
public class MainActivity: Activity, Java.Lang.Object, Readers.IRFIDReaderEventHandler
{
    public void RFIDReaderAppeared(ReaderDevice readerDevice)
    {
    // handle reader addition
    }
    public void RFIDReaderDisappeared(ReaderDevice readerDevice)
    {
    // handle reader removal
    }
}
                                                        

Special Connection Handling Cases

In a normal scenario, the reader connects fine, but the following are the cases which require special handling at the time of connection.

The following example demonstrates the connection is handled under try-catch block and OperationFailure exception is thrown by connection API is stored and used for further analysis.

 
    private OperationFailureException Ex;
    try {
    // Establish connection to the RFID Reader
        RfidReader.Connect();
    } catch (InvalidUsageException E) {
        E.PrintStackTrace();
    } catch (OperationFailureException E) {
        E.PrintStackTrace();
        Ex = E;
    }
                                                                

Region Is Not Configured

If the region is not configured, then exception gives RfidReaderRegionNotConfigured result the caller then gets supported regions and chooses operation regulatory region from list. Set region with required configurations

 
    if (ex.Results == RFIDResults.RfidReaderRegionNotConfigured) {
        // Get and Set regulatory configuration settings
        // RegulatoryConfig regulatoryConfig = rfidReader.Config.RegulatoryConfig;
        // RegionInfo regionInfo =
            rfidReader.ReaderCapabilities.SupportedRegions.GetRegionInfo(1);
        // regulatoryConfig.Region=regionInfo.RegionCode;
        // rfidReader.Config.RegulatoryConfig=regulatoryConfig;
        }
                                                                

Disconnect

When the application is done with the connection and operations on the RFID reader, it calls the following API to close the connection, and to release and clean up the resources.

RfidReader.Disconnect();

Note: If a reader disconnection occurs, the reader.isConnected() flag may return the value false. If the application calls reader.connect(), the application should call reader.disconnect() regardless of the flag status

Dispose

When the application main activity is destroyed, it is required to dispose the SDK instance so that it can cleanly exit (unregistration and unbind by SDK as required).

RfidReader.Dispose();

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 configurations in tutorials

Singulation

Please refer Singulation in tutorials

Tag 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.TagStorageSettings;
 // set tag storage settings on the reader with all fields
 tagStorageSettings.SetTagFields(TAG_FIELD.AllTagFields);
 Reader.Config.TagStorageSettings=tagStorageSettings;
                                                                    

Regulatory Configuration

The SDK supports managing of regulatory related parameters of a specific active RFID reader. Regulatory configuration includes the following

  • Code of selected region
  • Channel Hopping
  • Set of enabled channels

A set of enabled channels includes only such channels that are supported in the selected region. If hopping configuration is not allowed for the selected regions, a set of enabled channels is not specified.. Regulatory parameters could be retrieved and set via getRegulatoryConfig and setRegulatoryConfig API functions accordingly. getRegionInfo API. The following exampledemonstrates retrieving of current regulatory settings and configuring the RFID reader to operate in one of supported regions.

Following is general sequence to setup the region

  • gets supported regions
  • chooses operational regulatory region from list
  • Set region with required configurations i.e. hopping and set of channels
  • Application should update antenna power level and link profiles if it has cached same before changing regulatory

                // Get and Set regulatory configuration settings 
                RegulatoryConfig regulatoryConfig = reader.Config.getRegulatoryConfig(); 
                RegionInfo regionInfo = reader.ReaderCapabilities.SupportedRegions.getRegionInfo(1); 
                regulatoryConfig.setRegion(regionInfo.getRegionCode()); 
                regulatoryConfig.setIsHoppingOn(regionInfo.isHoppingConfigurable()); 
                regulatoryConfig.setEnabledChannels(regionInfo.getSupportedChannels()); 
                reader.Config.setRegulatoryConfig(regulatoryConfig);
                

Saving 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.SaveConfig();

Managing Events

The Application can register for one or more events so as to be notified of the same when it occurs. There are two main events.

  • eventReadNotify - Notifies whenever read tag event occurs with read tag data as argument. By default, the event comes with tag data. If not required, disable using function setAttachTagDataWithReadEvent.
  • eventStatusNotify - Notifies whenever status event occurs with status event data as argument.

Table

# Reader Events Detail
1 GpiEvent Not supported in Android RFID SDK.
2 BufferFullWarningEvent When the internal buffers are 90% full, this event is signaled
3 AntennaEvent Not supported in Android RFID SDK.
4 InventoryStartEvent Inventory Operation started. In case of periodic trigger, this event is triggered for each period.
5 InventoryStopEvent Inventory Operation has stopped. In case of periodic trigger this event is triggered for each period.
6 AccessStartEvent Not supported in Android RFID SDK
7 AccessStopEvent Not supported in Android RFID SDK
8 DisconnectionEvent Event notifying disconnection from the Reader. The Application can call reconnect method periodically to attempt reconnection or call disconnect method to cleanup and exit.
9 BufferFullEvent When the internal buffers are 100% full, this event is signaled and tags are discarded in FIFO manner.
10 NxpEasAlarmEvent Not Supported in Android RFID SDK.
6 ReaderExceptionEvent Event notifying that an exception has occurred in the Reader. When this event is signaled, StatusEventData. ReaderExceptionEventData. ReaderExceptionEventType can be called to know the reason for the exception which is coming as part of Events.StatusEventArgs. The Application can continue to use the connection if the reader renders is usable.
7 HandheldTriggerEvent A hand-held Gun/Button event Pull/Release has occurred..
8 TemperatureAlarmEvent When Temperature reaches Threshold level, this event is generated. The event data contains source name (PA/Ambient),current Temperature and alarm Level (Low, High or Critical)
9 BatteryEvent Events notifying different levels of battery, state of the battery, if charging or discharging.
10 OperationEndSummaryEvent Event generated when operation end summary has been generated. The data associated with the event contains total rounds, total number of tags and total time in micro secs.
11 PowerEvent Events which notify the different power states of the reader device. The event data contains cause, voltage, current and power

Registering for read tag data notification


        EventHandler eventHandler = new EventHandler();
        Reader.Events.AddEventsListener(eventHandler);
        // Subscribe required status notification
        Reader.Events.SetInventoryStartEvent(true);
        myReader.Events.setInventoryStopEvent(true);
        // enables tag read notification. if this is set to false, no tag read notification is send
        myReader.Events.SetTagReadEvent(true);
        myReader.Events.SetReaderDisconnectEvent(true);
        myReader.Events.SetBatteryEvent(true);
        

Implement the RfidEventsLister class to receive event notifications


    class EventHandler : Java.Lang.Object, IRfidEventsListener
    {
        // 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 = myReader.Actions.GetReadTags(100);
            if (myTags != null)
            {
                for (int index = 0; index < myTags.Length; index++)
                {
                    Console.Out.WriteLine("Tag ID " + myTags[index].TagID);
                    if (myTags[index].OpCode == ACCESS_OPERATION_CODE.AccessOperationRead
                        &&
                        myTags[index].OpStatus == ACCESS_OPERATION_STATUS.AccessSuccess)
                        {
                                if (myTags[index].MemoryBankData.Length > 0)
                                {
                                    Console.Out.WriteLine(" Mem Bank Data " + myTags[index].MemoryBankData);
                                }
                        }
                }
            }
        }
        // Status Event Notification
        public void EventStatusNotify(RfidStatusEvents e)
        {
            Console.Out.WriteLine("Status Notification: " +
            e.StatusEventData.StatusEventType);
        }
    }

Unregistering for read tag data notification


Reader.Events.RemoveEventsListener(eventHandler);;

Device status, such as battery, power, and temperature, is obtained through events after initiating the following API


                                                    Reader.Config.GetDeviceStatus(battery, power, temperature);
                                                

Response to the above API comes as battery event, power event, and temperature event according to the set boolean value in the respective parameters. The following is an example of how to get these events


    try
    {
        if (Reader != null)
        Reader.Config.GetDeviceStatus(true, false, false); else
        StopTimer();
    }
    catch (InvalidUsageException e)
    {
        e.PrintStackTrace();
    }
    catch (OperationFailureException e)
    {
        e.PrintStackTrace();
    }

Basic 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.TagStorageSettings;
Reader.Config.TagStorageSettings=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.TagStorageSettings;
    TAG_FIELD[] tagField = new TAG_FIELD[4];
    tagField[0] = TAG_FIELD.Pc; tagField[1] =
    TAG_FIELD.PeakRssi; tagField[2] =
    TAG_FIELD.TagSeenCount; tagField[3] =
    TAG_FIELD.Crc;
    tagStorageSettings.SetTagFields(tagField);
    Reader.Config.TagStorageSettings=tagStorageSettings;

                                                                

Tag storage usecases

  • Simple Inventory (Continuous

    Please refer inventory in tutorials

  • Simple Access Operations - On Single Tag

    Tag Access operations are performed on a specific tag or applied on tags that match a specific Access-Filter. If no Access-Filter is specified, the Access Operation is performed on all tags in the field of view of chosen antennas. This section covers the Simple Tag Access operation on a specific tag which is in the field of view of any of the antennas of the connected RFID reader.

    // dpo should be disabled before any access operation

    Reader.Config.DPOState=DYNAMIC_POWER_OPTIMIZATION.Disable;
  • Read

    Please refer read

  • Write, Block-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 = new
        TagAccess.BlockEraseAccessParams(tagAccess);
    blockEraseAccessParams.AccessPassword=0;
    blockEraseAccessParams.MemoryBank=(MEMORY_BANK.MemoryBankUser); // user memory bank
    blockEraseAccessParams.Offset=0; // start erasing from word offset 0
    blockEraseAccessParams.Count=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 AccessOperationBlockPermaLock and TagData.getOpStatus indicating the result of the operation; if TagData.OpStatus is AccessSuccess, TagData.getMemoryBankData contains the Block-Permalock Mask Data

    
                                                                            // Block-Perma Lock the tag
        String tagId = "1234ABCD00000000000025B1";
        TagAccess tagAccess = new TagAccess();
        TagAccess.BlockPermalockAccessParams blockPermalockAccessParams = new
        TagAccess.BlockPermalockAccessParams(tagAccess);
        byte[] permalockMask = new byte[] { (byte)0xF0, 0x00 };
        blockPermalockAccessParams.ReadLock=true;
        blockPermalockAccessParams.MemoryBank=MEMORY_BANK.MemoryBankUser;
        blockPermalockAccessParams.Offset=0; // start BlockPermalock from word offset 0
        blockPermalockAccessParams.Count=1; // start BlockPermalock from word offset 0
        blockPermalockAccessParams.SetMask(permalockMask);
        blockPermalockAccessParams.MaskLength=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 = new
            TagAccess.LockAccessParams(tagAccess);
        /* lock now */
        lockAccessParams.SetLockPrivilege(LOCK_DATA_FIELD.LockUserMemory,
        LOCK_PRIVILEGE.LockPrivilegeReadWrite);
        lockAccessParams.AccessPassword=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 = new
        TagAccess.KillAccessParams(tagAccess);
        killAccessParams.KillPassword=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, bool bPrefilter)

    Example

    Reader.Actions.TagAccess.ReadWait("2F2203447334C3100002EA55", readAccessParams, null, true);

    writeWait and blockWriteWait APIs have additional parameter for specifying whether to use TID memory bank as prefilter.

    WriteWait(Java.Lang.String tagID, TagAccess.WriteAccessParams writeAccessParams, AntennaInfo antennaInfo, TagData tagData, bool bPrefilter, bool bTIDPrefilter)

    Apply EPC memory bank as prefilter

    Reader.Actions.TagAccess.WriteWait(tagId, writeAccessParams, null, tagData, true, false);

    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 InvBNotInvAOrDsrtSlNotAsrtSl with InvB inventory state.TagAccess.WriteAccessParams have additional parameter to define number of retries

    WriteRetries=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

    AccessOperationWaitTimeout=int timeout

    Method to set access operation timeout for all synchronous tag access operations APIs

    Reader.Config.AccessOperationWaitTimeout=1000;

Advanced operations

Using Prefilters

Please refer Prefilters Tutorial

Singulation

Please refer Singulation

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.MemoryBank=MEMORY_BANK.MemoryBankReserved;
    accessFilter.TagPatternA.SetTagPattern(new byte[] { 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00,
    0x00, 0x00 }); accessFilter.TagPatternA.TagPatternBitCount=(8 * 8);
    accessFilter.TagPatternA.BitOffset=0;
    accessFilter.TagPatternA.SetTagMask(tagMask);
    accessFilter.TagPatternA.TagMaskBitCount=tagMask.Length * 8;
    accessFilter.AccessFilterMatchPattern=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 InventoryStopEvent/.

    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:

    
    Reader.Events.SetInventoryStartEvent(true);
    Reader.Events.SetInventoryStopEvent(true); // Data Read Notification from the reader
    class EventHandler : Java.Lang.Object, IRfidEventsListener
    {
        // Read Event Notification
        public void EventReadNotify(RfidReadEvents e)
        {
            TagData tag = e.ReadEventData.TagData;
            Console.Out.WriteLine("Tag ID " + tag.TagID);
            if (tag.OpCode == ACCESS_OPERATION_CODE.AccessOperationRead &&
                    tag.OpStatus == ACCESS_OPERATION_STATUS.AccessSuccess)
            {
                if (tag.MemoryBankData.Length > 0)
                {
                Console.Out.WriteLine(" Mem Bank Data " + tag.MemoryBankData);
                }
            }
        }
        // Status Event Notification
        public void EventStatusNotify(RfidStatusEvents e){
            if (e.StatusEventData.StatusEventType == STATUS_EVENT_TYPE.InventoryStartEvent)
            {
            // Access operation started
            }
            else if (e.StatusEventData.StatusEventType == STATUS_EVENT_TYPE.InventoryStopEvent)
            {
            // 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.MemoryBank=MEMORY_BANK.MemoryBankEpc;
     accessFilter.TagPatternA.SetTagPattern(new byte[] { 0x11, 0x22 });
     accessFilter.TagPatternA.TagPatternBitCount=2 * 8;
     accessFilter.TagPatternA.BitOffset=0;
     accessFilter.TagPatternA.SetTagMask(tagMask);
     accessFilter.TagPatternA.TagMaskBitCount=tagMask.Length * 8;
     accessFilter.AccessFilterMatchPattern=FILTER_MATCH_PATTERN.A;
     // Write user memory bank data
     TagAccess tagAccess = new TagAccess();
     TagAccess.WriteAccessParams writeAccessParams = new
    TagAccess.WriteAccessParams(tagAccess);
     String writeData = "ABCDABCD";
     writeAccessParams.AccessPassword=0;
     writeAccessParams.MemoryBank=MEMORY_BANK.MemoryBankUser;
     writeAccessParams.Offset=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

    
    Reader.Actions.TagAccess.OperationSequence.DeleteAll();
    // add Write Access operation - Write to User memory
        TagAccess tagAccess = new TagAccess();
        TagAccess.Sequence opSequence = new TagAccess.Sequence(tagAccess, tagAccess);
        TagAccess.Sequence.Operation op1 = new
    TagAccess.Sequence.Operation(opSequence);
        op1.AccessOperationCode=ACCESS_OPERATION_CODE.AccessOperationWrite;
        op1.WriteAccessParams.MemoryBank=MEMORY_BANK.MemoryBankUser;
        op1.WriteAccessParams.AccessPassword=0;
        op1.WriteAccessParams.Offset=0;
        op1.WriteAccessParams.SetWriteData("55667788" );
        op1.WriteAccessParams.WriteDataLength=4;
        Reader.Actions.TagAccess.OperationSequence.Add(op1);
    // add Write Access operation - Write to Reserved memory bank
        TagAccess.Sequence.Operation op2 = new TagAccess.Sequence.Operation(opSequence);
        op2.AccessOperationCode=ACCESS_OPERATION_CODE.AccessOperationWrite;
        op2.WriteAccessParams.MemoryBank=MEMORY_BANK.MemoryBankUser;
        op2.WriteAccessParams.AccessPassword=0;
        op2.WriteAccessParams.Offset=0;
        op2.WriteAccessParams.SetWriteData("BBBBCCCC");
    op2.WriteAccessParams.WriteDataLength=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();
                                                                    

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.Period=2000; // perform inventory for 2 seconds
    // stop trigger
    triggerInfo.StopTrigger.setTriggerType(STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_DURATION);
    triggerInfo.StopTrigger.DurationMilliSeconds=200; // stop after200 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.TriggerType=START_TRIGGER_TYPE.StartTriggerTypeImmediate;
    // stop trigger
    triggerInfo.StopTrigger.TriggerType=STOP_TRIGGER_TYPE.StopTriggerTypeAccessNAttemptsWithTimeout;
        triggerInfo.StopTrigger.NumAttempts.SetN((short)3); // perform 3 rounds of inventory
    triggerInfo.StopTrigger.NumAttempts.Timeout=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.TriggerType=START_TRIGGER_TYPE.StartTriggerTypeImmediate;
    // stop trigger
    triggerInfo.StopTrigger.TriggerType=STOP_TRIGGER_TYPE.StopTriggerTypeTagObservationWithTimeout;
    triggerInfo.StopTrigger.TagObservation.SetN((short)100); // stop inventory after reading 100 tags
    triggerInfo.StopTrigger.TagObservation.Timeout=3000; // timeout after 3 seconds
    // report back all read tags after getting 100 unique tags or after 3 second
                                                                    
  • 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.TriggerType=START_TRIGGER_TYPE.StartTriggerTypeHandheld;
    // Start Inventory when the Handheld trigger is pressed
    triggerInfo.StartTrigger.Handheld.HandheldTriggerEvent=
    HANDHELD_TRIGGER_EVENT_TYPE.HandheldTriggerPressed;
    triggerInfo.StopTrigger.TriggerType=STOP_TRIGGER_TYPE.StopTriggerTypeDuration;
    // Stop Inventory when the Handheld trigger is released
    triggerInfo.StopTrigger.Handheld.HandheldTriggerEvent =
    HANDHELD_TRIGGER_EVENT_TYPE.HandheldTriggerReleased;
    triggerInfo.StopTrigger.Handheld.HandheldTriggerTimeout=0;
                                                                    
  • Set the trigger using the following APIs, perform inventory and other operations which are using above set start and stop triggers.
    
    Reader.Config.StartTrigger=triggerInfo.StartTrigger;
    Reader.Config.StopTrigger=triggerInfo.StopTrigger;
    Reader.Actions.Inventory.Perform();
                                                                    

Gen2v2 Operations

This section covers the Gen2V2 operations that an application needs to performed on a RFID Reader which supports Gen2v2 commands such as authenticate, untraceable, and readbuffer

Authenticate

Authenticate operation takes in the message data and message length with few of the options such as decision on including the response length, sending the response, etc. The AuthenticateParams contain the message data, message length and other settings to be sent to the reader. The accessfilter parameter contains the tag pattern on which the operation occurs.


// authenticate
// Tag Pattern A
AccessFilter accessFilter = null;
accessFilter.TagPatternA.MemoryBank=MEMORY_BANK.MemoryBankEpc;
accessFilter.TagPatternA.SetTagPattern(new byte[] { (byte)0xe2, (byte)0xc0 });
accessFilter.TagPatternA.TagPatternBitCount=16;
accessFilter.TagPatternA.BitOffset=32;
accessFilter.TagPatternA.SetTagMask(tagMask);
accessFilter.TagPatternA.TagMaskBitCount=tagMask.Length * 8;
accessFilter.AccessFilterMatchPattern=(FILTER_MATCH_PATTERN.A);
// G2V2 authenticate
// Gen2V2 gen2V2 - new Gen2v2 ();
Gen2v2.AuthenticateParams AuthenticateParams = new Gen2v2.AuthenticateParams(gen2V2);
AuthenticateParams.MsgData="2001FD5D8048F48DD09AAD22000111";
AuthenticateParams.MsgLen=120;
AuthenticateParams.IncrespLen=true;
AuthenticateParams.StoreResp=false;
AuthenticateParams.SentResp=true;
try
{
    Reader.Actions.Gen2v2Access.Authenticate(AuthenticateParams, accessFilter,null);
}
catch (InvalidUsageException e)
{
    e.PrintStackTrace();
}
catch (OperationFailureException e)
{
    e.PrintStackTrace();
}
// Keep getting response in the eventReadNotify event if registered

The response and result in the Tagdata will contain the information obtained from the operation


public class EventHandler : Java.Lang.Object, IRfidEventsListener
{
    // 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++)
            {
                Console.Out.WriteLine("Tag ID " + myTags[index].TagID);
                if ((myTags[index].G2v2OpStatus != null) &&
                    (myTags[index].G2v2OpStatus == GEN2V2_OPERATION_STATUS.AccessSuccess))
                {
                    if (myTags[index].G2v2Response.Any())
                    {
                    Console.Out.WriteLine("Gen2v2 authenticate response " +
                    myTags[index].G2v2Response);
                    }
                }
            }
        }
    }// Status Event Notification
    public void EventStatusNotify(RfidStatusEvents e)
    {
        Console.Out.WriteLine("Status Notification: " + e.StatusEventData.StatusEventType);
        if (e.StatusEventData.StatusEventType == STATUS_EVENT_TYPE.InventoryStartEvent)
        {
        // Access operation started
        }
        else if (e.StatusEventData.StatusEventType ==
        STATUS_EVENT_TYPE.InventoryStopEvent)
        {
        // Access operation stopped - Can be used to signal waiting thread
        }
    }
}

Untraceable

Untraceable operation lets the user decide which memory bank to show and what length of the memory bank to show. Here the UntraceableParams contain the settings and password. The accessfilter parameter contains the tag pattern on which the operation occurs


// untraceable
AccessFilter accessFilter = new AccessFilter();
byte[] tagMask = new byte[] { (byte)0xff, (byte)0xff, };
// Tag Pattern A
accessFilter.TagPatternA.MemoryBank=MEMORY_BANK.MemoryBankEpc;
accessFilter.TagPatternA.SetTagPattern("2f22");
accessFilter.TagPatternA.TagPatternBitCount=32;
accessFilter.TagPatternA.BitOffset=32;
accessFilter.TagPatternA.SetTagMask(tagMask);
accessFilter.TagPatternA.TagMaskBitCount=tagMask.Length * 8;
accessFilter.AccessFilterMatchPattern=FILTER_MATCH_PATTERN.A;
Gen2v2 gen2V2 = new Gen2v2();
Gen2v2.UntraceableParams UntraceableParams = new
Gen2v2.UntraceableParams(gen2V2);
UntraceableParams.Password=0;
UntraceableParams.ShowEpc=true;
UntraceableParams.HideEpc=false;
UntraceableParams.ShowUser=false;
UntraceableParams.EpcLen=6;
UntraceableParams.Tid=UNTRACEABLE_TID.HideAllTid;
try
{
Reader.Actions.Gen2v2Access.Untraceable(UntraceableParams, accessFilter,
null);
}
catch (InvalidUsageException e)
{
e.PrintStackTrace();
}
catch (OperationFailureException e)
{
e.PrintStackTrace();
}

After this, when inventory is run, the effects of the settings sent are seen in untraceable operation

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

// Performing Tag Locationing on a particular tag ID
Reader.Actions.TagLocationing.Perform("E2002849491502421020B330", null, null);
    try
    {
        Thread.Sleep(5000);
    }
    catch (Java.Lang.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 : Java.Lang.Object, IRfidEventsListener
    {
    // 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++)
                {
                    Console.Out.WriteLine("Tag ID " + myTags[index].TagID);
                    if (myTags[index].IsContainsLocationInfo)
                    {
                        int tag = index; Console.Out.WriteLine("Tag locationing distance " +
                        myTags[tag].LocationInfo.RelativeDistance);
                    }
                }
            }
        }
    }
                                                                

Trigger Mode - RFID and Barcode

To set the trigger mode to work as RFID or Barcode functionality, use the following API.

rfidReader.Config.TriggerMode=(ENUM_TRIGGER_MODE.RfidMode, true);

First parameter is mode enum value and second parameter indicates whether SDK should take care of disabling scanner plugin. When second parameter is true; SDK executes code to disable scanner plugin.

Note:It is recommended that Application handle scanner plugin enable/disable in pause and resume activity respectively to avoid cross triggering to functionality not required.

Refer DataWedge documentation at following links