树莓派 + 扫码枪

最近参加了个比赛,须要用到扫码枪。html

经过上网查阅资料,发现扫码枪这种东西属于HID(Human Interface Device),扫描到结果后,数据发送到上位机的方式和键盘输入相似。
而且还获知,扫码枪发送完一串条形码序列后会输入一个回车符python

因此,咱们的步骤就是:git

  1. 遍历系统中的输入设备,找到扫码枪这个设备;
  2. 对扫码枪的输入进行监视;
  3. 当检测到回车符,即表示一串序列输入完毕。

首先咱们获取扫码枪在系统上面的名称

# coding:utf-8
from evdev import InputDevice, ecodes, list_devices, categorize
import signal, sys
import evdev
import redis


global dev
devices = map(InputDevice, list_devices())
for device in devices:
        print(device.name)

因为个人树莓派上面只接了一个扫码枪,因此运行脚本结果:
在这里插入图片描述
这个就是扫码枪名称了。github

监视该设备

# coding:utf-8
from evdev import InputDevice, ecodes, list_devices, categorize
import signal, sys
import evdev
import redis
import requests

scancodes = {
    # Scancode: ASCIICode
    0: None, 1: u'ESC', 2: u'1', 3: u'2', 4: u'3', 5: u'4', 6: u'5', 7: u'6', 8: u'7', 9: u'8',
    10: u'9', 11: u'0', 12: u'-', 13: u'=', 14: u'BKSP', 15: u'TAB', 16: u'q', 17: u'w', 18: u'e', 19: u'r',
    20: u't', 21: u'y', 22: u'u', 23: u'i', 24: u'o', 25: u'p', 26: u'[', 27: u']', 28: u'CRLF', 29: u'LCTRL',
    30: u'a', 31: u's', 32: u'd', 33: u'f', 34: u'g', 35: u'h', 36: u'j', 37: u'k', 38: u'l', 39: u';',
    40: u"'", 41: u'`', 42: u'LSHFT', 43: u'\\', 44: u'z', 45: u'x', 46: u'c', 47: u'v', 48: u'b', 49: u'n',
    50: u'm', 51: u',', 52: u'.', 53: u'/', 54: u'RSHFT', 56: u'LALT', 100: u'RALT',57:u" ", 74:u"-"
}

scancodes_leftshift = {
    # Scancode: ASCIICode
    0: None, 1: u'ESC', 2: u'!', 3: u'@', 4: u'#', 5: u'$', 6: u'%', 7: u'^', 8: u'&', 9: u'*',
    10: u'(', 11: u')', 12: u'_', 13: u'+', 14: u'BKSP', 15: u'TAB', 16: u'Q', 17: u'W', 18: u'E', 19: u'R',
    20: u'T', 21: u'Y', 22: u'U', 23: u'I', 24: u'O', 25: u'P', 26: u'{', 27: u'}', 28: u'CRLF', 29: u'LCTRL',
    30: u'A', 31: u'S', 32: u'D', 33: u'F', 34: u'G', 35: u'H', 36: u'J', 37: u'K', 38: u'L', 39: u':',
    40: u'"', 41: u'~', 42: u'LSHFT', 43: u'|', 44: u'Z', 45: u'X', 46: u'C', 47: u'V', 48: u'B', 49: u'N',
    50: u'M', 51: u'<', 52: u'>', 53: u'?', 54: u'RSHFT', 56: u'LALT', 100: u'RALT',57:u" ", 74:u"-"
}

dev = None #设备
barCodeDeviceString = "Newland Auto-ID NLS IOTC PRDs HID KBW"

def usb_scan_dev():
        global dev
        devices = map(InputDevice, list_devices())
        for device in devices:
                if device.name == barCodeDeviceString:
                        dev = InputDevice(device.fn)

        if not dev:
                print("not found dev")
                return

        def signal_handler(signalnum, frame):
		        print(signalnum)
		        print(frame)
                #根据退出信号,释放输入设备
                print("Stopping")
                dev.ungrab()
                sys.exit(0)
                
		# 信号处理函数
		# signal.SIGINT-终止进程
		# 若输入ctrl+c,则按照signal_handler函数对其进行处理
        signal.signal(signal.SIGINT, signal_handler)

	    dev_.grab()
	    barcode = ""
	    keymap = scancodes
	    for event in dev_.read_loop():
	        if event.type == ecodes.EV_KEY:
	            data = categorize(event)
	            # shift 键
	            if data.scancode == 42:
	                # 按下
	                if data.keystate == 1:
	                    keymap = scancodes_leftshift
	                # 未按下
	                elif data.keystate == 0:
	                    keymap = scancodes
	            # 若按下回车键
	            elif data.scancode == 28 and data.keystate == 1:
	                print("s" + str(Serial_Number) +": " + barcode)
	                put_code(barcode)
	                break
	            # 按下普通键
	            # 74才是"-"的编码
	            elif ((data.scancode >= 1 and data.scancode <= 57) or data.scancode == 74) and data.keystate == 1:
	                barcode += keymap[data.scancode]

# 表示该py文件做为单独脚本运行时,即执行usb_scan_dev方法
if __name__ == "__main__":
        usb_scan_dev()

如今运行该脚本便可获取商品条形码序列了:
在这里插入图片描述
可是如今问题又来了,光有了条形码序列也没用啊,咱们须要的是详细的商品信息。web

条形码序列查询

在此先安利一个很是不错的查询接口:
https://github.com/MZCretin/RollToolsApiredis

根据里面的描述,咱们能够将得到的这个序列化序号组成一个连接:api

Request_url = "http://www.mxnzp.com/api/barcode/goods/details?barcode=" + barcode

而后Get请求就行:svg

r = requests.get(Request_url, timeout=0.1)
print(r.text)

完整代码:函数

# coding:utf-8
from evdev import InputDevice, ecodes, list_devices, categorize
import signal, sys
import evdev
import redis
import requests

scancodes = {
    # Scancode: ASCIICode
    0: None, 1: u'ESC', 2: u'1', 3: u'2', 4: u'3', 5: u'4', 6: u'5', 7: u'6', 8: u'7', 9: u'8',
    10: u'9', 11: u'0', 12: u'-', 13: u'=', 14: u'BKSP', 15: u'TAB', 16: u'q', 17: u'w', 18: u'e', 19: u'r',
    20: u't', 21: u'y', 22: u'u', 23: u'i', 24: u'o', 25: u'p', 26: u'[', 27: u']', 28: u'CRLF', 29: u'LCTRL',
    30: u'a', 31: u's', 32: u'd', 33: u'f', 34: u'g', 35: u'h', 36: u'j', 37: u'k', 38: u'l', 39: u';',
    40: u"'", 41: u'`', 42: u'LSHFT', 43: u'\\', 44: u'z', 45: u'x', 46: u'c', 47: u'v', 48: u'b', 49: u'n',
    50: u'm', 51: u',', 52: u'.', 53: u'/', 54: u'RSHFT', 56: u'LALT', 100: u'RALT',57:u" "
}

scancodes_leftshift = {
    # Scancode: ASCIICode
    0: None, 1: u'ESC', 2: u'!', 3: u'@', 4: u'#', 5: u'$', 6: u'%', 7: u'^', 8: u'&', 9: u'*',
    10: u'(', 11: u')', 12: u'_', 13: u'+', 14: u'BKSP', 15: u'TAB', 16: u'Q', 17: u'W', 18: u'E', 19: u'R',
    20: u'T', 21: u'Y', 22: u'U', 23: u'I', 24: u'O', 25: u'P', 26: u'{', 27: u'}', 28: u'CRLF', 29: u'LCTRL',
    30: u'A', 31: u'S', 32: u'D', 33: u'F', 34: u'G', 35: u'H', 36: u'J', 37: u'K', 38: u'L', 39: u':',
    40: u'"', 41: u'~', 42: u'LSHFT', 43: u'|', 44: u'Z', 45: u'X', 46: u'C', 47: u'V', 48: u'B', 49: u'N',
    50: u'M', 51: u'<', 52: u'>', 53: u'?', 54: u'RSHFT', 56: u'LALT', 100: u'RALT',57:u" "
}

dev = None #设备
barCodeDeviceString = "Newland Auto-ID NLS IOTC PRDs HID KBW"

def usb_scan_dev():
        global dev
        devices = map(InputDevice, list_devices())
        for device in devices:
                if device.name == barCodeDeviceString:
                        dev = InputDevice(device.fn)

        if not dev:
                print("not found dev")
                return

        def signal_handler(signalnum, frame):
		     	print(signalnum)
		        print(frame)
                #根据退出信号,释放输入设备
                print("Stopping")
                dev.ungrab()
                sys.exit(0)
                
		# 信号处理函数
		# signal.SIGINT-终止进程
		# 若输入ctrl+c,则按照signal_handler函数对其进行处理
        signal.signal(signal.SIGINT, signal_handler)

        dev.grab() #成为全部事件中惟一接收者

        barcode = ""
        keymap = scancodes
        for event in dev.read_loop():
                if event.type == ecodes.EV_KEY:
                        data = categorize(event)
                        if data.scancode == 42:
                                if data.keystate == 1:
                                        keymap = scancodes_leftshift
                                if data.keystate == 0:
                                        keymap = scancodes

                        #只接收输入,不接收输出,也不接收回车
                        if data.keystate == 1 and data.scancode != 42:
                                if data.scancode == 28:
                                        print(barcode)
                                        Request_url = "http://www.mxnzp.com/api/barcode/goods/details?barcode=" + barcode
                                        r = requests.get(Request_url, timeout=0.1)
										print(r.text)
                                        barcode = ""
                                else:
                                        if data.scancode >= 1 and data.scancode <= 57:
                                                barcode += keymap[data.scancode]

# 表示该py文件做为单独脚本运行时,即执行usb_scan_dev方法
if __name__ == "__main__":
        usb_scan_dev()

结果:
在这里插入图片描述oop


附:
evdev:https://python-evdev.readthedocs.io/en/latest/apidoc.html