The Impinj IoT device interface (Impinj IoT interface) includes a reader configuration REST API and a web UI that empower IoT developers to easily connect applications to configure and control devices and consume RAIN data. With native support for industry-standard data formats and protocols, such as HTTP streaming and MQTT output, the Impinj IoT interface makes it easier to scale while quickly designing solutions that will integrate with IoT platforms.
For more information, see the Impinj IoT Device Interface support page.
Supported Products
The following products support this interface:
- Impinj reader firmware version 8.2 or later
- Impinj R700 RAIN RFID reader
- Impinj R720 RAIN RFID reader
Getting Started
- Download the OpenAPI 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 "Impinj IoT Device Interface".
- The default RFID interface is "Impinj IoT Device Interface" in the 8.2 firmware, so this may already be set.
- Change the interface from LLRP to Impinj Iot Device Interface using either RShell or the web interface.
- Note that host configuration operations under the
system
endpoint are still available when that RFID interface is set to LLRP. Only the RFID operations (non-system endpoints) require the RFID interface to be set to "Impinj IoT Device Interface."
- Connect your generated client to your reader and start your application
Documentation
The full description and documentation of the reader configuration REST API can be found within OpenAPI specification
Features
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
A preset is a defined configuration that contains the settings required for a specific profile. When a preset is started from the reader configuration REST API or Web UI the reader will begin RFID operation.
Impinj provides some presets that allow users to start receiving data from a reader in just a few lines of code. Additional presets can be configured to meet the needs of a specific application via the REST API or Web UI.
Supported Protocols
The IoT Device interface supports HTTP Streaming, Kafka, and MQTT as data output protocols.
Sample Python Application and Tutorial
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 <your-reader-hostname>
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 much of the functionality of the Impinj Reader API.
Getting the reader status
python reader_client.py --reader <your-reader-hostname> --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 <your-reader-hostname> --start default
Consuming the event stream
python reader_client.py --reader <your-reader-hostname> --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 <your-reader-hostname> --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 <your-reader-hostname> --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 <your-reader-hostname> --delete my-custom-preset
Will delete a custom preset. Note that the factory default preset--default --cannot be deleted.
Getting inventory preset details
python reader_client.py --reader <your-reader-hostname> --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 <your-reader-hostname> --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 Python code:
import base64
import binascii
my_epc = 'dHADJSAWhYUQABAJ'
binascii.b2a_hex(base64.urlsafe_b64decode(my_epc))
Comments
Article is closed for comments.