Search code examples
pythonbarcodebarcode-scanner

Read from USB barcode scanner only if data is available


UPDATED:

I've successfully been able to read a USB barcode scanner using Python. I want to be able to escape the fp.read() if it is empty and check if the user has pushed the left LCD button

def read Barcode
lcd.backlight(lcd.GREEN)
hid = { 4: 'a', 5: 'b', 6: 'c', 7: 'd', 8: 'e', 9: 'f', 10: 'g', 11: 'h', 12: 'i', 13: 'j', 14: 'k', 15: 'l', 16: 'm', 17: 'n', 18: 'o', 19: 'p', 20: 'q', 21: 'r', 22: 's', 23: 't', 24: 'u', 25: 'v', 26: 'w', 27: 'x', 28: 'y', 29: 'z', 30: '1', 31: '2', 32: '3', 33: '4', 34: '5', 35: '6', 36: '7', 37: '8', 38: '9', 39: '0', 44: ' ', 45: '-', 46: '=', 47: '[', 48: ']', 49: '\\', 51: ';' , 52: '\'', 53: '~', 54: ',', 55: '.', 56: '/'  }
hid2 = { 4: 'A', 5: 'B', 6: 'C', 7: 'D', 8: 'E', 9: 'F', 10: 'G', 11: 'H', 12: 'I', 13: 'J', 14: 'K', 15: 'L', 16: 'M', 17: 'N', 18: 'O', 19: 'P', 20: 'Q', 21: 'R', 22: 'S', 23: 'T', 24: 'U', 25: 'V', 26: 'W', 27: 'X', 28: 'Y', 29: 'Z', 30: '!', 31: '@', 32: '#', 33: '$', 34: '%', 35: '^', 36: '&', 37: '*', 38: '(', 39: ')', 44: ' ', 45: '_', 46: '+', 47: '{', 48: '}', 49: '|', 51: ':' , 52: '"', 53: '~', 54: '<', 55: '>', 56: '?'  }
backPressed = False
lcd.clear()
lcd.message("accn: \nLocation: ")
lcd.setCursor(7, 1)
print("Scan Next Accn:")
while not backPressed:
  fp = open('/dev/hidraw0', 'r')
  accn = ""
  shift = False
  done = False
  print("should loop")
  r, w, e = select.select([ fp ], [], [], 0)
  print("Should be a line here")
  if fp in r:
    print("Fp is in r")
    while not done:
        print("looping")
        buffer = os.read(fp.fileno(), 8)
        for c in buffer:
          if ord(c) > 0:
             if int(ord(c)) == 40:
                done = True
                fp.flush()
                fp.close()
                print("Done = True")
                break;
             if shift: 
                if int(ord(c)) == 2 :
                   shift = True
                else:
                   accn += hid2[ int(ord(c)) ]
                   shift = False
             else:
                if int(ord(c)) == 2 :
                   shift = True
                else:
                   accn += hid[ int(ord(c)) ]
    print("accn: " + accn)
    fileAccn(accn)
    fp.close()
    backPressed = lcd.buttonPressed(lcd.LEFT)
    if(backPressed):
      lcd.backlight(lcd.WHITE)
      return
  backPressed = lcd.buttonPressed(lcd.LEFT)
  if(backPressed):
    return
return

Since the barcode scanner doesn't send an EOF Using fp.read() without arguments wont return if it's empty. Any help is appreciated. I'm hesitant to use interrupts or timeouts because I don't want to end the function in the middle of scanning a barcode.

Thanks in advance.


Solution

  • I just wanted to update with a legit answer. I think this problem is best solved with evdev. Here is the function I have cobbled together.

    Basically, when it's called it will read one event from the barcode scanner event = dev.read_one(). If there is no even it moves along.

    When it hits a character, it will keep checking the contents of the even until it gets a return key event. At that point, the barcode is finished and it returns. To exit the loop, the user can press the back button lcd.LEFT is pushed

    A couple of notes, it might be a good idea to read every event before entering the function or at the start. I don't think this functions clears out all of the events and if events happen before the function is called (i.e. you scan a barcode) it could catch the last few characters.

    #!/usr/bin/env python
    
    from evdev import *
    import signal, sys, time
    
    keys = {
        # 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'
    }
    dev = InputDevice('/dev/input/event0')
    def scanBarcode():
      barcode = ''
      while True:
          event = dev.read_one()
          if event is None and barcode == '':
            #There are blank events in between characters, 
            #so we don't want to break if we've started
            #reading them
            break #nothing of importance, start a new read. 
          try:
            if event is not None:
              if event.type == ecodes.EV_KEY:
                data = categorize(event)
                if data.keystate == 0 and data.scancode != 42: # Catch only keyup, and not Enter
                  if data.scancode == 28: #looking return key to be pressed
                    return barcode
                  else:
                      barcode += keys[data.scancode] # add the new char to the barcode
          except AttributeError:
              print "error parsing stream"
              return 'SOMETHING WENT WRONG'
          if lcd.buttonPressed(lcd.LEFT):
            return