1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/iot/models/iot.py
2024-12-10 09:04:09 +07:00

146 lines
6.3 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import secrets
from odoo import api, fields, models
# ----------------------------------------------------------
# Models for client
# ----------------------------------------------------------
class IotBox(models.Model):
_name = 'iot.box'
_description = 'IoT Box'
name = fields.Char('Name', readonly=True)
identifier = fields.Char(string='Identifier (Mac Address)', readonly=True)
device_ids = fields.One2many('iot.device', 'iot_id', string="Devices")
device_count = fields.Integer(compute='_compute_device_count')
ip = fields.Char('Domain Address', readonly=True)
ip_url = fields.Char('IoT Box Home Page', readonly=True, compute='_compute_ip_url')
drivers_auto_update = fields.Boolean('Automatic drivers update', help='Automatically update drivers when the IoT Box boots', default=True)
version = fields.Char('Image Version', readonly=True)
company_id = fields.Many2one('res.company', 'Company')
def _compute_ip_url(self):
for box in self:
if not box.ip:
box.ip_url = False
else:
url = 'https://%s' if box.get_base_url()[:5] == 'https' else 'http://%s:8069'
box.ip_url = url % box.ip
def _compute_device_count(self):
for box in self:
box.device_count = len(box.device_ids)
class IotDevice(models.Model):
_name = 'iot.device'
_description = 'IOT Device'
iot_id = fields.Many2one('iot.box', string='IoT Box', required=True, ondelete='cascade')
name = fields.Char('Name')
identifier = fields.Char(string='Identifier', readonly=True)
type = fields.Selection([
('printer', 'Printer'),
('camera', 'Camera'),
('keyboard', 'Keyboard'),
('scanner', 'Barcode Scanner'),
('device', 'Device'),
('payment', 'Payment Terminal'),
('scale', 'Scale'),
('display', 'Display'),
('fiscal_data_module', 'Fiscal Data Module'),
], readonly=True, default='device', string='Type',
help="Type of device.")
manufacturer = fields.Char(string='Manufacturer', readonly=True)
connection = fields.Selection([
('network', 'Network'),
('direct', 'USB'),
('bluetooth', 'Bluetooth'),
('serial', 'Serial'),
('hdmi', 'Hdmi'),
], readonly=True, string="Connection",
help="Type of connection.")
report_ids = fields.Many2many('ir.actions.report', string='Reports')
iot_ip = fields.Char(related="iot_id.ip")
company_id = fields.Many2one('res.company', 'Company', related="iot_id.company_id")
connected = fields.Boolean(string='Status', help='If device is connected to the IoT Box', readonly=True)
keyboard_layout = fields.Many2one('iot.keyboard.layout', string='Keyboard Layout')
display_url = fields.Char('Display URL', help="URL of the page that will be displayed by the device, leave empty to use the customer facing display of the POS.")
manual_measurement = fields.Boolean('Manual Measurement', compute="_compute_manual_measurement", help="Manually read the measurement from the device")
is_scanner = fields.Boolean(string='Is Scanner', compute="_compute_is_scanner", inverse="_set_scanner",
help="Manually switch the device type between keyboard and scanner")
@api.depends('iot_id')
def _compute_display_name(self):
for i in self:
i.display_name = f"[{i.iot_id.name}] {i.name}"
@api.depends('type')
def _compute_is_scanner(self):
for device in self:
device.is_scanner = True if device.type == 'scanner' else False
def _set_scanner(self):
for device in self:
device.type = 'scanner' if device.is_scanner else 'keyboard'
@api.depends('manufacturer')
def _compute_manual_measurement(self):
for device in self:
device.manual_measurement = device.manufacturer == 'Adam'
class KeyboardLayout(models.Model):
_name = 'iot.keyboard.layout'
_description = 'Keyboard Layout'
name = fields.Char('Name')
layout = fields.Char('Layout')
variant = fields.Char('Variant')
class IotChannel(models.Model):
_name = "iot.channel"
_description = "The Websocket Iot Channel"
SYSTEM_PARAMETER_KEY = 'iot.ws_channel'
# TODO: remove in master, too complicate and scenario to handle multi-company with the IoT
name = fields.Char('Name', default=lambda self: f'iot_channel-{secrets.token_hex(16)}')
company_id = fields.Many2one('res.company', default=lambda self: self.env.company) #One2one
def _get_iot_no_company_set_ws_company_id(self):
"""Get the company ID of the default company when no company is set on the IoT device"""
# When the IoT reaches the server to get the WS channel,
# it does a public request thus the environment is set on the "public user"
# In this case, if no ID is set on the IoT, it will default to the current environment company.
# It's computation can be simplified to the following lines
# simplification of Environment.company computation
public_user_companies = self.env.ref('base.public_user')._get_company_ids()
return public_user_companies[0] if public_user_companies else False
def _create_channel_if_not_exist(self):
# Temporary workaround to adapt the previous model to the new one
# If a WS already exist, we keep its value, otherwise, we generate it randomly
icp = self.env['ir.config_parameter'].sudo()
existing_channel = self.with_company(
self._get_iot_no_company_set_ws_company_id()).env['iot.channel'].search(
[('company_id', "=", self.env.company.id)], limit=1)
iot_channel = existing_channel.name or f'iot_channel-{secrets.token_hex(16)}'
icp.set_param(self.SYSTEM_PARAMETER_KEY, iot_channel)
return iot_channel
def get_iot_channel(self):
if self.env.is_system() or self.env.user.has_group('base.group_user'):
icp = self.env['ir.config_parameter'].sudo()
iot_channel = icp.get_param(self.SYSTEM_PARAMETER_KEY)
return iot_channel or self._create_channel_if_not_exist()
return False
_sql_constraints = [
('unique_name', 'unique(name)', 'The channel name must be unique'),
]