odoo.define('point_of_sale.BarcodeReader', function (require) { "use strict"; var core = require('web.core'); // this module interfaces with the barcode reader. It assumes the barcode reader // is set-up to act like a keyboard. Use connect() and disconnect() to activate // and deactivate the barcode reader. Use set_action_callbacks to tell it // what to do when it reads a barcode. var BarcodeReader = core.Class.extend({ actions:[ 'product', 'cashier', 'client', ], init: function (attributes) { this.pos = attributes.pos; this.action_callbacks = {}; this.exclusive_callbacks = {}; this.proxy = attributes.proxy; this.remote_scanning = false; this.remote_active = 0; this.barcode_parser = attributes.barcode_parser; this.action_callback_stack = []; core.bus.on('barcode_scanned', this, function (barcode) { this.scan(barcode); }); }, set_barcode_parser: function (barcode_parser) { this.barcode_parser = barcode_parser; }, // when a barcode is scanned and parsed, the callback corresponding // to its type is called with the parsed_barcode as a parameter. // (parsed_barcode is the result of parse_barcode(barcode)) // // callbacks is a Map of 'actions' : callback(parsed_barcode) // that sets the callback for each action. if a callback for the // specified action already exists, it is replaced. // // possible actions include : // 'product' | 'cashier' | 'client' | 'discount' set_action_callback: function (name, callback) { if (this.action_callbacks[name]) { this.action_callbacks[name].add(callback); } else { this.action_callbacks[name] = new Set([callback]); } }, remove_action_callback: function(name, callback) { if (!callback) { delete this.action_callbacks[name]; return; } const callbacks = this.action_callbacks[name]; if (callbacks) { callbacks.delete(callback); if (callbacks.size === 0) { delete this.action_callbacks[name]; } } }, /** * Allow setting of exclusive callbacks. If there are exclusive callbacks, * these callbacks are called neglecting the regular callbacks. This is * useful for rendered Components that wants to take exclusive access * to the barcode reader. * * @param {String} name * @param {Function} callback function that takes parsed barcode */ set_exclusive_callback: function (name, callback) { if (this.exclusive_callbacks[name]) { this.exclusive_callbacks[name].add(callback); } else { this.exclusive_callbacks[name] = new Set([callback]); } }, remove_exclusive_callback: function (name, callback) { if (!callback) { delete this.exclusive_callbacks[name]; return; } const callbacks = this.exclusive_callbacks[name]; if (callbacks) { callbacks.delete(callback); if (callbacks.size === 0) { delete this.exclusive_callbacks[name]; } } }, scan: function (code) { if (!code) return; const callbacks = Object.keys(this.exclusive_callbacks).length ? this.exclusive_callbacks : this.action_callbacks; const parsed_result = this.barcode_parser.parse_barcode(code); if (callbacks[parsed_result.type]) { [...callbacks[parsed_result.type]].map((cb) => cb(parsed_result)); } else if (callbacks.error) { [...callbacks.error].map((cb) => cb(parsed_result)); } else { console.warn('Ignored Barcode Scan:', parsed_result); } }, // the barcode scanner will listen on the hw_proxy/scanner interface for // scan events until disconnect_from_proxy is called connect_to_proxy: function () { var self = this; this.remote_scanning = true; if (this.remote_active >= 1) { return; } this.remote_active = 1; function waitforbarcode(){ return self.proxy.connection.rpc('/hw_proxy/scanner',{},{shadow: true, timeout:7500}) .then(function (barcode) { if (!self.remote_scanning) { self.remote_active = 0; return; } self.scan(barcode); waitforbarcode(); }, function () { if (!self.remote_scanning) { self.remote_active = 0; return; } waitforbarcode(); }); } waitforbarcode(); }, // the barcode scanner will stop listening on the hw_proxy/scanner remote interface disconnect_from_proxy: function () { this.remote_scanning = false; }, }); return BarcodeReader; });