Files
2026-06-03 11:05:46 +08:00

152 lines
5.8 KiB
Python

import json
import logging
from odoo import fields, models, api
_logger = logging.getLogger(__name__)
def _strip_face_template(message_data_str):
"""移除 message_data JSON 中的 face_template 字段(图片base64太长)"""
if not message_data_str:
return message_data_str
try:
data = json.loads(message_data_str)
if isinstance(data, dict) and 'face_template' in data:
data.pop('face_template')
_logger.info("已移除 face_template 字段")
return json.dumps(data, ensure_ascii=False)
if isinstance(data, list):
changed = False
for item in data:
if isinstance(item, dict) and 'face_template' in item:
item.pop('face_template')
changed = True
if changed:
_logger.info("已移除列表中的 face_template 字段")
return json.dumps(data, ensure_ascii=False)
return message_data_str
except (json.JSONDecodeError, TypeError):
return message_data_str
class IotMessage(models.Model):
_name = 'iot.message'
_description = 'mqtt 消息,发送和接收'
name = fields.Char(string='消息')
topic = fields.Char(string='设备订阅主题')
device_sn = fields.Char(string='设备编码')
model = fields.Many2one('ir.model', string='模型')
id = fields.Integer(string='模型id')
message_data = fields.Text(string='message 数据')
state = fields.Selection(
[('draft', '待下发'), ('waiting', '下发完成等待结果'), ('done', '完成'), ('exception', '异常')], string='状态',
default='draft')
# 响应信息
res_data = fields.Text(string='发送后的响应信息')
face_data = fields.Text(string='照片数据')
@api.model_create_multi
def create(self, vals_list):
# 保留全部数据(含 face_template),MQTT 下发时需要原样发给设备
records = super().create(vals_list)
# 从 message_data 提取 face_template 存入单独字段,并在 message_data 中移除
for rec in records:
if rec.message_data:
try:
data = json.loads(rec.message_data)
if isinstance(data, dict) and 'face_template' in data:
face_tpl = data.pop('face_template')
rec.write({
'face_data': face_tpl,
'message_data': json.dumps(data, ensure_ascii=False),
})
except (json.JSONDecodeError, TypeError):
pass
# 创建设备日志时同步更新关联设备的最后更新时间
if rec.device_sn:
devices = self.env['attendance.iot'].sudo().search([('name', '=', rec.device_sn)], limit=1)
if devices:
devices.touch_last_update()
return records
def write(self, vals):
return super().write(vals)
def action_clear_face_template(self):
"""批量清除已有记录的 face_template 参数"""
count = 0
for record in self:
if not record.message_data:
continue
try:
data = json.loads(record.message_data)
changed = False
if isinstance(data, dict) and 'face_template' in data:
data.pop('face_template')
changed = True
elif isinstance(data, list):
for item in data:
if isinstance(item, dict) and 'face_template' in item:
item.pop('face_template')
changed = True
if changed:
record.write({'message_data': json.dumps(data, ensure_ascii=False)})
count += 1
except (json.JSONDecodeError, TypeError):
continue
_logger.info(f"已清理 {count} 条记录的 face_template")
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': '完成',
'message': f'已清理 {count} 条记录的 face_template',
'sticky': False,
'type': 'success',
}
}
@api.model
def to_reply(self, data):
_logger.info(f'返回消息:{data}')
id = int(data.get('to'))
if id:
record = self.browse(id)
if record:
if data.get('data').get('code') == 0:
record.write({
'state': 'done',
'res_data': json.dumps(data, ensure_ascii=False)
})
else:
record.write({
'state': 'exception',
'res_data': json.dumps(data, ensure_ascii=False)
})
return data
@api.model
def get_draft_records(self):
records = self.search([('state', '=', 'draft')], offset=0, limit=10)
result = []
for record in records:
msg_data = record.message_data
# 如果有独立存的面部照片,重新拼回去下发
if record.face_data:
try:
data = json.loads(msg_data) if msg_data else {}
if isinstance(data, dict):
data['face_template'] = record.face_data
msg_data = json.dumps(data, ensure_ascii=False)
except (json.JSONDecodeError, TypeError):
pass
result.append({
'id': record.id,
'topic': record.topic,
'message_data': msg_data
})
records.write({'state': 'waiting'})
return result