summaryrefslogtreecommitdiff
path: root/addons/hw_drivers
diff options
context:
space:
mode:
authorAntoine Prieels <anp@odoo.com>2020-04-29 13:10:48 +0000
committerAntoine Prieels <anp@odoo.com>2020-06-25 06:08:33 +0000
commitc5e1af7a35f349ca2cce58dc824c2001b234b547 (patch)
tree041502d2f4aed290ac88198ab3d6bf3923857ab8 /addons/hw_drivers
parentbc81853ba5242d82a62de393aac8efe765699cb0 (diff)
[FIX] hw_drivers: IoT Box connection
In Chrome 84, mixed content will be completely blocked for security reasons ([see blog](https://blog.chromium.org/2019/10/no-more-mixed-messages-about-https.html)) Other browsers will probably follow in the next months. As IoT Boxes don't have a valid certificate before connecting to a DB, we used mixed passive content to communicate with the boxes. This won't be possible anymore, and we have no possible way to communicate directly from the browser to the box. - When an IoT Box boots without registered DB, a unique code will be created with a validity of 5 minutes. - This code will be shown on the customer display and printed on the status ticket. - The box will call a route on odoo.com and a record will be created in odoo.com with the unique code. - The user will have to enter the code manually in his DB to connect to the IoT Box, the DB will then contact odoo.com to search for a record containing the unique code. If it's found, the `openerp.enterprise.database` will be added to the record. - The box will then query odoo.com at regular intervals (10 seconds) to check if a DB is linked to the code. closes odoo/odoo#53623 Taskid: 2246535 X-original-commit: c55f12e32598a713105f3c049ac053e46ba15bb2 Related: odoo/enterprise#11421 Signed-off-by: pimodoo <pimodoo@users.noreply.github.com>
Diffstat (limited to 'addons/hw_drivers')
-rwxr-xr-xaddons/hw_drivers/controllers/driver.py63
-rw-r--r--addons/hw_drivers/iot_handlers/drivers/DisplayDriver.py6
-rw-r--r--addons/hw_drivers/iot_handlers/drivers/PrinterDriver.py12
-rw-r--r--addons/hw_drivers/views/pos_display.html73
4 files changed, 124 insertions, 30 deletions
diff --git a/addons/hw_drivers/controllers/driver.py b/addons/hw_drivers/controllers/driver.py
index 1b055a315a2..46605790bf2 100755
--- a/addons/hw_drivers/controllers/driver.py
+++ b/addons/hw_drivers/controllers/driver.py
@@ -1,10 +1,12 @@
#!/usr/bin/python3
from base64 import b64decode
+from datetime import datetime, timedelta
from dbus.mainloop.glib import DBusGMainLoop
from importlib import util
import json
import logging
import os
+import requests
import socket
import subprocess
import sys
@@ -289,6 +291,63 @@ class EventManager(object):
event_manager = EventManager()
+#----------------------------------------------------------
+# ConnectionManager
+#----------------------------------------------------------
+
+class ConnectionManager(Thread):
+ def __init__(self):
+ super(ConnectionManager, self).__init__()
+ self.pairing_code = False
+ self.pairing_uuid = False
+
+ def run(self):
+ if not helpers.get_odoo_server_url():
+ end_time = datetime.now() + timedelta(minutes=5)
+ while (datetime.now() < end_time):
+ self._connect_box()
+ time.sleep(10)
+ self.pairing_code = False
+ self.pairing_uuid = False
+ self._refresh_displays()
+
+ def _connect_box(self):
+ data = {
+ 'jsonrpc': 2.0,
+ 'params': {
+ 'pairing_code': self.pairing_code,
+ 'pairing_uuid': self.pairing_uuid,
+ }
+ }
+
+ urllib3.disable_warnings()
+ req = requests.post('https://iot-proxy.odoo.com/odoo-enterprise/iot/connect-box', json=data, verify=False)
+ result = req.json().get('result', {})
+
+ if all(key in result for key in ['pairing_code', 'pairing_uuid']):
+ self.pairing_code = result['pairing_code']
+ self.pairing_uuid = result['pairing_uuid']
+ elif all(key in result for key in ['url', 'token', 'db_uuid', 'enterprise_code']):
+ self._connect_to_server(result['url'], result['token'], result['db_uuid'], result['enterprise_code'])
+
+ def _connect_to_server(self, url, token, db_uuid, enterprise_code):
+ if db_uuid and enterprise_code:
+ helpers.add_credential(db_uuid, enterprise_code)
+
+ # Save DB URL and token
+ subprocess.check_call([get_resource_path('point_of_sale', 'tools/posbox/configuration/connect_to_server.sh'), url, '', token, 'noreboot'])
+ # Notify the DB, so that the kanban view already shows the IoT Box
+ m.send_alldevices()
+ # Restart to checkout the git branch, get a certificate, load the IoT handlers...
+ subprocess.check_call(["sudo", "service", "odoo", "restart"])
+
+ def _refresh_displays(self):
+ """Refresh all displays to hide the pairing code"""
+ for d in iot_devices:
+ if iot_devices[d].device_type == 'display':
+ iot_devices[d].action({
+ 'action': 'display_refresh'
+ })
#----------------------------------------------------------
# Manager
@@ -386,6 +445,10 @@ class Manager(Thread):
# Must be started from main thread
DBusGMainLoop(set_as_default=True)
+cm = ConnectionManager()
+cm.daemon = True
+cm.start()
+
m = Manager()
m.daemon = True
m.start()
diff --git a/addons/hw_drivers/iot_handlers/drivers/DisplayDriver.py b/addons/hw_drivers/iot_handlers/drivers/DisplayDriver.py
index 52e38c7728a..468a9f40601 100644
--- a/addons/hw_drivers/iot_handlers/drivers/DisplayDriver.py
+++ b/addons/hw_drivers/iot_handlers/drivers/DisplayDriver.py
@@ -13,6 +13,11 @@ from odoo import http
from odoo.addons.hw_drivers.tools import helpers
from odoo.addons.hw_drivers.controllers.driver import Driver, event_manager, iot_devices
+try:
+ from odoo.addons.hw_drivers.controllers.driver import cm
+except:
+ cm = None
+
path = os.path.realpath(os.path.join(os.path.dirname(__file__), '../../views'))
loader = jinja2.FileSystemLoader(path)
@@ -215,4 +220,5 @@ class DisplayController(http.Controller):
'cust_js': cust_js,
'display_ifaces': display_ifaces,
'display_identifier': display_identifier,
+ 'pairing_code': cm and cm.pairing_code,
})
diff --git a/addons/hw_drivers/iot_handlers/drivers/PrinterDriver.py b/addons/hw_drivers/iot_handlers/drivers/PrinterDriver.py
index 1685e59e47a..e820ab7fa1d 100644
--- a/addons/hw_drivers/iot_handlers/drivers/PrinterDriver.py
+++ b/addons/hw_drivers/iot_handlers/drivers/PrinterDriver.py
@@ -20,6 +20,11 @@ from odoo.addons.hw_drivers.iot_handlers.interfaces.PrinterInterface import PPDs
from odoo.addons.hw_drivers.tools import helpers
from odoo.addons.hw_proxy.controllers.main import drivers as old_drivers
+try:
+ from odoo.addons.hw_drivers.controllers.driver import cm
+except:
+ cm = None
+
_logger = logging.getLogger(__name__)
def print_star_error(deviceId):
@@ -231,6 +236,7 @@ class PrinterDriver(Driver):
ip = ''
mac = ''
homepage = ''
+ pairing_code = ''
ssid = helpers.get_ssid()
wlan = '\nWireless network:\n%s\n\n' % ssid
@@ -256,11 +262,15 @@ class PrinterDriver(Driver):
mac = '\nMAC Address:\n%s\n' % helpers.get_mac_address()
homepage = '\nHomepage:\nhttp://%s:8069\n\n' % main_ips
+ code = cm and cm.pairing_code
+ if code:
+ pairing_code = '\nPairing Code:\n%s\n' % code
+
center = b'\x1b\x61\x01'
title = b'\n\x1b\x21\x30\x1b\x4d\x01IoTBox Status\x1b\x4d\x00\x1b\x21\x00\n'
cut = b'\x1d\x56\x41'
- self.print_raw(center + title + wlan.encode() + mac.encode() + ip.encode() + homepage.encode() + cut + b'\n')
+ self.print_raw(center + title + wlan.encode() + mac.encode() + ip.encode() + homepage.encode() + pairing_code.encode() + cut + b'\n')
def open_cashbox(self):
"""Sends a signal to the current printer to open the connected cashbox."""
diff --git a/addons/hw_drivers/views/pos_display.html b/addons/hw_drivers/views/pos_display.html
index cfe848f6645..4cd91f68ab4 100644
--- a/addons/hw_drivers/views/pos_display.html
+++ b/addons/hw_drivers/views/pos_display.html
@@ -22,7 +22,12 @@
background: linear-gradient(to right bottom, #77717e, #c9a8a9);
height: 100vh;
}
- .pos-display-status {
+ .pos-display-boxes {
+ position: absolute;
+ right: 20px;
+ bottom: 20px;
+ }
+ .pos-display-box {
padding: 10px 20px;
background: rgba(0, 0, 0, 0.17);
border: 1px solid rgba(0, 0, 0, 0.06);
@@ -30,9 +35,10 @@
color: #fff;
border-radius: 8px;
width: 500px;
- position: absolute;
- right: 20px;
- bottom: 20px;
+ margin-top: 20px;
+ }
+ .pos-display-box hr {
+ background-color: #fff;
}
.info-text {
font-size: 15px;
@@ -48,31 +54,40 @@
<img style="width: 150px;" src="/web/static/src/img/logo_inverse_white_206px.png">
<p class="mt-3" style="color: #fff;font-size: 30px;">IoTBox</p>
</div>
- <div class="pos-display-status">
- <h4 class="text-center mb-3">POS Client display</h4>
- <table class="table table-hover table-sm table-pos-info">
- <thead>
- <tr>
- <th>Interface</th>
- <th>IP</th>
- </tr>
- </thead>
- <tbody>
- {% for display_iface in display_ifaces -%}
- <tr>
- <td><i class="fa fa-{{ display_iface.icon }}"/> {{ display_iface.essid }}</td>
- <td>{{ display_iface.addr }}</td>
- </tr>
- {%- endfor %}
- </tbody>
- </table>
- <p class="mb-2 info-text">
- <i class="fa fa-info-circle mr-1"></i>The customer cart will be displayed here once a Point of Sale session is started.
- </p>
- <p class="mb-2 info-text">
- <i class="fa fa-info-circle mr-1"></i>Odoo version 11 or above is required.
- </p>
- <div class="error-message alert alert-danger mb-2 d-none" role="alert" />
+ <div class="pos-display-boxes">
+ {% if pairing_code %}
+ <div class="pos-display-box">
+ <h4 class="text-center mb-3">Pairing Code</h4>
+ <hr/>
+ <h4 class="text-center mb-3">{{ pairing_code }}</h4>
+ </div>
+ {% endif %}
+ <div class="pos-display-box">
+ <h4 class="text-center mb-3">POS Client display</h4>
+ <table class="table table-hover table-sm table-pos-info">
+ <thead>
+ <tr>
+ <th>Interface</th>
+ <th>IP</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for display_iface in display_ifaces -%}
+ <tr>
+ <td><i class="fa fa-{{ display_iface.icon }}"/> {{ display_iface.essid }}</td>
+ <td>{{ display_iface.addr }}</td>
+ </tr>
+ {%- endfor %}
+ </tbody>
+ </table>
+ <p class="mb-2 info-text">
+ <i class="fa fa-info-circle mr-1"></i>The customer cart will be displayed here once a Point of Sale session is started.
+ </p>
+ <p class="mb-2 info-text">
+ <i class="fa fa-info-circle mr-1"></i>Odoo version 11 or above is required.
+ </p>
+ <div class="error-message alert alert-danger mb-2 d-none" role="alert" />
+ </div>
</div>
</div>
</body>