[IMP] point_of_sale: Realtime printer & scanner online status
authorFrédéric van der Essen <fva@openerp.com>
Sun, 26 Jan 2014 21:55:28 +0000 (22:55 +0100)
committerFrédéric van der Essen <fva@openerp.com>
Sun, 26 Jan 2014 21:55:28 +0000 (22:55 +0100)
bzr revid: fva@openerp.com-20140126215528-q32v2q8keh6m0ufo

addons/hw_proxy/controllers/main.py
addons/point_of_sale/static/src/css/pos.css
addons/point_of_sale/static/src/js/devices.js
addons/point_of_sale/static/src/js/models.js
addons/point_of_sale/static/src/js/widgets.js
addons/point_of_sale/static/src/xml/pos.xml

index 1888c23..3ea2de4 100644 (file)
@@ -42,6 +42,10 @@ class Proxy(http.Controller):
             'Access-Control-Allow-Methods': 'GET',
             })
 
+    @http.route('/hw_proxy/handshake', type='json', auth='admin')
+    def handshake(self):
+        return True
+
     @http.route('/hw_proxy/status', type='http', auth='admin')
     def status_http(self):
         resp = '<html>\n<body>\n<h1>Hardware Proxy Status</h1>\n'
@@ -71,14 +75,9 @@ class Proxy(http.Controller):
             'Access-Control-Allow-Methods': 'GET',
             })
 
-    @http.route('/hw_proxy/status', type='json', auth='admin')
+    @http.route('/hw_proxy/status_json', type='json', auth='admin')
     def status_json(self):
-        return request.make_response(simplejson.dumps(self.get_status()),{
-            'Cache-Control': 'no-cache', 
-            'Content-Type': 'text/html; charset=utf-8',
-            'Access-Control-Allow-Origin':  '*',
-            'Access-Control-Allow-Methods': 'GET',
-            })
+        return self.get_status()
 
     @http.route('/hw_proxy/scan_item_success', type='json', auth='admin')
     def scan_item_success(self, ean):
index 41fc503..8051595 100644 (file)
@@ -379,13 +379,16 @@ td {
     width:20px; height:16px;
     color: white;
 }
-.pos .oe_icon.oe_red{
+.pos .oe_status .oe_red,
+.pos .oe_icon.oe_red {
     color: rgb(197, 52, 0);
 }
-.pos .oe_icon.oe_green{
+.pos .oe_statu .oe_green,
+.pos .oe_icon.oe_green {
     color: rgb(94, 185, 55);
 }
-.pos .oe_icon.oe_orange{
+.pos .oe_status .oe_orange,
+.pos .oe_icon.oe_orange {
     color: rgb(239, 153, 65);
 }
 
index e86bb7c..f31fb89 100644 (file)
@@ -105,38 +105,80 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
             this.bypass_proxy = false;
 
             this.connection = null; 
-            this.connected = new $.Deferred();
-            this.status    = 'disconnected';
-
-            window.proxy = this;
+            this.connected  = null;
+            this.host       = '';
+            this.keptalive  = false;
+            this.status = {};
+
+            this.status_callback = options.status_callback || null;
+            this.set_connection_status('disconnected');
+
+            window.hw_proxy = this;
+        },
+        set_connection_status: function(status,drivers){
+            this.status.status = status;
+            this.status.drivers = status === 'disconnected' ? {} : this.status.drivers;
+            this.status.drivers = drivers ? drivers : this.status.drivers;
+            if(this.status_callback){
+                this.status_callback(status,drivers);
+            }
         },
-        close: function(){
-            if(this.status !== 'disconnected'){
+        disconnect: function(){
+            if(this.status.status !== 'disconnected'){
                 this.connection.destroy();
-                this.status = 'disconnected';
+                this.set_connection_status('disconnected');
             }
         },
         connect : function(url){
             var self = this;
             this.connection = new instance.web.Session(undefined,url);
-            this.status = 'connecting';
+            this.host   = url;
+            this.set_connection_status('connecting',{});
+            if(this.connected){
+                this.connected.reject();
+            }
+            this.connected = new $.Deferred();
 
-            return this.message('handshake').then(function(){
-                    self.status = 'connected';
-                    localStorage['hw_proxy_url'] = url;
-                    self.connected.resolve();
+            return this.message('handshake').then(function(response){
+                    if(response){
+                        self.set_connection_status('connected');
+                        localStorage['hw_proxy_url'] = url;
+                        self.connected.resolve();
+                        self.keepalive();
+                    }else{
+                        self.set_connection_status('disconnected');
+                        self.connected.reject();
+                        console.error('Connection refused by the Proxy');
+                    }
                 },function(){
-                    self.status = 'disconnected';
+                    self.set_connection_status('disconnected');
                     self.connected.reject();
                     console.error('Could not connect to the Proxy');
                 });
         },
+        keepalive: function(){
+            var self = this;
+            if(!this.keptalive){
+                this.keptalive = true;
+                function status(){
+                    self.connection.rpc('/hw_proxy/status_json',{})       
+                        .then(function(driver_status){
+                            self.set_connection_status('connected',driver_status);
+                        },function(){
+                            self.set_connection_status('disconnected');
+                        }).always(function(){
+                            setTimeout(status,5000);
+                        });
+                }
+                status();
+            };
+        },
         message : function(name,params){
             var callbacks = this.notifications[name] || [];
             for(var i = 0; i < callbacks.length; i++){
                 callbacks[i](params);
             }
-            if(this.status !== 'disconnected'){
+            if(this.status.status !== 'disconnected'){
                 return this.connection.rpc('/hw_proxy/' + name, params || {});       
             }else{
                 return (new $.Deferred()).reject();
@@ -245,8 +287,6 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
             }
             this.notifications[name].push(callback);
         },
-
-        
         
         //a product has been scanned and recognized with success
         // ean is a parsed ean object
@@ -702,7 +742,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
         disconnect_from_proxy: function(){
             this.remote_scanning = false;
         },
-        connect_to_proxy: function(){
+        connect_to_proxy: function(){ //FIXME prevent double connections
             var self = this;
             this.remote_scanning = true;
 
@@ -714,13 +754,11 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
                         if(!self.remote_scanning){ 
                             return; 
                         }
-                        self.pos.set('proxy_status','connected');
                         self.scan(barcode);
                         waitforbarcode();
                     },
                     function(){
                         setTimeout(waitforbarcode,5000);
-                        self.pos.set('proxy_status','disconnected');
                     });
                 });
         },
index 58f87b6..aae0263 100644 (file)
@@ -55,7 +55,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
                 'synch':            { state:'connected', pending:0 }, 
                 'orders':           new module.OrderCollection(),
                 'selectedOrder':    null,
-                'proxy_status':     'connecting',
+                'proxy_status':     {status: 'connecting', drivers: {}},
             });
 
             this.bind('change:synch',function(pos,synch){
@@ -92,17 +92,24 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
             this.barcode_reader.disconnect_from_proxy();
         },
 
+        set_proxy_status: function(status,drivers){
+            this.set('proxy_status',{status:status,drivers:drivers || {}});
+        },
         connect_to_proxy: function(){
             var self = this;
             this.barcode_reader.disconnect_from_proxy();
             this.pos_widget.loading_message(_t('Connecting to the PosBox'),0);
-            this.set('proxy_status', 'connecting');
+            this.set_proxy_status('connecting');
             
             this.pos_widget.loading_skip(function(){
                     self.proxy.stop_searching();
-                    self.set('proxy_status', 'disconnected'); 
+                    this.set_proxy_status('disconnected');
                 });
 
+            this.proxy.status_callback = function(status,driver_status){
+                self.set_proxy_status(status,driver_status);
+            };
+
             return this.proxy.find_proxy({
                     force_ip: self.config.proxy_ip || undefined,
                     progress: function(prog){ 
@@ -114,9 +121,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
                         if(self.config.iface_scan_via_proxy){
                             self.barcode_reader.connect_to_proxy();
                         }
-                        self.set('proxy_status', 'connected');
+                        self.set_proxy_status('connected');
                     }else{
-                        self.set('proxy_status', 'disconnected');
+                        self.set_proxy_status('disconnected');
                     }
                 });
         },
index 393b0b2..1bfda51 100644 (file)
@@ -856,13 +856,39 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
     // this is used to notify the user if the pos is connected to the proxy
     module.ProxyStatusWidget = module.StatusWidget.extend({
         template: 'ProxyStatusWidget',
+        set_smart_status: function(status){
+            if(status.status === 'connected'){
+                var warning = false;
+                var msg = ''
+                if(this.pos.config.iface_scan_via_proxy){
+                    var scanner = status.drivers.scanner ? status.drivers.scanner.status : false;
+                    if( scanner != 'connected' && scanner != 'connecting'){
+                        warning = true;
+                        msg += _t('Scanner');
+                    }
+                }
+                if( this.pos.config.iface_print_via_proxy || 
+                    this.pos.config.iface_cashdrawer ){
+                    var printer = status.drivers.escpos ? status.drivers.escpos.status : false;
+                    if( printer != 'connected' && printer != 'connecting'){
+                        warning = true;
+                        msg = msg ? msg + ' & ' : msg;
+                        msg += _t('Printer');
+                    }
+                }
+                msg = msg ? msg + ' ' + _t('Offline') : msg;
+                this.set_status(warning ? 'warning' : 'connected', msg);
+            }else{
+                this.set_status(status.status,'');
+            }
+        },
         start: function(){
             var self = this;
             
-            this.set_status(this.pos.get('proxy_status'),'');
+            this.set_smart_status(this.pos.get('proxy_status'));
 
             this.pos.bind('change:proxy_status', function(pos,status){
-                self.set_status(status,'');
+                self.set_smart_status(status);
             });
 
             this.$el.click(function(){
index 179d4ac..748fcbf 100644 (file)
 
     <t t-name="ProxyStatusWidget">
         <div class="oe_status js_proxy">
-            <span class='js_msg oe_hidden'></span>
+            <span class='js_msg oe_orange oe_hidden'></span>
             <div class="js_connected oe_icon oe_green">
                 <i class='fa fa-fw fa-sitemap'></i>
             </div>
             <div class="js_connecting oe_icon oe_hidden">
                 <i class='fa fa-fw fa-spin fa-spinner'></i>
             </div>
+            <div class="js_warning oe_icon oe_orange oe_hidden">
+                <i class='fa fa-fw fa-sitemap'></i>
+            </div>
             <div class="js_disconnected oe_icon oe_red oe_hidden">
                 <i class='fa fa-fw fa-sitemap'></i>
             </div>