diff --git a/addons/hw_posbox_homepage/controllers/main.py b/addons/hw_posbox_homepage/controllers/main.py
index 65b276075d2..8a448e386f5 100644
--- a/addons/hw_posbox_homepage/controllers/main.py
+++ b/addons/hw_posbox_homepage/controllers/main.py
@@ -58,7 +58,10 @@ index_template = """
If you need to grant remote debugging access to a developer, you can do it here.
- The PosBox software installed on this posbox is version 15,
+ If you need to display the current customer basket on another device, you can do it here.
+
+
+ The PosBox software installed on this posbox is version 16,
the posbox version number is independent from Odoo. You can upgrade
the software on the upgrade page.
diff --git a/addons/hw_screen/__init__.py b/addons/hw_screen/__init__.py
new file mode 100644
index 00000000000..502f47ce57c
--- /dev/null
+++ b/addons/hw_screen/__init__.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2015 Tiny SPRL ().
+#
+# 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 .
+#
+##############################################################################
+
+import controllers
diff --git a/addons/hw_screen/__openerp__.py b/addons/hw_screen/__openerp__.py
new file mode 100644
index 00000000000..1e6438bf25c
--- /dev/null
+++ b/addons/hw_screen/__openerp__.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2015 Tiny SPRL ().
+#
+# 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 .
+#
+##############################################################################
+
+
+{
+ 'name': 'Screen Driver',
+ 'version': '1.0',
+ 'category': 'Hardware Drivers',
+ 'sequence': 6,
+ 'summary': 'Provides support for customer facing displays',
+ 'website': 'https://www.odoo.com/page/point-of-sale',
+ 'description': """
+Screen Driver
+=============
+
+This module allows the POS client to send rendered HTML to a remotely
+installed screen. This module then displays this HTML using a web
+browser.
+""",
+ 'author': 'OpenERP SA',
+ 'depends': ['hw_proxy'],
+ 'installable': False,
+ 'auto_install': False,
+}
diff --git a/addons/hw_screen/controllers/__init__.py b/addons/hw_screen/controllers/__init__.py
new file mode 100644
index 00000000000..517985a53ef
--- /dev/null
+++ b/addons/hw_screen/controllers/__init__.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2015 Tiny SPRL ().
+#
+# 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 .
+#
+##############################################################################
+
+import main
diff --git a/addons/hw_screen/controllers/main.py b/addons/hw_screen/controllers/main.py
new file mode 100644
index 00000000000..aa4b8a1a729
--- /dev/null
+++ b/addons/hw_screen/controllers/main.py
@@ -0,0 +1,185 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2015 Tiny SPRL ().
+#
+# 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 .
+#
+##############################################################################
+
+
+from openerp import http
+from openerp.tools import config
+from openerp.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': """
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 = """
+
+
+
+ Odoo -- Point of Sale
+
+
+
+
+
+
+
+
+
+
+
+
+
Odoo Point of Sale
+
POSBox Client display
+
My IPs
+
+
+
Interface
+
IP
+
Netmask
+
+ """ + display_ifaces + """
+
+
The customer cart will be displayed here once a Point of Sale session is started.
+
Odoo version 11 or above is required.
+
+
+
+
+
+ """
+ return html
diff --git a/addons/hw_screen/static/src/css/cust_css.css b/addons/hw_screen/static/src/css/cust_css.css
new file mode 100644
index 00000000000..69fddb25457
--- /dev/null
+++ b/addons/hw_screen/static/src/css/cust_css.css
@@ -0,0 +1,21 @@
+html {
+ width: 100%;
+ height: 100%;
+ font-size: 11px;
+}
+
+body {
+ width: 100%;
+ height: 100%;
+ font-size: 14px;
+ margin: 0;
+}
+
+.original_body {
+ background-color: #797083;
+ color: white;
+}
+
+.ajax_got_body {
+ color: black;
+}
\ No newline at end of file
diff --git a/addons/hw_screen/static/src/js/worker.js b/addons/hw_screen/static/src/js/worker.js
new file mode 100644
index 00000000000..55e389e78ab
--- /dev/null
+++ b/addons/hw_screen/static/src/js/worker.js
@@ -0,0 +1,60 @@
+ $(function() {
+ "use strict";
+ // mergedHead will be turned to true the first time we receive something from a new host
+ // It allows to transform the only once
+ var mergedHead = false;
+ var current_client_url = "";
+ var stop_longpolling = false;
+
+ function longpolling() {
+ $.ajax({
+ type: 'POST',
+ url: 'http://'+window.location.host+'/point_of_sale/get_serialized_order',
+ dataType: 'json',
+ beforeSend: function(xhr){xhr.setRequestHeader('Content-Type', 'application/json');},
+ data: JSON.stringify({jsonrpc: '2.0'}),
+
+ success: function(data) {
+ if (typeof data.result.stop_longpolling !== 'undefined') {
+ stop_longpolling = data.result.stop_longpolling;
+ }
+ if (data.result.ip_from && data.result.rendered_html) {
+ var trimmed = $.trim(data.result.rendered_html);
+ var $parsedHTML = $('
').html($.parseHTML(trimmed,true)); // WARNING: the true here will executes any script present in the string to parse
+ var new_client_url = $parsedHTML.find(".resources > base").attr('href');
+
+ if (!mergedHead || (current_client_url !== new_client_url)) {
+
+ mergedHead = true;
+ current_client_url = new_client_url;
+ $("body").removeClass('original_body').addClass('ajax_got_body');
+ $("head").children().not('.origin').remove();
+ $("head").append($parsedHTML.find(".resources").html());
+ }
+
+ $(".container").html($parsedHTML.find('.pos-customer_facing_display').html());
+ $(".container").attr('class', 'container').addClass($parsedHTML.find('.pos-customer_facing_display').attr('class'));
+
+ var d = $('.pos_orderlines_list');
+ d.scrollTop(d.prop("scrollHeight"));
+
+ // Here we execute the code coming from the pos, apparently $.parseHTML() executes scripts right away,
+ // Since we modify the dom afterwards, the script might not have any effect
+ if (typeof foreign_js !== 'undefined' && $.isFunction(foreign_js)) {
+ foreign_js();
+ }
+ }
+ },
+
+ complete: function(jqXHR,err) {
+ if (!stop_longpolling) {
+ longpolling();
+ }
+ },
+
+ timeout: 30000,
+ });
+ };
+
+ longpolling();
+ });
\ No newline at end of file
diff --git a/addons/point_of_sale/tools/posbox/configuration/setup_ramdisks.sh b/addons/point_of_sale/tools/posbox/configuration/setup_ramdisks.sh
index ce2f2e633e6..618c4b1fd48 100755
--- a/addons/point_of_sale/tools/posbox/configuration/setup_ramdisks.sh
+++ b/addons/point_of_sale/tools/posbox/configuration/setup_ramdisks.sh
@@ -11,7 +11,7 @@ create_ramdisk () {
echo "Creating ramdisk for ${1} of size ${SIZE}..."
mount -t tmpfs -o size="${SIZE}" tmpfs "${RAMDISK}"
- rsync -a --exclude="swap" --exclude="apt" --exclude="dpkg" "${ORIGINAL}/" "${RAMDISK}/"
+ rsync -a --exclude="swap" --exclude="apt" --exclude="dpkg" --exclude=".mozilla" "${ORIGINAL}/" "${RAMDISK}/"
mount --bind "${RAMDISK}" "${ORIGINAL}"
}
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/lightdm/lightdm.conf b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/lightdm/lightdm.conf
new file mode 100644
index 00000000000..977903c1c90
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/lightdm/lightdm.conf
@@ -0,0 +1,8 @@
+
+[LightDM]
+user-authority-in-system-dir=true
+
+[SeatDefaults]
+xserver-command=/usr/bin/X -s 0 dpms -nolisten tcp
+greeter-hide-users=false
+autologin-user=pi
\ No newline at end of file
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/xdg/openbox/autostart b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/xdg/openbox/autostart
new file mode 100755
index 00000000000..e2b61e2f591
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/xdg/openbox/autostart
@@ -0,0 +1,6 @@
+#!/bin/bash
+xset s off
+xset -dpms
+
+export HOME=/tmp
+/usr/bin/firefox http://localhost:8069/point_of_sale/display &
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/META-INF/manifest.mf b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/META-INF/manifest.mf
new file mode 100644
index 00000000000..63a9098e00d
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/META-INF/manifest.mf
@@ -0,0 +1,32 @@
+Manifest-Version: 1.0
+
+Name: install.rdf
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: xnFKNbJgc33dy/FJ+4cmHA==
+SHA1-Digest: 4YLgHgdgCw4lGCfsX7+r4zVmKJ4=
+
+Name: chrome.manifest
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: O5ce4bajAqUxG6iVul0K2w==
+SHA1-Digest: wb6VleWnV5GgLypmg1ij9TfmPLE=
+
+Name: content/rkioskbrowser.js
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: /cF15tfVnbkfbxRVTL5N+g==
+SHA1-Digest: lvbY92PbsjwY+0TguEYoXWw0lxQ=
+
+Name: content/rkioskbrowser.xul
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: NFOIpAmZtn20Y+XfTo4cpw==
+SHA1-Digest: VVIo7GdG+4mvAOtgR0DJUsSc/yg=
+
+Name: content/rkioskunknownContentType.xul
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: 6cNGoHJS9Xvm+wmvo4IesQ==
+SHA1-Digest: T8i1MkMKjmn5HICqWv+iXSPRKIU=
+
+Name: content/rkioskxpinstallConfirm.xul
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: SxN1YnRJiuood2WhU85v9g==
+SHA1-Digest: Msj21u4bTAKUi496xld5YCGdjiA=
+
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/META-INF/mozilla.rsa b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/META-INF/mozilla.rsa
new file mode 100644
index 00000000000..521b08d182a
Binary files /dev/null and b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/META-INF/mozilla.rsa differ
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/META-INF/mozilla.sf b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/META-INF/mozilla.sf
new file mode 100644
index 00000000000..37eae3e21fb
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/META-INF/mozilla.sf
@@ -0,0 +1,4 @@
+Signature-Version: 1.0
+MD5-Digest-Manifest: 7hFyhNW67+H+rf9OhWGDkA==
+SHA1-Digest-Manifest: HvfAQQLXphSZ9m8KBorJMX8MUnE=
+
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/README b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/README
new file mode 100644
index 00000000000..c8c1ce58823
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/README
@@ -0,0 +1,3 @@
+The R-kiosk module has been downloaded from https://addons.mozilla.org/en-US/firefox/addon/r-kiosk/
+It is in the public domain as stated on https://addons.mozilla.org/en-US/firefox/addon/r-kiosk/eula/
+This mozilla module is shipped by Odoo to provide out of the box Client facing display to Odoo's Posbox
\ No newline at end of file
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/chrome.manifest b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/chrome.manifest
new file mode 100644
index 00000000000..e4957b8d5e8
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/chrome.manifest
@@ -0,0 +1,4 @@
+content RKiosk content/
+overlay chrome://browser/content/browser.xul chrome://rkiosk/content/rkioskbrowser.xul
+overlay chrome://mozapps/content/xpinstall/xpinstallConfirm.xul chrome://rkiosk/content/rkioskxpinstallConfirm.xul
+overlay chrome://mozapps/content/downloads/unknownContentType.xul chrome://rkiosk/content/rkioskunknownContentType.xul
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskbrowser.js b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskbrowser.js
new file mode 100644
index 00000000000..5ece9a9e06b
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskbrowser.js
@@ -0,0 +1,34 @@
+function Rkiosk_donothing()
+{
+
+
+}
+
+function rkioskclose()
+{
+ close();
+}
+
+function Rkiosk_navbar_setting()
+{
+ var rkiosk_navbar_enable="true";
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"].
+ getService(Components.interfaces.nsIPrefBranch);
+ if (prefs.getPrefType("rkiosk.navbar") == prefs.PREF_BOOL){
+ if (prefs.getBoolPref("rkiosk.navbar")) rkiosk_navbar_enable = "false";
+ }
+ var rkiosk_element = document.getElementById("navigator-toolbox");
+ rkiosk_element.setAttribute("hidden", rkiosk_navbar_enable);
+}
+
+function RkioskBrowserStartup()
+{
+ Rkiosk_navbar_setting();
+ BrowserStartup();
+ setTimeout(RkioskdelayedStartup, 1000);
+}
+
+function RkioskdelayedStartup()
+{
+ window.fullScreen = true;
+}
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskbrowser.xul b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskbrowser.xul
new file mode 100644
index 00000000000..d5fb0c140d1
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskbrowser.xul
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskunknownContentType.xul b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskunknownContentType.xul
new file mode 100644
index 00000000000..faf2381d1fa
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskunknownContentType.xul
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskxpinstallConfirm.xul b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskxpinstallConfirm.xul
new file mode 100644
index 00000000000..b96deadeee6
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/content/rkioskxpinstallConfirm.xul
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/install.rdf b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/install.rdf
new file mode 100644
index 00000000000..5be400e52e8
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/lib/firefox-esr/browser/extensions/{4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}/install.rdf
@@ -0,0 +1,19 @@
+
+
+
+
+
+ {4D498D0A-05AD-4fdb-97B5-8A0AABC1FC5B}
+ R-kiosk
+ 0.9.0.1-signed.1-signed
+ RKiosk (Real Kiosk), fullscreen kiosk mode: all menus, keys etc. disabled
+ Kimmo Heinaaro
+
+
+ {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
+ 2.0
+ 6.*
+
+
+
+
\ No newline at end of file
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/share/firefox-esr/browser/defaults/preferences/all-posbox.js b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/share/firefox-esr/browser/defaults/preferences/all-posbox.js
new file mode 100644
index 00000000000..8de5d5d60a4
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/usr/share/firefox-esr/browser/defaults/preferences/all-posbox.js
@@ -0,0 +1,7 @@
+// Preferences to allow unattended install of R-Kiosk extension
+// Needed for Odoo posbox Client display
+pref("app.update.checkInstallTime", false);
+pref("devtools.webide.widget.autoinstall", false);
+pref("xpinstall.customConfirmationUI", false);
+pref("xpinstall.signatures.required", false);
+pref("browser.shell.checkDefaultBrowser",false)
diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init.d/odoo b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init.d/odoo
index 30be4bd26d3..4ab50a456a1 100755
--- a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init.d/odoo
+++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init.d/odoo
@@ -26,7 +26,7 @@ test -x $DAEMON || exit 0
set -e
function _start() {
- start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$USER --background --make-pidfile --exec $DAEMON -- --config $CONFIG --logfile $LOGFILE --load=web,hw_proxy,hw_posbox_homepage,hw_posbox_upgrade,hw_scale,hw_scanner,hw_escpos,hw_blackbox_be
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$USER --background --make-pidfile --exec $DAEMON -- --config $CONFIG --logfile $LOGFILE --load=web,hw_proxy,hw_posbox_homepage,hw_posbox_upgrade,hw_scale,hw_scanner,hw_escpos,hw_blackbox_be,hw_screen
}
function _stop() {
diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh
index 5c7895822a3..a9dfda63070 100755
--- a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh
+++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh
@@ -8,17 +8,25 @@ __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
__base="$(basename ${__file} .sh)"
+# Since we are emulating, the real /boot is not mounted,
+# leading to mismatch between kernel image and modules.
+mount /dev/sda1 /boot
+
# Recommends: antiword, graphviz, ghostscript, postgresql, python-gevent, poppler-utils
export DEBIAN_FRONTEND=noninteractive
+echo "nameserver 8.8.8.8" >> /etc/resolv.conf
-mount /dev/sda1 /boot
apt-get update
apt-get -y dist-upgrade
+# Do not be too fast to upgrade to more recent firmware and kernel than 4.38
+# Firmware 4.44 seems to prevent the LED mechanism from working
-PKGS_TO_INSTALL="adduser postgresql-client python python-dateutil python-decorator python-docutils python-feedparser python-imaging python-jinja2 python-ldap python-libxslt1 python-lxml python-mako python-mock python-openid python-passlib python-psutil python-psycopg2 python-pybabel python-pychart python-pydot python-pyparsing python-pypdf python-reportlab python-requests python-simplejson python-tz python-unittest2 python-vatnumber python-vobject python-werkzeug python-xlwt python-yaml postgresql python-gevent python-serial python-pip python-dev localepurge vim mc mg screen iw hostapd isc-dhcp-server git rsync console-data"
+PKGS_TO_INSTALL="adduser postgresql-client python python-dateutil python-decorator python-docutils python-feedparser python-imaging python-jinja2 python-ldap python-libxslt1 python-lxml python-mako python-mock python-openid python-passlib python-psutil python-psycopg2 python-pybabel python-pychart python-pydot python-pyparsing python-pypdf python-reportlab python-requests python-simplejson python-tz python-unittest2 python-vatnumber python-vobject python-werkzeug python-xlwt python-yaml postgresql python-gevent python-serial python-pip python-dev localepurge vim mc mg screen iw hostapd isc-dhcp-server git rsync console-data lightdm xserver-xorg-video-fbdev xserver-xorg-input-evdev iceweasel xdotool unclutter x11-utils openbox python-netifaces rpi-update"
-apt-get -y install ${PKGS_TO_INSTALL}
+# KEEP OWN CONFIG FILES DURING PACKAGE CONFIGURATION
+# http://serverfault.com/questions/259226/automatically-keep-current-version-of-config-files-when-apt-get-install
+apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes install ${PKGS_TO_INSTALL}
apt-get clean
localepurge
@@ -32,13 +40,20 @@ pip install pyusb==1.0.0b1
pip install qrcode
pip install evdev
+# --upgrade because websocket_client in wheezy is bad:
+# https://github.com/docker/compose/issues/1288
+pip install --upgrade websocket_client
+
groupadd usbusers
usermod -a -G usbusers pi
usermod -a -G lp pi
+usermod -a -G input lightdm
sudo -u postgres createuser -s pi
mkdir /var/log/odoo
chown pi:pi /var/log/odoo
+chown pi:pi -R /home/pi/odoo/
+chmod 770 -R /home/pi/odoo/
# logrotate is very picky when it comes to file permissions
chown -R root:root /etc/logrotate.d/
@@ -54,6 +69,31 @@ update-rc.d -f isc-dhcp-server remove
systemctl daemon-reload
systemctl enable ramdisks.service
systemctl disable dphys-swapfile.service
+systemctl enable ssh
+
+# USER PI AUTO LOGIN (from nano raspi-config)
+# We take the whole algorithm from raspi-config in order to stay compatible with raspbian infrastructure
+if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then
+ SYSTEMD=1
+elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
+ SYSTEMD=0
+else
+ echo "Unrecognised init system"
+ return 1
+fi
+if [ $SYSTEMD -eq 1 ]; then
+ systemctl set-default graphical.target
+ ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service
+else
+ update-rc.d lightdm enable 2
+fi
+
+# disable overscan in /boot/config.txt, we can't use
+# overwrite_after_init because it's on a different device
+# (/dev/mmcblk0p1) and we don't mount that afterwards.
+# This option disables any black strips around the screen
+# cf: https://www.raspberrypi.org/documentation/configuration/raspi-config.md
+echo "disable_overscan=1" >> /boot/config.txt
# https://www.raspberrypi.org/forums/viewtopic.php?p=79249
# to not have "setting up console font and keymap" during boot take ages
@@ -68,5 +108,6 @@ create_ramdisk_dir "/var"
create_ramdisk_dir "/etc"
create_ramdisk_dir "/tmp"
mkdir /root_bypass_ramdisks
+umount /dev/sda1
reboot
diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/udev/rules.d/99-z-input.rules b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/udev/rules.d/99-z-input.rules
new file mode 100644
index 00000000000..aab19f2d1c7
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/udev/rules.d/99-z-input.rules
@@ -0,0 +1,2 @@
+SUBSYSTEM=="input", GROUP="input", MODE="0660"
+KERNEL=="tty[0-9]*", GROUP="tty", MODE="0660"
\ No newline at end of file
diff --git a/addons/point_of_sale/tools/posbox/posbox_create_image.sh b/addons/point_of_sale/tools/posbox/posbox_create_image.sh
index 1e4c9d1277c..a9ec8bc102d 100755
--- a/addons/point_of_sale/tools/posbox/posbox_create_image.sh
+++ b/addons/point_of_sale/tools/posbox/posbox_create_image.sh
@@ -36,20 +36,25 @@ fi
cp -a *raspbian*.img posbox.img
CLONE_DIR="${OVERWRITE_FILES_BEFORE_INIT_DIR}/home/pi/odoo"
+
rm -rf "${CLONE_DIR}"
-mkdir "${CLONE_DIR}"
-git clone -b 8.0 --no-checkout --depth 1 https://github.com/odoo/odoo.git "${CLONE_DIR}"
-cd "${CLONE_DIR}"
-git config core.sparsecheckout true
-echo "addons/web
+
+if [ ! -d $CLONE_DIR ]; then
+ echo "Clone Github repo"
+ mkdir -p "${CLONE_DIR}"
+ git clone -b 8.0 --no-local --no-checkout --depth 1 https://github.com/odoo/odoo.git "${CLONE_DIR}"
+ cd "${CLONE_DIR}"
+ git config core.sparsecheckout true
+ echo "addons/web
addons/web_kanban
addons/hw_*
addons/point_of_sale/tools/posbox/configuration
openerp/
odoo.py" | tee --append .git/info/sparse-checkout > /dev/null
-git read-tree -mu HEAD
-cd "${__dir}"
+ git read-tree -mu HEAD
+fi
+cd "${__dir}"
USR_BIN="${OVERWRITE_FILES_BEFORE_INIT_DIR}/usr/bin/"
mkdir -p "${USR_BIN}"
cd "/tmp"
@@ -60,9 +65,11 @@ cd "${__dir}"
mv /tmp/ngrok "${USR_BIN}"
# zero pad the image to be around 3.5 GiB, by default the image is only ~1.3 GiB
+echo "Enlarging the image..."
dd if=/dev/zero bs=1M count=2048 >> posbox.img
# resize partition table
+echo "Fdisking"
START_OF_ROOT_PARTITION=$(fdisk -l posbox.img | tail -n 1 | awk '{print $2}')
(echo 'p'; # print
echo 'd'; # delete
@@ -75,7 +82,7 @@ START_OF_ROOT_PARTITION=$(fdisk -l posbox.img | tail -n 1 | awk '{print $2}')
echo 'p'; # print
echo 'w') | fdisk posbox.img # write and quit
-LOOP_MAPPER_PATH=$(kpartx -av posbox.img | tail -n 1 | cut -d ' ' -f 3)
+LOOP_MAPPER_PATH=$(kpartx -avs posbox.img | tail -n 1 | cut -d ' ' -f 3)
LOOP_MAPPER_PATH="/dev/mapper/${LOOP_MAPPER_PATH}"
sleep 5