Как я могу получить строку с устройства HID в Python с evdev?
Я новичок в Python, но у меня есть опыт работы с HID-устройствами и evdev. У меня есть 2D сканер штрих-кода, который взаимодействует как HID-устройство. Цель состоит в том, чтобы получить строку из QR-кода. Я могу распознать сканер в Linux и даже нашел его местоположение в /dev/input.
Я нашел evdev и реализовал приведенный ниже пример со своим сканером. Это просто код по умолчанию на их сайте. Он читает значения, но печатает длинные коды событий со взлетами и падениями. Я не вижу простой способ превратить это в строку. Все, что я хочу сделать, это прочитать строку со сканера HID в Python. Любая помощь или направление будут оценены (возможно, 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 ответа
Здесь вам не хватает шага конвертации. Ваш вывод уже в хорошем формате, поэтому я помогу вам разобрать его немного подробнее:
Timestamp , scancode, keycode, keystate
key event at 1383327570.147000, 2 (KEY_1), down
key event at 1383327570.147990, 2 (KEY_1), up
Чтобы понять это, вам нужно сделать пару вещей:
- Прослушивать события типа key_down по фильтру можно только для состояния ключа определенного типа (Down = 1, Up = 0)
- Преобразуйте скан-код в код ASCII, который может различаться в зависимости от устройства и в зависимости от того, как он отображается в системе!
Однако есть простой способ отобразить их. С помощью онлайн-сервиса создайте известный штрих-код со всеми используемыми символами, затем отсканируйте этот штрих-код и сопоставьте каждый выведенный скан-код с правильной буквой / номером для вашего сканера. Вы можете использовать следующий слегка измененный фрагмент кода, чтобы лучше контролировать вывод:
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!
Как только вы сгенерируете несколько штрих-кодов онлайн, вы будете знать, какой скан-код сопоставлен с каким значением! Построй свой собственный стол и получай прибыль!
НТН
Код VooDooNOFX был чрезвычайно полезным и помог мне в правильном направлении. Я хотел бы ответить на свой вопрос, чтобы внести ясность для тех, кто пытается подключить Honeywell MS7580 или аналогичный оптический сканер к эмуляции клавиатуры с python на linux.
Этот проект был выполнен с использованием 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.
большое спасибо, это действительно полезно. а вот версия 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`