[FIX] hw_escpos: Backport driver robustness
This commit is contained in:
parent
2067a206ec
commit
3cf45e1111
|
@ -16,6 +16,14 @@ import pickle
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
try:
|
||||||
|
from .. escpos import *
|
||||||
|
from .. escpos.exceptions import *
|
||||||
|
from .. escpos.printer import Usb
|
||||||
|
except ImportError:
|
||||||
|
escpos = printer = None
|
||||||
|
|
||||||
from threading import Thread, Lock
|
from threading import Thread, Lock
|
||||||
from Queue import Queue, Empty
|
from Queue import Queue, Empty
|
||||||
|
|
||||||
|
@ -24,13 +32,6 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
usb = None
|
usb = None
|
||||||
|
|
||||||
try:
|
|
||||||
from .. import escpos
|
|
||||||
from ..escpos import printer
|
|
||||||
from ..escpos import supported_devices
|
|
||||||
except ImportError:
|
|
||||||
escpos = printer = None
|
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from openerp import http
|
from openerp import http
|
||||||
|
@ -110,24 +111,19 @@ class EscposDriver(Thread):
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def get_escpos_printer(self):
|
def get_escpos_printer(self):
|
||||||
try:
|
|
||||||
printers = self.connected_usb_devices()
|
printers = self.connected_usb_devices()
|
||||||
if len(printers) > 0:
|
if len(printers) > 0:
|
||||||
self.set_status('connected','Connected to '+printers[0]['name'])
|
self.set_status('connected','Connected to '+printers[0]['name'])
|
||||||
return escpos.printer.Usb(printers[0]['vendor'], printers[0]['product'])
|
return Usb(printers[0]['vendor'], printers[0]['product'])
|
||||||
else:
|
else:
|
||||||
self.set_status('disconnected','Printer Not Found')
|
self.set_status('disconnected','Printer Not Found')
|
||||||
return None
|
|
||||||
except Exception as e:
|
|
||||||
self.set_status('error',str(e))
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
self.push_task('status')
|
self.push_task('status')
|
||||||
return self.status
|
return self.status
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def open_cashbox(self,printer):
|
def open_cashbox(self,printer):
|
||||||
printer.cashdraw(2)
|
printer.cashdraw(2)
|
||||||
printer.cashdraw(5)
|
printer.cashdraw(5)
|
||||||
|
@ -150,11 +146,13 @@ class EscposDriver(Thread):
|
||||||
_logger.warning('ESC/POS Device Disconnected: '+message)
|
_logger.warning('ESC/POS Device Disconnected: '+message)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
if not escpos:
|
if not escpos:
|
||||||
_logger.error('ESC/POS cannot initialize, please verify system dependencies.')
|
_logger.error('ESC/POS cannot initialize, please verify system dependencies.')
|
||||||
return
|
return
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
error = True
|
||||||
timestamp, task, data = self.queue.get(True)
|
timestamp, task, data = self.queue.get(True)
|
||||||
|
|
||||||
printer = self.get_escpos_printer()
|
printer = self.get_escpos_printer()
|
||||||
|
@ -162,6 +160,7 @@ class EscposDriver(Thread):
|
||||||
if printer == None:
|
if printer == None:
|
||||||
if task != 'status':
|
if task != 'status':
|
||||||
self.queue.put((timestamp,task,data))
|
self.queue.put((timestamp,task,data))
|
||||||
|
error = False
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
continue
|
continue
|
||||||
elif task == 'receipt':
|
elif task == 'receipt':
|
||||||
|
@ -178,11 +177,25 @@ class EscposDriver(Thread):
|
||||||
self.print_status(printer)
|
self.print_status(printer)
|
||||||
elif task == 'status':
|
elif task == 'status':
|
||||||
pass
|
pass
|
||||||
|
error = False
|
||||||
|
|
||||||
|
except NoDeviceError as e:
|
||||||
|
print "No device found %s" %str(e)
|
||||||
|
except HandleDeviceError as e:
|
||||||
|
print "Impossible to handle the device due to previous error %s" % str(e)
|
||||||
|
except TicketNotPrinted as e:
|
||||||
|
print "The ticket does not seems to have been fully printed %s" % str(e)
|
||||||
|
except NoStatusError as e:
|
||||||
|
print "Impossible to get the status of the printer %s" % str(e)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.set_status('error', str(e))
|
self.set_status('error', str(e))
|
||||||
errmsg = str(e) + '\n' + '-'*60+'\n' + traceback.format_exc() + '-'*60 + '\n'
|
errmsg = str(e) + '\n' + '-'*60+'\n' + traceback.format_exc() + '-'*60 + '\n'
|
||||||
_logger.error(errmsg);
|
_logger.error(errmsg);
|
||||||
|
finally:
|
||||||
|
if error:
|
||||||
|
self.queue.put((timestamp, task, data))
|
||||||
|
if printer:
|
||||||
|
printer.close()
|
||||||
|
|
||||||
def push_task(self,task, data = None):
|
def push_task(self,task, data = None):
|
||||||
self.lockedstart()
|
self.lockedstart()
|
||||||
|
|
|
@ -8,6 +8,13 @@ CTL_FF = '\x0c' # Form feed
|
||||||
CTL_CR = '\x0d' # Carriage return
|
CTL_CR = '\x0d' # Carriage return
|
||||||
CTL_HT = '\x09' # Horizontal tab
|
CTL_HT = '\x09' # Horizontal tab
|
||||||
CTL_VT = '\x0b' # Vertical tab
|
CTL_VT = '\x0b' # Vertical tab
|
||||||
|
|
||||||
|
# RT Status commands
|
||||||
|
DLE_EOT_PRINTER = '\x10\x04\x01' # Transmit printer status
|
||||||
|
DLE_EOT_OFFLINE = '\x10\x04\x02'
|
||||||
|
DLE_EOT_ERROR = '\x10\x04\x03'
|
||||||
|
DLE_EOT_PAPER = '\x10\x04\x04'
|
||||||
|
|
||||||
# Printer hardware
|
# Printer hardware
|
||||||
HW_INIT = '\x1b\x40' # Clear data in buffer and reset modes
|
HW_INIT = '\x1b\x40' # Clear data in buffer and reset modes
|
||||||
HW_SELECT = '\x1b\x3d\x01' # Printer select
|
HW_SELECT = '\x1b\x3d\x01' # Printer select
|
||||||
|
|
|
@ -1,13 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
'''
|
|
||||||
@author: Manuel F Martinez <manpaz@bashlinux.com>
|
|
||||||
@organization: Bashlinux
|
|
||||||
@copyright: Copyright (c) 2012 Bashlinux
|
|
||||||
@license: GPL
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import time
|
import time
|
||||||
import copy
|
import copy
|
||||||
import io
|
import io
|
||||||
|
@ -21,19 +13,15 @@ import xml.dom.minidom as minidom
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import jcconv
|
import jcconv
|
||||||
except ImportError:
|
except ImportError:
|
||||||
jcconv = None
|
jcconv = None
|
||||||
_logger.warning('ESC/POS: please install jcconv for improved Japanese receipt printing:\n # pip install jcconv')
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import qrcode
|
import qrcode
|
||||||
except ImportError:
|
except ImportError:
|
||||||
qrcode = None
|
qrcode = None
|
||||||
_logger.warning('ESC/POS: please install the qrcode python module for qrcode printing in point of sale receipts:\n # pip install qrcode')
|
|
||||||
|
|
||||||
from constants import *
|
from constants import *
|
||||||
from exceptions import *
|
from exceptions import *
|
||||||
|
@ -107,14 +95,14 @@ class StyleStack:
|
||||||
'off': TXT_BOLD_OFF,
|
'off': TXT_BOLD_OFF,
|
||||||
'on': TXT_BOLD_ON,
|
'on': TXT_BOLD_ON,
|
||||||
# must be issued after 'size' command
|
# must be issued after 'size' command
|
||||||
# because ESC ! resets ESC E
|
# because ESC ! resets ESC -
|
||||||
'_order': 10,
|
'_order': 10,
|
||||||
},
|
},
|
||||||
'font': {
|
'font': {
|
||||||
'a': TXT_FONT_A,
|
'a': TXT_FONT_A,
|
||||||
'b': TXT_FONT_B,
|
'b': TXT_FONT_B,
|
||||||
# must be issued after 'size' command
|
# must be issued after 'size' command
|
||||||
# because ESC ! resets ESC M
|
# because ESC ! resets ESC -
|
||||||
'_order': 10,
|
'_order': 10,
|
||||||
},
|
},
|
||||||
'size': {
|
'size': {
|
||||||
|
@ -122,7 +110,7 @@ class StyleStack:
|
||||||
'double-height': TXT_2HEIGHT,
|
'double-height': TXT_2HEIGHT,
|
||||||
'double-width': TXT_2WIDTH,
|
'double-width': TXT_2WIDTH,
|
||||||
'double': TXT_DOUBLE,
|
'double': TXT_DOUBLE,
|
||||||
'_order': 1,
|
'_order': 1,
|
||||||
},
|
},
|
||||||
'color': {
|
'color': {
|
||||||
'black': TXT_COLOR_BLACK,
|
'black': TXT_COLOR_BLACK,
|
||||||
|
@ -181,9 +169,8 @@ class StyleStack:
|
||||||
def to_escpos(self):
|
def to_escpos(self):
|
||||||
""" converts the current style to an escpos command string """
|
""" converts the current style to an escpos command string """
|
||||||
cmd = ''
|
cmd = ''
|
||||||
# Sort commands because some commands affect others (see _order attributes above)
|
|
||||||
ordered_cmds = self.cmds.keys()
|
ordered_cmds = self.cmds.keys()
|
||||||
ordered_cmds.sort(lambda x, y: cmp(self.cmds[x]['_order'], self.cmds[y]['_order']))
|
ordered_cmds.sort(lambda x,y: cmp(self.cmds[x]['_order'], self.cmds[y]['_order']))
|
||||||
for style in ordered_cmds:
|
for style in ordered_cmds:
|
||||||
cmd += self.cmds[style][self.get(style)]
|
cmd += self.cmds[style][self.get(style)]
|
||||||
return cmd
|
return cmd
|
||||||
|
|
|
@ -78,3 +78,39 @@ class CashDrawerError(Error):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Valid pin must be set to send pulse"
|
return "Valid pin must be set to send pulse"
|
||||||
|
|
||||||
|
class NoStatusError(Error):
|
||||||
|
def __init__(self, msg=""):
|
||||||
|
Error.__init__(self, msg)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 70
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Impossible to get status from the printer"
|
||||||
|
|
||||||
|
class TicketNotPrinted(Error):
|
||||||
|
def __init__(self, msg=""):
|
||||||
|
Error.__init__(self, msg)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 80
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "A part of the ticket was not been printed"
|
||||||
|
|
||||||
|
class NoDeviceError(Error):
|
||||||
|
def __init__(self, msg=""):
|
||||||
|
Error.__init__(self, msg)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 90
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Impossible to find the printer Device"
|
||||||
|
|
||||||
|
class HandleDeviceError(Error):
|
||||||
|
def __init__(self, msg=""):
|
||||||
|
Error.__init__(self, msg)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 100
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Impossible to handle device"
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
'''
|
|
||||||
@author: Manuel F Martinez <manpaz@bashlinux.com>
|
|
||||||
@organization: Bashlinux
|
|
||||||
@copyright: Copyright (c) 2012 Bashlinux
|
|
||||||
@license: GPL
|
|
||||||
'''
|
|
||||||
|
|
||||||
import usb.core
|
import usb.core
|
||||||
import usb.util
|
import usb.util
|
||||||
|
@ -14,6 +8,7 @@ import socket
|
||||||
from escpos import *
|
from escpos import *
|
||||||
from constants import *
|
from constants import *
|
||||||
from exceptions import *
|
from exceptions import *
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
class Usb(Escpos):
|
class Usb(Escpos):
|
||||||
""" Define USB printer """
|
""" Define USB printer """
|
||||||
|
@ -26,6 +21,9 @@ class Usb(Escpos):
|
||||||
@param in_ep : Input end point
|
@param in_ep : Input end point
|
||||||
@param out_ep : Output end point
|
@param out_ep : Output end point
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
self.errorText = "ERROR PRINTER\n\n\n\n\n\n"+PAPER_FULL_CUT
|
||||||
|
|
||||||
self.idVendor = idVendor
|
self.idVendor = idVendor
|
||||||
self.idProduct = idProduct
|
self.idProduct = idProduct
|
||||||
self.interface = interface
|
self.interface = interface
|
||||||
|
@ -33,35 +31,102 @@ class Usb(Escpos):
|
||||||
self.out_ep = out_ep
|
self.out_ep = out_ep
|
||||||
self.open()
|
self.open()
|
||||||
|
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
""" Search device on USB tree and set is as escpos device """
|
""" Search device on USB tree and set is as escpos device """
|
||||||
|
|
||||||
self.device = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
|
self.device = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
|
||||||
if self.device is None:
|
if self.device is None:
|
||||||
print "Cable isn't plugged in"
|
raise NoDeviceError()
|
||||||
|
|
||||||
if self.device.is_kernel_driver_active(0):
|
|
||||||
try:
|
|
||||||
self.device.detach_kernel_driver(0)
|
|
||||||
except usb.core.USBError as e:
|
|
||||||
print "Could not detatch kernel driver: %s" % str(e)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if self.device.is_kernel_driver_active(self.interface):
|
||||||
|
self.device.detach_kernel_driver(self.interface)
|
||||||
self.device.set_configuration()
|
self.device.set_configuration()
|
||||||
self.device.reset()
|
usb.util.claim_interface(self.device, self.interface)
|
||||||
except usb.core.USBError as e:
|
except usb.core.USBError as e:
|
||||||
print "Could not set configuration: %s" % str(e)
|
raise HandleDeviceError(e)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
i = 0
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
if not self.device.is_kernel_driver_active(self.interface):
|
||||||
|
usb.util.release_interface(self.device, self.interface)
|
||||||
|
self.device.attach_kernel_driver(self.interface)
|
||||||
|
usb.util.dispose_resources(self.device)
|
||||||
|
else:
|
||||||
|
self.device = None
|
||||||
|
return True
|
||||||
|
except usb.core.USBError as e:
|
||||||
|
i += 1
|
||||||
|
if i > 100:
|
||||||
|
return False
|
||||||
|
|
||||||
|
sleep(0.1)
|
||||||
|
|
||||||
def _raw(self, msg):
|
def _raw(self, msg):
|
||||||
""" Print any command sent in raw format """
|
""" Print any command sent in raw format """
|
||||||
self.device.write(self.out_ep, msg, self.interface)
|
if len(msg) != self.device.write(self.out_ep, msg, self.interface):
|
||||||
|
self.device.write(self.out_ep, self.errorText, self.interface)
|
||||||
|
raise TicketNotPrinted()
|
||||||
|
|
||||||
|
def __extract_status(self):
|
||||||
|
maxiterate = 0
|
||||||
|
rep = None
|
||||||
|
while rep == None:
|
||||||
|
maxiterate += 1
|
||||||
|
if maxiterate > 10000:
|
||||||
|
raise NoStatusError()
|
||||||
|
r = self.device.read(self.in_ep, 20, self.interface).tolist()
|
||||||
|
while len(r):
|
||||||
|
rep = r.pop()
|
||||||
|
return rep
|
||||||
|
|
||||||
|
def get_printer_status(self):
|
||||||
|
status = {
|
||||||
|
'printer': {},
|
||||||
|
'offline': {},
|
||||||
|
'error' : {},
|
||||||
|
'paper' : {},
|
||||||
|
}
|
||||||
|
|
||||||
|
self.device.write(self.out_ep, DLE_EOT_PRINTER, self.interface)
|
||||||
|
printer = self.__extract_status()
|
||||||
|
self.device.write(self.out_ep, DLE_EOT_OFFLINE, self.interface)
|
||||||
|
offline = self.__extract_status()
|
||||||
|
self.device.write(self.out_ep, DLE_EOT_ERROR, self.interface)
|
||||||
|
error = self.__extract_status()
|
||||||
|
self.device.write(self.out_ep, DLE_EOT_PAPER, self.interface)
|
||||||
|
paper = self.__extract_status()
|
||||||
|
|
||||||
|
status['printer']['status_code'] = printer
|
||||||
|
status['printer']['status_error'] = not ((printer & 147) == 18)
|
||||||
|
status['printer']['online'] = not bool(printer & 8)
|
||||||
|
status['printer']['recovery'] = bool(printer & 32)
|
||||||
|
status['printer']['paper_feed_on'] = bool(printer & 64)
|
||||||
|
status['printer']['drawer_pin_high'] = bool(printer & 4)
|
||||||
|
status['offline']['status_code'] = offline
|
||||||
|
status['offline']['status_error'] = not ((offline & 147) == 18)
|
||||||
|
status['offline']['cover_open'] = bool(offline & 4)
|
||||||
|
status['offline']['paper_feed_on'] = bool(offline & 8)
|
||||||
|
status['offline']['paper'] = not bool(offline & 32)
|
||||||
|
status['offline']['error'] = bool(offline & 64)
|
||||||
|
status['error']['status_code'] = error
|
||||||
|
status['error']['status_error'] = not ((error & 147) == 18)
|
||||||
|
status['error']['recoverable'] = bool(error & 4)
|
||||||
|
status['error']['autocutter'] = bool(error & 8)
|
||||||
|
status['error']['unrecoverable'] = bool(error & 32)
|
||||||
|
status['error']['auto_recoverable'] = not bool(error & 64)
|
||||||
|
status['paper']['status_code'] = paper
|
||||||
|
status['paper']['status_error'] = not ((paper & 147) == 18)
|
||||||
|
status['paper']['near_end'] = bool(paper & 12)
|
||||||
|
status['paper']['present'] = not bool(paper & 96)
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
""" Release USB interface """
|
""" Release USB interface """
|
||||||
if self.device:
|
if self.device:
|
||||||
usb.util.dispose_resources(self.device)
|
self.close()
|
||||||
self.device = None
|
self.device = None
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,3 +199,4 @@ class Network(Escpos):
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
""" Close TCP connection """
|
""" Close TCP connection """
|
||||||
self.device.close()
|
self.device.close()
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ class Scanner(Thread):
|
||||||
if status == 'error' and message:
|
if status == 'error' and message:
|
||||||
_logger.error('Barcode Scanner Error: '+message)
|
_logger.error('Barcode Scanner Error: '+message)
|
||||||
elif status == 'disconnected' and message:
|
elif status == 'disconnected' and message:
|
||||||
_logger.warning('Disconnected Barcode Scanner: '+message)
|
_logger.info('Disconnected Barcode Scanner: %s', message)
|
||||||
|
|
||||||
def get_device(self):
|
def get_device(self):
|
||||||
try:
|
try:
|
||||||
|
@ -168,41 +168,41 @@ class Scanner(Thread):
|
||||||
device.ungrab()
|
device.ungrab()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.set_status('error',str(e))
|
self.set_status('error',str(e))
|
||||||
device = self.get_device()
|
|
||||||
if not device:
|
|
||||||
time.sleep(5) # wait until a suitable device is plugged
|
|
||||||
else:
|
else:
|
||||||
try:
|
time.sleep(5) # wait until a suitable device is plugged
|
||||||
device.grab()
|
device = self.get_device()
|
||||||
shift = False
|
|
||||||
barcode = []
|
|
||||||
|
|
||||||
while True: # keycode loop
|
try:
|
||||||
r,w,x = select([device],[],[],5)
|
device.grab()
|
||||||
if len(r) == 0: # timeout
|
shift = False
|
||||||
break
|
barcode = []
|
||||||
events = device.read()
|
|
||||||
|
|
||||||
for event in events:
|
while True: # keycode loop
|
||||||
if event.type == evdev.ecodes.EV_KEY:
|
r,w,x = select([device],[],[],5)
|
||||||
#_logger.debug('Evdev Keyboard event %s',evdev.categorize(event))
|
if len(r) == 0: # timeout
|
||||||
if event.value == 1: # keydown events
|
break
|
||||||
if event.code in self.keymap:
|
events = device.read()
|
||||||
if shift:
|
|
||||||
barcode.append(self.keymap[event.code][1])
|
|
||||||
else:
|
|
||||||
barcode.append(self.keymap[event.code][0])
|
|
||||||
elif event.code == 42 or event.code == 54: # SHIFT
|
|
||||||
shift = True
|
|
||||||
elif event.code == 28: # ENTER, end of barcode
|
|
||||||
self.barcodes.put( (time.time(),''.join(barcode)) )
|
|
||||||
barcode = []
|
|
||||||
elif event.value == 0: #keyup events
|
|
||||||
if event.code == 42 or event.code == 54: # LEFT SHIFT
|
|
||||||
shift = False
|
|
||||||
|
|
||||||
except Exception as e:
|
for event in events:
|
||||||
self.set_status('error',str(e))
|
if event.type == evdev.ecodes.EV_KEY:
|
||||||
|
#_logger.debug('Evdev Keyboard event %s',evdev.categorize(event))
|
||||||
|
if event.value == 1: # keydown events
|
||||||
|
if event.code in self.keymap:
|
||||||
|
if shift:
|
||||||
|
barcode.append(self.keymap[event.code][1])
|
||||||
|
else:
|
||||||
|
barcode.append(self.keymap[event.code][0])
|
||||||
|
elif event.code == 42 or event.code == 54: # SHIFT
|
||||||
|
shift = True
|
||||||
|
elif event.code == 28: # ENTER, end of barcode
|
||||||
|
self.barcodes.put( (time.time(),''.join(barcode)) )
|
||||||
|
barcode = []
|
||||||
|
elif event.value == 0: #keyup events
|
||||||
|
if event.code == 42 or event.code == 54: # LEFT SHIFT
|
||||||
|
shift = False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.set_status('error',str(e))
|
||||||
|
|
||||||
s = Scanner()
|
s = Scanner()
|
||||||
|
|
||||||
|
@ -212,5 +212,4 @@ class ScannerDriver(hw_proxy.Proxy):
|
||||||
@http.route('/hw_proxy/scanner', type='json', auth='none', cors='*')
|
@http.route('/hw_proxy/scanner', type='json', auth='none', cors='*')
|
||||||
def scanner(self):
|
def scanner(self):
|
||||||
return s.get_barcode()
|
return s.get_barcode()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue