Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyUsb USB Barcode Scanner

I'm trying to output a string from a barcode or qrcode using a Honeywell USB 3310g scanner in Ubuntu. I have libusb and a library called metro-usb (http://gitorious.org/other/metro-usb) which are enabling my scanner to work. If i open gedit and scan, I successfully get the qrcode data fine! I need to be able to build this pragmatically and send the data to a web service.

I've downloaded and instally pyusb and this seems to be the best solution best on my research. I have a script based on things i've found on the web that waits for the scan and successfully gives me a result on the scan even. however, I am unsure how to read the data. I get an array of data that doesn't really make any sense. I'm not familiar with USB programming or Python either. Can anyone direct me to the best way to simply get the string of data from the USB barcode scan? I can most-likely figure out the rest. Also, I am getting an error that I always have to comment out to get the program to run when I try to set_configuration. I always get a Error saying Resource is Busy...not sure if this has anything to do with it..I've gotten this script off the web, and the Product ID and Vendor ID from my lsusb command. When i run this with the set_configuration commented out, I get:

Waiting to read...

When scanned:

0x0 0x0 0xb 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x17 0x0 0x0 0x0 0x0 0x0
Traceback (most recent call last):
  File "reader.py", line 81, in <module>
  print lecture_code_barre()
File "reader.py", line 76, in lecture_code_barre
lecture+=NO_SCAN_CODE[data[n+2]]
KeyError: 11

Here is the py script:

import sys
import usb.core
import usb.util

def lecture_code_barre():
VENDOR_ID = 0x0c2e
PRODUCT_ID = 0x0b61
#VENDOR_ID = 0x04b4
#PRODUCT_ID = 0x0100
DATA_SIZE = 16 # 224
NO_SCAN_CODE = {0x1E:'1', 0x1F:'2', 0x20:'3', 0x21:'4', 0x22:'5', 0x23:'6', 0x24:'7'
    , 0x25:'8', 0x26:'9', 0x27:'0', 0x28:''} # 28=enter

device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)

if device is None:
    sys.exit("Could not find Id System Barcode Reader.")

if device.is_kernel_driver_active(0):   # On détache le périphérique du kernel, plus d'envoi sur stdin
    try:
        device.detach_kernel_driver(0)
    except usb.core.USBError as e:
        sys.exit("Could not detatch kernel driver: %s" % str(e))

#try:
#    device.set_configuration()
#    device.reset()
#except usb.core.USBError as e:
#    sys.exit("Could not set configuration: %s" % str(e))

endpoint = device[0][(0,0)][0]
data = []
lu = False
print "Waiting to read..."
lecture=''

while 1:
    try:
        data += device.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize)

        if not lu:
            print "Waiting to read..."
        lu = True

    except usb.core.USBError as e:
        if e.args == (110,'Operation timed out') and lu:
            if len(data) < DATA_SIZE:
                print "Lecture incorrecte, recommencez. (%d bytes)" % len(data)
                print "Data: %s" % ''.join(map(hex, data))
                data = []
                lu = False
                continue
            else:
                for n in range(0,len(data),16):
                    print ' '.join(map(hex,data[n:n+16]))
                    lecture+=NO_SCAN_CODE[data[n+2]]
                break   # Code lu
return lecture

if __name__ == '__main__':
print lecture_code_barre()

Output from device with looping:

....
print device.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize)
...

parallels@ubuntu:~/Documents/pyusb$ sudo python scan.py 
<usb.core.Device object at 0x7fa5f34df610>
array('B', [0, 0, 38, 0, 0, 0, 0, 0])
array('B', [2, 0, 0, 0, 0, 0, 0, 0])
array('B', [2, 0, 11, 0, 0, 0, 0, 0])
array('B', [2, 0, 22, 0, 0, 0, 0, 0])
array('B', [0, 0, 0, 0, 0, 0, 0, 0])
array('B', [0, 0, 81, 0, 0, 0, 0, 0])
array('B', [2, 0, 0, 0, 0, 0, 0, 0])
array('B', [2, 0, 24, 0, 0, 0, 0, 0])
array('B', [2, 0, 14, 0, 0, 0, 0, 0])
array('B', [0, 0, 0, 0, 0, 0, 0, 0])
array('B', [0, 0, 81, 0, 0, 0, 0, 0])
array('B', [0, 0, 11, 0, 0, 0, 0, 0])
array('B', [0, 0, 23, 0, 0, 0, 0, 0])
array('B', [0, 0, 0, 0, 0, 0, 0, 0])
array('B', [0, 0, 23, 0, 0, 0, 0, 0])
array('B', [0, 0, 19, 0, 0, 0, 0, 0])
array('B', [2, 0, 0, 0, 0, 0, 0, 0])
array('B', [2, 0, 51, 0, 0, 0, 0, 0])
array('B', [0, 0, 0, 0, 0, 0, 0, 0])
array('B', [0, 0, 56, 0, 0, 0, 0, 0])
array('B', [0, 0, 0, 0, 0, 0, 0, 0])
array('B', [0, 0, 56, 0, 0, 0, 0, 0])
array('B', [0, 0, 26, 0, 0, 0, 0, 0])
array('B', [0, 0, 0, 0, 0, 0, 0, 0])
array('B', [0, 0, 26, 0, 0, 0, 0, 0])
array('B', [0, 0, 0, 0, 0, 0, 0, 0])
array('B', [0, 0, 26, 0, 0, 0, 0, 0])
array('B', [0, 0, 55, 0, 0, 0, 0, 0])
array('B', [0, 0, 5, 0, 0, 0, 0, 0])
array('B', [0, 0, 21, 0, 0, 0, 0, 0])
array('B', [0, 0, 18, 0, 0, 0, 0, 0])
array('B', [0, 0, 26, 0, 0, 0, 0, 0])
array('B', [0, 0, 17, 0, 0, 0, 0, 0])
array('B', [0, 0, 5, 0, 0, 0, 0, 0])
array('B', [0, 0, 18, 0, 0, 0, 0, 0])
array('B', [0, 0, 0, 0, 0, 0, 0, 0])
array('B', [0, 0, 18, 0, 0, 0, 0, 0])
array('B', [0, 0, 14, 0, 0, 0, 0, 0])
array('B', [0, 0, 55, 0, 0, 0, 0, 0])
array('B', [0, 0, 17, 0, 0, 0, 0, 0])
array('B', [0, 0, 8, 0, 0, 0, 0, 0])
array('B', [0, 0, 23, 0, 0, 0, 0, 0])
array('B', [0, 0, 81, 0, 0, 0, 0, 0])
array('B', [0, 0, 22, 0, 0, 0, 0, 0])
array('B', [0, 0, 8, 0, 0, 0, 0, 0])
array('B', [0, 0, 21, 0, 0, 0, 0, 0])
array('B', [0, 0, 25, 0, 0, 0, 0, 0])
array('B', [0, 0, 12, 0, 0, 0, 0, 0])
array('B', [0, 0, 6, 0, 0, 0, 0, 0])
array('B', [0, 0, 8, 0, 0, 0, 0, 0])
like image 879
Michael Avatar asked Jan 29 '13 03:01

Michael


Video Answer


2 Answers

Grab a Quick Start Guide, scan "USB Serial"-mode barcode, then "Save" barcode to make this setting permanent. Now your 3310g is in serail emulation mode, note new /dev/ttyACM0 or /dev/ttyUSB0 device. Read serial port with simple file operations from python:

f = open('/dev/ttyACM0')
print f.read(13)
like image 102
Pashka Avatar answered Oct 23 '22 09:10

Pashka


The error you're receiving is from this line:

lecture+=NO_SCAN_CODE[data[n+2]]

and data[n+2] = 11, which equates to doing the following

NO_SCAN_CODE[11]

NO_SCAN_CODE is a dictionary that only contains values for the keys [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], not 11.

The fact that you're getting this error means that you've received a usb.core.USBError, and len(data) >= DATA_SIZE.


If I was debugging this, I'd add a whole lot more print statements. I suggest trying something simple like this initially, then adding more logic when you figure out what the device is returning:

# Initialise variables
VENDOR_ID = 0x0c2e
PRODUCT_ID = 0x0b61

# Set up device
device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)
print device

# Do more setup things here
# detach_kernel_driver and set_configuration ?
# Perhaps try these in combination with reading the usb.core documentation, and see what happens?

# Loop 10 times (to start with - try more later?)
for i in range(10):
    # Don't catch any errors, just print what the device is returning
    print device.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize)
like image 37
Alex L Avatar answered Oct 23 '22 09:10

Alex L