Tom
Tom

Reputation: 21

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.

Upvotes: 1

Views: 11852

Answers (2)

Tom
Tom

Reputation: 21

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

Upvotes: 1

magnetometer
magnetometer

Reputation: 656

Maybe the answer to this question could help. It suggests to use os.read() with a specified number of bytes instead of the regular read, as os.read() will return when it has read anything.

Upvotes: 0

Related Questions