Python:从活动 window 之外的 HID 设备获取输入?

Python: get input from HID device outside the active window?

描述

我使用 Kivy 框架和 运行 Python 3 中的一个脚本,该脚本从 HID 设备读取输入。该设备是条码扫描器,模拟键盘。

问题

脚本在后台同时打开一个弹出窗口和条形阅读程序。每次尝试读取条形码我都必须处于活动状态 window。在我的例子中,这是提示符(控制台)。这意味着我必须单击控制台 window,然后 reader 才能工作。无论我如何从主脚本(方法、线程、子进程、Clock.schedule_once)调用读取过程,都会发生这种情况。如何在提示 window 之外获取输入,例如在控制台外的主要 kivy gui 中?

这些其他帖子确实有帮助,但没有提供答案:

  1. How can I get a String from HID device in Python with evdev?
  2. python :Read from a USB HID device
  3. How can I get a String from HID device in Python with evdev?
  4. Read HID input while window is "out of focus" in Python

代码

使用 str = input("") 作为子进程:

#!/usr/bin/python3.5 python3.5
# -*- coding: utf-8 -*-

# This script reads the output from HID device e.g. bar/rfid scanner

import sys
import inspect
import csv

# return the current line number
def lineno():
    return inspect.currentframe().f_back.f_lineno
    
str = input("Enter your input: ")

使用 evdev.ecodes.EV_KEY 作为子进程:

import evdev
from evdev import InputDevice, categorize, ecodes
device = evdev.InputDevice('/dev/input/event20')
while True:
    try:
        for event in device.read_loop():
            if event.type == evdev.ecodes.EV_KEY:
                print(evdev.categorize(event))
    except:
        print("Keyboard Interrupt")
        break

我在 post 此处 https://khanhicetea.com/post/read_input_from_usb_keyboard_in_linux/ 之后找到了解决方案。我将输入检测文件称为子进程。由于我没有在 CODE_MAP_CHAR{} 中找到 enter 键的快速替代品,我添加了 scancodes{}enter 键的不同类型的代码。要找出不同设备的名称和其他属性,请使用 cat /proc/bus/input/devices。下面是工作代码。

#!/usr/bin/python3.5 python3.5
# -*- coding: utf-8 -*-
# This script reads the output from HID device e.g. ECCO bar/rfid scanner
# Make sure evdev is installed or install it with: pip3 install evdev.
# The Kernel on the Pi creates an input device which resides in /dev/input/.
# You can find out the names and other attributes of different devices using:
# cat /proc/bus/input/devices

import sys
import inspect
import serial
import time
import random
import csv

import evdev
from evdev import InputDevice, categorize, ecodes, list_devices

device = evdev.InputDevice('/dev/input/event20')
print(device)

# reserve the device
device.grab()

#setup vars
eccoOut=[]
x = ''
caps = False


CODE_MAP_CHAR = {
    'KEY_MINUS': "-",
    'KEY_SPACE': " ",    
    'KEY_U': "U",
    'KEY_W': "W",
    'KEY_BACKSLASH': "\",
    'KEY_GRAVE': "`",
    'KEY_NUMERIC_STAR': "*",
    'KEY_NUMERIC_3': "3",
    'KEY_NUMERIC_2': "2",
    'KEY_NUMERIC_5': "5",
    'KEY_NUMERIC_4': "4",
    'KEY_NUMERIC_7': "7",
    'KEY_NUMERIC_6': "6",
    'KEY_NUMERIC_9': "9",
    'KEY_NUMERIC_8': "8",
    'KEY_NUMERIC_1': "1",
    'KEY_NUMERIC_0': "0",
    'KEY_E': "E",
    'KEY_D': "D",
    'KEY_G': "G",
    'KEY_F': "F",
    'KEY_A': "A",
    'KEY_C': "C",
    'KEY_B': "B",
    'KEY_M': "M",
    'KEY_L': "L",
    'KEY_O': "O",
    'KEY_N': "N",
    'KEY_I': "I",
    'KEY_H': "H",
    'KEY_K': "K",
    'KEY_J': "J",
    'KEY_Q': "Q",
    'KEY_P': "P",
    'KEY_S': "S",
    'KEY_X': "X",
    'KEY_Z': "Z",
    'KEY_q': "q",
    'KEY_w': "w",
    'KEY_e': "e",
    'KEY_r': "r",
    'KEY_t': "t",
    'KEY_z': "z",
    'KEY_u': "u",
    'KEY_i': "i",
    'KEY_o': "o",
    'KEY_p': "p",
    'KEY_a': "a",
    'KEY_s': "s",
    'KEY_d': "d",
    'KEY_f': "f",
    'KEY_g': "g",
    'KEY_h': "h",
    'KEY_j': "k",
    'KEY_l': "l",
    'KEY_y': "y",
    'KEY_x': "x",
    'KEY_c': "c",
    'KEY_v': "v",
    'KEY_b': "b",
    'KEY_n': "n",
    'KEY_m': "m",
    'KEY_KP4': "4",
    'KEY_KP5': "5",
    'KEY_KP6': "6",
    'KEY_KP7': "7",
    'KEY_KP0': "0",
    'KEY_KP1': "1",
    'KEY_KP2': "2",
    'KEY_KP3': "3",
    'KEY_KP8': "8",
    'KEY_KP9': "9",
    'KEY_5': "5",
    'KEY_4': "4",
    'KEY_7': "7",
    'KEY_6': "6",
    'KEY_1': "1",
    'KEY_0': "0",
    'KEY_3': "3",
    'KEY_2': "2",
    'KEY_9': "9",
    'KEY_8': "8",
    'KEY_LEFTBRACE': "[",
    'KEY_RIGHTBRACE': "]",    
    'KEY_COMMA': ",",
    'KEY_EQUAL': "=",    
    'KEY_SEMICOLON': ";",
    'KEY_APOSTROPHE': "'",
    'KEY_T': "T",
    'KEY_V': "V",
    'KEY_R': "R",
    'KEY_Y': "Y",
    'KEY_TAB': "\t",
    'KEY_DOT': ".",
    'KEY_SLASH': "/",
}

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'
}

def parse_key_to_char(val):
    return CODE_MAP_CHAR[val] if val in CODE_MAP_CHAR else ""

if __name__ == "__main__":
    print("list of devices:")
    devices = [InputDevice(fn) for fn in list_devices()]
    for device in devices:
        print("\t{}\t{}".format(device.fn, device.name))
        
    event_id = 20   # check your events to set the correct value
    exclusive_access = 1

    device = InputDevice('/dev/input/event{}'.format(event_id))
    if int(exclusive_access) == 1:
        device.grab()

    eccoBarcodeList = []
    for event in device.read_loop():
        if event.type == evdev.ecodes.EV_KEY:
            e = categorize(event)
            if e.keystate == e.key_up:
                sys.stdout.write(parse_key_to_char(e.keycode))
                cifra = parse_key_to_char(e.keycode)
                eccoBarcodeList.append(cifra)
                print(eccoBarcodeList)
                sys.stdout.flush()
            if e.scancode == 28:
                print("return key detected, exiting...")
                break