如何使用evdev从Python中获取HID设备的字符串?

时间:2013-11-01 18:25:31

标签: python hid

我是python的新手,但有HID设备和evdev的经验。我有一个2D条形码扫描仪,它作为HID设备接口。目标是从QR码中获取字符串。我能够在Linux中识别扫描仪,甚至在/ dev / input中找到它的位置。

我找到了evdev,并使用我的扫描仪实现了下面的示例。这只是他们网站上的默认代码。它会读取值,但会打印带有向下和向下的长事件代码。我看不到将其变成字符串的简单方法。我想做的就是用Python中的HID扫描器读取一个字符串。任何帮助或方向将不胜感激(也许evdev不是答案)。

这是我当前的python代码,其中包含一些示例输出:

from evdev import *
dev = InputDevice('/dev/input/event1')

print(dev)

for event in dev.read_loop():
    if event.type == ecodes.EV_KEY:
        print(categorize(event))

以下是一些条形码的输出:

key event at 1383327570.147000, 2 (KEY_1), down
key event at 1383327570.147990, 2 (KEY_1), up
key event at 1383327570.148997, 3 (KEY_2), down
key event at 1383327570.150010, 3 (KEY_2), up
key event at 1383327570.151009, 29 (KEY_LEFTCTRL), down
key event at 1383327570.151009, 42 (KEY_LEFTSHIFT), down
key event at 1383327570.152017, 36 (KEY_J), down
key event at 1383327570.153005, 36 (KEY_J), up
key event at 1383327570.154004, 29 (KEY_LEFTCTRL), up
key event at 1383327570.155005, 32 (KEY_D), down
key event at 1383327570.155993, 32 (KEY_D), up
key event at 1383327570.157002, 48 (KEY_B), down
key event at 1383327570.158015, 48 (KEY_B), up
key event at 1383327570.158997, 48 (KEY_B), down
key event at 1383327570.282002, 18 (KEY_E), up
key event at 1383327570.283004, 49 (KEY_N), down
key event at 1383327570.284005, 49 (KEY_N), up
key event at 1383327570.284968, 18 (KEY_E), down

非常感谢!

3 个答案:

答案 0 :(得分:13)

这里有一个转换步骤。你的输出已经是一个漂亮的格式,所以我会帮你分解一下:

             Timestamp        , scancode, keycode, keystate
key event at 1383327570.147000, 2         (KEY_1), down
key event at 1383327570.147990, 2         (KEY_1), up

要对此有任何有用的认识,您需要做一些事情:

  1. 仅通过过滤器仅侦听特定类型的keystate(Down = 1,Up = 0)
  2. 来监听key_down类型事件
  3. 将扫描码转换为ASCII码,该码可能因设备而异,并因其映射到系统的方式而异;
  4. 然而,有一种简单的方法来映射它们。使用在线服务生成包含所有可用字符的已知条形码,然后扫描该条形码并将输出的每个扫描码映射到扫描仪的正确字母/数字。您可以使用以下稍微修改过的代码片段来更好地控制输出:

    import evdev
    from evdev import InputDevice, categorize  # import * is evil :)
    dev = InputDevice('/dev/input/event1')
    
    # Provided as an example taken from my own keyboard attached to a Centos 6 box:
    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'
    }
    for event in dev.read_loop():
        if event.type == evdev.ecodes.EV_KEY:
            data = evdev.categorize(event)  # Save the event temporarily to introspect it
            if data.keystate == 1:  # Down events only
                key_lookup = scancodes.get(data.scancode) or u'UNKNOWN:{}'.format(data.scancode)  # Lookup or return UNKNOWN:XX
                print u'You Pressed the {} key!'.format(key_lookup)  # Print it all out!
    

    以下是此脚本的一些示例输出

    You Pressed the A key!
    You Pressed the B key!
    You Pressed the C key!
    You Pressed the UNKNOWN:99 key!
    

    在线生成一些条形码后,您就会知道哪个扫描码被映射到哪个值!建立自己的桌子和利润!

    HTH

答案 1 :(得分:9)

VooDooNOFX的代码非常有用,并把我踢向了正确的方向。我想回答我自己的问题,以增加其他任何试图将霍尼韦尔MS7580或类似光学扫描仪与Linux上的python键盘仿真接口的人的清晰度。

这个项目是使用BeagleBone Black完成的,我只能使用命令行访问,因此无法将扫描仪用作常规键盘。为了正确处理换档,我必须在按下换档按钮时添加第二组扫描码。这是我从QR码读取字符串的最终代码:

import evdev
from evdev import InputDevice, categorize, ecodes  
dev = InputDevice('/dev/input/event1')

# Provided as an example taken from my own keyboard attached to a Centos 6 box:
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', 57: u' ', 100: u'RALT'
}

capscodes = {
    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',  57: u' ', 100: u'RALT'
}
#setup vars
x = ''
caps = False

#grab provides exclusive access to the device
dev.grab()

#loop
for event in dev.read_loop():
    if event.type == ecodes.EV_KEY:
        data = categorize(event)  # Save the event temporarily to introspect it
        if data.scancode == 42:
            if data.keystate == 1:
                caps = True
            if data.keystate == 0:
                caps = False
        if data.keystate == 1:  # Down events only
            if caps:
                key_lookup = u'{}'.format(capscodes.get(data.scancode)) or u'UNKNOWN:[{}]'.format(data.scancode)  # Lookup or return UNKNOWN:XX
            else:
                key_lookup = u'{}'.format(scancodes.get(data.scancode)) or u'UNKNOWN:[{}]'.format(data.scancode)  # Lookup or return UNKNOWN:XX
            if (data.scancode != 42) and (data.scancode != 28):
                x += key_lookup  
            if(data.scancode == 28):
                print x          # Print it all out!
                x = ''

非常感谢VooDoo用evdev指引我正确的方向。

答案 2 :(得分:1)

非常感谢,真的很有帮助。 这是python3版本:

import evdev
from evdev import *
import time 
#dev =evdev.InputDevice('/dev/input/by-id/usb-SM_SM-2D_PRODUCT_HID_KBW_APP-000000000-event-kbd')
dev =evdev.InputDevice('/dev/input/event1')
dev.grab()
print(dev)

# for event in dev.read_loop():
#     if event.type == ecodes.EV_KEY:
#         print(categorize(event))

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', 57: u' ', 100: u'RALT' 
} 

capscodes = { 
    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', 57: u' ', 100: u'RALT' 
} 
#setup vars 
x = '' 
caps = False 

#grab provides exclusive access to the device 


#loop 
for event in dev.read_loop(): 
    if event.type == ecodes.EV_KEY: 
     data = categorize(event) # Save the event temporarily to introspect it 
     if data.scancode == 42: 
      if data.keystate == 1: 
       caps = True 
      if data.keystate == 0: 
       caps = False 
     if data.keystate == 1: # Down events only 
      if caps: 
       key_lookup = u'{}'.format(capscodes.get(data.scancode)) or u'UNKNOWN:[{}]'.format(data.scancode) # Lookup or return UNKNOWN:XX 
      else: 
       key_lookup = u'{}'.format(scancodes.get(data.scancode)) or u'UNKNOWN:[{}]'.format(data.scancode) # Lookup or return UNKNOWN:XX 
      if (data.scancode != 42) and (data.scancode != 28): 
       x += key_lookup 
      if(data.scancode == 28): 
       print (x)   # Print it all out! 
       x = '' `enter code here`