[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:
parent
4d7121cd24
commit
0fd4888e84
Binary file not shown.
Before Width: | Height: | Size: 11 KiB |
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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:
|
||||
|
|
@ -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:
|
|
@ -0,0 +1,3 @@
|
|||
import main
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue