Impinj IoT Device Interface
Overview
The Impinj IoT Device Interface provides both high and low-level control for RFID reader operations, with helpful profiles, presets and system control endpoints. One of the key driving principles behind the interface is the use of sensible defaults, with options for overriding specific settings when needed.
Supported Products
The following products support this interface:
- Impinj R700 RAIN RFID reader, with firmware version 7.1 or later
Getting Started
- Download the Swagger file that describes the interface
- Use an Open API Standard tool to generate a client in one of the many supported programming languages
- Set the interface on the reader to "RESTful Interface"
- For the R700, change the interface from LLRP to RESTful using either RShell or the web interface
- Connect your generated client to your reader and start your application
Documentation
The full description of the Impinj Reader API can be found here.
Introduction
The primary aim of this interface is to allow developers to quickly start receiving data from a reader using sensible defaults and without needing to specify detailed RFID configuration parameters. As a developer's familiarity with RFID concepts improves, they can override specific settings provided by the presets using JSON.
Profiles
Specific reader use-cases, such as inventory, are referred to as profiles. A profile defines the RF setting for a specific use case.
Presets
Getting started with developing an RAIN-based application can be daunting since there are so many different configuration options. To help developers get up and running quickly, we provide a small collection of predefined configurations called "presets." Leveraging these presets, a developer can start receiving data from the reader in just a few lines of code. Further, developers can define their own presets to tailor the reader's settings to their needs and environment.
System Control Endpoints
System control endpoints enable actions including firmware updates, rebooting the reader, and network configuration.
Getting and Using the Sample Python Code
To complete the following tutorial, you need to download the following files:
Basic Python Setup
To use the provided python sample code, you'll need to ensure that the requests
package is
installed. You can install this Python package using the Pip utility like so:
pip install requests
Using hello_reader.py
This simple python application will start the default preset and connect to the event stream.
python hello_reader.py --reader
If any tags are within the field of view, TagInventoryEvents should be published to the stream.
{\"TagInventoryEvent\":{\"epc\":\"mZkQBiAUAAAAAwAQ\",\"antennaPort\":1,\"peakRssiCdbm\":-5700}, \"timestamp\":\"2018-10-24T17:17:50.324240614Z\"}
{\"TagInventoryEvent\":{\"epc\":\"mZkQBiAUAAAAAwAj\",\"antennaPort\":1,\"peakRssiCdbm\":-6300}, \"timestamp\":\"2018-10-24T17:17:50.324245202Z\"}
{\"TagInventoryEvent\":{\"epc\":\"dHADJSAWhYUQABAJ\",\"antennaPort\":1,\"peakRssiCdbm\":-5100}, \"timestamp\":\"2018-10-24T17:17:50.324253758Z\"}
{\"EndOfCycleEvent\":{}, \"timestamp\":\"2018-10-24T17:17:50.326205774Z\"}
...
Using reader_client.py
The reader_client.py script is an example python utility that highlights most of the functionality of the Impinj Reader API.
Getting the reader status
python reader_client.py --reader --status
The reader status will be returned:
{
\"status\":\"running\",
\"time\":\"2019-02-28T23:01:17.873299\",
\"serialNumber\":\"370-17-16-0022\"
}
Starting a preset
The following can be used to start the default preset.
python reader_client.py --reader --start default
Consuming the event stream
python reader_client.py --reader --stream
Will get the stream of events :
{\"TagInventoryEvent\":{\"epc\":\"dHADJSAWhYUQABAJ\",\"antennaPort\":1,\"peakRssiCdbm\":-5700}, \"timestamp\":\"2018-10-24T17:17:50.324240614Z\"}
{\"TagInventoryEvent\":{\"epc\":\"dHADJSAWhYUQABAZ\",\"antennaPort\":1,\"peakRssiCdbm\":-6300}, \"timestamp\":\"2018-10-24T17:17:50.324245202Z\"}
{\"TagInventoryEvent\":{\"epc\":\"dHADJSAWhYUQABAQ\",\"antennaPort\":1,\"peakRssiCdbm\":-5100}, \"timestamp\":\"2018-10-24T17:17:50.324253758Z\"}
{\"EndOfCycleEvent\":{}, \"timestamp\":\"2018-10-24T17:17:50.326205774Z\"}
...
Storing a custom preset
python reader_client.py --reader --store my_custom_preset.json
Will store a custom preset with the name \"my-custom-preset\".
Getting all inventory presets
python reader_client.py --reader --presets
Will return a list of presets :
[
{
\"url\": \"/api/v0/profiles/inventory/presets/deep-scan\",
\"id\": \"deep-scan\"
},
{
\"url\": \"/api/v0/profiles/inventory/presets/default\",
\"id\": \"default\"
},
{
\"url\": \"/api/v0/profiles/inventory/presets/dense-reader\",
\"id\": \"dense-reader\"
},
{
\"url\": \"/api/v0/profiles/inventory/presets/my-custom-preset\",
\"id\": \"my-custom-preset\"
}
]
Deleting a preset
python reader_client.py --reader --delete my-custom-preset
Will delete a custom preset. Note that the factory default presets--default, deep-scan, dense-reader--cannot be deleted.
Getting inventory preset details
python reader_client.py --reader --details dense-reader
Will return the preset details.
{
\"antennaConfigs\": [
{
\"transmitPowerCdbm\": 3000,
\"antennaPort\": 1,
\"inventorySearchMode\": \"single-target\",
\"estimatedTagPopulation\": 4,
\"inventorySession\": 2,
\"rfMode\": \"auto-set-static-drm\"
}
],
\"id\": \"dense-reader\"
}
Getting inventory preset schema
python reader_client.py --reader --schema
Will return an inventory preset schema.
{
\"presets\": \"/api/v0/profiles/inventory/presets\",
\"schema\": {
\"required\": [
\"id\",
\"antennaConfigs\"
],
\"properties\": {
\"stopTriggers\": {
\"minItems\": 1,
\"items\": {
\"type\": \"object\",
\"id\": \"/properties/startTriggers/items\",
\"properties\": {
\"gpiTransitionEvent\": {
\"type\": \"object\",
\"id\": \"/properties/startTriggers/items/gpiTransitionEvent\",
\"properties\": {
\"transition\": {
\"enum\": [
\"high-to-low\",
\"low-to-high\"
],
\"type\": \"string\",
\"id\": \"/properties/startTriggers/items/gpiTransitionEvent/properties/transition\"
},
\"gpi\": {
\"minimum\": 1,
\"type\": \"integer\",
\"id\": \"/properties/startTriggers/items/gpiTransitionEvent/properties/gpi\",
\"maximum\": 4
}
}
}
}
},
\"type\": \"array\",
\"id\": \"/properties/stopTriggers\"
},
\"antennaConfigs\": {
\"additionalItems\": false,
\"minItems\": 1,
\"items\": {
\"additionalProperties\": false,
\"required\": [
\"antennaPort\",
\"inventorySearchMode\",
\"inventorySession\",
\"transmitPowerCdbm\",
\"rfMode\",
\"estimatedTagPopulation\"
],
\"type\": \"object\",
\"id\": \"/properties/antennaConfigs/items\",
\"properties\": {
\"filtering\": {
\"required\": [
\"filters\"
],
\"type\": \"object\",
\"id\": \"/properties/antennaConfigs/items/properties/filtering\",
\"properties\": {
\"filterLink\": {
\"default\": \"union\",
\"enum\": [
\"union\",
\"intersection\"
],
\"type\": \"string\",
\"id\": \"/properties/antennaConfigs/items/properties/filtering/properties/filterLink\"
},
\"filters\": {
\"minItems\": 1,
\"items\": {
\"required\": [
\"action\",
\"tagMemoryBank\",
\"bitOffset\",
\"mask\"
],
\"id\": \"/properties/antennaConfigs/items/properties/filtering/properties/filters/items\",
\"properties\": {
\"action\": {
\"enum\": [
\"include\",
\"exclude\"
],
\"type\": \"string\",
\"id\": \"/properties/antennaConfigs/items/properties/filtering/properties/filters/items/properties/action\"
},
\"bitOffset\": {
\"minimum\": 0,
\"type\": \"integer\",
\"id\": \"/properties/antennaConfigs/items/properties/filtering/properties/filters/items/properties/bitOffset\"
},
\"mask\": {
\"pattern\": \"^[0-9A-F]+$\",
\"minLength\": 1,
\"type\": \"string\",
\"id\": \"/properties/antennaConfigs/items/properties/filtering/properties/filters/items/properties/mask\",
\"maxLength\": 64
},
\"maskLength\": {
\"minimum\": 1,
\"type\": \"integer\",
\"id\": \"/properties/antennaConfigs/items/properties/filtering/properties/filters/items/properties/maskLength\",
\"maximum\": 255
},
\"tagMemoryBank\": {
\"enum\": [
\"epc\",
\"tid\",
\"user\"
],
\"type\": \"string\",
\"id\": \"/properties/antennaConfigs/items/properties/filtering/properties/filters/items/properties/tagMemoryBank\"
}
}
},
\"type\": \"array\",
\"id\": \"/properties/antennaConfigs/items/properties/filtering/properties/filters\",
\"maxItems\": 2
}
}
},
\"rfMode\": {
\"enum\": [
\"max-throughput\",
\"hybrid\",
\"dense-reader-m4\",
\"dense-reader-m8\",
\"max-miller\",
\"auto-set-dense-reader\",
\"auto-set-dense-reader-deep-scan\",
\"auto-set-static-fast\",
\"auto-set-static-drm\"
],
\"type\": \"string\",
\"id\": \"/properties/antennaConfigs/items/properties/rfMode\"
},
\"transmitPowerCdbm\": {
\"multipleOf\": 25,
\"minimum\": 1000,
\"type\": \"integer\",
\"id\": \"/properties/antennaConfigs/items/properties/transmitPowerCdbm\",
\"maximum\": 3150
},
\"inventorySearchMode\": {
\"enum\": [
\"single-target\",
\"dual-target\",
\"single-target-with-suppression\",
\"single-target-b-to-a\",
\"dual-target-with-b-to-a-select\"
],
\"type\": \"string\",
\"id\": \"/properties/antennaConfigs/items/properties/inventorySearchMode\"
},
\"estimatedTagPopulation\": {
\"minimum\": 1,
\"type\": \"integer\",
\"id\": \"/properties/antennaConfigs/items/properties/tagPopulation\",
\"maximum\": 32768
},
\"antennaPort\": {
\"minimum\": 1,
\"type\": \"integer\",
\"id\": \"/properties/antennaConfigs/items/properties/antennaPort\",
\"maximum\": 4
},
\"inventorySession\": {
\"minimum\": 0,
\"type\": \"integer\",
\"id\": \"/properties/antennaConfigs/items/properties/inventorySession\",
\"maximum\": 3
},
\"powerSweeping\": {
\"required\": [
\"minimumPowerCdbm\",
\"stepSizeCdb\"
],
\"type\": \"object\",
\"id\": \"/properties/antennaConfigs/items/properties/powerSweeping\",
\"properties\": {
\"minimumPowerCdbm\": {
\"minimum\": 1000,
\"type\": \"integer\",
\"id\": \"/properties/antennaConfigs/items/properties/powerSweeping/properties/minimumPowerCdbm\",
\"maximum\": 3150,
\"multipleOf\": 25
},
\"stepSizeCdb\": {
\"minimum\": 100,
\"type\": \"integer\",
\"id\": \"/properties/antennaConfigs/items/properties/powerSweeping/properties/stepSizeCdb\",
\"multipleOf\": 25
}
}
},
\"tagMemoryReads\": {
\"minItems\": 1,
\"items\": {
\"required\": [
\"memoryBank\",
\"wordOffset\",
\"wordCount\"
],
\"type\": \"object\",
\"id\": \"/properties/antennaConfigs/items/properties/tagMemoryReads/items\",
\"properties\": {
\"memoryBank\": {
\"enum\": [
\"epc\",
\"tid\",
\"user\",
\"reserved\"
],
\"type\": \"string\",
\"id\": \"/properties/antennaConfigs/items/properties/tagMemoryReads/items/properties/memoryBank\"
},
\"wordOffset\": {
\"minimum\": 0,
\"type\": \"integer\",
\"id\": \"/properties/antennaConfigs/items/properties/tagMemoryReads/items/properties/wordOffset\",
\"format\": \"int32\"
},
\"wordCount\": {
\"minimum\": 1,
\"type\": \"integer\",
\"id\": \"/properties/antennaConfigs/items/properties/tagMemoryReads/items/properties/wordCount\",
\"maximum\": 255
}
}
},
\"type\": \"array\",
\"id\": \"/properties/antennaConfigs/items/properties/tagMemoryReads\",
\"maxItems\": 4
}
}
},
\"uniqueItems\": true,
\"type\": \"array\",
\"id\": \"/properties/antennaConfigs\"
},
\"id\": {
\"minLength\": 1,
\"type\": \"string\",
\"pattern\": \"^[a-zA-Z0-9_.-]*$\",
\"id\": \"/properties/id\",
\"maxLength\": 20
},
\"startTriggers\": {
\"minItems\": 1,
\"items\": {
\"type\": \"object\",
\"id\": \"/properties/startTriggers/items\",
\"properties\": {
\"gpiTransitionEvent\": {
\"type\": \"object\",
\"id\": \"/properties/startTriggers/items/gpiTransitionEvent\",
\"properties\": {
\"transition\": {
\"enum\": [
\"high-to-low\",
\"low-to-high\"
],
\"type\": \"string\",
\"id\": \"/properties/startTriggers/items/gpiTransitionEvent/properties/transition\"
},
\"gpi\": {
\"minimum\": 1,
\"type\": \"integer\",
\"id\": \"/properties/startTriggers/items/gpiTransitionEvent/properties/gpi\",
\"maximum\": 4
}
}
}
}
},
\"type\": \"array\",
\"id\": \"/properties/startTriggers\"
}
},
\"additionalProperties\": false,
\"definitions\": {},
\"$schema\": \"http://json-schema.org/draft-04/schema#\",
\"type\": \"object\",
\"id\": \"http://developer.impinj.com/reader-api/schema/inventory/schema-template.json\"
}
}
Decoding A Base64Url-Encoded EPC Into Its Hex-Equivalent
Base64Url-encoded EPCs are the most efficient way of transmitting binary data in JSON. To decode this data into its hex-equivalent, you can run the following code:
import base64
import binascii
my_epc = 'dHADJSAWhYUQABAJ'
binascii.b2a_hex(base64.urlsafe_b64decode(my_epc))