[hw_scanner] implementation of the server side component of the barcode scanner proxy

bzr revid: fva@openerp.com-20140102141519-jaqi8mcqff282c6n
This commit is contained in:
Frédéric van der Essen 2014-01-02 15:15:19 +01:00
parent 4d7121cd24
commit 0fd4888e84
10 changed files with 230 additions and 8 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@ -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)

View File

@ -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))

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import controllers
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'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:

View File

@ -0,0 +1,3 @@
import main
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -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

View File

@ -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,

View File

@ -786,7 +786,7 @@
<field name="cash_control" />
</tree>
</field>
<group string="Material Interfaces" >
<group string="Settings" >
<group>
<field name="iface_self_checkout" />
<field name="iface_cashdrawer" />
@ -796,10 +796,14 @@
<group>
<field name="iface_electronic_scale" />
<field name="iface_vkeyboard" />
<field name="iface_print_via_proxy" />
<field name="iface_big_scrollbars" />
</group>
</group>
<group string="Receipt" >
<field name="iface_print_via_proxy" />
<field name="receipt_header" placeholder="A custom receipt header message"/>
<field name="receipt_footer" placeholder="A custom receipt header footage"/>
</group>
</sheet>
</form>

View File

@ -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,