PyUsb USB条形码扫描仪
我正在尝试在Ubuntu系统中使用Honeywell USB 3310g扫描仪输出条形码或二维码的字符串。我已经安装了libusb和一个叫metro-usb的库(http://gitorious.org/other/metro-usb),这让我的扫描仪可以正常工作。如果我打开gedit并进行扫描,我可以成功获取二维码的数据!我需要能够以编程的方式构建这个过程,并将数据发送到一个网络服务。
我下载并安装了pyusb,这似乎是根据我的研究得出的最佳解决方案。我有一个基于网上找到的内容的脚本,它可以等待扫描并成功给我扫描结果。然而,我不太确定如何读取数据。我得到的数据是一个数组,但看起来并没有什么意义。我对USB编程和Python也不太熟悉。有没有人能告诉我如何简单地从USB条形码扫描中获取字符串数据?我大概能搞定其他的部分。此外,当我尝试设置配置时,总是会出现一个错误,我必须注释掉这部分才能让程序运行。错误提示是“资源忙”,我不确定这是否与此有关。我是从网上获取的这个脚本,产品ID和供应商ID是通过lsusb命令得到的。当我在注释掉set_configuration的情况下运行这个脚本时,我得到了:
Waiting to read...
扫描时:
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
这是py脚本:
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()
设备输出(循环):
....
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])
2 个回答
你遇到的错误是来自这一行:
lecture+=NO_SCAN_CODE[data[n+2]]
还有 data[n+2] = 11
,这就相当于做了以下操作:
NO_SCAN_CODE[11]
NO_SCAN_CODE
是一个字典,它只包含键 [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
的值,而不包含 11
。
你收到这个错误的原因是你遇到了一个 usb.core.USBError
,并且 len(data) >= DATA_SIZE
。
如果我是调试这个问题,我会添加很多打印语句。我建议你先尝试一些简单的,比如这样,然后在弄清楚设备返回了什么后再添加更多的逻辑:
# 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)
首先,拿到一个快速入门指南,然后扫描“USB串口”模式的条形码,接着选择“保存”条形码,这样设置就会永久生效。现在你的3310g就进入了串口仿真模式,注意新的设备名称是/dev/ttyACM0或/dev/ttyUSB0。接下来,可以通过简单的文件操作在Python中读取串口:
f = open('/dev/ttyACM0')
print f.read(13)