Stack Exchange
Python evdev and bar code scanner
I have a following code which I use to catch input from bar code scanner. The problem is in that I want to save whole scanned code in database, but every character of code prints on new line:
#!/usr/bin/env python

from evdev import InputDevice, ecodes, list_devices
from select import select

keys = "X^1234567890XXXXqwertzuiopXXXXasdfghjklXXXXXyxcvbnmXXXXXXXXXXXXXXXXXXXXXXX"
dev = InputDevice("/dev/input/event10")

barcode = ""
while True:
    r,w,x = select([dev], [], [])

    for event in dev.read():
        if event.type == 1 and event.value == 1:
             barcode += (keys[event.code])

    print barcode

# sudo ./bar-code-test.py                                                                           
#0
#00
#00
#000
#001
#1001
#0017
#70017
#00170
#000170
#001708
#8001708
#0017085
#50017085
#00170853
#300170853
#001708531
#1001708531
#0017085316
#60017085316
#00170853160
#000170853160
#001708531601
#1001708531601
#0017085316013
#30017085316013
#00170853160131
#100170853160131
#00170853160131X
#00170853160131X

I Am newbie with python, so any help will be appreciated.

Found a solution. Bar code scanner after each scanned code send 42 scan code (Enter key), so we need check scan code:
#!/usr/bin/env python

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

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'
}
barCodeDeviceString = "Metrologic Metrologic Scanner"

devices = map(InputDevice, list_devices())
for device in devices:
    if device.name == barCodeDeviceString:
        dev = InputDevice(device.fn)

def signal_handler(signal, frame):
    print 'Stopping'
    dev.ungrab()
    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

dev.grab()

barcode = ""
for event in dev.read_loop():
    if event.type == ecodes.EV_KEY:
        data = categorize(event)
        if data.keystate == 1 and data.scancode != 42: # Catch only keydown, and not Enter
            if data.scancode == 28:
                print barcode
                barcode = ""
            else:
                barcode += keys[data.scancode]


what if I would like to trigger an event (e.g. call a REST api) after print barcode is triggered or when data.scancode ==28? And prevent subsequent scans being recorded while the event is carried out. How to achieve it? I've tried to ungrab the device but it doesn't seem to exit the dev.read_loop()

@user1872384 I think you need then some kind of flag which will indicate that barcode is processed. For example set some variable to True and check in a loop that variable. If it's True, then loop continues even if there is a new events (e.g. new barcode scanned). Once barcode processed and REST API returned something set that flag back to False so further barcodes can be scanned.

Thanks @bosha. I've tried to place a flag in the loop. However, it doesn't seem to take effect. It will still enter the for loop after the flag is set to true. I would like something to stop the scan event totally.

@user1872384 I think you done something wrong. Please share relevant code parts. Here is something that comes to my mind - https://paste.ee/p/2oEcf

What about if you read the length of the string, and until it reaches your desired value or length, you exit the loop and print out the barcode read. 
I modified the code like this and it just prints one line:
#!/usr/bin/env python

from evdev import InputDevice, ecodes, list_devices
from select import select

keys = "X^1234567890XXXXqwertzuiopXXXXasdfghjklXXXXXyxcvbnmXXXXXXXXXXXXXXXXXXXXXXX"
dev = InputDevice("/dev/input/event1")

barcode = ""
while True:
    r,w,x = select([dev], [], [])

    for event in dev.read():
        if event.type == 1 and event.value == 1:
             barcode += (keys[event.code])
    if (len (barcode)) > 13:
    break;



print barcode

I tried it in Arduino Yun, with OpenWrt, and it worked just fine:
root@Arduino:/mnt/sda1# python pybar.py
7501483187071X

