mods for raspi and hw_screen
This commit is contained in:
parent
4b8918e04c
commit
7c6ba1e1ec
|
@ -5,7 +5,7 @@ services:
|
|||
depends_on:
|
||||
- db
|
||||
ports:
|
||||
- 8069:8069
|
||||
- 80:8069
|
||||
volumes:
|
||||
- odoo-web-data:/var/lib/odoo
|
||||
networks:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM odoo:11
|
||||
FROM local/odoo:11
|
||||
|
||||
USER root
|
||||
|
||||
|
@ -15,3 +15,4 @@ RUN git clone --depth=1 -b 11.0 https://github.com/it-projects-llc/pos-addons.gi
|
|||
/opt/posbox/addons
|
||||
|
||||
COPY odoo.conf /etc/odoo/odoo.conf
|
||||
COPY bootstrap.min.js /usr/lib/python3/dist-packages/odoo/addons/web/static/lib/bootstrap/js/
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -55,6 +55,9 @@ RUN pip install -U pip setuptools \
|
|||
RUN git clone --depth=1 -b 11.0 https://github.com/it-projects-llc/pos-addons.git \
|
||||
/opt/posbox/addons
|
||||
|
||||
COPY hw_screen_main.py /usr/lib/python3/dist-packages/odoo/addons/hw_screen/controllers/main.py
|
||||
COPY hw_screen_main.py /usr/lib/python2.7/dist-packages/openerp/addons/hw_screen/controllers/main.py
|
||||
|
||||
# Set default user when running the container
|
||||
USER odoo
|
||||
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2015 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
from openerp import http
|
||||
from openerp.tools import config
|
||||
from openerp.addons.web.controllers import main as web
|
||||
from openerp.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['xmlrpc_port'] or 8069)
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
class Homepage(homepage.PosboxHomepage):
|
||||
|
||||
def get_hw_screen_message(self):
|
||||
return """
|
||||
<p>
|
||||
If you need to display the current customer basket on another device, you can do it <a href='/point_of_sale/display'>here</a>.
|
||||
</p>
|
||||
"""
|
||||
|
||||
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://192.168.25.132:8069/web/static/lib/jquery/jquery.js" >
|
||||
</script>
|
||||
<script type="text/javascript" class="origin">
|
||||
""" + cust_js + """
|
||||
</script>
|
||||
<link rel="stylesheet" class="origin" href="http://192.168.25.132:8069/web/static/lib/bootstrap/css/bootstrap.css" >
|
||||
</link>
|
||||
<script class="origin" src="http://192.168.25.132:8069/web/static/lib/bootstrap/js/bootstrap.min.js"></script>
|
||||
<style class="origin">
|
||||
""" + cust_css + """
|
||||
</style>
|
||||
</head>
|
||||
<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
|
Reference in New Issue