pythonrfidllrp

Read the Tag Inventory of a Motorola/Zebra FX9500 RFID Reader using Python sllurp library


I am trying to write an application for reading an inventory of tags using Zebra FX9500 RFID reader. I tried to install the SDK from the manufacturers website, but couldn't understand how to use it and I'm also not familiar with C,C# or Java so instead I found a Python library (sllurp) that uses the LLRP protocol to communicate with RFID readers.

The readme file from git provides an example code, which seems simple enough and should return some tags:

# 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()

Using this, the program will return "tags = []".

The library also provides a CLI used to obtain the inventory from the RFID reader. Running sllurp inventory from the command line, the program will start communicating with the reader and remain in what seems to be an infinite inventory reading loop (the LED on the reader keeps flashing). At this point I can only seem to stop it by using CTRL+C. After it stops, the program will return a list of tags.

So far so good, but I actually wanted to connect to the reader, read just once (or for a few seconds, I don't know) and get a set of tags.

Tried debugging myself but could only get so far. Seems I can't post the log here, because it has too many characters, but I opened an issue in GIT here.

If anyone has any experience with the sllurp module or the LLRP protocol, maybe you could help. How could I stop the inventory reading loop? Could I send a STOP_ROSPEC/ROSpecStopTrigger to terminate the inventory reading? How would I do that?

Thanks!


Solution

  • If anyone ever has the same issue, I found a way of doing what I want:

    READER_IP_ADDRESS = '169.254.1.1'
    SCAN_TIME = 20
    
    def tagreportcb(llrp_msg):
        tags = llrp_msg.msgdict['RO_ACCESS_REPORT']['TagReportData']
        tag_list = set()
        for tag in tags:
            tag_list.add(tag.get('EPC-96',None))
        return tag_list
    
    def report(llrp_msg):
        tag_list = tagreportcb(llrp_msg)
        with open('tags.txt', mode='w+') as report:
            for tag in tag_list:
                if tag not in report.readlines():
                    report.write(str(tag)[2:26] + '\n')
    
    def shutdown(factory):
        return factory.politeShutdown()
    
    def main():
        factory = llrp.LLRPClientFactory(antennas=[0], duration=0.5)
        factory.addTagReportCallback(report)
        reactor.connectTCP(READER_IP_ADDRESS, llrp.LLRP_PORT, factory, timeout=3)
        reactor.addSystemEventTrigger('before', 'shutdown', shutdown, factory)
        # https://twistedmatrix.com/documents/current/core/howto/time.html
        reactor.callLater(SCAN_TIME, shutdown, factory)
        reactor.run()
    
    if __name__ == "__main__":
        main()
    

    I added reactor.callLater(SCAN_TIME, shutdown, factory), which calls the shutdown function after a given period of time.