We have a rule: we never talk directly to interrogators, we always use BizTalk RFID DSPI providers to abstract hardware. But rules are made to be broken, so every now and then we have to use raw Basic Reader Interface (BRI) commands over the DSPI. And from time to time we have to write an application entirely over BRI. This post is about one of this times.
One of the more important tasks we have to do on RFID projects is the site survey. On this site surveys we usually try a bunch of portal topologies, antennas, orientations and settings, measuring the reading (or writing) experience. DSPI provider is focused on generalities, not specialization, so in order to get specific parameters like Received Signal Strength Indication (RSSI) we have to write our own antenna tuning application from ground up.
<update>It turns out that DSPI does support RSSI on vendor specific data</update>
The good news is it’s really easy. We often use Intermec’s products, and the SDK is really easy to integrate with .NET.
Intermec has 2 approaches:
- Advanced BRI: higher level API. Gives us primitives like ReadTags(), StartReadingTags(), PollTags(). Implemented using the Basic BRI reader.
- Basic BRI: lower level API. Basically executes BRI commands and gets the response as string.
Here’s a typical BRI session:
READ ANT COUNT RSSI REPORT=NO
H000000000000000000000003 1 51 -44.3
H000000000000000000000004 1 51 -50.8
H000000000000000000000006 1 51 -51.4
H000000000000000000000007 1 50 -51.6
H000000000000000000000002 1 50 -53.1
H000000000000000000000005 1 50 -53.7
H000000000000000000000001 1 21 -59.4
Now for some strange reason Intermec’s SDK doesn’t seem to provide RSSI information on the simpler Advanced BRI – at least I didn’t found out how, even after reversing Intermec’s SDK code. Oh well, porting our auto tuning application from Advanced to Basic was simple enough. Here’s a sample:
/// Return a list of TagReading, given a tags whitelist, for a time span.
/// <param name="tagsWhiteList">List of tags to read - ignore all of the rest.</param>
/// <param name="timeSpan">Cycle timeout.</param>
private TagReading GetTagCountsAndRSSI(List<String> tagsWhiteList, TimeSpan timeSpan)
BasicBRIReader reader = new BasicBRIReader(owner);
// 1. open connection
// 2. StartReading
reader.Execute("READ ANT COUNT RSSI REPORT=NO");
// 3. Wait
// 4. Collect tags
Tag tags = BRIParser.GetTags(
SupportClassAdv.ToByteArray(reader.Execute("READ POLL")), // NOTE: SupportClassAdv.ToByteArray reversed from SDK
// 5. Stop polling
// 6. Filter, project and return results
return tags == null ?
new TagReading :
.Where(x => tagsWhiteList == null || tagsWhiteList.Count == 0 || tagsWhiteList.Contains(x.ToString()))
x => new TagReading()
Id = x.ToString(),
Count = (int)x.TagFields.FieldArray.DataInt,
Rssi = float.Parse(x.TagFields.FieldArray.DataString)
// 7. cleanup
if (reader != null && reader.IsConnected)