• Api Documentation
  • Programmer's Guide
Show / Hide Table of Contents
  • Introduction
  • Generic Reader Interface
    • Connecting to Reader
    • Knowing the Reader Capabilities
    • Configuring the Reader
    • Managing Events
    • Managing Tags
    • Basic Operations
    • Advanced Operations
    • Tag Locationing
    • NXP Commands
    • Impinj Commands
    • Disconnecting from the Reader
  • Reader Management Interface
    • Connecting to the Reader
    • Updating Firmware of the Software
    • Read Points
    • Antenna Modes
    • Reader and System Information
    • Managing Reader Configurations
    • Managing LLRP connection and configuration
    • USB Operation Mode
    • GPI Debounce Time
    • Local Time
    • Time Zone
    • User LED
    • Reader Statistics
    • Restarting the Reader
    • Disconnecting the Reader
    • Cable Loss Compensation
    • Idle Mode
    • Power Negotiation
    • Region configuration
    • User App Deployment
    • User Management

Advanced Operations

Tag Event Reporting

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;

TriggerInfo triggerInfo = new TriggerInfo();

triggerInfo.EnableTagEventReport = true;

triggerInfo.TagEventReportInfo.ReportNewTagEvent = TAG_EVENT_REPORT_TRIGGER.MODERATED;

triggerInfo.TagEventReportInfo.ReportTagInvisibleEvent = TAG_EVENT_REPORT_TRIGGER.MODERATED;

triggerInfo.TagEventReportInfo.ReportTagBackToVisibilityEvent = TAG_EVENT_REPORT_TRIGGER.MODERATED;

triggerInfo.TagEventReportInfo.NewTagEventModeratedTimeoutMilliseconds = 100;

triggerInfo.TagEventReportInfo.TagInvisibleEventModeratedTimeoutMilliseconds = 100;

triggerInfo.TagEventReportInfo.TagBackToVisibilityModeratedTimeoutMilliseconds = 100;

rfidApi.Actions.Inventory.Perform(null, triggerInfo, null);

TAG_EVENT reported as part of TAG_DATA indicates the visibility state of the Tag.

Using Pre-Filters

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 IsTagInventoryStateAwareSingulationSupported in the ReaderCapabilities class.

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- rfidApi.Actions.PreFilters.Add) so that while performing inventory, tags can be instructed to participate (singulation - rfidApi.Config.Antennas[1].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 method rfidApi.Actions.PreFilters.Add.

Selected Flag

Tags provide a selected flag, SL, which can be asserted or deasserted based on match criteria using method rfidApi.Actions.PreFilters.Add

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 method rfidApi.Actions.PreFilters.Add 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 re compute 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 rfidApi.ReaderCapabilites.MaxNumPreFilters property which can be known using the ReaderCapabilities.

The application can set pre-filters using rfidApi.Actions.PreFilters.Add and remove using rfidApi.Actions.PreFilters.Delete.

State-Unaware Singulation

// Add state unaware pre-filter

PreFilters.PreFilter filter = new PreFilters.PreFilter();

byte[] tagMask = new byte[2] { 0x12, 0x11 };

filter.AntennaID = 3;// Set this filter for Antenna ID 3

filter.TagPattern = tagMask;// Tags which starts with 0x1211

filter.TagPatternBitCount = (uint)tagMask.Length * 8;

filter.BitOffset = 32; // skip PC bits (always it should be in bit length)

filter.MemoryBank = MEMORY_BANK.MEMORY_BANK_EPC;

filter.FilterAction = FILTER_ACTION.FILTER_ACTION_STATE_UNAWARE; // use state unaware singulation

filter.StateUnawareAction.Action = STATE_UNAWARE_ACTION.STATE_UNAWARE_ACTION_UNSELECT;  // do not select the tags that match the pre-filter criteria

rfidApi.Actions.PreFilters.Add(filter);

State-Aware Singulation

// Add state aware pre-filter

PreFilters.PreFilter filter = new PreFilters.PreFilter();

byte[] tagMask = new byte[2] { 0x12, 0x11 };

filter.AntennaID = 3;// Set this filter for Antenna ID 3

filter.TagPattern = tagMask;// Tags which starts with 0x1211

filter.TagPatternBitCount = (uint)tagMask.Length * 8;

filter.BitOffset = 32; // skip PC bits (always it should be in bit length)

filter.MemoryBank = MEMORY_BANK.MEMORY_BANK_EPC;

filter.FilterAction = FILTER_ACTION.FILTER_ACTION_STATE_AWARE; // use state aware singulation

filter.StateAwareAction.Target = TARGET.TARGET_INVENTORIED_STATE_S1; // inventoried flag of session S1 of matching tags to B

filter.StateAwareAction.Action = STATE_AWARE_ACTION.STATE_AWARE_ACTION_INV_B; // not to select tags that match the criteria

rfidApi.Actions.PreFilters.Add(filter);

// It is also required to set appropriate singulation control not to 

// get tags with inventoried flag B for session 1

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 rfidApi.Config.Antennas[1].SetSingulationControl(). Singulation Control must be specified with respect to each Antenna like Pre-Filters.

State-Unaware Singulation

// Set the singulation control

Antennas.SingulationControl s1_singulationControl = new Antennas.SingulationControl();

s1_singulationControl.Session = SESSION.SESSION_S1; // Set session to operate on S1. If not specified, reader uses its own way of implementing the state-unware singulation

rfidApi.Config.Antennas[3].SetSingulationControl(s1_singulationControl);

State-Aware Singulation
// Set the singulation control

Antennas.SingulationControl s1_singulationControl = new Antennas.SingulationControl();

s1_singulationControl.Session = SESSION.SESSION_S1;

s1_singulationControl.Action.InventoryState = INVENTORY_STATE.INVENTORY_STATE_B;

s1_singulationControl.Action.SLFlag = SL_FLAG.SL_FLAG_DEASSERTED;

s1_singulationControl.Action.PerformStateAwareSingulationAction = true;

rfidApi.Config.Antennas[3].SetSingulationControl(s1_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.

Using Triggers

Triggers are the conditions that should be 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.

The following are some use-cases of using TRIGGER_INFO:

  1. GPI based Inventory – Start inventory when GPI port ‘n’ changes state to ‘TRUE’ and stop inventory when GPI port ‘n’ changes state to ‘FALSE’.
TriggerInfo triggerInfo = new TriggerInfo();

// start trigger GPI port 1 changes to true

triggerInfo.StartTrigger.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_GPI;

triggerInfo.StartTrigger.GPI.PortNumber = 1;

triggerInfo.StartTrigger.GPI.GPIEvent = true;

// stop trigger GPI port 1 changes to false

triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_GPI_WITH_TIMEOUT;

triggerInfo.StopTrigger.GPI.PortNumber = 1;

triggerInfo.StopTrigger.GPI.GPIEvent = false; 

triggerInfo.StopTrigger.GPI.Timeout = 1000; // 1 sec

// report back each tag report as and when it is read by Reader

triggerInfo.TagReportTrigger = 1;
  1. Periodic Inventory – Start inventory at a specified time for a specified duration repeatedly.
TriggerInfo triggerInfo = new TriggerInfo();

// start inventory on 12th of this month and 12am and runs 200 milliseconds of every 2 seconds

triggerInfo.StartTrigger.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_PERIODIC;

// perform inventory for 2 seconds

triggerInfo.StartTrigger.Periodic.Period = 2000; 

// start time

     DateTime currentTime = DateTime.UtcNow;

     DateTime startTime = new DateTime(currentTime.Year, currentTime.Month, 12, 12, currentTime.Minute, currentTime.Second);

triggerInfo.StartTrigger.Periodic.StartTime = startTime;

// stop trigger 

triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_DURATION;

// stop after 200 milliseconds

triggerInfo.StopTrigger.Duration = 200; 

// report back all read tags after completion of one round of inventory (i.e. one period)

triggerInfo.TagReportTrigger = 0;
  1. 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.
TriggerInfo triggerInfo = new TriggerInfo();

// start inventory immediate

triggerInfo.StartTrigger.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE;

// stop trigger 

triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_N_ATTEMPTS_WITH_TIMEOUT;

// perform 3 rounds of inventory

triggerInfo.StopTrigger.NumAttempts.N = 3; 

// timeout after 3 seconds

triggerInfo.StopTrigger.NumAttempts.Timeout = 3000; 

// report back all read tags after 3 rounds of inventory

triggerInfo.TagReportTrigger = 0;
  1. 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.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE;

// stop trigger 

triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_TAG_OBSERVATION_WITH_TIMEOUT;

triggerInfo.StopTrigger.TagObservation.N = 100; // stop inventory after reading 100 tags

triggerInfo.StopTrigger.NumAttempts.TimeoutMilliseconds = 3000; // timeout after 3 seconds

// report back all read tags after getting 100 unique tags or after 3 seconds

triggerInfo.TagReportTrigger = 0;
  1. Periodic Tag Reporting - Tags will be periodically reported on a specified timer interval elapsed. ReportTriggers takes precedence over TagReportTrigger property. In order to use TagReportTrigger feature, set the ReportTriggers.Period set to 0.
TriggerInfo triggerInfo = new TriggerInfo();

// Tags will be periodically reported in every 10 seconds

triggerInfo.ReportTriggers.Period = 10;

Inventory

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.

TriggerInfo triggerInfo = new TriggerInfo();

// perform inventory on antenna 1 & 3

ushort[] antennaList = new ushort[2] { 1, 3 };

AntennaInfo antennaInfo = new AntennaInfo(antennaList);

// start inventory immediate

triggerInfo.StartTrigger.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE;

// stop trigger 

triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_N_ATTEMPTS_WITH_TIMEOUT;

// perform 1 round of inventory

triggerInfo.StopTrigger.NumAttempts.N = 1; 

triggerInfo.StopTrigger.NumAttempts.Timeout = 0; // reader default timeout

// report back all read tags after 1 round of inventor

triggerInfo.TagReportTrigger = 0;

// perform inventory

rfidApi.Actions.Inventory.Perform(null, triggerInfo, antennaInfo);

Using Post-Filters

Post-filters are those filters which are applied on the Tags that the reader received through the pre-filters (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 0x1122 and 0x2233.

PostFilter postFilter = new PostFilter();

byte[] tagMask = new byte[2] { 0xff, 0xff };

// Tag Pattern A 

postFilter.TagPatternA.MemoryBank = MEMORY_BANK.MEMORY_BANK_EPC;

postFilter.TagPatternA.TagPattern = new byte[2] { 0x11, 0x22 };

postFilter.TagPatternA.TagPatternBitCount = 2 * 8;

postFilter.TagPatternA.BitOffset = 0;

postFilter.TagPatternA.TagMask = tagMask;

postFilter.TagPatternA.TagMaskBitCount = (uint)tagMask.Length * 8;

// Tag Pattern B

postFilter.TagPatternB.MemoryBank = MEMORY_BANK.MEMORY_BANK_EPC;

postFilter.TagPatternB.TagPattern = new byte[2] { 0x22, 0x33 };

postFilter.TagPatternB.TagPatternBitCount = 2 * 8;

postFilter.TagPatternB.BitOffset = 32; //skip PC 

postFilter.TagPatternB.TagMask = tagMask;

postFilter.TagPatternB.TagMaskBitCount = (uint)tagMask.Length * 8;

postFilter.MatchPattern = MATCH_PATTERN.NOTA_AND_NOTB;

// perform inventory with post filter

rfidApi.Actions.Inventory.Perform(postFilter, 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 IsRssiFilterSupported of ReaderCaps. The following code snippet does filtering of tags which have RSSI value in range -40 to -10.

PostFilter postFilter = new PostFilter();

postFilter.UseRSSIRangeFilter = true;

postFilter.RssiRangeFilter.MatchRange = MATCH_RANGE.WITHIN_RANGE;

postFilter.RssiRangeFilter.PeakRSSILowerLimit = -40;

postFilter.RssiRangeFilter.PeakRSSIUpperLimit = -10;

rfidApi.Actions.Inventory.Perform(postFilter, null, null);

Access

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.

AccessFilter accessFilter = new AccessFilter();

byte[] tagMask = new byte[8] { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

// Tag Pattern A 

accessFilter.TagPatternA.MemoryBank = MEMORY_BANK.MEMORY_BANK_RESERVED;

accessFilter.TagPatternA.TagPattern = new byte[8] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

accessFilter.TagPatternA.TagPatternBitCount = 8 * 8;

accessFilter.TagPatternA.BitOffset = 0;

accessFilter.TagPatternA.TagMask = tagMask;

accessFilter.TagPatternA.TagMaskBitCount = (uint)tagMask.Length * 8;

// Tag Pattern B

accessFilter.TagPatternB = null;

accessFilter.MatchPattern = 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 Dll signals the rfidApi.Events.StatusNotify event with event data as ACCESS_STOP_EVENT. The Application can call the method rfidApi.Actions.TagAccess.GetLastAccessResult to know the result. In case of Read access operation (rfidApi.Actions.TagAccess.ReadEvent) the event rfidApi.Events.ReadNotify is signalled when Tags are reported.

The following snippet shows a sample write-access operation:

// Create Event to signify access operation complete

AutoResetEvent AccessComplete;

AccessComplete = new AutoResetEvent(false);

rfidApi.Events.NotifyAccessStartEvent = true;

rfidApi.Events.NotifyAccessStopEvent = true;

rfidApi.Events.StatusNotify += new Events.StatusNotifyHandler(Events_StatusNotify);

// Status Notification from the reader

public void Events_StatusNotify(object sender, Events.StatusEventArgs e)

{

    switch (e.StatusEventData.StatusEventType)

    {

        case Events.STATUS_EVENT_TYPE.ACCESS_START_EVENT:

            AccessComplete.Reset();

            break;

        case Events.STATUS_EVENT_TYPE.ACCESS_STOP_EVENT:

            AccessComplete.Set();

            break;

    }

}

// Access Filter - EPC ID starting with 0x1122

AccessFilter accessFilter = new AccessFilter();

byte[] tagMask = new byte[2] { 0xff, 0xff };

// Tag Pattern A 

accessFilter.TagPatternA.MemoryBank = MEMORY_BANK.MEMORY_BANK_EPC;

accessFilter.TagPatternA.TagPattern = new byte[2] { 0x11, 0x22};

accessFilter.TagPatternA.TagPatternBitCount = 2 * 8;

accessFilter.TagPatternA.BitOffset = 0;

accessFilter.TagPatternA.TagMask = tagMask;

accessFilter.TagPatternA.TagMaskBitCount = (uint)tagMask.Length * 8;

// Tag Pattern B

accessFilter.TagPatternB = null;

accessFilter.MatchPattern = MATCH_PATTERN.A;

// Write user memory bank data

TagAccess.WriteAccessParams writeParams = new TagAccess.WriteAccessParams();

byte[] writeData = new byte[4] { 0xff, 0xff, 0xff, 0xff };

writeParams.AccessPassword = 0;

writeParams.MemoryBank = MEMORY_BANK.MEMORY_BANK_USER;

writeParams.ByteOffset = 0;

writeParams.WriteDataLength = (uint)writeData.Length;

writeParams.WriteData = writeData;

// Asynchronous write operation

rfidApi.Actions.TagAccess.WriteEvent(writeParams, accessFilter, null);

// wait for access operation to complete

AccessComplete.WaitOne();

uint successCount = 0;

uint failureCount = 0;

// Get Access operation results

rfidApi.Actions.TagAccess.GetLastAccessResult(ref successCount, ref failureCount);

Using Access Sequence

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 rfidApi.ReaderCapabilites.MaxNumOperationsInAccessSequenceof ReaderCapabilities class.

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 rfidApi.Actions.TagAccess.OperationSequence.Delete and finally de-initialized if no more needed by calling the function rfidApi.Actions.TagAccess.OperationSequence.DeleteAll().

// Create Event to signify access sequence operation complete

AutoResetEvent AccessComplete;

AccessComplete = new AutoResetEvent(false);

// add Write Access operation - Write to User memory

TagAccess.Sequence.Operation op1 = new TagAccess.Sequence.Operation();

op1.AccessOperationCode = ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE;

op1.WriteAccessParams.MemoryBank = MEMORY_BANK.MEMORY_BANK_USER;

op1.WriteAccessParams.AccessPassword = 0;

op1.WriteAccessParams.ByteOffset = 0;

op1.WriteAccessParams.WriteData = new byte[4] { 0x55, 0x66, 0x77, 0x88 };

op1.WriteAccessParams.WriteDataLength = 4;

rfidApi.Actions.TagAccess.OperationSequence.Add(op1);

// add Write Access operation - Write to Reserved memory bank

TagAccess.Sequence.Operation op2 = new TagAccess.Sequence.Operation();

op2.AccessOperationCode = ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE;

op2.WriteAccessParams.MemoryBank = MEMORY_BANK.MEMORY_BANK_USER;

op2.WriteAccessParams.AccessPassword = 0;

op2.WriteAccessParams.ByteOffset = 0;

op2.WriteAccessParams.WriteData = new byte[4] { 0xBB, 0xBB, 0xBB, 0xBB };

op2.WriteAccessParams.WriteDataLength = 4;

rfidApi.Actions.TagAccess.OperationSequence.Add(op1);

// perform access sequence

rfidApi.Actions.TagAccess.OperationSequence.PerformSequence(null, null, null);

// wait for access operation complete

AccessComplete.WaitOne();

// get the access operation result

uint successCount = 0;

uint failureCount = 0;

rfidApi.Actions.TagAccess.GetLastAccessResult(ref successCount, ref failureCount);

// if the access operation is to be terminated without meeting stop trigger (if specified), 

// stopSequence method can be called

rfidApi.Actions.TagAccess.OperationSequence.StopSequence();
Back to top