# -*- coding: utf-8 -*- # Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details. from flectra import http from flectra.tools import config from flectra.addons.web.controllers import main as web from flectra.addons.hw_posbox_homepage.controllers import main as homepage import logging import netifaces as ni import os from subprocess import call import time import threading self_port = str(config['http_port'] or 7073) _logger = logging.getLogger(__name__) class Homepage(homepage.PosboxHomepage): def get_hw_screen_message(self): return """

If you need to display the current customer basket on another device, you can do it here.

""" class HardwareScreen(web.Home): event_data = threading.Event() pos_client_data = {'rendered_html': False, 'ip_from': False} display_in_use = '' failure_count = {} def _call_xdotools(self, keystroke): os.environ['DISPLAY'] = ":0.0" os.environ['XAUTHORITY'] = "/run/lightdm/pi/xauthority" try: call(['xdotool', 'key', keystroke]) return "xdotool succeeded in stroking " + keystroke except: return "xdotool threw an error, maybe it is not installed on the posbox" @http.route('/hw_proxy/display_refresh', type='json', auth='none', cors='*') def display_refresh(self): return self._call_xdotools('F5') # POS CASHIER'S ROUTES @http.route('/hw_proxy/customer_facing_display', type='json', auth='none', cors='*') def update_user_facing_display(self, html=None): request_ip = http.request.httprequest.remote_addr if request_ip == HardwareScreen.pos_client_data.get('ip_from', ''): HardwareScreen.pos_client_data['rendered_html'] = html HardwareScreen.event_data.set() return {'status': 'updated'} else: return {'status': 'failed'} @http.route('/hw_proxy/take_control', type='json', auth='none', cors='*') def take_control(self, html=None): # ALLOW A CASHIER TO TAKE CONTROL OVER THE POSBOX, IN CASE OF MULTIPLE CASHIER PER POSBOX HardwareScreen.pos_client_data['rendered_html'] = html HardwareScreen.pos_client_data['ip_from'] = http.request.httprequest.remote_addr HardwareScreen.event_data.set() return {'status': 'success', 'message': 'You now have access to the display'} @http.route('/hw_proxy/test_ownership', type='json', auth='none', cors='*') def test_ownership(self): if HardwareScreen.pos_client_data.get('ip_from') == http.request.httprequest.remote_addr: return {'status': 'OWNER'} else: return {'status': 'NOWNER'} # POSBOX ROUTES (SELF) @http.route('/point_of_sale/display', type='http', auth='none') def render_main_display(self): return self._get_html() @http.route('/point_of_sale/get_serialized_order', type='json', auth='none') def get_serialized_order(self): request_addr = http.request.httprequest.remote_addr result = HardwareScreen.pos_client_data if HardwareScreen.display_in_use and request_addr != HardwareScreen.display_in_use: if not HardwareScreen.failure_count.get(request_addr): HardwareScreen.failure_count[request_addr] = 0 if HardwareScreen.failure_count[request_addr] > 0: time.sleep(10) HardwareScreen.failure_count[request_addr] += 1 return {'rendered_html': """

Not Authorized. Another browser is in use to display for the client. Please refresh.

""", 'stop_longpolling': True, 'ip_from': request_addr} # IMPLEMENTATION OF LONGPOLLING # Times out 2 seconds before the JS request does if HardwareScreen.event_data.wait(28): HardwareScreen.event_data.clear() HardwareScreen.failure_count[request_addr] = 0 return result return {'rendered_html': False, 'ip_from': HardwareScreen.pos_client_data['ip_from']} def _get_html(self): cust_js = None interfaces = ni.interfaces() my_ip = '127.0.0.1' HardwareScreen.display_in_use = http.request.httprequest.remote_addr with open(os.path.join(os.path.dirname(__file__), "../static/src/js/worker.js")) as js: cust_js = js.read() with open(os.path.join(os.path.dirname(__file__), "../static/src/css/cust_css.css")) as css: cust_css = css.read() display_ifaces = "" for iface_id in interfaces: iface_obj = ni.ifaddresses(iface_id) ifconfigs = iface_obj.get(ni.AF_INET, []) for conf in ifconfigs: if conf.get('addr'): display_ifaces += "" + iface_id + "" display_ifaces += "" + conf.get('addr') + "" display_ifaces += "" + conf.get('netmask') + "" # What is my external IP ? if iface_id != 'lo': my_ip = conf.get('addr') my_ip_port = my_ip + ":" + self_port html = """ Flectra -- Point of Sale

Flectra Point of Sale

POSBox Client display

My IPs

""" + display_ifaces + """
Interface IP Netmask

The customer cart will be displayed here once a Point of Sale session is started.

Flectra version 11 or above is required.

""" return html