sllurp is a Python library to interface with RFID readers. It is a pure-Python implementation of the Low Level Reader Protocol (LLRP).
These readers are known to work well with sllurp, but it should be adaptable with not much effort to other LLRP-compatible readers:
- Impinj Speedway (R1000)
- Impinj Speedway Revolution (R220, R420)
- Impinj Speedway xPortal
- Motorola MC9190-Z (handheld)
File an issue on GitHub if you would like help getting another kind of reader to work.
sllurp is distributed under version 3 of the GNU General Public License. See
LICENSE.txt
for details.
Install from PyPI:
$ virtualenv .venv $ source .venv/bin/activate $ pip install sllurp $ sllurp inventory ip.add.re.ss
Run sllurp --help
and sllurp inventory --help
to see options.
Or install from GitHub:
$ git clone https://github.com/ransford/sllurp.git $ cd sllurp $ virtualenv .venv $ source .venv/bin/activate $ pip install . $ sllurp inventory ip.add.re.ss
If the reader gets into a funny state because you're debugging against it
(e.g., if your program or sllurp has crashed), you can set it back to an idle
state by running sllurp reset ip.add.re.ss
.
sllurp relies on Twisted for network interaction with the reader. To make a connection, create an LLRPClientFactory and hand it to Twisted:
# Minimal example; see inventory.py for more.
from sllurp import llrp
from twisted.internet import reactor
import logging
logging.getLogger().setLevel(logging.INFO)
def cb (tagReport):
tags = tagReport.msgdict['RO_ACCESS_REPORT']['TagReportData']
print 'tags:', tags
factory = llrp.LLRPClientFactory()
factory.addTagReportCallback(cb)
reactor.connectTCP('myreader', llrp.LLRP_PORT, factory)
reactor.run()
When initializing LLRPClientFactory
, set flags in the
tag_content_selector
dictionary argument:
llrp.LLRPClientFactory(tag_content_selector={
'EnableROSpecID': False,
'EnableSpecIndex': False,
'EnableInventoryParameterSpecID': False,
'EnableAntennaID': True,
'EnableChannelIndex': False,
'EnablePeakRSSI': True,
'EnableFirstSeenTimestamp': False,
'EnableLastSeenTimestamp': True,
'EnableTagSeenCount': True,
'EnableAccessSpecID': False,
}, ...)
sllurp logs under the name sllurp
, so if you wish to log its output, you
can do this the application that imports sllurp:
sllurp_logger = logging.getLogger('sllurp')
sllurp_logger.setLevel(logging.DEBUG)
sllurp_logger.setHandler(logging.FileHandler('sllurp.log'))
# or .setHandler(logging.StreamHandler()) to log to stderr...
sllurp has limited support for vendor extensions through LLRP's custom message facilities. For example, sllurp inventory --impinj-search-mode N allows you to set the Impinj search mode to single target (1) or dual target (2).
To see what inventory settings an Impinj reader is currently using (i.e., to fetch the current ROSpec), ssh to the reader and
> show rfid llrp rospec 0
The "nuclear option" for resetting a reader is:
> reboot
Start an issue on GitHub! Please follow Simon Tatham's guide on writing good bug reports.
Bug reports are most useful when they're accompanied by verbose error messages.
Turn sllurp's log level up to DEBUG, which you can do by specifying the -d
command-line option to sllurp
. You can log to a logfile with the -l
[filename]
option. Or simply put this at the beginning of your own code:
import logging
logging.getLogger('sllurp').setLevel(logging.DEBUG)
Reader mode selection is confusing, not least because most readers seem to
conflate ModeIndex
and ModeIdentifier
. If you're using sllurp
inventory
, use --mode-identifier N
. Check your reader's manual to see
what mode identifiers it supports via the C1G2RFControl
parameter, or run
sllurp --debug inventory
against a reader to see a dump of the supported
modes in the capabilities description.
Want to contribute? Here are some areas that need improvement:
- Encode more protocol messages in the
construct
branch. - Write tests for common encoding and decoding tasks.
Much of the code in sllurp is by Ben Ransford, although it began its life in August 2013 as a fork of LLRPyC. Many fine citizens of GitHub have contributed code to sllurp since the fork.