From 0fd4888e84f6dc922f4b1774439dd519741005ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Thu, 2 Jan 2014 15:15:19 +0100 Subject: [PATCH] [hw_scanner] implementation of the server side component of the barcode scanner proxy bzr revid: fva@openerp.com-20140102141519-jaqi8mcqff282c6n --- .../hw_escpos/controllers/logo_grayscale.png | Bin 11377 -> 0 bytes addons/hw_escpos/controllers/main.py | 5 +- addons/hw_proxy/controllers/main.py | 11 ++ addons/hw_scanner/__init__.py | 25 ++++ addons/hw_scanner/__openerp__.py | 46 +++++++ addons/hw_scanner/controllers/__init__.py | 3 + addons/hw_scanner/controllers/main.py | 125 ++++++++++++++++++ addons/point_of_sale/point_of_sale.py | 12 +- addons/point_of_sale/point_of_sale_view.xml | 8 +- addons/point_of_sale/static/src/js/models.js | 3 + 10 files changed, 230 insertions(+), 8 deletions(-) delete mode 100644 addons/hw_escpos/controllers/logo_grayscale.png create mode 100644 addons/hw_scanner/__init__.py create mode 100644 addons/hw_scanner/__openerp__.py create mode 100644 addons/hw_scanner/controllers/__init__.py create mode 100644 addons/hw_scanner/controllers/main.py diff --git a/addons/hw_escpos/controllers/logo_grayscale.png b/addons/hw_escpos/controllers/logo_grayscale.png deleted file mode 100644 index acc3fa43f77b49493c33effd8f1ce88b05108658..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11377 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 diff --git a/addons/hw_escpos/controllers/main.py b/addons/hw_escpos/controllers/main.py index c4031417357..fbc79865297 100644 --- a/addons/hw_escpos/controllers/main.py +++ b/addons/hw_escpos/controllers/main.py @@ -123,7 +123,8 @@ class EscposDriver(hw_proxy.Proxy): eprint.text(receipt['company']['email'] + '\n') if check(receipt['company']['website']): eprint.text(receipt['company']['website'] + '\n') - + if check(receipt['header']): + eprint.text(receipt['header']+'\n') if check(receipt['cashier']): eprint.text('-'*32+'\n') eprint.text('Served by '+receipt['cashier']+'\n') @@ -177,6 +178,8 @@ class EscposDriver(hw_proxy.Proxy): eprint.text(printline(_('Taxes'),money(receipt['total_tax']),width=40, ratio=0.6)) # Footer + if check(receipt['footer']): + eprint.text('\n'+receipt['footer']+'\n\n') eprint.text(receipt['name']+'\n') eprint.text( str(receipt['date']['date']).zfill(2) +'/'+ str(receipt['date']['month']+1).zfill(2) diff --git a/addons/hw_proxy/controllers/main.py b/addons/hw_proxy/controllers/main.py index c3e01a34822..9b8e87bb4ac 100644 --- a/addons/hw_proxy/controllers/main.py +++ b/addons/hw_proxy/controllers/main.py @@ -136,6 +136,17 @@ class Proxy(http.Controller): def print_receipt(self, receipt): print 'print_receipt' + str(receipt) + @http.route('/hw_proxy/is_scanner_connected', type='json', auth='admin') + def print_receipt(self, receipt): + print 'is_scanner_connected?' + return False + + @http.route('/hw_proxy/scanner', type='json', auth='admin') + def print_receipt(self, receipt): + print 'scanner' + time.sleep(10) + return '' + @http.route('/hw_proxy/log', type='json', auth='admin') def log(self, arguments): _logger.info(' '.join(str(v) for v in arguments)) diff --git a/addons/hw_scanner/__init__.py b/addons/hw_scanner/__init__.py new file mode 100644 index 00000000000..a208bc1c551 --- /dev/null +++ b/addons/hw_scanner/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import controllers + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/hw_scanner/__openerp__.py b/addons/hw_scanner/__openerp__.py new file mode 100644 index 00000000000..9007304f2ae --- /dev/null +++ b/addons/hw_scanner/__openerp__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'Barcode Scanner Hardware Driver', + 'version': '1.0', + 'category': 'Hardware Drivers', + 'sequence': 6, + 'summary': 'Hardware Driver for Barcode Scanners', + 'description': """ +Barcode Scanner Hardware Driver +================================ + +This module allows the web client to access a remotely installed barcode +scanner, and is used by the posbox to provide barcode scanner support to the +point of sale module. + +""", + 'author': 'OpenERP SA', + 'depends': [], + 'test': [ + ], + 'installable': True, + 'auto_install': False, +} + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/hw_scanner/controllers/__init__.py b/addons/hw_scanner/controllers/__init__.py new file mode 100644 index 00000000000..b5f0bcc9ec6 --- /dev/null +++ b/addons/hw_scanner/controllers/__init__.py @@ -0,0 +1,3 @@ +import main +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/hw_scanner/controllers/main.py b/addons/hw_scanner/controllers/main.py new file mode 100644 index 00000000000..82e940cc5c3 --- /dev/null +++ b/addons/hw_scanner/controllers/main.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +import logging +import os +from os import listdir +from os.path import join +import openerp +import openerp.addons.hw_proxy.controllers.main as hw_proxy +from openerp.tools.translate import _ + +from openerp import http +from openerp.http import request + +_logger = logging.getLogger(__name__) + +from evdev import InputDevice, ecodes, categorize, list_devices +from select import select + +class ScannerDriver(hw_proxy.Proxy): + def __init__(self): + self.input_dir = '/dev/input/by-id/' + self.keymap = { + 2: ("1","!"), + 3: ("2","@"), + 4: ("3","#"), + 5: ("4","$"), + 6: ("5","%"), + 7: ("6","^"), + 8: ("7","&"), + 9: ("8","*"), + 10:("9","("), + 11:("0",")"), + 12:("-","_"), + 13:("=","+"), + # 14 BACKSPACE + # 15 TAB + 16:("q","Q"), + 17:("w","W"), + 18:("e","E"), + 19:("r","R"), + 20:("t","T"), + 21:("y","Y"), + 22:("u","U"), + 23:("i","I"), + 24:("o","O"), + 25:("p","P"), + 26:("[","{"), + 27:("]","}"), + # 28 ENTER + # 29 LEFT_CTRL + 30:("a","A"), + 31:("s","S"), + 32:("d","D"), + 33:("f","F"), + 34:("g","G"), + 35:("h","H"), + 36:("j","J"), + 37:("k","K"), + 38:("l","L"), + 39:(";",":"), + 40:("'","\""), + 41:("`","~"), + # 42 LEFT SHIFT + 43:("\\","|"), + 44:("z","Z"), + 45:("x","X"), + 46:("c","C"), + 47:("v","V"), + 48:("b","B"), + 49:("n","N"), + 50:("m","M"), + 51:(",","<"), + 52:(".",">"), + 53:("/","?"), + # 54 RIGHT SHIFT + 57:(" "," "), + } + + def get_device(self): + devices = [ device for device in listdir(self.input_dir)] + keyboards = [ device for device in devices if 'kbd' in device ] + scanners = [ device for device in devices if ('barcode' in device.lower()) or ('scanner' in device.lower()) ] + if len(scanners) > 0: + return InputDevice(join(self.input_dir,scanners[0])) + elif len(keyboards) > 0: + return InputDevice(join(self.input_dir,keyboards[0])) + else: + return None + + @http.route('/hw_proxy/is_scanner_connected', type='http', auth='admin') + def is_scanner_connected(self): + return self.get_device() != None + + @http.route('/hw_proxy/scanner', type='http', auth='admin') + def scanner(self): + device = self.get_device() + barcode = [] + shift = False + if not device: + return '' + else: + device.grab() + while True: + r,w,x = select([device],[],[],10) + if len(r) == 0: # timeout + device.ungrab() + return '' + for event in device.read(): + if event.type == ecodes.EV_KEY: + if event.value == 1: # keydown events + print categorize(event) + 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 + device.ungrab() + return ''.join(barcode); + elif event.value == 0: #keyup events + if event.code == 42 or event.code == 54: # LEFT SHIFT + shift = False + + diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index e34207cbdc3..78f5b0d8417 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -58,13 +58,15 @@ class pos_config(osv.osv): help="Accounting journal used to post sales entries."), 'iface_self_checkout' : fields.boolean('Self Checkout Mode', help="Check this if this point of sale should open by default in a self checkout mode. If unchecked, OpenERP uses the normal cashier mode by default."), - 'iface_cashdrawer' : fields.boolean('Cashdrawer Interface'), - 'iface_payment_terminal' : fields.boolean('Payment Terminal Interface'), - 'iface_electronic_scale' : fields.boolean('Electronic Scale Interface'), - 'iface_vkeyboard' : fields.boolean('Virtual KeyBoard Interface'), - 'iface_print_via_proxy' : fields.boolean('Print via Proxy'), + 'iface_cashdrawer' : fields.boolean('Cashdrawer',help="Automatically open the cashdrawer"), + 'iface_payment_terminal' : fields.boolean('Payment Terminal', help="Enables Payment Terminal integration"), + 'iface_electronic_scale' : fields.boolean('Electronic Scale', help="Enables Electronic Scale integration"), + 'iface_vkeyboard' : fields.boolean('Virtual KeyBoard', help="Enables an integrated Virtual Keyboard"), + 'iface_print_via_proxy' : fields.boolean('Print via Proxy', help="Bypass browser printing and prints via the hardware proxy"), 'iface_invoicing': fields.boolean('Invoicing',help='Enables invoice generation from the Point of Sale'), 'iface_big_scrollbars': fields.boolean('Large Scrollbars',help='For imprecise industrial touchscreens'), + 'receipt_header': fields.text('Receipt Header',help="A short text that will be inserted as a header in the printed receipt"), + 'receipt_footer': fields.text('Receipt Footer',help="A short text that will be inserted as a footer in the printed receipt"), 'state' : fields.selection(POS_CONFIG_STATE, 'Status', required=True, readonly=True), 'sequence_id' : fields.many2one('ir.sequence', 'Order IDs Sequence', readonly=True, diff --git a/addons/point_of_sale/point_of_sale_view.xml b/addons/point_of_sale/point_of_sale_view.xml index bdd59f98a49..af98eb698f0 100644 --- a/addons/point_of_sale/point_of_sale_view.xml +++ b/addons/point_of_sale/point_of_sale_view.xml @@ -786,7 +786,7 @@ - + @@ -796,10 +796,14 @@ - + + + + + diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 2d2965f3117..7ac2f42212e 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -138,6 +138,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal 'iface_self_checkout', 'iface_led', 'iface_cashdrawer', 'iface_payment_terminal', 'iface_electronic_scale', 'iface_barscan', 'iface_vkeyboard', 'iface_print_via_proxy','iface_cashdrawer','iface_invoicing','iface_big_scrollbars', + 'receipt_header','receipt_footer', 'state','sequence_id','session_ids'], [['id','=', self.pos_session.config_id[0]]] ); @@ -869,6 +870,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal client: client ? client.name : null , invoice_id: null, //TODO cashier: cashier ? cashier.name : null, + header: this.pos.config.receipt_header || '', + footer: this.pos.config.receipt_footer || '', precision: { price: 2, money: 2,