mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-20 03:11:58 +02:00
Add 19 payment provider modules needed by the sale module:
payment_adyen, payment_aps, payment_asiapay, payment_authorize,
payment_buckaroo, payment_demo, payment_dpo, payment_flutterwave,
payment_iyzico, payment_mercado_pago, payment_mollie, payment_nuvei,
payment_paymob, payment_paypal, payment_razorpay, payment_redsys,
payment_stripe, payment_worldline, payment_xendit
Add 3 IoT modules needed for point_of_sale:
iot_base, iot_box_image, iot_drivers
Note: Stripe test API keys replaced with placeholders.
🤖 assisted by claude
181 lines
6.9 KiB
Python
181 lines
6.9 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
import logging
|
|
import requests
|
|
import schedule
|
|
import subprocess
|
|
from threading import Thread
|
|
import time
|
|
|
|
from odoo.addons.iot_drivers.tools import certificate, helpers, upgrade, wifi
|
|
from odoo.addons.iot_drivers.tools.system import IS_RPI
|
|
from odoo.addons.iot_drivers.websocket_client import WebsocketClient
|
|
|
|
if IS_RPI:
|
|
from dbus.mainloop.glib import DBusGMainLoop
|
|
DBusGMainLoop(set_as_default=True) # Must be started from main thread
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
drivers = []
|
|
interfaces = {}
|
|
iot_devices = {}
|
|
unsupported_devices = {}
|
|
|
|
|
|
class Manager(Thread):
|
|
daemon = True
|
|
ws_channel = ""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.identifier = helpers.get_identifier()
|
|
self.domain = self._get_domain()
|
|
self.version = helpers.get_version(detailed_version=True)
|
|
self.previous_iot_devices = {}
|
|
self.previous_unsupported_devices = {}
|
|
|
|
def _get_domain(self):
|
|
"""
|
|
Get the iot box domain based on the IP address and subject.
|
|
"""
|
|
subject = helpers.get_conf('subject')
|
|
ip_addr = helpers.get_ip()
|
|
if subject and ip_addr:
|
|
return ip_addr.replace('.', '-') + subject.strip('*')
|
|
return ip_addr or '127.0.0.1'
|
|
|
|
def _get_changes_to_send(self):
|
|
"""
|
|
Check if the IoT Box information has changed since the last time it was sent.
|
|
Returns True if any tracked property has changed.
|
|
"""
|
|
changed = False
|
|
|
|
current_devices = set(iot_devices.keys()) | set(unsupported_devices.keys())
|
|
previous_devices = set(self.previous_iot_devices.keys()) | set(self.previous_unsupported_devices.keys())
|
|
if current_devices != previous_devices:
|
|
self.previous_iot_devices = iot_devices.copy()
|
|
self.previous_unsupported_devices = unsupported_devices.copy()
|
|
changed = True
|
|
|
|
# IP address change
|
|
new_domain = self._get_domain()
|
|
if self.domain != new_domain:
|
|
self.domain = new_domain
|
|
changed = True
|
|
# Version change
|
|
new_version = helpers.get_version(detailed_version=True)
|
|
if self.version != new_version:
|
|
self.version = new_version
|
|
changed = True
|
|
|
|
return changed
|
|
|
|
@helpers.require_db
|
|
def _send_all_devices(self, server_url=None):
|
|
"""This method send IoT Box and devices information to Odoo database
|
|
|
|
As the server can be down or not started yet (in case of local testing),
|
|
we retry to send the data several times with a delay between each attempt.
|
|
|
|
:param server_url: URL of the Odoo server (provided by decorator).
|
|
"""
|
|
iot_box = {
|
|
'identifier': self.identifier,
|
|
'ip': self.domain,
|
|
'token': helpers.get_token(),
|
|
'version': self.version,
|
|
}
|
|
devices_list = {}
|
|
for device in self.previous_iot_devices.values():
|
|
identifier = device.device_identifier
|
|
devices_list[identifier] = {
|
|
'name': device.device_name,
|
|
'type': device.device_type,
|
|
'manufacturer': device.device_manufacturer,
|
|
'connection': device.device_connection,
|
|
'subtype': device.device_subtype if device.device_type == 'printer' else '',
|
|
}
|
|
devices_list.update(self.previous_unsupported_devices)
|
|
|
|
delay = .5
|
|
max_retries = 5
|
|
for attempt in range(1, max_retries + 1):
|
|
try:
|
|
response = requests.post(
|
|
server_url + "/iot/setup",
|
|
json={'params': {'iot_box': iot_box, 'devices': devices_list}},
|
|
timeout=5,
|
|
)
|
|
response.raise_for_status()
|
|
data = response.json()
|
|
self.ws_channel = data.get('result', '')
|
|
break # Success, exit the retry loop
|
|
except requests.exceptions.RequestException:
|
|
if attempt < max_retries:
|
|
_logger.warning(
|
|
'Could not reach configured server to send all IoT devices, retrying in %s seconds (%d/%d attempts)',
|
|
delay, attempt, max_retries, exc_info=True
|
|
)
|
|
time.sleep(delay)
|
|
else:
|
|
_logger.exception('Could not reach configured server to send all IoT devices after %d attempts.', max_retries)
|
|
except ValueError:
|
|
_logger.exception('Could not load JSON data: Received data is not valid JSON.\nContent:\n%s', response.content)
|
|
break
|
|
|
|
def run(self):
|
|
"""Thread that will load interfaces and drivers and contact the odoo server
|
|
with the updates. It will also reconnect to the Wi-Fi if the connection is lost.
|
|
"""
|
|
if IS_RPI:
|
|
# ensure that the root filesystem is writable retro compatibility (TODO: remove this in 19.0)
|
|
subprocess.run(["sudo", "mount", "-o", "remount,rw", "/"], check=False)
|
|
subprocess.run(["sudo", "mount", "-o", "remount,rw", "/root_bypass_ramdisks/"], check=False)
|
|
|
|
wifi.reconnect(helpers.get_conf('wifi_ssid'), helpers.get_conf('wifi_password'))
|
|
|
|
helpers.start_nginx_server()
|
|
_logger.info("IoT Box Image version: %s", helpers.get_version(detailed_version=True))
|
|
upgrade.check_git_branch()
|
|
|
|
if IS_RPI and helpers.get_odoo_server_url():
|
|
helpers.generate_password()
|
|
|
|
certificate.ensure_validity()
|
|
|
|
# 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_all_devices()
|
|
helpers.download_iot_handlers()
|
|
helpers.load_iot_handlers()
|
|
|
|
for interface in interfaces.values():
|
|
interface().start()
|
|
|
|
# Set scheduled actions
|
|
schedule.every().day.at("00:00").do(certificate.ensure_validity)
|
|
schedule.every().day.at("00:00").do(helpers.reset_log_level)
|
|
|
|
# Set up the websocket connection
|
|
ws_client = WebsocketClient(self.ws_channel)
|
|
if ws_client:
|
|
ws_client.start()
|
|
|
|
# Check every 3 seconds if the list of connected devices has changed and send the updated
|
|
# list to the connected DB.
|
|
while 1:
|
|
try:
|
|
if self._get_changes_to_send():
|
|
self._send_all_devices()
|
|
if IS_RPI and helpers.get_ip() != '10.11.12.1':
|
|
wifi.reconnect(helpers.get_conf('wifi_ssid'), helpers.get_conf('wifi_password'))
|
|
time.sleep(3)
|
|
schedule.run_pending()
|
|
except Exception:
|
|
# No matter what goes wrong, the Manager loop needs to keep running
|
|
_logger.exception("Manager loop unexpected error")
|
|
|
|
|
|
manager = Manager()
|
|
manager.start()
|