diff options
| author | Antoine Prieels <anp@odoo.com> | 2020-04-29 13:10:48 +0000 |
|---|---|---|
| committer | Antoine Prieels <anp@odoo.com> | 2020-06-25 06:08:33 +0000 |
| commit | c5e1af7a35f349ca2cce58dc824c2001b234b547 (patch) | |
| tree | 041502d2f4aed290ac88198ab3d6bf3923857ab8 | |
| parent | bc81853ba5242d82a62de393aac8efe765699cb0 (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>
| -rwxr-xr-x | addons/hw_drivers/controllers/driver.py | 63 | ||||
| -rw-r--r-- | addons/hw_drivers/iot_handlers/drivers/DisplayDriver.py | 6 | ||||
| -rw-r--r-- | addons/hw_drivers/iot_handlers/drivers/PrinterDriver.py | 12 | ||||
| -rw-r--r-- | addons/hw_drivers/views/pos_display.html | 73 |
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> |
