diff --git a/addons/hw_drivers/__init__.py b/addons/hw_drivers/__init__.py index da5e919c051..5c5ac36b364 100644 --- a/addons/hw_drivers/__init__.py +++ b/addons/hw_drivers/__init__.py @@ -9,3 +9,4 @@ from . import exception_logger from . import http from . import interface from . import main +from . import websocket_client diff --git a/addons/hw_drivers/main.py b/addons/hw_drivers/main.py index 5995d3e0360..b6c392087a3 100644 --- a/addons/hw_drivers/main.py +++ b/addons/hw_drivers/main.py @@ -10,6 +10,7 @@ import time import urllib3 from odoo.addons.hw_drivers.tools import helpers +from odoo.addons.hw_drivers.websocket_client import WebsocketClient _logger = logging.getLogger(__name__) @@ -25,7 +26,7 @@ iot_devices = {} class Manager(Thread): - def send_alldevices(self): + def send_alldevices(self, iot_client): """ This method send IoT Box and devices informations to Odoo database """ @@ -57,7 +58,7 @@ class Manager(Thread): urllib3.disable_warnings() http = urllib3.PoolManager(cert_reqs='CERT_NONE') try: - http.request( + resp = http.request( 'POST', server + "/iot/setup", body=json.dumps(data).encode('utf8'), @@ -66,6 +67,7 @@ class Manager(Thread): 'Accept': 'text/plain', }, ) + iot_client.iot_channel = json.loads(resp.data).get('result', '') except Exception as e: _logger.error('Could not reach configured server') _logger.error('A error encountered : %s ' % e) @@ -85,9 +87,10 @@ class Manager(Thread): _logger.warning("An error happened when trying to get the HTTPS certificate: %s", certificate_details) + iot_client = WebsocketClient(helpers.get_odoo_server_url()) # We first add the IoT Box to the connected DB because IoT handlers cannot be downloaded if # the identifier of the Box is not found in the DB. So add the Box to the DB. - self.send_alldevices() + self.send_alldevices(iot_client) helpers.download_iot_handlers() helpers.load_iot_handlers() @@ -100,6 +103,8 @@ class Manager(Thread): except Exception as e: _logger.error("Error in %s: %s", str(interface), e) + #Setup the websocket connection + iot_client.start() # Check every 3 secondes if the list of connected devices has changed and send the updated # list to the connected DB. self.previous_iot_devices = [] @@ -107,7 +112,7 @@ class Manager(Thread): try: if iot_devices != self.previous_iot_devices: self.previous_iot_devices = iot_devices.copy() - self.send_alldevices() + self.send_alldevices(iot_client) time.sleep(3) except Exception: # No matter what goes wrong, the Manager loop needs to keep running diff --git a/addons/hw_drivers/websocket_client.py b/addons/hw_drivers/websocket_client.py new file mode 100644 index 00000000000..e11257e7c29 --- /dev/null +++ b/addons/hw_drivers/websocket_client.py @@ -0,0 +1,81 @@ +import websocket +import json +import logging +import time +import urllib3 + +from threading import Thread +from odoo.addons.hw_drivers import main +from odoo.addons.hw_drivers.tools import helpers + +_logger = logging.getLogger(__name__) + +def send_to_controller(print_id, device_identifier): + server = helpers.get_odoo_server_url() + try: + urllib3.disable_warnings() + http = urllib3.PoolManager(cert_reqs='CERT_NONE') + http.request( + 'POST', + server + "/iot/printer/status", + body=json.dumps( + {'params': { + 'print_id': print_id, + 'device_identifier': device_identifier, + }}).encode('utf8'), + headers={ + 'Content-type': 'application/json', + 'Accept': 'text/plain', + }, + ) + except Exception as e: + _logger.error('Could not reach configured server') + _logger.error('A error encountered : %s ', e) + + +def on_message(ws, messages): + """ + When a message is receive, this function is triggered + The message is load and if its type is 'print', is sent to the printer + """ + messages = json.loads(messages) + for document in messages: + if (document['message']['type'] == 'print'): + payload = document['message']['payload'] + if helpers.get_mac_address() in payload['iotDevice']['iotIdentifiers']: + #send box confirmation + for device in payload['iotDevice']['identifiers']: + if device['identifier'] in main.iot_devices: + main.iot_devices[device["identifier"]]._action_default(payload) + send_to_controller(payload['print_id'], device['identifier']) + + +def on_error(ws, error): + _logger.error(error) + +class WebsocketClient(Thread): + iot_channel = "" + + def on_open(self, ws): + """ + When the client is setup, this function send a message to subscribe to the iot websocket channel + """ + ws.send( + '{"event_name":"subscribe","data":{"channels":["' + self.iot_channel + '"],"last":0}}' + ) + + def __init__(self, url): + if url: + self.url = url.replace("http", "ws") + Thread.__init__(self) + + def start_client(self): + self.ws = websocket.WebSocketApp(self.url + "/websocket", + on_open=self.on_open, on_message=on_message, + on_error=on_error) + while 1: + self.ws.run_forever() + time.sleep(10) + + def run(self): + self.start_client() 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 cef468e79d8..54bbc62ca53 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 @@ -119,7 +119,8 @@ PIP_TO_INSTALL=" PyKCS11 \ vcgencmd \ RPi.GPIO \ - rjsmin==1.1.0" + rjsmin==1.1.0 \ + websocket-client==1.6.3" mkdir venv python3 -m venv venv