Files
odoo_source/addons/hw_screen/controllers/main.py
T

167 lines
6.9 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import http
from odoo.tools import config
from odoo.addons.web.controllers import main as web
import logging
import netifaces as ni
import os
from subprocess import call
import time
import threading
self_port = str(config['xmlrpc_port'] or 8069)
_logger = logging.getLogger(__name__)
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': """<div class="pos-customer_facing_display"><p>Not Authorized. Another browser is in use to display for the client. Please refresh.</p></div> """,
'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 += "<tr><td>" + iface_id + "</td>"
display_ifaces += "<td>" + conf.get('addr') + "</td>"
display_ifaces += "<td>" + conf.get('netmask') + "</td></tr>"
# What is my external IP ?
if iface_id != 'lo':
my_ip = conf.get('addr')
my_ip_port = my_ip + ":" + self_port
html = """
<!DOCTYPE html>
<html>
<head>
<title class="origin">Odoo -- Point of Sale</title>
<script type="text/javascript" class="origin" src="http://""" + my_ip_port + """/web/static/lib/jquery/jquery.js" >
</script>
<script type="text/javascript" class="origin">
""" + cust_js + """
</script>
<link rel="stylesheet" class="origin" href="http://""" + my_ip_port + """/web/static/lib/bootstrap/css/bootstrap.css" >
</link>
<script class="origin" src="http://""" + my_ip_port + """/web/static/lib/bootstrap/js/bootstrap.min.js"></script>
<style class="origin">
""" + cust_css + """
</style>
</head>
<body class="original_body">
<div hidden class="shadow"></div>
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<h1>Odoo Point of Sale</h1>
<h2>POSBox Client display</h2>
<h3>My IPs</h3>
<table id="table_ip" class="table table-condensed">
<tr>
<th>Interface</th>
<th>IP</th>
<th>Netmask</th>
</tr>
""" + display_ifaces + """
</table>
<p>The customer cart will be displayed here once a Point of Sale session is started.</p>
<p>Odoo version 11 or above is required.</p>
</div>
</div>
</div>
</body>
</html>
"""
return html