PyUsb USB 条码扫描器

Posted

技术标签:

【中文标题】PyUsb USB 条码扫描器【英文标题】:PyUsb USB Barcode Scanner 【发布时间】:2013-01-12 13:56:03 【问题描述】:

我正在尝试使用 Ubuntu 中的 Honeywell USB 3310g 扫描仪从条形码或 qrcode 输出字符串。我有 libusb 和一个名为 metro-usb (http://gitorious.org/other/metro-usb) 的库,它们使我的扫描仪能够工作。如果我打开gedit并扫描,我成功地得到了二维码数据!我需要能够务实地构建它并将数据发送到 Web 服务。

我已经下载并安装了 pyusb,这似乎是我研究中最好的解决方案。我有一个基于我在网上找到的东西的脚本,它等待扫描并成功地给我一个扫描结果。但是,我不确定如何读取数据。我得到了一系列没有任何意义的数据。我也不熟悉 USB 编程或 Python。谁能指导我从 USB 条形码扫描中获取数据字符串的最佳方法?我很可能会弄清楚其余的。另外,我收到一个错误,当我尝试 set_configuration 时,我总是必须注释掉才能让程序运行。我总是收到一个错误,说资源正忙...不确定这是否与它有关..我已经从网络上获取了这个脚本,以及来自我的 lsusb 命令的产品 ID 和供应商 ID。当我在 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])

【问题讨论】:

它不会将自己暴露为 HID 设备? 我相信确实如此,我可以在 lsusb 中看到它。我只是无法/不确定如何通过 pyusb / python 解释扫描的输出。 HID 设备不需要 libusb,并非所有 USB 设备都是 HID 设备。 扫描“PAP131.”,使用事件子系统,然后转储 libusb。 我不确定您所说的扫描“PAP131”是什么意思。抱歉,我对 USB 编程不是很熟悉。我的印象是我需要使用 libusb 与设备进行交互。 【参考方案1】:

获取Quick Start Guide,扫描“USB 串行”模式条码,然后“保存”条码以使此设置永久化。现在您的 3310g 处于串行仿真模式,请注意新的 /dev/ttyACM0 或 /dev/ttyUSB0 设备。从 python 中通过简单的文件操作读取串口:

f = open('/dev/ttyACM0')
print f.read(13)

【讨论】:

这很好用!唯一的问题是每次我扫描新代码时,我只收到前 13 个字符。我知道这需要对 Python 进行更多的研究和学习,但是是否可以仅解释最后“行”或仅解释当前扫描的数据? 发现这篇博文让我朝着正确的方向前进。stealth-x.com/programming/driver-writing-with-python.php 非常感谢您在这方面的帮助! 您可以通过回车分隔代码。使用快速入门指南扫描“后缀”部分中名为“添加 CR 后缀”的相应代码。在此之后,您可以循环读取 1 个字符,等待每个条形码末尾的 CR (#13)。 快速入门指南链接已失效【参考方案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.USBErrorlen(data) &gt;= 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)

【讨论】:

谢谢,试过了。这是结果,我用 20 做了一些扫描,并且能够在它运行时进行一些扫描:parallels@ubuntu:~/Documents/pyusb$ sudo python scan.py array('B ', [0, 0, 18, 0, 0, 0, 0, 0]) array('B', [0, 0, 14, 0, 0, 0, 0, 0]) ...18 以上结束。我不太确定这意味着什么,它与我第一次的输出基本相同,但是我不确定如何从代码中获取价值?谢谢! @Michael 你知道你期望得到什么价值吗?您能否将完整的输出添加到您的问题中? 我认为这可能是问题的一部分。我不知道我应该或将要收到什么。我一直在看这个文档:honeywellaidc.com/CatalogDocuments/… 但我无法确定如何解析输出。我正在将完整的输出添加到问题中。谢谢!

以上是关于PyUsb USB 条码扫描器的主要内容,如果未能解决你的问题,请参考以下文章

条码扫描枪与键盘不能共同使用

Excel 条码扫描宏

支持颤振的外部键盘

条码扫描枪与手机条码扫描枪有啥区别

PDA怎么使用,是怎么扫描条码的?

条码扫描枪输入为啥不能用键盘输入代替