Reputation: 1061
I am new to python but have experience with HID devices and evdev. I have a 2D barcode scanner which interfaces as HID device. The goal is to get the string from a QR code. I am able to recognize the scanner in Linux and even found its location in /dev/input.
I found evdev and have implemented the example below with my scanner. This is just the default code on their site. It reads the values but it prints long event codes with downs and ups. I can't see an easy way to turn this into string. All I want to do is read in a string from the HID scanner in Python. Any help or direction would be appreciated (maybe evdev isnt the answer).
Here is my current python code with some example output:
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))
Here is the output from some barcodes:
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
Many thanks!
Upvotes: 15
Views: 18711
Reputation: 41
thanks a lot ,it really helpful. and here is the python3 version:
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`
Upvotes: 4
Reputation: 1061
VooDooNOFX's code was hugely helpful and kicked me in the right direction. I wanted to answer my own question to add clarity for anyone else trying to interface a Honeywell MS7580 or similar optical scanner with keyboard emulation with python on linux.
This project was done using a BeagleBone Black where I had only command line access and thus could not just use the scanner as a regular keyboard. In order to process the shifts properly I had to add a second group of scancodes for when the shift button was depressed. Here is my final code for reading a string from a QR code:
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 = ''
Thanks so much to VooDoo for pointing me in the right direction with evdev.
Upvotes: 13
Reputation: 4762
There's a conversion step you're missing here. Your output is already in a pretty format, so i'll help you break it down a little more:
Timestamp , scancode, keycode, keystate
key event at 1383327570.147000, 2 (KEY_1), down
key event at 1383327570.147990, 2 (KEY_1), up
To make any useful sense of this, you need to do a couple of things:
There's a simple-ish way to map them however. Generate a known barcode with all useable characters using an online service, then scan that barcode and map each scancode outputted to the correct letter/number for your scanner. You can use the following slightly modified piece of code to take better control of the output:
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!
Here's some sample output from this script for me
You Pressed the A key!
You Pressed the B key!
You Pressed the C key!
You Pressed the UNKNOWN:99 key!
Once you generate some barcodes online, you'll know which scancode gets mapped to which value! Build your own table and profit!
HTH
Upvotes: 19