运行日志数据接入

This commit is contained in:
mgw
2024-08-16 16:57:32 +08:00
parent cc13e5cd9a
commit f537fbc597
7 changed files with 219 additions and 18 deletions

View File

@@ -30,6 +30,7 @@
'views/machine_info_present.xml', 'views/machine_info_present.xml',
'views/delivery_record.xml', 'views/delivery_record.xml',
'views/res_config_settings_views.xml', 'views/res_config_settings_views.xml',
'views/maintenance_views.xml',
], ],
'assets': { 'assets': {

View File

@@ -1,11 +1,45 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import re
import ast import ast
import json import json
import logging import logging
from datetime import datetime
from odoo import http from odoo import http
from odoo.http import request from odoo.http import request
def convert_to_seconds(time_str):
# 修改正则表达式,使 H、M、S 部分可选
pattern = r"(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?"
match = re.match(pattern, time_str)
if match:
# 提取各时间单位如果某个单位缺失则默认设为0
hours = int(match.group(1)) if match.group(1) else 0
minutes = int(match.group(2)) if match.group(2) else 0
seconds = int(match.group(3)) if match.group(3) else 0
# 计算总秒数
total_seconds = hours * 3600 + minutes * 60 + seconds
if total_seconds == 0:
# return None
pattern = r"(?:(\d+)小时)?(?:(\d+)分钟)?(?:(\d+)秒)?"
match = re.match(pattern, time_str)
if match:
# 提取各时间单位如果某个单位缺失则默认设为0
hours = int(match.group(1)) if match.group(1) else 0
minutes = int(match.group(2)) if match.group(2) else 0
seconds = int(match.group(3)) if match.group(3) else 0
# 计算总秒数
total_seconds = hours * 3600 + minutes * 60 + seconds
return total_seconds
else:
return None
return total_seconds
class Sf_Dashboard_Connect(http.Controller): class Sf_Dashboard_Connect(http.Controller):
@http.route('/api/get_machine_datas/list', type='http', auth='public', methods=['GET', 'POST'], csrf=False, @http.route('/api/get_machine_datas/list', type='http', auth='public', methods=['GET', 'POST'], csrf=False,
@@ -18,6 +52,11 @@ class Sf_Dashboard_Connect(http.Controller):
""" """
res = {'status': 1, 'message': '成功', 'data': []} res = {'status': 1, 'message': '成功', 'data': []}
logging.info('前端请求机床数据的参数为:%s' % kw) logging.info('前端请求机床数据的参数为:%s' % kw)
# 获取当前时间的时间戳
current_timestamp = datetime.now().timestamp()
print(current_timestamp)
# tem_list = [ # tem_list = [
# "XT-GNJC-WZZX-X800-Y550-Z550-T24-A5-1", "XT-GNJC-LSZX-X800-Y550-Z550-T24-A3-3", # "XT-GNJC-WZZX-X800-Y550-Z550-T24-A5-1", "XT-GNJC-LSZX-X800-Y550-Z550-T24-A3-3",
# "XT-GNJC-LSZX-X800-Y550-Z550-T24-A3-4", "XT-GNJC-LSZX-X800-Y550-Z550-T24-A3-5", # "XT-GNJC-LSZX-X800-Y550-Z550-T24-A3-4", "XT-GNJC-LSZX-X800-Y550-Z550-T24-A3-5",
@@ -33,8 +72,21 @@ class Sf_Dashboard_Connect(http.Controller):
machine_list = ast.literal_eval(kw['machine_list']) machine_list = ast.literal_eval(kw['machine_list'])
for item in machine_list: for item in machine_list:
machine_data = equipment_obj.search([('code', '=', item)]) machine_data = equipment_obj.search([('code', '=', item)])
# 机床上线时间段
first_online_duration = current_timestamp - int(machine_data.first_online_time.timestamp())
power_off_time = None
power_off_rate = None
if machine_data.machine_power_on_time:
power_off_time = first_online_duration - convert_to_seconds(machine_data.machine_power_on_time)
power_off_rate = round((power_off_time / first_online_duration), 3)
else:
power_off_time = False
power_off_rate = False
if machine_data: if machine_data:
res['data'].append({ res['data'].append({
'active': machine_data.status,
'id': machine_data.id, 'id': machine_data.id,
'name': machine_data.name, 'name': machine_data.name,
'brand': machine_data.type_id.name, 'brand': machine_data.type_id.name,
@@ -92,6 +144,13 @@ class Sf_Dashboard_Connect(http.Controller):
# 计算出来的数据 # 计算出来的数据
# 开动率:运行时间/通电时间 # 开动率:运行时间/通电时间
'run_rate': machine_data.run_rate, 'run_rate': machine_data.run_rate,
# 关机时长:初次上线时间 - 通电时间
'power_off_time': power_off_time,
# 关机率:关机时长/初次上线时间
'power_off_rate': power_off_rate,
'first_online_duration': first_online_duration,
# 停机时间:关机时间 - 运行时间
# 停机时长:关机时间 - 初次上线时间
}) })
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@@ -101,6 +160,95 @@ class Sf_Dashboard_Connect(http.Controller):
res['message'] = '前端请求机床数据失败,原因:%s' % e res['message'] = '前端请求机床数据失败,原因:%s' % e
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
# @http.route('/api/logs/list', type='http', auth='public', methods=['GET', 'POST'], csrf=False,
# cors="*")
# def logs_list(self, **kw):
# """
# 拿到日志数据返回给大屏展示
# :param kw:
# :return:
# """
# res = {'status': 1, 'message': '成功', 'data': []}
# logging.info('前端请求日志数据的参数为:%s' % kw)
#
# try:
# # 获取请求的日志数据
# logs_obj = request.env['maintenance.equipment.oee.log.detail'].sudo()
# # 获取请求的机床数据
# machine_list = ast.literal_eval(kw['machine_list'])
# begin_time_str = kw['begin_time'].strip('"')
# end_time_str = kw['end_time'].strip('"')
#
# begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S')
# end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
#
# print('begin_time: %s' % begin_time)
# for item in machine_list:
# log_datas = logs_obj.search(
# [('equipment_code', '=', item), ('time', '>=', begin_time), ('time', '<=', end_time)])
# print('log_datas: %s' % log_datas)
# for log_data in log_datas:
# res['data'].append({
# 'equipment_code': log_data.equipment_code,
# 'time': log_data.time.strftime('%Y-%m-%d %H:%M:%S'),
# 'state': log_data.state
#
# })
#
# return json.JSONEncoder().encode(res)
#
# except Exception as e:
# logging.info('前端请求日志数据失败,原因:%s' % e)
# res['status'] = -1
# res['message'] = '前端请求日志数据失败,原因:%s' % e
# return json.JSONEncoder().encode(res)
@http.route('/api/logs/list', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
def logs_list(self, **kw):
"""
拿到日志数据返回给大屏展示
:param kw:
:return:
"""
res = {'status': 1, 'message': '成功', 'data': {}}
logging.info('前端请求日志数据的参数为:%s' % kw)
try:
# 获取请求的日志数据
logs_obj = request.env['maintenance.equipment.oee.log.detail'].sudo()
# 获取请求的机床数据
machine_list = ast.literal_eval(kw['machine_list'])
begin_time_str = kw['begin_time'].strip('"')
end_time_str = kw['end_time'].strip('"')
begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S')
end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
print('begin_time: %s' % begin_time)
for item in machine_list:
log_datas = logs_obj.search(
[('equipment_code', '=', item), ('time', '>=', begin_time), ('time', '<=', end_time)])
print('log_datas: %s' % log_datas)
# 将数据按照 equipment_code 进行分组
if item not in res['data']:
res['data'][item] = []
for log_data in log_datas:
res['data'][item].append({
'time': log_data.time.strftime('%Y-%m-%d %H:%M:%S'),
'state': log_data.state
})
return json.dumps(res) # 注意使用 json.dumps 而不是直接用 json.JSONEncoder().encode()
except Exception as e:
logging.info('前端请求日志数据失败,原因:%s' % e)
res['status'] = -1
res['message'] = '前端请求日志数据失败,原因:%s' % e
return json.dumps(res)
# 返回CNC机床列表 # 返回CNC机床列表
@http.route('/api/CNCList', type='http', auth='public', methods=['GET', 'POST'], csrf=False, @http.route('/api/CNCList', type='http', auth='public', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")

View File

@@ -121,6 +121,13 @@ class Machine_ftp(models.Model):
""" """
_inherit = 'maintenance.equipment' _inherit = 'maintenance.equipment'
# 机床首次上线时间(默认取值2024年08月01日零点)
def _get_default_online_time(self):
return datetime(2024, 1, 1, 0, 0, 0)
first_online_time = fields.Datetime(string='首次上线时间', default=_get_default_online_time)
# workorder_ids = fields.One2many('mrp.workorder', 'machine_tool_id', string='工单') # workorder_ids = fields.One2many('mrp.workorder', 'machine_tool_id', string='工单')
# # 机床配置项目 # # 机床配置项目
@@ -278,6 +285,26 @@ class Machine_ftp(models.Model):
# # 开动率 # # 开动率
run_rate = fields.Char('开动率', readonly=True) run_rate = fields.Char('开动率', readonly=True)
# 同步CNC设备到oee
def sync_oee(self):
"""
同步CNC设备到oee
:return:
"""
for record in self:
record.ensure_one()
cnc_oee_dict = {
'equipment_id': record.id,
'type_id': record.type_id.id,
'machine_tool_picture': record.machine_tool_picture,
'equipment_code': record.code,
'function_type': record.function_type,
}
if self.env['maintenance.equipment.oee.logs'].search([('equipment_id', '=', record.id)]):
self.env['maintenance.equipment.oee.logs'].write(cnc_oee_dict)
else:
self.env['maintenance.equipment.oee.logs'].create(cnc_oee_dict)
class WorkCenterBarcode(models.Model): class WorkCenterBarcode(models.Model):
""" """

View File

@@ -18,6 +18,7 @@
<field name="run_status"/> <field name="run_status"/>
<field name="run_time"/> <field name="run_time"/>
<field name="system_date"/> <field name="system_date"/>
<field name="first_online_time"/>
</group> </group>
<group> <group>
<field name="cut_status"/> <field name="cut_status"/>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<odoo>
<!-- 修改设备列表视图-->
<record id="sf_machine_hr_equipment_view_tree_inherit" model="ir.ui.view">
<field name="name">sf.machine.hr.equipment.view.tree.inherit</field>
<field name="model">maintenance.equipment</field>
<field name="inherit_id" ref="maintenance.hr_equipment_view_tree"/>
<field name="arch" type="xml">
<xpath expr="//tree" position="inside">
<header>
<button name="sync_oee" type="object" string="同步设备至OEE"/>
</header>
</xpath>
</field>
</record>
</odoo>

View File

@@ -41,29 +41,32 @@ class SfMaintenanceEquipmentOEELog(models.Model):
_name = 'maintenance.equipment.oee.logs' _name = 'maintenance.equipment.oee.logs'
_description = '设备运行日志' _description = '设备运行日志'
equipment_id = fields.Many2one('maintenance.equipment', '机台号') equipment_id = fields.Many2one('maintenance.equipment', '机台号', readonly='True')
equipment_code = fields.Char('设备编码') equipment_code = fields.Char('设备编码', readonly='True')
name = fields.Char('设备名称', readonly='True') name = fields.Char('设备名称', readonly='True')
function_type = fields.Selection(
[("ZXJGZX", "钻铣加工中心"), ("CXJGZX", "车削加工中心"), ("FHJGZX", "复合加工中心")],
default="", string="功能类型")
machine_tool_picture = fields.Binary('设备图片') machine_tool_picture = fields.Binary('设备图片')
type_id = fields.Many2one('sf.machine_tool.type', '品牌型号') type_id = fields.Many2one('sf.machine_tool.type', '品牌型号', reaonly='True')
state = fields.Selection([("加工", "加工"), ("关机", "关机"), ("待机", "待机"), ("故障", "故障"), state = fields.Selection([("加工", "加工"), ("关机", "关机"), ("待机", "待机"), ("故障", "故障"),
("检修", "检修"), ("保养", "保养")], default="", string="实时状态") ("检修", "检修"), ("保养", "保养")], default="", string="实时状态")
online_time = fields.Char('开机时长') online_time = fields.Char('开机时长', reaonly='True')
offline_time = fields.Char('关机时长') offline_time = fields.Char('关机时长', reaonly='True')
offline_nums = fields.Integer('关机次数') offline_nums = fields.Integer('关机次数', reaonly='True')
# 待机时长 # 待机时长
idle_time = fields.Char('待机时长') idle_time = fields.Char('待机时长', reaonly='True')
# 待机率 # 待机率
idle_rate = fields.Char('待机率') idle_rate = fields.Char('待机率', reaonly='True')
work_time = fields.Char('加工时长') work_time = fields.Char('加工时长', reaonly='True')
work_rate = fields.Char('可用率') work_rate = fields.Char('可用率', reaonly='True')
fault_time = fields.Char('故障时长') fault_time = fields.Char('故障时长', reaonly='True')
fault_rate = fields.Char('故障率') fault_rate = fields.Char('故障率', reaonly='True')
fault_nums = fields.Integer('故障次数') fault_nums = fields.Integer('故障次数', reaonly='True')
detail_ids = fields.One2many('maintenance.equipment.oee.log.detail', 'log_id', string='日志详情') detail_ids = fields.One2many('maintenance.equipment.oee.log.detail', 'log_id', string='日志详情')
@@ -82,11 +85,13 @@ class SfMaintenanceEquipmentOEELogDetail(models.Model):
_name = 'maintenance.equipment.oee.log.detail' _name = 'maintenance.equipment.oee.log.detail'
_description = '设备运行日志详情' _description = '设备运行日志详情'
sequence = fields.Integer('序号') # sequence = fields.Integer('序号', related='id')
time = fields.Datetime('时间') time = fields.Datetime('时间')
state = fields.Selection([("加工", "加工"), ("关机", "关机"), ("待机", "待机"), ("故障", "故障"), state = fields.Selection([("加工", "加工"), ("关机", "关机"), ("待机", "待机"), ("故障", "故障"),
("检修", "检修"), ("保养", "保养")], default="", string="事件/状态") ("检修", "检修"), ("保养", "保养")], default="", string="事件/状态")
production_id = fields.Many2one('mrp.production', '加工工单') production_id = fields.Many2one('mrp.production', '加工工单')
log_id = fields.Many2one('maintenance.equipment.oee.logs', '日志') log_id = fields.Many2one('maintenance.equipment.oee.logs', '日志')
# equipment_code = fields.Char('设备编码', related='log_id.equipment_code')
equipment_code = fields.Char('设备编码', readonly='True')

View File

@@ -159,6 +159,8 @@
<field name="equipment_id" domain="[('name','ilike','加工中心')]"/> <field name="equipment_id" domain="[('name','ilike','加工中心')]"/>
<field name="type_id"/> <field name="type_id"/>
<field name="state"/> <field name="state"/>
<field name="equipment_code"/>
<field name="function_type"/>
</group> </group>
</group> </group>
<group> <group>
@@ -202,7 +204,7 @@
<!-- <field name="detail_ids" domain="[('time','&lt;',(datetime.datetime.now() - datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S'))]"> --> <!-- <field name="detail_ids" domain="[('time','&lt;',(datetime.datetime.now() - datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S'))]"> -->
<field name="detail_ids" domain="[('state','ilike','加工')]"> <field name="detail_ids" domain="[('state','ilike','加工')]">
<tree> <tree>
<field name="sequence"/> <!-- <field name="sequence"/> -->
<field name="time"/> <field name="time"/>
<field name="state"/> <field name="state"/>
<field name="production_id"/> <field name="production_id"/>
@@ -219,7 +221,7 @@
<page string="历史日志详情"> <page string="历史日志详情">
<field name="detail_ids"> <field name="detail_ids">
<tree> <tree>
<field name="sequence"/> <!-- <field name="sequence"/> -->
<field name="time"/> <field name="time"/>
<field name="state"/> <field name="state"/>
<field name="production_id"/> <field name="production_id"/>
@@ -263,7 +265,7 @@
<field name="model">maintenance.equipment.oee.log.detail</field> <field name="model">maintenance.equipment.oee.log.detail</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree> <tree>
<field name="sequence"/> <!-- <field name="sequence"/> -->
<field name="time"/> <field name="time"/>
<field name="state"/> <field name="state"/>
<field name="production_id"/> <field name="production_id"/>
@@ -283,7 +285,7 @@
<field name="production_id"/> <field name="production_id"/>
</group> </group>
<group> <group>
<field name="sequence"/> <!-- <field name="sequence"/> -->
<field name="time"/> <field name="time"/>
</group> </group>
</group> </group>