master-sf1.0
This commit is contained in:
2
sf_machine_connect/__init__.py
Normal file
2
sf_machine_connect/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import models
|
||||
from . import wizard
|
||||
42
sf_machine_connect/__manifest__.py
Normal file
42
sf_machine_connect/__manifest__.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
{
|
||||
'name': '机企猫智能工厂 对接机床',
|
||||
'version': '1.0',
|
||||
'summary': 'sf_machine_connect',
|
||||
'sequence': 10,
|
||||
'description': """
|
||||
这是一个连接机床的模块
|
||||
====================
|
||||
""",
|
||||
'category': 'sf',
|
||||
'author': 'jikimo',
|
||||
'website': 'https://sf.cs.jikimo.com',
|
||||
'depends': ['sf_base', 'sf_manufacturing', 'barcodes', ],
|
||||
'data': [
|
||||
# 定义权限组放在最上面
|
||||
# 权限组
|
||||
'security/ir.model.access.csv',
|
||||
'wizard/up_select.xml',
|
||||
'views/default_delivery.xml',
|
||||
'views/ftp_button.xml',
|
||||
|
||||
'views/compensation.xml',
|
||||
|
||||
'views/SfWorkOrderBarcodes.xml',
|
||||
'views/WorkCenterBarcodes.xml',
|
||||
'views/Stock_picking_Barcodes.xml',
|
||||
'views/machine_monitor.xml',
|
||||
'views/machine_info_present.xml',
|
||||
'views/delivery_record.xml',
|
||||
|
||||
],
|
||||
|
||||
'assets': {
|
||||
},
|
||||
|
||||
'installable': True,
|
||||
'application': True,
|
||||
# 'auto_install': False,
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
3
sf_machine_connect/models/__init__.py
Normal file
3
sf_machine_connect/models/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from . import ftp_client
|
||||
from . import ftp_operate
|
||||
from . import py2opcua
|
||||
487
sf_machine_connect/models/ftp_client.py
Normal file
487
sf_machine_connect/models/ftp_client.py
Normal file
@@ -0,0 +1,487 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import base64
|
||||
import logging
|
||||
import os
|
||||
import json
|
||||
import hashlib
|
||||
import time
|
||||
import requests
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from odoo import fields, models, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.addons.sf_machine_connect.models import py2opcua, ftp_operate
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Models for client
|
||||
# ----------------------------------------------------------
|
||||
|
||||
class FtpButton(models.Model):
|
||||
_inherit = 'sf.cnc.processing'
|
||||
|
||||
user_permissions = fields.Boolean(string='权限', related='workorder_id.user_permissions')
|
||||
state = fields.Selection(string='状态', related='workorder_id.state')
|
||||
|
||||
@api.onchange('users_ids')
|
||||
def get_user_permissions(self):
|
||||
uid = self.env.uid
|
||||
for workorder in self:
|
||||
if workorder.users_ids:
|
||||
list_user_id = []
|
||||
for item in workorder.users_ids:
|
||||
list_user_id.append(item.id)
|
||||
if uid in list_user_id:
|
||||
workorder.user_permissions = True
|
||||
else:
|
||||
workorder.user_permissions = False
|
||||
else:
|
||||
workorder.user_permissions = False
|
||||
|
||||
def up(self):
|
||||
"""
|
||||
此函数用于将NC代码下发到机床
|
||||
:return:
|
||||
"""
|
||||
# 点击下发按钮自动补偿三元检测偏差值
|
||||
|
||||
try:
|
||||
try:
|
||||
if self.sequence_number == '1':
|
||||
self.check_compensation_before_up()
|
||||
except Exception:
|
||||
raise UserError("补偿值写入执行超时,请检查机床状态或者写入状态")
|
||||
|
||||
# host="192.168.2.158", port=8080, username="MITSUBISHI", password="CNC"
|
||||
host = self.workorder_id.workcenter_id.machine_tool_id.ftp_host
|
||||
port = self.workorder_id.workcenter_id.machine_tool_id.ftp_port
|
||||
username = self.workorder_id.workcenter_id.machine_tool_id.ftp_num
|
||||
pwd = self.workorder_id.workcenter_id.machine_tool_id.ftp_pwd
|
||||
remote_path = self.workorder_id.workcenter_id.machine_tool_id.ftp_remote_path
|
||||
print(host, port, username, pwd, remote_path)
|
||||
ftp = ftp_operate.FtpController(host, port, username, pwd)
|
||||
# ftp.delAllfile('C://Users//马广威//Desktop//ftp')
|
||||
a = self.cnc_id
|
||||
datas = base64.standard_b64decode(a.datas)
|
||||
|
||||
# file_path = '{}\{}\{}'.format(a._filestore(), a.store_fname.split('/'[0]), a.display_name)
|
||||
file_path_local = '{}/{}'.format('/nc2machine', a.display_name)
|
||||
# file_path_remote = '{}\{}'.format('//M80(192,168,2,142)//DS', a.display_name)
|
||||
file_path_remote = '{}\{}'.format(remote_path, a.display_name)
|
||||
|
||||
with open(file_path_local, mode='wb+') as file:
|
||||
file.write(datas)
|
||||
# 存在本地的文件下发到机床
|
||||
ftp.upload_file(remotepath=file_path_remote, localpath=file_path_local)
|
||||
_logger.info("======%s下发成功======" % a.display_name)
|
||||
ftp.close_ftp()
|
||||
|
||||
up_time = str(datetime.now() + timedelta(hours=8))
|
||||
self.env['delivery.record'].create({
|
||||
'workorder_id': self.workorder_id.id,
|
||||
'delivery_type': '单个下发',
|
||||
'delivery_time': up_time,
|
||||
'influence_record': self.sequence_number,
|
||||
})
|
||||
# self.workorder_id.delivery_records.sudo().create({
|
||||
# 'delivery_type': '单个下发',
|
||||
# 'delivery_time': 'up_time',
|
||||
# 'influence_record': 'self.sequence_number',
|
||||
# })
|
||||
except Exception as e:
|
||||
_logger.info("=====================================", e)
|
||||
raise UserError('NC下发执行超时, 请检查下发状态')
|
||||
|
||||
# 补偿下发都执行完毕后,按钮标志位变为true
|
||||
self.button_state = True
|
||||
|
||||
def check_compensation_before_up(self):
|
||||
"""
|
||||
下发NC代码前自动补偿三元检测偏差值
|
||||
:return:
|
||||
"""
|
||||
hongbianliang550 = self.workorder_id.workcenter_id.machine_tool_id.x_compensation_node
|
||||
hongbianliang551 = self.workorder_id.workcenter_id.machine_tool_id.y_compensation_node
|
||||
try:
|
||||
temp_dict = {}
|
||||
temp_dict[hongbianliang550] = self.workorder_id.compensation_value_x
|
||||
temp_dict[hongbianliang551] = self.workorder_id.compensation_value_y
|
||||
temp = py2opcua.Py2opcua()
|
||||
temp.write(temp_dict)
|
||||
except Exception as e:
|
||||
_logger.info("=====================================", e)
|
||||
raise UserError('补偿值获取失败,或机床未连接,请检查')
|
||||
|
||||
|
||||
class Machine_ftp(models.Model):
|
||||
"""
|
||||
数据采集类
|
||||
"""
|
||||
_inherit = 'sf.machine_tool'
|
||||
|
||||
workorder_ids = fields.One2many('mrp.workorder', 'machine_tool_id', string='工单')
|
||||
|
||||
# 机床配置项目
|
||||
# ftp相关
|
||||
ftp_num = fields.Char('ftp账号')
|
||||
ftp_pwd = fields.Char('ftp密码')
|
||||
ftp_host = fields.Char('ftp地址')
|
||||
ftp_port = fields.Integer('ftp端口')
|
||||
ftp_remote_path = fields.Char('机床ftp路径')
|
||||
# 补偿值写入相关
|
||||
x_compensation_node = fields.Char('x补偿值节点')
|
||||
y_compensation_node = fields.Char('y补偿值节点')
|
||||
# 数采配置相关
|
||||
machine_ip = fields.Char('机床IP')
|
||||
machine_signed = fields.Char('机床刷新间隔')
|
||||
machine_status = fields.Char('机床在线状态')
|
||||
machine_cnc_type = fields.Char('机床CNC型号')
|
||||
machine_axis_count = fields.Char('机床轴总数')
|
||||
machine_run_status = fields.Char('机床运行状态')
|
||||
machine_emg_status = fields.Char('机床急停状态')
|
||||
machine_cut_status = fields.Char('机床当前切削状态')
|
||||
machine_mode = fields.Char('机床当前操作模式')
|
||||
machine_spindle_load = fields.Char('机床主轴负载')
|
||||
machine_x_mach = fields.Char('机床X轴机械坐标')
|
||||
machine_x_abs_mach = fields.Char('机床X轴当前位置')
|
||||
machine_x_rel_mach = fields.Char('机床X轴相对工件坐标')
|
||||
machine_x_dis_mach = fields.Char('机床X轴目标距离')
|
||||
machine_x_axis_load = fields.Char('机床X轴伺服轴负载')
|
||||
machine_y_mach = fields.Char('机床Y轴机械坐标')
|
||||
machine_y_abs_mach = fields.Char('机床Y轴当前位置')
|
||||
machine_y_rel_mach = fields.Char('机床Y轴相对工件坐标')
|
||||
machine_y_dis_mach = fields.Char('机床Y轴目标距离')
|
||||
machine_y_axis_load = fields.Char('机床Y轴伺服轴负载')
|
||||
machine_z_mach = fields.Char('机床Z轴机械坐标')
|
||||
machine_z_abs_mach = fields.Char('机床Z轴当前位置')
|
||||
machine_z_rel_mach = fields.Char('机床Z轴相对工件坐标')
|
||||
machine_z_dis_mach = fields.Char('机床Z轴目标距离')
|
||||
machine_z_axis_load = fields.Char('机床Z轴伺服轴负载')
|
||||
machine_tool_num = fields.Char('机床当前刀位号')
|
||||
machine_program = fields.Char('机床主程序名称')
|
||||
machine_current_prg = fields.Char('机床当前执行指令')
|
||||
machine_prg_seq = fields.Char('机床当前执行语句号')
|
||||
machine_spindle_speed_set = fields.Char('机床设定主轴速度')
|
||||
machine_act_spindle_speed = fields.Char('机床实际主轴转速')
|
||||
machine_feed_speed_set = fields.Char('机床设定进给速度')
|
||||
machine_act_feed_speed = fields.Char('机床实际进给速度')
|
||||
machine_spindle_feed = fields.Char('机床主轴倍率')
|
||||
machine_feed_rate = fields.Char('机床进给倍率')
|
||||
machine_rapid_feed = fields.Char('机床快速移动倍率')
|
||||
machine_run_time = fields.Char('机床运行时间')
|
||||
machine_cut_time = fields.Char('机床切削时间')
|
||||
machine_keep_alive_time = fields.Char('机床上电时间')
|
||||
machine_circle_time = fields.Char('机床循环时间')
|
||||
machine_product_counts = fields.Char('机床加工件数')
|
||||
machine_system_date = fields.Char('机床系统日期')
|
||||
machine_system_time = fields.Char('机床系统时间')
|
||||
machine_alarm_msg = fields.Char('机床系统报警')
|
||||
|
||||
# 机床采集项目
|
||||
timestamp = fields.Datetime('时间戳', readonly=True)
|
||||
signed = fields.Integer('刷新间隔', readonly=True)
|
||||
status = fields.Boolean('在线状态', readonly=True)
|
||||
time_on = fields.Char('总在线时长', readonly=True)
|
||||
time_on_now = fields.Char('本次在线时长', readonly=True)
|
||||
tool_num = fields.Integer('当前刀具', readonly=True)
|
||||
program = fields.Char('当前程序', readonly=True)
|
||||
run_status = fields.Selection([('0', '空闲中'), ('1', '加工中'), ('2', '加工中'), ('3', '加工中')], string='运行状态',
|
||||
readonly=True, default='0')
|
||||
run_time = fields.Char('总运行时长', readonly=True)
|
||||
cut_time = fields.Char('总切削时长', readonly=True)
|
||||
cut_status = fields.Selection([('0', '未切削'), ('1', '切削中'), ('2', '切削中'), ('3', '切削中')], string='切削状态',
|
||||
readonly=True, default='0')
|
||||
spindle_speed = fields.Char('主轴转速', readonly=True)
|
||||
|
||||
tool_num_process_time1 = fields.Char('刀位1', readonly=True, default='0')
|
||||
tool_num_process_time2 = fields.Char('刀位2', readonly=True, default='0')
|
||||
tool_num_process_time3 = fields.Char('刀位3', readonly=True, default='0')
|
||||
tool_num_process_time4 = fields.Char('刀位4', readonly=True, default='0')
|
||||
tool_num_process_time5 = fields.Char('刀位5', readonly=True, default='0')
|
||||
tool_num_process_time6 = fields.Char('刀位6', readonly=True, default='0')
|
||||
tool_num_process_time7 = fields.Char('刀位7', readonly=True, default='0')
|
||||
tool_num_process_time8 = fields.Char('刀位8', readonly=True, default='0')
|
||||
tool_num_process_time9 = fields.Char('刀位9', readonly=True, default='0')
|
||||
tool_num_process_time10 = fields.Char('刀位10', readonly=True, default='0')
|
||||
tool_num_process_time11 = fields.Char('刀位11', readonly=True, default='0')
|
||||
tool_num_process_time12 = fields.Char('刀位12', readonly=True, default='0')
|
||||
tool_num_process_time13 = fields.Char('刀位13', readonly=True, default='0')
|
||||
tool_num_process_time14 = fields.Char('刀位14', readonly=True, default='0')
|
||||
tool_num_process_time15 = fields.Char('刀位15', readonly=True, default='0')
|
||||
tool_num_process_time16 = fields.Char('刀位16', readonly=True, default='0')
|
||||
tool_num_process_time17 = fields.Char('刀位17', readonly=True, default='0')
|
||||
tool_num_process_time18 = fields.Char('刀位18', readonly=True, default='0')
|
||||
tool_num_process_time19 = fields.Char('刀位19', readonly=True, default='0')
|
||||
tool_num_process_time20 = fields.Char('刀位20', readonly=True, default='0')
|
||||
tool_num_process_time21 = fields.Char('刀位21', readonly=True, default='0')
|
||||
tool_num_process_time22 = fields.Char('刀位22', readonly=True, default='0')
|
||||
tool_num_process_time23 = fields.Char('刀位23', readonly=True, default='0')
|
||||
tool_num_process_time24 = fields.Char('刀位24', readonly=True, default='0')
|
||||
|
||||
|
||||
class WorkCenterBarcode(models.Model):
|
||||
"""
|
||||
扫码托盘码可查到制造订单,由制造订单查工单
|
||||
"""
|
||||
_inherit = "mrp.workorder"
|
||||
|
||||
compensation_value_x = fields.Float(string='X轴补偿值')
|
||||
compensation_value_y = fields.Float(string='Y轴补偿值')
|
||||
button_compensation_state = fields.Boolean(string='是否已经补偿', readonly=True)
|
||||
button_up_all_state = fields.Boolean(string='是否已经全部下发', readonly=True)
|
||||
machine_tool_id = fields.Many2one('sf.machine_tool', string='机床')
|
||||
machine_tool_name = fields.Char(string='机床名称', default='未知机床', compute='_run_info', readonly=True)
|
||||
machine_tool_type_id = fields.Char(string='机床型号', default='未知型号', compute='_run_info', readonly=True)
|
||||
machine_tool_status = fields.Boolean(string='在线状态', compute='_run_info', readonly=True)
|
||||
machine_tool_run_status = fields.Selection([('0', '空闲中'), ('1', '加工中'), ('2', '加工中'), ('3', '加工中')],
|
||||
string='运行状态', compute='_run_info', readonly=True, default='0')
|
||||
machine_tool_timestamp = fields.Datetime('时间戳', compute='_run_info', readonly=True)
|
||||
machine_tool_time_on = fields.Char('总在线时长', compute='_run_info', readonly=True)
|
||||
machine_tool_time_on_now = fields.Char('本次在线时长', compute='_run_info', readonly=True)
|
||||
machine_tool_tool_num = fields.Integer('当前刀具', compute='_run_info', readonly=True)
|
||||
machine_tool_program = fields.Char('当前程序', compute='_run_info', readonly=True)
|
||||
machine_tool_machine_ip = fields.Char('机床IP', compute='_run_info', readonly=True)
|
||||
machine_tool_cut_status = fields.Selection([('0', '未切削'), ('1', '切削中'), ('2', '切削中'), ('3', '切削中')],
|
||||
string='切削状态', compute='_run_info', readonly=True, default='0')
|
||||
machine_tool_compensation_value_x = fields.Char('x补偿值', compute='_run_info', readonly=True)
|
||||
machine_tool_compensation_value_y = fields.Char('y补偿值', compute='_run_info', readonly=True)
|
||||
delivery_records = fields.One2many('delivery.record', 'workorder_id', string="下发记录")
|
||||
|
||||
@api.depends('workcenter_id.machine_tool_id.timestamp')
|
||||
def _run_info(self):
|
||||
# self.machine_tool_name = '1号机床'
|
||||
self.machine_tool_name = self.workcenter_id.machine_tool_id.name
|
||||
self.machine_tool_type_id = self.workcenter_id.machine_tool_id.type_id.name
|
||||
self.machine_tool_status = self.workcenter_id.machine_tool_id.status
|
||||
self.machine_tool_run_status = self.workcenter_id.machine_tool_id.run_status
|
||||
self.machine_tool_timestamp = self.workcenter_id.machine_tool_id.timestamp
|
||||
self.machine_tool_time_on = self.workcenter_id.machine_tool_id.time_on
|
||||
self.machine_tool_time_on_now = self.workcenter_id.machine_tool_id.time_on_now
|
||||
self.machine_tool_tool_num = self.workcenter_id.machine_tool_id.tool_num
|
||||
self.machine_tool_program = self.workcenter_id.machine_tool_id.program
|
||||
self.machine_tool_machine_ip = self.workcenter_id.machine_tool_id.machine_ip
|
||||
self.machine_tool_cut_status = self.workcenter_id.machine_tool_id.cut_status
|
||||
self.machine_tool_compensation_value_x = self.compensation_value_x
|
||||
self.machine_tool_compensation_value_y = self.compensation_value_y
|
||||
|
||||
def compensation(self):
|
||||
|
||||
|
||||
hongbianliang550 = self.workcenter_id.machine_tool_id.x_compensation_node
|
||||
hongbianliang551 = self.workcenter_id.machine_tool_id.y_compensation_node
|
||||
try:
|
||||
temp_dict = {}
|
||||
temp_dict[hongbianliang550] = self.compensation_value_x
|
||||
temp_dict[hongbianliang551] = self.compensation_value_y
|
||||
|
||||
print(temp_dict)
|
||||
temp = py2opcua.Py2opcua()
|
||||
_logger.info("====================2===============%s" % temp_dict)
|
||||
temp.write(temp_dict)
|
||||
_logger.info("================补偿完成==============")
|
||||
except Exception as e:
|
||||
_logger.info("=====================================", e)
|
||||
raise UserError('补偿值获取失败,或机床未连接,请检查')
|
||||
# 补偿执行完毕后,按钮标志位变为true
|
||||
self.button_compensation_state = True
|
||||
|
||||
def up_all(self):
|
||||
"""
|
||||
此函数用于将NC代码全部下发到机床
|
||||
:return:
|
||||
"""
|
||||
# 一键下发前删除机床上的全部程序
|
||||
try:
|
||||
filepath = '/nc2machine'
|
||||
del_list = os.listdir(filepath)
|
||||
_logger.info("=====================================%s" % del_list)
|
||||
for f in del_list:
|
||||
file_path = os.path.join(filepath, f)
|
||||
if os.path.isfile(file_path):
|
||||
os.remove(file_path)
|
||||
except Exception as e:
|
||||
_logger.info("=====================================", e)
|
||||
raise UserError('程序删除失败,请重试')
|
||||
# host="192.168.2.158", port=8080, username="MITSUBISHI", password="CNC"
|
||||
try:
|
||||
self.compensation()
|
||||
except Exception:
|
||||
raise UserError("补偿值写入执行超时,请检查机床状态或者写入状态")
|
||||
sequence_collect = []
|
||||
host = self.workcenter_id.machine_tool_id.ftp_host
|
||||
port = self.workcenter_id.machine_tool_id.ftp_port
|
||||
username = self.workcenter_id.machine_tool_id.ftp_num
|
||||
pwd = self.workcenter_id.machine_tool_id.ftp_pwd
|
||||
remote_path = self.workcenter_id.machine_tool_id.ftp_remote_path
|
||||
_logger.info("=====================1666666661111================%s,%s,%s,%s" % (host, port, username, pwd))
|
||||
ftp = ftp_operate.FtpController(host, port, username, pwd)
|
||||
_logger.info("=====================1777777777111================")
|
||||
|
||||
|
||||
|
||||
try:
|
||||
for item in self.cnc_ids:
|
||||
a = item.cnc_id
|
||||
sequence_collect.append(item.sequence_number)
|
||||
datas = base64.standard_b64decode(a.datas)
|
||||
# file_path = '{}\{}\{}'.format(a._filestore(), a.store_fname.split('/'[0]), a.display_name)
|
||||
file_path_local = '{}/{}'.format('/nc2machine', a.display_name)
|
||||
# 本地测试一键下发
|
||||
# file_path_local = '{}/{}'.format('D:\\jikimo', a.display_name)
|
||||
# file_path_remote = '{}\{}'.format('//M80(192,168,2,142)//DS', a.display_name)
|
||||
file_path_remote = '{}\{}'.format(remote_path, a.display_name)
|
||||
|
||||
with open(file_path_local, mode='wb+') as file:
|
||||
file.write(datas)
|
||||
# 存在本地的文件下发到机床
|
||||
ftp.upload_file(remotepath=file_path_remote, localpath=file_path_local)
|
||||
_logger.info("======%s下发成功======" % a.display_name)
|
||||
item.button_state = True
|
||||
ftp.close_ftp()
|
||||
# 增加一键下发记录
|
||||
up_time = str(datetime.now() + timedelta(hours=8))
|
||||
sequence_str = ','.join(sequence_collect)
|
||||
self.delivery_records.create({
|
||||
'delivery_type': '一键下发',
|
||||
'delivery_time': up_time,
|
||||
'influence_record': sequence_str,
|
||||
})
|
||||
_logger.info("=====================22================")
|
||||
except Exception as e:
|
||||
_logger.info("=====================================", e)
|
||||
raise UserError('NC下发执行超时, 请检查下发状态')
|
||||
|
||||
def up_merge_all(self):
|
||||
"""
|
||||
此函数用于将NC代码一键合并下发到机床
|
||||
:return:
|
||||
"""
|
||||
# 一键合并下发前删除机床上的全部程序
|
||||
try:
|
||||
filepath = '/nc2machine'
|
||||
del_list = os.listdir(filepath)
|
||||
_logger.info("=====================================%s" % del_list)
|
||||
for f in del_list:
|
||||
file_path = os.path.join(filepath, f)
|
||||
if os.path.isfile(file_path):
|
||||
os.remove(file_path)
|
||||
except Exception as e:
|
||||
_logger.info("=====================================", e)
|
||||
raise UserError('程序删除失败,请重试')
|
||||
# host="192.168.2.158", port=8080, username="MITSUBISHI", password="CNC"
|
||||
try:
|
||||
self.compensation()
|
||||
except Exception:
|
||||
raise UserError("补偿值写入执行超时,请检查机床状态或者写入状态")
|
||||
sequence_collect = []
|
||||
host = self.workcenter_id.machine_tool_id.ftp_host
|
||||
port = self.workcenter_id.machine_tool_id.ftp_port
|
||||
username = self.workcenter_id.machine_tool_id.ftp_num
|
||||
pwd = self.workcenter_id.machine_tool_id.ftp_pwd
|
||||
remote_path = self.workcenter_id.machine_tool_id.ftp_remote_path
|
||||
_logger.info("=====================1666666661111================%s,%s,%s,%s" % (host, port, username, pwd))
|
||||
ftp = ftp_operate.FtpController(host, port, username, pwd)
|
||||
_logger.info("=====================1777777777111================")
|
||||
file_path_local = ''
|
||||
file_path_remote = ''
|
||||
|
||||
try:
|
||||
# 给文件名
|
||||
_logger.info('启动')
|
||||
begin_name1 = self.cnc_ids[0].cnc_id.display_name.split('-')
|
||||
_logger.info(begin_name1)
|
||||
temp_name1 = begin_name1[-1].split('.')
|
||||
final_name = '%s-ALL-MERGE.%s' % (begin_name1[0], temp_name1[-1])
|
||||
_logger.info(final_name)
|
||||
for item in self.cnc_ids:
|
||||
a = item.cnc_id
|
||||
sequence_collect.append(item.sequence_number)
|
||||
datas = base64.standard_b64decode(a.datas)
|
||||
# file_path = '{}\{}\{}'.format(a._filestore(), a.store_fname.split('/'[0]), a.display_name)
|
||||
file_path_local = '{}/{}'.format('/nc2machine', final_name)
|
||||
# 本地测试一键下发
|
||||
# file_path_local = '{}/{}'.format('D:\\jikimo', a.display_name)
|
||||
# file_path_remote = '{}\{}'.format('//M80(192,168,2,142)//DS', a.display_name)
|
||||
file_path_remote = '{}\{}'.format(remote_path, final_name)
|
||||
# 合并文件
|
||||
with open(file_path_local, mode='ab+') as file:
|
||||
file.write(datas)
|
||||
item.button_state = True
|
||||
_logger.info('========一键下发前合并成功===============')
|
||||
|
||||
# 去除合并文件中间部分的头尾
|
||||
with open(file_path_local, mode='rb+') as f:
|
||||
# _logger.info(f.read())
|
||||
# content = f.read()
|
||||
# _logger.info(content)
|
||||
new_content = f.read().replace(b'\r\nM30\r\n%\r\n%\r\n', b'\r\n')
|
||||
# _logger.info(new_content)
|
||||
f.seek(0)
|
||||
f.truncate()
|
||||
f.write(new_content)
|
||||
_logger.info('========二次合并成功===============')
|
||||
|
||||
# 存在本地的文件下发到机床
|
||||
ftp.upload_file(remotepath=file_path_remote, localpath=file_path_local)
|
||||
_logger.info("======%s一键合并下发成功======" % a.display_name)
|
||||
ftp.close_ftp()
|
||||
# 增加一键合并下发记录
|
||||
up_time = str(datetime.now() + timedelta(hours=8))
|
||||
sequence_str = ','.join(sequence_collect)
|
||||
self.delivery_records.create({
|
||||
'delivery_type': '一键合并下发',
|
||||
'delivery_time': up_time,
|
||||
'influence_record': sequence_str,
|
||||
})
|
||||
_logger.info("=====================22================")
|
||||
except Exception as e:
|
||||
for item in self.cnc_ids:
|
||||
item.button_state = False
|
||||
_logger.info("=====================================", e)
|
||||
raise UserError('NC下发执行超时, 请检查下发状态')
|
||||
|
||||
def get__state(self):
|
||||
pay_time = str(datetime.now())
|
||||
json = {
|
||||
'params': {
|
||||
'model_name': 'jikimo.process.order',
|
||||
'field_name': 'name',
|
||||
'default_code': 'PO-2022-1207-0020',
|
||||
'state': '待付款',
|
||||
# 'pay_time': pay_time,
|
||||
# 'get_order_sf': 21,
|
||||
},
|
||||
}
|
||||
# res_str = json.dumps(vals)
|
||||
url = 'https://bfm.cs.jikimo.com/api/get/state'
|
||||
requests.post(url, json=json, data=None)
|
||||
|
||||
|
||||
class DeliveryRecord(models.Model):
|
||||
"""
|
||||
扫码托盘码可查到制造订单,由制造订单查工单
|
||||
"""
|
||||
_name = "delivery.record"
|
||||
_description = 'Delivery Record'
|
||||
|
||||
delivery_type = fields.Char(string='下发方式', readonly=True)
|
||||
delivery_time = fields.Char(string='下发时间', readonly=True)
|
||||
influence_record = fields.Char(string='影响记录', readonly=True)
|
||||
workorder_id = fields.Many2one('mrp.workorder', string='工单')
|
||||
sf_cnc_processing_id = fields.Many2one('sf.cnc.processing', string='NC')
|
||||
|
||||
# @api.model
|
||||
# def create(self, values):
|
||||
# try:
|
||||
# values['order_code'] = self.env['ir.sequence'].next_by_code('sf_machine_connect.delivery.record')
|
||||
# stock = self.env['sunrise.u.stock']
|
||||
# if 'order_items' in values.keys():
|
||||
# for item in values['order_items']:
|
||||
# stock_commodity = stock.search([('commodity', '=', item[2]['commodity'])])
|
||||
# stock_commodity.amount += item[2]['amount']
|
||||
# return super().create(values)
|
||||
# except:
|
||||
# raise Exception('b_purchase_order.py:create()')
|
||||
134
sf_machine_connect/models/ftp_operate.py
Normal file
134
sf_machine_connect/models/ftp_operate.py
Normal file
@@ -0,0 +1,134 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import logging
|
||||
from ftplib import FTP
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FTP_P(FTP):
|
||||
"""
|
||||
重写FTP类,重写dirs方法
|
||||
"""
|
||||
|
||||
def dirs(self, *args):
|
||||
"""List a directory in long form.
|
||||
By default list current directory to stdout.
|
||||
Optional last argument is callback function; all
|
||||
non-empty arguments before it are concatenated to the
|
||||
LIST command. (This *should* only be used for a pathname.)"""
|
||||
cmd = 'LIST'
|
||||
templist = []
|
||||
tempdic = {}
|
||||
func = None
|
||||
if args[-1:] and type(args[-1]) != type(''):
|
||||
args, func = args[:-1], args[-1]
|
||||
for arg in args:
|
||||
if arg:
|
||||
cmd = cmd + (' ' + arg)
|
||||
self.retrlines(cmd, templist.append)
|
||||
# 处理返回结果,只需要目录名称
|
||||
r_files = [file.split(" ")[-1] for file in templist]
|
||||
tempdic['name'] = [file for file in r_files if file != "." and file != ".."]
|
||||
# 去除. ..
|
||||
return tempdic
|
||||
# return [file for file in r_files if file != "." and file != ".."]
|
||||
|
||||
|
||||
# FTP接口类
|
||||
class FtpController:
|
||||
"""
|
||||
这是ftp接口类,在类初始化的时候就连接了ftp服务器,能否成功连接有反馈。
|
||||
类中定义了两个接口:上传接口和删除接口
|
||||
"""
|
||||
|
||||
# 三菱机床连接
|
||||
def __init__(self, host="192.168.2.158", port=8080, username="MITSUBISHI", password="CNC"):
|
||||
_logger.info("===================ftppppp==================")
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.username = username
|
||||
self.password = password
|
||||
# _logger.info("===================ftppppp==================%s,%s,%s,%s" % self.host, self.port, self.username, self.password)
|
||||
# 测试
|
||||
print("==============================================")
|
||||
print(self.username, self.port, self.host, self.password)
|
||||
ftp = FTP_P()
|
||||
_logger.info("===================connect==================")
|
||||
# self.ftp.set_debuglevel(2) #打开调试级别2,显示详细信息
|
||||
ftp.set_pasv(0) # 0主动模式 1 #被动模式
|
||||
try:
|
||||
ftp.connect(self.host, self.port)
|
||||
ftp.login(self.username, self.password)
|
||||
_logger.info("=================连接成功==================")
|
||||
print("连接成功")
|
||||
self.ftp = ftp
|
||||
except Exception as e:
|
||||
print("连接失败" + str(e))
|
||||
|
||||
# 试验接口
|
||||
def prin(self):
|
||||
print("这是试验接口")
|
||||
|
||||
# 三菱代码下发
|
||||
def upload_file(self, remotepath='/(192,168,199,2)/DS/Z4.5.NC', localpath='D:/ftp/up/Z4.5.NC'):
|
||||
"""
|
||||
第一个是要上传到ftp服务器路径下的文件,第二个是本地要上传的的路径文件
|
||||
:param remotepath: 上传和下载都需要设置工作目录,注意只能使用文件名,不能有路径中的冒号
|
||||
:param localpath:
|
||||
:return:
|
||||
"""
|
||||
bufsize = 8192
|
||||
# fp = open(localpath, 'rb')
|
||||
# self.ftp.storbinary('STOR ' + remotepath, fp, bufsize)
|
||||
# fp.close()
|
||||
with open(localpath, mode='rb') as file:
|
||||
self.ftp.storbinary('STOR ' + remotepath, file, bufsize)
|
||||
|
||||
# 关闭连接
|
||||
def close_ftp(self):
|
||||
"""
|
||||
下发完成后关闭ftp连接,减少资源损耗
|
||||
"""
|
||||
self.ftp.close()
|
||||
|
||||
|
||||
def delAllfile(self, ftppath):
|
||||
"""
|
||||
删除ftp服务器端全部文件
|
||||
:param ftppath:
|
||||
:return:
|
||||
"""
|
||||
dir_res = []
|
||||
try:
|
||||
print(ftppath)
|
||||
try:
|
||||
self.ftp.cwd(ftppath)
|
||||
except Exception as e:
|
||||
print("进入ftp目录失败" + str(e))
|
||||
self.ftp.dir('.', dir_res.append) # 对当前目录进行dir(),将结果放入列表
|
||||
print(dir_res)
|
||||
# for i in dir_res:
|
||||
# if i.startswith("d"):
|
||||
# dirName = i.split(" ")[-1]
|
||||
# print("开始删除" + dirName + "文件夹")
|
||||
# delAllfile(ftp, ftp.pwd() + "/" + dirName)
|
||||
# ftp.cwd('..')
|
||||
# print(ftppath + "/" + dirName)
|
||||
# ftp.rmd(ftppath + '/' + dirName)
|
||||
# else:
|
||||
# filelist = ftp.getfiles(ftppath)
|
||||
# for f in filelist:
|
||||
# print("删除FTP目录:" + ftppath + "下存在文件:" + f)
|
||||
# ftp.delete(f)
|
||||
except Exception as e:
|
||||
print("删除失败" + str(e))
|
||||
|
||||
# 出现550 not found file是路径不对
|
||||
def del_file(self, delpath='/(192,168,199,2)/DS/Z4.5.NC'):
|
||||
"""
|
||||
删除ftp服务器端指定文件
|
||||
:param delpath:
|
||||
:return:
|
||||
"""
|
||||
self.ftp.delete(delpath)
|
||||
46
sf_machine_connect/models/py2opcua.py
Normal file
46
sf_machine_connect/models/py2opcua.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from opcua import ua, Client
|
||||
|
||||
|
||||
class Py2opcua:
|
||||
"""
|
||||
将三元检测补偿值写入opcua服务器
|
||||
"""
|
||||
|
||||
def __init__(self, url='opc.tcp://192.168.2.99:4840'):
|
||||
self.client = Client(url, timeout=3600000)
|
||||
|
||||
# 连接客户端
|
||||
# def connect(self):
|
||||
# try:
|
||||
# self.client.connect()
|
||||
# print("opcua服务器连接成功,可以写入")
|
||||
# return self.client
|
||||
# except Exception as e:
|
||||
# print("opcua服务器连接失败,请检查" + str(e))
|
||||
|
||||
def write(self, temp_dict):
|
||||
"""
|
||||
补偿值写入方法,参数是一个字典,键是节点名,值是补偿值
|
||||
:param temp_dict:
|
||||
:return:
|
||||
"""
|
||||
# try:
|
||||
self.client.connect()
|
||||
# print("opcua服务器连接成功,可以写入")
|
||||
# return self.client
|
||||
# except Exception as e:
|
||||
# print("opcua服务器连接失败,请检查" + str(e))
|
||||
# temp_dict = temp_dict
|
||||
temp_list = list(temp_dict.items())
|
||||
for i in range(len(temp_list)):
|
||||
# 寻找节点上的变量
|
||||
var = self.client.get_node(temp_list[i][0])
|
||||
# var.set_value(ua.Variant(1.234, ua.VariantType.Float))
|
||||
# 通过set_value写值
|
||||
var.set_value(ua.Variant(temp_list[i][1], ua.VariantType.Double))
|
||||
# print("%s 已写入" % var.get_value())
|
||||
self.client.disconnect()
|
||||
|
||||
# 断开连接
|
||||
# def disconnect(self):
|
||||
# self.client.disconnect()
|
||||
20
sf_machine_connect/security/iot_security.xml
Normal file
20
sf_machine_connect/security/iot_security.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="iot_box_comp_rule" model="ir.rule">
|
||||
<field name="name">IoT Box multi company rule</field>
|
||||
<field name="model_id" ref="model_iot_box"/>
|
||||
<field eval="True" name="global"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="iot_device_comp_rule" model="ir.rule">
|
||||
<field name="name">IoT Device multi company rule</field>
|
||||
<field name="model_id" ref="model_iot_device"/>
|
||||
<field eval="True" name="global"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
5
sf_machine_connect/security/ir.model.access.csv
Normal file
5
sf_machine_connect/security/ir.model.access.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
|
||||
access_up_select_wizard,up.select.wizard,model_up_select_wizard,base.group_user,1,1,1,1
|
||||
access_delivery_record,delivery.record,model_delivery_record,base.group_user,1,1,1,1
|
||||
access_mrp_workorder,mrp.workorder,model_mrp_workorder,base.group_user,1,1,1,1
|
||||
|
BIN
sf_machine_connect/static/description/icon.png
Normal file
BIN
sf_machine_connect/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
30
sf_machine_connect/static/src/css/MyWidget.css
Normal file
30
sf_machine_connect/static/src/css/MyWidget.css
Normal file
@@ -0,0 +1,30 @@
|
||||
.o_int_colorpicker {
|
||||
.o_color_pill {
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
margin: 4px;
|
||||
border-radius: 25px;
|
||||
position: relative;
|
||||
@for $size from 1 through length($o-colors) {
|
||||
&.o_color_#{$size - 1} {
|
||||
background-color: nth($o-colors, $size);
|
||||
&:not(.readonly):hover {
|
||||
transform: scale(1.2);
|
||||
transition: 0.3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
&.active:after{
|
||||
content: "\f00c";
|
||||
display: inline-block;
|
||||
font: normal normal normal 14px/1 FontAwesome;
|
||||
font-size: inherit;
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
padding: 4px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
sf_machine_connect/static/src/css/iot.css
Normal file
5
sf_machine_connect/static/src/css/iot.css
Normal file
@@ -0,0 +1,5 @@
|
||||
.o_button_iot {
|
||||
min-width: 120px;
|
||||
min-height: 40px;
|
||||
margin-left: 50px;
|
||||
}
|
||||
13
sf_machine_connect/static/src/css/many2one_field.scss
Normal file
13
sf_machine_connect/static/src/css/many2one_field.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
.o_form_view:not(.o_field_highlight) {
|
||||
.o_field_many2one_selection {
|
||||
.o_external_button, .o_dropdown_button {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&:hover, &:focus-within {
|
||||
.o_external_button, .o_dropdown_button {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
82
sf_machine_connect/static/src/js/test.js
Normal file
82
sf_machine_connect/static/src/js/test.js
Normal file
@@ -0,0 +1,82 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
import { Dialog } from "@web/core/dialog/dialog";
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
import { useChildRef, useOwnedDialogs, useService } from "@web/core/utils/hooks";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { isMobileOS } from "@web/core/browser/feature_detection";
|
||||
import * as BarcodeScanner from "@web/webclient/barcode/barcode_scanner";
|
||||
|
||||
const {xml, Component} = owl;
|
||||
import { standardFieldProps } from "@web/views/fields/standard_field_props";
|
||||
// Import the registry
|
||||
import {registry} from "@web/core/registry";
|
||||
|
||||
|
||||
export class CodeField extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
}
|
||||
async onBarcodeBtnClick() {
|
||||
const barcode = await BarcodeScanner.scanBarcode();
|
||||
if (barcode) {
|
||||
await this.onBarcodeScanned(barcode);
|
||||
if ("vibrate" in browser.navigator) {
|
||||
browser.navigator.vibrate(100);
|
||||
}
|
||||
} else {
|
||||
this.notification.add(this.env._t("Please, scan again !"), {
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
}
|
||||
async search(barcode) {
|
||||
const results = await this.orm.call("sf.tray", "name_search", [code], {
|
||||
name: barcode,
|
||||
args: this.getDomain(),
|
||||
operator: "ilike",
|
||||
limit: 2, // If one result we set directly and if more than one we use normal flow so no need to search more
|
||||
context: this.context,
|
||||
});
|
||||
return results.map((result) => {
|
||||
const [id, displayName] = result;
|
||||
return {
|
||||
id,
|
||||
name: displayName,
|
||||
};
|
||||
});
|
||||
}
|
||||
async onBarcodeScanned(barcode) {
|
||||
const results = await this.search(barcode);
|
||||
const records = results.filter((r) => !!r.id);
|
||||
if (records.length === 1) {
|
||||
this.update([{ id: records[0].id, name: records[0].name }]);
|
||||
} else {
|
||||
const searchInput = this.autocompleteContainerRef.el.querySelector("input");
|
||||
searchInput.value = barcode;
|
||||
searchInput.dispatchEvent(new Event("input"));
|
||||
if (this.env.isSmall) {
|
||||
searchInput.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CodeField.template = xml`
|
||||
<button
|
||||
t-on-click="onBarcodeBtnClick"
|
||||
type="button"
|
||||
class="btn ms-3 o_barcode"
|
||||
tabindex="-1"
|
||||
draggable="false"
|
||||
aria-label="Scan barcode"
|
||||
title="Scan barcode"
|
||||
data-tooltip="Scan barcode"
|
||||
/>
|
||||
`;
|
||||
// CodeField.template = 'sf_machine_connect.CodeField';
|
||||
CodeField.props = standardFieldProps;
|
||||
|
||||
// Add the field to the correct category
|
||||
registry.category("fields").add("code", CodeField);
|
||||
94
sf_machine_connect/static/src/xml/Barcode_Scan_template.xml
Normal file
94
sf_machine_connect/static/src/xml/Barcode_Scan_template.xml
Normal file
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="sf_machine_connect.Barcode_Scan_template" t-inherit="web.Legacy.ControlPanel" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//div[hasclass('o_cp_pager')]" position="inside">
|
||||
<button
|
||||
style="float:left"
|
||||
t-on-click="onBarcodeScanned"
|
||||
type="button"
|
||||
class="btn ms-3 o_barcode"
|
||||
tabindex="-1"
|
||||
draggable="false"
|
||||
aria-label="Scan barcode"
|
||||
title="Scan barcode"
|
||||
data-tooltip="Scan barcode"
|
||||
>扫码</button>
|
||||
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
<!-- <t t-name="web.Many2OneField.CreateConfirmationDialog" owl="1">-->
|
||||
<!-- <Dialog title="title" size="'md'">-->
|
||||
<!-- <div>-->
|
||||
<!-- Create <strong t-esc="props.value"/> as a new <t t-esc="props.name"/>?-->
|
||||
<!-- </div>-->
|
||||
<!-- <t t-set-slot="footer">-->
|
||||
<!-- <button class="btn btn-primary" t-on-click="onCreate">Create</button>-->
|
||||
<!-- <button class="btn" t-on-click="() => props.close()">Discard</button>-->
|
||||
<!-- </t>-->
|
||||
<!-- </Dialog>-->
|
||||
<!-- </t>-->
|
||||
|
||||
<!-- <t t-name="web.Many2OneField" owl="1">-->
|
||||
<!-- <t t-if="props.readonly">-->
|
||||
<!-- <t t-if="!props.canOpen">-->
|
||||
<!-- <span>-->
|
||||
<!-- <span t-esc="displayName" />-->
|
||||
<!-- <t t-foreach="extraLines" t-as="extraLine" t-key="extraLine_index">-->
|
||||
<!-- <br />-->
|
||||
<!-- <span t-esc="extraLine" />-->
|
||||
<!-- </t>-->
|
||||
<!-- </span>-->
|
||||
<!-- </t>-->
|
||||
<!-- <t t-else="">-->
|
||||
<!-- <a-->
|
||||
<!-- t-if="props.value"-->
|
||||
<!-- class="o_form_uri"-->
|
||||
<!-- t-att-href="props.value ? `#id=${props.value[0]}&model=${relation}` : '#'"-->
|
||||
<!-- t-on-click.prevent="onClick"-->
|
||||
<!-- >-->
|
||||
<!-- <span t-esc="displayName" />-->
|
||||
<!-- <t t-foreach="extraLines" t-as="extraLine" t-key="extraLine_index">-->
|
||||
<!-- <br />-->
|
||||
<!-- <span t-esc="extraLine" />-->
|
||||
<!-- </t>-->
|
||||
<!-- </a>-->
|
||||
<!-- </t>-->
|
||||
<!-- </t>-->
|
||||
<!-- <t t-else="">-->
|
||||
<!-- <div class="o_field_many2one_selection">-->
|
||||
<!-- <Many2XAutocomplete t-props="Many2XAutocompleteProps"/>-->
|
||||
<!-- <t t-if="hasExternalButton">-->
|
||||
<!-- <button-->
|
||||
<!-- type="button"-->
|
||||
<!-- class="btn btn-secondary fa o_external_button"-->
|
||||
<!-- t-att-class="props.openTarget === 'current' ? 'fa-arrow-right' : 'fa-external-link'"-->
|
||||
<!-- tabindex="-1"-->
|
||||
<!-- draggable="false"-->
|
||||
<!-- aria-label="Internal link"-->
|
||||
<!-- data-tooltip="Internal link"-->
|
||||
<!-- t-on-click="onExternalBtnClick"-->
|
||||
<!-- />-->
|
||||
<!-- </t>-->
|
||||
<!-- <button-->
|
||||
<!-- t-if="hasBarcodeButton"-->
|
||||
<!-- t-on-click="onBarcodeBtnClick"-->
|
||||
<!-- type="button"-->
|
||||
<!-- class="btn ms-3 o_barcode"-->
|
||||
<!-- tabindex="-1"-->
|
||||
<!-- draggable="false"-->
|
||||
<!-- aria-label="Scan barcode"-->
|
||||
<!-- title="Scan barcode"-->
|
||||
<!-- data-tooltip="Scan barcode"-->
|
||||
<!-- />-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="o_field_many2one_extra">-->
|
||||
<!-- <t t-foreach="extraLines" t-as="extraLine" t-key="extraLine_index">-->
|
||||
<!-- <br t-if="!extraLine_first" />-->
|
||||
<!-- <span t-esc="extraLine" />-->
|
||||
<!-- </t>-->
|
||||
<!-- </div>-->
|
||||
<!-- </t>-->
|
||||
<!-- </t>-->
|
||||
|
||||
</templates>
|
||||
10
sf_machine_connect/static/src/xml/Flush.xml
Normal file
10
sf_machine_connect/static/src/xml/Flush.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="owl_demo.PartnerOrderSummary2" owl="1">
|
||||
<div class="row" style="padding-top: 20px;">
|
||||
<p>
|
||||
显示累加字符串:aaaaaabbb
|
||||
</p>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
27
sf_machine_connect/static/src/xml/MyComponent.xml
Normal file
27
sf_machine_connect/static/src/xml/MyComponent.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="owl_demo.MyComponent1" owl="1">
|
||||
<div class="container">
|
||||
<div class="jumbotron">
|
||||
<h1>欢迎登陆页面!</h1>
|
||||
<p>这是一个超大屏幕(Jumbotron)的实例。</p>
|
||||
<p><a class="btn btn-primary btn-lg" role="button">
|
||||
学习更多</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="bg-info text-center p-2">-->
|
||||
<!-- <i class="fa fa-arrow-left p-1 left"-->
|
||||
<!-- style="cursor: pointer;"-->
|
||||
<!-- t-on-click="onPrevious"> </i>-->
|
||||
<!-- <b t-esc="messageList[Math.abs(-->
|
||||
<!-- state.currentIndex%4)]"/>-->
|
||||
<!-- <i class="fa fa-arrow-right p-1 right"-->
|
||||
<!-- style="cursor: pointer;"-->
|
||||
<!-- t-on-click="onNext"> </i>-->
|
||||
<!-- <i class="fa fa-close p-1 float-right"-->
|
||||
<!-- style="cursor: pointer;"-->
|
||||
<!-- t-on-click="onRemove"> </i>-->
|
||||
<!-- </div>-->
|
||||
</t>
|
||||
</templates>
|
||||
4
sf_machine_connect/static/src/xml/MyWidget.xml
Normal file
4
sf_machine_connect/static/src/xml/MyWidget.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates>
|
||||
|
||||
</templates>
|
||||
32
sf_machine_connect/static/src/xml/PartnerOrderSummary2.xml
Normal file
32
sf_machine_connect/static/src/xml/PartnerOrderSummary2.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="sf_machine_connect.PartnerOrderSummary2" owl="1">
|
||||
<!-- <div class="row" style="padding-top: 20px;">-->
|
||||
<div style="padding-top: 20px;">
|
||||
|
||||
<button
|
||||
t-on-click="onBarcodeBtnClick"
|
||||
type="button"
|
||||
class="btn ms-3 o_barcode"
|
||||
tabindex="-1"
|
||||
draggable="false"
|
||||
aria-label="Scan barcode"
|
||||
title="Scan barcode"
|
||||
data-tooltip="Scan barcode"
|
||||
>扫码</button>
|
||||
|
||||
|
||||
<!-- <div class="o_barcode_mobile_container">-->
|
||||
<!-- <a role="button" class="btn btn-primary o_mobile_barcode">-->
|
||||
<!-- <i class="fa fa-camera fa-2x o_barcode_mobile_camera"/>-->
|
||||
<!-- Tap to scan-->
|
||||
<!-- </a>-->
|
||||
<!--<!– <img src="/barcodes/static/img/barcode.png" alt="Barcode"/>–>-->
|
||||
<!-- <span class="o_barcode_laser"/>-->
|
||||
<!-- </div>-->
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</t>
|
||||
</templates>
|
||||
15
sf_machine_connect/static/src/xml/barcodes.xml
Normal file
15
sf_machine_connect/static/src/xml/barcodes.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="mobile_barcode_template">
|
||||
<div class="o_barcode_mobile_container">
|
||||
<a role="button" class="btn btn-primary o_mobile_barcode">
|
||||
<i class="fa fa-camera fa-2x o_barcode_mobile_camera"/>
|
||||
Tap to scan
|
||||
</a>
|
||||
<img src="/barcodes/static/img/barcode.png" alt="Barcode"/>
|
||||
<span class="o_barcode_laser"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates>
|
||||
<div t-name="iot.scan_progress_template">
|
||||
<h4>Range(s) to scan</h4>
|
||||
<ul class="scan_ranges list-group mb-2"/>
|
||||
<div class="input-group mb-4">
|
||||
<input type="text" name="add_scan_range_ip" class="add_scan_range_ip form-control" placeholder="Scan another range, e.g.: 10.1.1.*"/>
|
||||
<a role="button" class="add_scan_range btn btn-primary" tabindex="-1">Add</a>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<h4 class="scan_network"></h4>
|
||||
<h4 class="iot_box_found"></h4>
|
||||
<ul class="found_devices list-group"/>
|
||||
</div>
|
||||
</div>
|
||||
</templates>
|
||||
20
sf_machine_connect/static/src/xml/many2one_field.xml
Normal file
20
sf_machine_connect/static/src/xml/many2one_field.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="sf_machine_connect.CodeField" owl="1">
|
||||
<div class="o_field_many2one_selection">
|
||||
<button
|
||||
t-on-click="onBarcodeBtnClick"
|
||||
type="button"
|
||||
class="btn ms-3 o_barcode"
|
||||
tabindex="-1"
|
||||
draggable="false"
|
||||
aria-label="Scan barcode"
|
||||
title="Scan barcode"
|
||||
data-tooltip="Scan barcode"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
17
sf_machine_connect/static/src/xml/stack.xml
Normal file
17
sf_machine_connect/static/src/xml/stack.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" >
|
||||
<t t-extend="stock_barcode_lines_template">
|
||||
<t t-jquery="div[class='o_barcode_line list-group-item d-flex flex-row flex-nowrap']"
|
||||
t-operation="append">
|
||||
<div class="o_barcode_pic position-relative text-center mt-2 mb-1">
|
||||
<i class="fa fa-5x mx-auto fa-exclamation-triangle text-white d-none"/>
|
||||
<img class="o_barcode_icon" src="/stock_barcode/static/img/barcode.svg" alt="Barcode" height="40px"/>
|
||||
<!-- <t t-if='widget.mobileMethods.scanBarcode'> -->
|
||||
|
||||
<div class="o_stock_mobile_barcode"/> <!-- Used to open the device scanner -->
|
||||
<span> Tap to scan</span>
|
||||
<!-- </t> -->
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
||||
15
sf_machine_connect/views/SfWorkOrderBarcodes.xml
Normal file
15
sf_machine_connect/views/SfWorkOrderBarcodes.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="sf_install_the_tray_workorder_form_view__scan_barcode" model="ir.ui.view">
|
||||
<field name="name">sf.install.the.tray.workorder.form.scan.barcode</field>
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group//field[@name='processing_panel']" position="after">
|
||||
<!-- invisible="1" -->
|
||||
<field name="_barcode_scanned" widget="barcode_handler" string="扫码" attrs='{"invisible": [("routing_type","!=","装夹")]}'/>
|
||||
</xpath>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
18
sf_machine_connect/views/Stock_picking_Barcodes.xml
Normal file
18
sf_machine_connect/views/Stock_picking_Barcodes.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="stock_picking_form_vieww_scan_barcode_search" model="ir.ui.view">
|
||||
<field name="name">stock.picking.search</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_internal_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='name']" position="before">
|
||||
<!-- <field name="tray_code" filter_domain="[('production_id.tray_ids.code','=',self)]"/>-->
|
||||
<field name="origin"/>
|
||||
</xpath>
|
||||
<!-- <xpath expr="//search//group//filter[@name='product']" position="before">-->
|
||||
<!-- <filter string="Tray code" name="traycode" domain="[]" context="{'group_by': 'tray_code'}"/>-->
|
||||
<!-- </xpath>-->
|
||||
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
20
sf_machine_connect/views/WorkCenterBarcodes.xml
Normal file
20
sf_machine_connect/views/WorkCenterBarcodes.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="workcenter_form_vieww_scan_barcode_search" model="ir.ui.view">
|
||||
<field name="name">work.order.search</field>
|
||||
<!-- <field name="model">mrp.workcenter</field>-->
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="inherit_id" ref="mrp.view_mrp_production_work_order_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='production_id']" position="before">
|
||||
<!-- <field name="name" filter_domain="['|', '|', ('明确的字段内容', 'ilike', self), ('shortdesc', 'ilike', self), ('name', 'ilike', self)]" string="Theme"/>-->
|
||||
<field name="tray_code" filter_domain="[('production_id.tray_ids.code','=',self)]"/>
|
||||
<!-- <field name="production_id"/>-->
|
||||
</xpath>
|
||||
<!-- <xpath expr="//search//group//filter[@name='product']" position="before">-->
|
||||
<!-- <filter string="Tray code" name="traycode" domain="[]" context="{'group_by': 'tray_code'}"/>-->
|
||||
<!-- </xpath>-->
|
||||
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
42
sf_machine_connect/views/compensation.xml
Normal file
42
sf_machine_connect/views/compensation.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="compensation_view" model="ir.ui.view">
|
||||
<field name="name">compensation</field>
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page//field[@name='cnc_ids']" position="before">
|
||||
<group>
|
||||
<group>
|
||||
<field name="compensation_value_x"/>
|
||||
<field name="compensation_value_y"/>
|
||||
</group>
|
||||
<div>
|
||||
<div>
|
||||
<field name="button_compensation_state" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
<button string="一键补偿" name="compensation" type="object" confirm="是否确认下发补偿"
|
||||
class="btn-primary" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
<span> </span>
|
||||
<!-- <field name="button_up_all_state" attrs='{"invisible": ["|",-->
|
||||
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
|
||||
<button string="一键下发" name="up_all" type="object" style="text-align: right;" confirm="是否确认一键下发"
|
||||
class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
<span> </span>
|
||||
<button string="合并下发" id="action_up_select" name="%(sf_machine_connect.action_up_select)d"
|
||||
type="action" class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
<span> </span>
|
||||
<button string="一键合并下发" name="up_merge_all" type="object" style="text-align: right;" confirm="是否确认一键合并下发"
|
||||
class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
</xpath>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
51
sf_machine_connect/views/default_delivery.xml
Normal file
51
sf_machine_connect/views/default_delivery.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- 缺省sf.cnc.processing视图 -->
|
||||
<record id="sf_cnc_processing_tree" model="ir.ui.view">
|
||||
<field name="name">sf.cnc.processing.tree</field>
|
||||
<field name="model">sf.cnc.processing</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="sequence_number"/>
|
||||
<field name="program_name"/>
|
||||
<field name="cnc_id" string="文件"/>
|
||||
<field name="cutting_tool_name"/>
|
||||
<field name="cutting_tool_no"/>
|
||||
<field name="processing_type"/>
|
||||
<field name="margin_x_y"/>
|
||||
<field name="margin_z"/>
|
||||
<field name="depth_of_processing_z"/>
|
||||
<field name="cutting_tool_extension_length"/>
|
||||
<field name="cutting_tool_handle_type"/>
|
||||
<field name="estimated_processing_time"/>
|
||||
<field name="remark"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="delivery_tree" model="ir.ui.view">
|
||||
<field name="name">delivery.record.tree</field>
|
||||
<field name="model">delivery.record</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="delivery_type"/>
|
||||
<field name="delivery_time"/>
|
||||
<field name="influence_record"/>
|
||||
</tree>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
<record id="delivery_form" model="ir.ui.view">
|
||||
<field name="name">delivery.record.form</field>
|
||||
<field name="model">delivery.record</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<field name="delivery_type"/>
|
||||
<field name="delivery_time"/>
|
||||
<field name="influence_record"/>
|
||||
</form>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
32
sf_machine_connect/views/delivery_record.xml
Normal file
32
sf_machine_connect/views/delivery_record.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="view_delivery_record_form_inherit_sf" model="ir.ui.view">
|
||||
<field name="name">delivery.record.form.inherit.sf</field>
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[last()-3]" position="before">
|
||||
<!-- <page string="下发记录" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>-->
|
||||
<page string="下发记录" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
|
||||
<field name="delivery_records">
|
||||
<tree create="false">
|
||||
<field name="delivery_type"/>
|
||||
<field name="delivery_time"/>
|
||||
<field name="influence_record"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
||||
|
||||
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<!-- <record id="seqence_b_purchase_order" model='ir.sequence'> -->
|
||||
<!-- <field name='name'>Purchase Order</field> -->
|
||||
<!-- <field name='code'>sf_machine_connect.delivery.record</field> -->
|
||||
<!-- <field name='prefix'>%(year)s%(month)s%(day)s</field> -->
|
||||
<!-- <field name='padding'>5</field> -->
|
||||
<!-- </record> -->
|
||||
|
||||
</odoo>
|
||||
45
sf_machine_connect/views/ftp_button.xml
Normal file
45
sf_machine_connect/views/ftp_button.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="sf_install_the_tray_workorder_form_view_inherit" model="ir.ui.view">
|
||||
<field name="name">sale.order.inherit</field>
|
||||
<field name="model">mrp.workorder</field>
|
||||
<!-- <field name="model">cnc.processing</field>-->
|
||||
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='remark']" position="after">
|
||||
<!-- <button string="测试按钮" name="pri" type="object" class="btn-primary"/>-->
|
||||
<!-- <field name="workorder_id" invisible="1"/>-->
|
||||
<field name="user_permissions" invisible="1"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="button_state" attrs='{"invisible": ["|",("state","!=","progress"),
|
||||
("user_permissions","!=",True)]}' optional="hide"/>
|
||||
<!-- <button string="下发" name="up" type="object" class="btn-primary" confirm="是否确认下发此程序" -->
|
||||
<!-- attrs='{"invisible": ["|",("state","!=","progress"), -->
|
||||
<!-- ("user_permissions","!=",True)]}'/> -->
|
||||
<!-- <button string="下发" name="up" type="object" class="btn-primary" confirm="是否确认下发此程序" context="{'default_cnc_ids': cnc_ids}"/> -->
|
||||
<button string="下发" name="up" type="object" class="btn-primary" confirm="是否确认下发此程序" context="{'default_sf_cnc_processing_id': id}" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
<!-- <button string="下发" name="up" type="object" class="btn-primary" confirm="是否确认下发此程序"-->
|
||||
<!-- />-->
|
||||
|
||||
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<!-- <record id="app_view_quotation_tree" model="ir.ui.view">-->
|
||||
<!-- <field name="name">app.sale.order.form</field>-->
|
||||
<!-- <field name="model">mrp.workorder</field>-->
|
||||
<!-- <field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>-->
|
||||
<!-- <field name="arch" type="xml">-->
|
||||
<!-- <xpath expr="//page//field[@name='cnc_ids']//tree" position="attributes">-->
|
||||
<!-- <attribute name="bg_colors">-->
|
||||
<!--<!– Gold:state in ('sale');LightGreen:state in ('done')–>-->
|
||||
<!-- LightGreen:button_state is ('False')-->
|
||||
<!-- </attribute>-->
|
||||
<!-- </xpath>-->
|
||||
<!-- </field>-->
|
||||
<!-- </record>-->
|
||||
</odoo>
|
||||
|
||||
31
sf_machine_connect/views/machine_info_present.xml
Normal file
31
sf_machine_connect/views/machine_info_present.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="view_machine_info_form_inherit_sf" model="ir.ui.view">
|
||||
<field name="name">machine.info.form.inherit.sf</field>
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[last()-3]" position="before">
|
||||
<page string="机床信息" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
|
||||
<group string="机床信息">
|
||||
<field name="machine_tool_name"/>
|
||||
<field name="machine_tool_type_id"/>
|
||||
<field name="machine_tool_machine_ip"/>
|
||||
</group>
|
||||
<group string="运行信息">
|
||||
<field name="machine_tool_timestamp"/>
|
||||
<field name="machine_tool_status"/>
|
||||
<field name="machine_tool_run_status"/>
|
||||
<field name="machine_tool_time_on"/>
|
||||
|
||||
<field name="machine_tool_tool_num"/>
|
||||
<field name="machine_tool_program"/>
|
||||
<field name="machine_tool_cut_status"/>
|
||||
<field name="machine_tool_compensation_value_x"/>
|
||||
<field name="machine_tool_compensation_value_y"/>
|
||||
</group>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
201
sf_machine_connect/views/machine_monitor.xml
Normal file
201
sf_machine_connect/views/machine_monitor.xml
Normal file
@@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_tree_mrs_machine_tool_inherited" model="ir.ui.view">
|
||||
<field name="name">sf_base_extension</field>
|
||||
<field name="model">sf.machine_tool</field>
|
||||
<field name="inherit_id" ref="sf_base.sf_machine_tool_form"/>
|
||||
<field eval="20" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- <xpath expr="//field[@name='knife_type']" position="before">-->
|
||||
<xpath expr="//form//notebook//page[1]" position="inside">
|
||||
<!-- <xpath expr="//page[@name='other']" position="before">-->
|
||||
<notebook>
|
||||
<page string="机床监控">
|
||||
<!-- <group string="监控">-->
|
||||
<group col='12'>
|
||||
<field name="timestamp"/>
|
||||
<field name="signed"/>
|
||||
<field name="status"/>
|
||||
<field name="time_on"/>
|
||||
<field name="time_on_now"/>
|
||||
<field name="run_status"/>
|
||||
<field name="run_time"/>
|
||||
<field name="cut_status"/>
|
||||
<!-- <field name="cut_time"/>-->
|
||||
<field name="program"/>
|
||||
<field name="tool_num"/>
|
||||
<field name="spindle_speed"/>
|
||||
|
||||
</group>
|
||||
<group string='刀位统计' col='8'>
|
||||
<field name="tool_num_process_time1"/>
|
||||
<field name="tool_num_process_time2"/>
|
||||
<field name="tool_num_process_time3"/>
|
||||
<field name="tool_num_process_time4"/>
|
||||
<field name="tool_num_process_time5"/>
|
||||
<field name="tool_num_process_time6"/>
|
||||
<field name="tool_num_process_time7"/>
|
||||
<field name="tool_num_process_time8"/>
|
||||
<field name="tool_num_process_time9"/>
|
||||
<field name="tool_num_process_time10"/>
|
||||
<field name="tool_num_process_time11"/>
|
||||
<field name="tool_num_process_time12"/>
|
||||
<field name="tool_num_process_time13"/>
|
||||
<field name="tool_num_process_time14"/>
|
||||
<field name="tool_num_process_time15"/>
|
||||
<field name="tool_num_process_time16"/>
|
||||
<field name="tool_num_process_time17"/>
|
||||
<field name="tool_num_process_time18"/>
|
||||
<field name="tool_num_process_time19"/>
|
||||
<field name="tool_num_process_time20"/>
|
||||
<field name="tool_num_process_time21"/>
|
||||
<field name="tool_num_process_time22"/>
|
||||
<field name="tool_num_process_time23"/>
|
||||
<field name="tool_num_process_time24"/>
|
||||
|
||||
<!-- <div class="o_address_format"> -->
|
||||
<!-- <label for="tool_num_process_time1" string="刀位1"/> -->
|
||||
<!-- <field name="tool_num_process_time1" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time2" string="刀位2"/> -->
|
||||
<!-- <field name="tool_num_process_time2" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time3" string="刀位3"/> -->
|
||||
<!-- <field name="tool_num_process_time3" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time4" string="刀位4"/> -->
|
||||
<!-- <field name="tool_num_process_time4" class="o_form_label"/> -->
|
||||
<!-- <div></div> -->
|
||||
<!-- <label for="tool_num_process_time5" string="刀位5"/> -->
|
||||
<!-- <field name="tool_num_process_time5" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time6" string="刀位6"/> -->
|
||||
<!-- <field name="tool_num_process_time6" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time7" string="刀位7"/> -->
|
||||
<!-- <field name="tool_num_process_time7" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time8" string="刀位8"/> -->
|
||||
<!-- <field name="tool_num_process_time8" class="o_form_label"/> -->
|
||||
<!-- <div></div> -->
|
||||
<!-- <label for="tool_num_process_time9" string="刀位9"/> -->
|
||||
<!-- <field name="tool_num_process_time9" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time10" string="刀位10"/> -->
|
||||
<!-- <field name="tool_num_process_time10" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time11" string="刀位11"/> -->
|
||||
<!-- <field name="tool_num_process_time11" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time12" string="刀位12"/> -->
|
||||
<!-- <field name="tool_num_process_time12" class="o_form_label"/> -->
|
||||
<!-- <div></div> -->
|
||||
<!-- <label for="tool_num_process_time13" string="刀位13"/> -->
|
||||
<!-- <field name="tool_num_process_time13" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time14" string="刀位14"/> -->
|
||||
<!-- <field name="tool_num_process_time14" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time15" string="刀位15"/> -->
|
||||
<!-- <field name="tool_num_process_time15" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time16" string="刀位16"/> -->
|
||||
<!-- <field name="tool_num_process_time16" class="o_form_label"/> -->
|
||||
<!-- <div></div> -->
|
||||
<!-- <label for="tool_num_process_time17" string="刀位17"/> -->
|
||||
<!-- <field name="tool_num_process_time17" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time18" string="刀位18"/> -->
|
||||
<!-- <field name="tool_num_process_time18" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time19" string="刀位19"/> -->
|
||||
<!-- <field name="tool_num_process_time19" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time20" string="刀位20"/> -->
|
||||
<!-- <field name="tool_num_process_time20" class="o_form_label"/> -->
|
||||
<!-- <div></div> -->
|
||||
<!-- <label for="tool_num_process_time21" string="刀位21"/> -->
|
||||
<!-- <field name="tool_num_process_time21" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time22" string="刀位22"/> -->
|
||||
<!-- <field name="tool_num_process_time22" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time23" string="刀位23"/> -->
|
||||
<!-- <field name="tool_num_process_time23" class="o_form_label"/> -->
|
||||
<!-- <span>&nbsp;</span> -->
|
||||
<!-- <label for="tool_num_process_time24" string="刀位24"/> -->
|
||||
<!-- <field name="tool_num_process_time24" class="o_form_label"/> -->
|
||||
<!-- </div> -->
|
||||
</group>
|
||||
</page>
|
||||
<page string="机床配置">
|
||||
<!-- <group string="机床配置">-->
|
||||
<group>
|
||||
<group string="ftp相关">
|
||||
<field name="ftp_num"/>
|
||||
<field name="ftp_pwd"/>
|
||||
<field name="ftp_host"/>
|
||||
<field name="ftp_port"/>
|
||||
<field name="ftp_remote_path"/>
|
||||
</group>
|
||||
<group string="补偿值相关">
|
||||
<field name="x_compensation_node"/>
|
||||
<field name="y_compensation_node"/>
|
||||
</group>
|
||||
<group string="数采相关">
|
||||
<field name="machine_ip"/>
|
||||
<field name="machine_signed"/>
|
||||
<field name="machine_status"/>
|
||||
<field name="machine_cnc_type"/>
|
||||
<field name="machine_axis_count"/>
|
||||
<field name="machine_run_status"/>
|
||||
<field name="machine_emg_status"/>
|
||||
<field name="machine_cut_status"/>
|
||||
<field name="machine_mode"/>
|
||||
<field name="machine_spindle_load"/>
|
||||
<field name="machine_x_mach"/>
|
||||
<field name="machine_x_abs_mach"/>
|
||||
<field name="machine_x_rel_mach"/>
|
||||
<field name="machine_x_dis_mach"/>
|
||||
<field name="machine_x_axis_load"/>
|
||||
<field name="machine_y_mach"/>
|
||||
<field name="machine_y_abs_mach"/>
|
||||
<field name="machine_y_rel_mach"/>
|
||||
<field name="machine_y_dis_mach"/>
|
||||
<field name="machine_y_axis_load"/>
|
||||
<field name="machine_z_mach"/>
|
||||
<field name="machine_z_abs_mach"/>
|
||||
<field name="machine_z_rel_mach"/>
|
||||
<field name="machine_z_dis_mach"/>
|
||||
<field name="machine_z_axis_load"/>
|
||||
<field name="machine_tool_num"/>
|
||||
<field name="machine_program"/>
|
||||
<field name="machine_current_prg"/>
|
||||
<field name="machine_prg_seq"/>
|
||||
<field name="machine_spindle_speed_set"/>
|
||||
<field name="machine_act_spindle_speed"/>
|
||||
<field name="machine_feed_speed_set"/>
|
||||
<field name="machine_act_feed_speed"/>
|
||||
<field name="machine_spindle_feed"/>
|
||||
<field name="machine_feed_rate"/>
|
||||
<field name="machine_rapid_feed"/>
|
||||
<field name="machine_run_time"/>
|
||||
<field name="machine_cut_time"/>
|
||||
<field name="machine_keep_alive_time"/>
|
||||
<field name="machine_circle_time"/>
|
||||
<field name="machine_product_counts"/>
|
||||
<field name="machine_system_date"/>
|
||||
<field name="machine_system_time"/>
|
||||
<field name="machine_alarm_msg"/>
|
||||
</group>
|
||||
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
|
||||
|
||||
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
13
sf_machine_connect/views/project_sequence.xml
Normal file
13
sf_machine_connect/views/project_sequence.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<odoo noupdate="1">
|
||||
|
||||
<record id="seq_test" model="ir.sequence">
|
||||
<field name="name">Test</field>
|
||||
<field name="code">sf_machine_connect.delivery.record</field>
|
||||
<field name="prefix">T%(range_year)s</field>
|
||||
<field name="padding">4</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
1
sf_machine_connect/wizard/__init__.py
Normal file
1
sf_machine_connect/wizard/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import action_up
|
||||
113
sf_machine_connect/wizard/action_up.py
Normal file
113
sf_machine_connect/wizard/action_up.py
Normal file
@@ -0,0 +1,113 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import base64
|
||||
import logging
|
||||
import os
|
||||
import json
|
||||
import hashlib
|
||||
import time
|
||||
import requests
|
||||
from datetime import datetime
|
||||
|
||||
from odoo import fields, models, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.addons.sf_machine_connect.models import py2opcua, ftp_operate
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UpSelectWizard(models.TransientModel):
|
||||
_name = 'up.select.wizard'
|
||||
_description = 'Up Select Wizard'
|
||||
|
||||
workorder_id = fields.Many2one('mrp.workorder', string='工单', readonly=True)
|
||||
workcenter_id = fields.Many2one('mrp.workcenter', string='工作中心', related='workorder_id.workcenter_id',
|
||||
readonly=True)
|
||||
program_ids = fields.Many2many('sf.cnc.processing', string='程序列表')
|
||||
|
||||
|
||||
def confirm_up(self):
|
||||
# 合并下发前删除机床上的全部程序
|
||||
try:
|
||||
filepath = '/nc2machine'
|
||||
del_list = os.listdir(filepath)
|
||||
_logger.info("=====================================%s" % del_list)
|
||||
for f in del_list:
|
||||
file_path = os.path.join(filepath, f)
|
||||
if os.path.isfile(file_path):
|
||||
os.remove(file_path)
|
||||
except Exception as e:
|
||||
_logger.info("=====================================", e)
|
||||
raise UserError('程序删除失败,请重试')
|
||||
host = self.workcenter_id.machine_tool_id.ftp_host
|
||||
port = self.workcenter_id.machine_tool_id.ftp_port
|
||||
username = self.workcenter_id.machine_tool_id.ftp_num
|
||||
pwd = self.workcenter_id.machine_tool_id.ftp_pwd
|
||||
remote_path = self.workcenter_id.machine_tool_id.ftp_remote_path
|
||||
print(host, port, username, pwd, remote_path)
|
||||
ftp = ftp_operate.FtpController(host, port, username, pwd)
|
||||
sequence_collect = []
|
||||
file_path_local = ''
|
||||
file_path_remote = ''
|
||||
try:
|
||||
# 给文件名
|
||||
begin_name1 = self.program_ids[0].cnc_id.display_name.split('-')
|
||||
temp_name1 = begin_name1[-1].split('.')
|
||||
final_name = '%s-MERGE.%s' % (begin_name1[0], temp_name1[-1])
|
||||
print(final_name)
|
||||
|
||||
for item in self.program_ids:
|
||||
# print(item.program_name)
|
||||
# print(item.cnc_id)
|
||||
sequence_collect.append(item.sequence_number)
|
||||
a = item.cnc_id
|
||||
print(a.display_name)
|
||||
_logger.info(a.public)
|
||||
_logger.info(a.display_name)
|
||||
datas = base64.standard_b64decode(a.datas)
|
||||
file_path_local = '{}/{}'.format('/nc2machine', final_name)
|
||||
|
||||
# 本地测试合并下发
|
||||
# file_path_local = '{}/{}'.format('D:\\jikimo', a.display_name)
|
||||
# file_path_remote = '{}\{}'.format('//M80(192,168,2,142)//DS', a.display_name)
|
||||
file_path_remote = '{}\{}'.format(remote_path, final_name)
|
||||
# 合并文件
|
||||
with open(file_path_local, mode='ab+') as file:
|
||||
file.write(datas)
|
||||
# 下发成功标识
|
||||
item.button_state = True
|
||||
_logger.info('========初次合并成功===============')
|
||||
_logger.info(file_path_local)
|
||||
# 去除合并文件中间部分的头尾
|
||||
with open(file_path_local, mode='rb+') as f:
|
||||
# _logger.info(f.read())
|
||||
# content = f.read()
|
||||
# _logger.info(content)
|
||||
new_content = f.read().replace(b'\r\nM30\r\n%\r\n%\r\n', b'\r\n')
|
||||
# _logger.info(new_content)
|
||||
f.seek(0)
|
||||
_logger.info(111111111111111111111111111111111111111)
|
||||
f.truncate()
|
||||
_logger.info(2222222222222222222222222)
|
||||
f.write(new_content)
|
||||
_logger.info(3333333333333333333333333)
|
||||
_logger.info('========二次合并成功===============')
|
||||
# 存在本地的文件下发到机床
|
||||
_logger.info("==========存在服务器成功,准备下发===========")
|
||||
ftp.upload_file(remotepath=file_path_remote, localpath=file_path_local)
|
||||
ftp.close_ftp()
|
||||
|
||||
up_time = str(datetime.now())
|
||||
sequence_str = ','.join(sequence_collect)
|
||||
self.workorder_id.delivery_records.create({
|
||||
'delivery_type': '合并下发',
|
||||
'delivery_time': up_time,
|
||||
'influence_record': sequence_str,
|
||||
})
|
||||
_logger.info("==============合并下发成功==============")
|
||||
except Exception as e:
|
||||
for item in self.program_ids:
|
||||
item.button_state = False
|
||||
_logger.info("=====================================", e)
|
||||
raise UserError('NC下发执行超时, 请检查下发状态')
|
||||
|
||||
34
sf_machine_connect/wizard/up_select.xml
Normal file
34
sf_machine_connect/wizard/up_select.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="action_up_select_form" model="ir.ui.view">
|
||||
<field name="name">CNC工单</field>
|
||||
<field name="model">up.select.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group>
|
||||
<field name="workcenter_id"/>
|
||||
<field name="workorder_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="program_ids" widget='many2many_tags' domain="[('workorder_id', '=', workorder_id)]"/>
|
||||
<!-- <field name="program_ids" domain="[('workorder_id', '=', workorder_id)]"/>-->
|
||||
</group>
|
||||
<footer>
|
||||
<button string="合并下发" name="confirm_up" type="object" class="btn-primary" confirm="是否确认合并下发"/>
|
||||
<button string="取消" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_up_select" model="ir.actions.act_window">
|
||||
<field name="name">选择要下发的NC程序</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<!-- <field name="res_model">up.select.wizard</field>-->
|
||||
<field name="res_model">up.select.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="action_up_select_form"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user