For a new project, I need to read input from a USB barcode scanner (that registers as a keyboard) and perform some actions on the "typed" text whenever the Enter key was pressed.
The requirement is that this code run on a headless Raspberry Pi 3, and that it be started on boot, indefinitely waiting for input. I know how to wait for and process keyboard input in, for example, Python, but I have no idea how to do it in a background process (e.g., by starting the script in rc.local or via crontab).
Are there any techniques how to achieve this kind of requirement? It doesn't have to be in Python, but it has to run on Raspbian. Some code examples would be perfect, but links to tutorials/techniques/documentation are greatly appreciated, too.
2 Answers 2
I think this link is probably what you are looking for.
Briefly, if your device works similar to the one mentioned in the link above, there should be a file created as /dev/????
when you plug it in, which you could open in a python script and continuously read line by line using readline (assuming each scan prints the barcode followed by newline) and process it. You can launch the script as a background process by adding the following line near the end (but before the exit 0
) of /etc/rc.local like so
python /home/pi/scripts/barscanner.py &
- it is critical the process is started in the background using
&
as the OS will not finish the boot process until the/etc/rc.local
script exits - needless to say if you are going to plug in the device after booting the Pi, your script will need to wait for the file
/dev/????
to get created (you can usestat
to check say every second) before attempting to read from it
-
Thanks, the solution given in the link works! Now I encountered another problem, but I'll open a new question for that.TheWolf– TheWolf2016年09月26日 11:54:57 +00:00Commented Sep 26, 2016 at 11:54
-
@TheWolf I am working a similar project and would be interested in reading about any discussion preceding or trailing this EXCELLENT Q&A discussion.gatorback– gatorback2016年10月30日 12:48:34 +00:00Commented Oct 30, 2016 at 12:48
-
@gatorback My other question is here: raspberrypi.stackexchange.com/questions/55527/… It is only remotely related, though.TheWolf– TheWolf2016年11月15日 11:39:52 +00:00Commented Nov 15, 2016 at 11:39
If one desires to process an inbound HID text string in Python, an alternative is to use EVDEV:
import evdev
from evdev import InputDevice, categorize, ecodes
dev = InputDevice('/dev/input/event1')
# Modify as needed
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 = ''[enter link description here][1]