using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Documents; using Admin.Core.Common; using Admin.Core.IService; using Admin.Core.Model; using Aucma.Core.HwPLc; using Microsoft.Extensions.DependencyInjection; using NetTaste; namespace Aucma.Core.SheetMetal.Business; /// /// 箱壳计划任务处理 /// public class SheetMetalPlanTaskHandle { /// /// 刷新当前正在执行的计划 /// public delegate void RefreshCurrentPlanInfo(ExecutePlanInfo planInfo); public event RefreshCurrentPlanInfo RefreshCurrentPlanInfoEvent; protected readonly IExecutePlanInfoServices? _executePlanInfoServices; protected readonly IRecordSidePanelComplateServices _sidePanelComplateServices; protected readonly IRecordBackPanelComplateServices _backPanelComplateServices; public HwPLc.PlcModel plc1 = null; public SheetMetalPlanTaskHandle() { _executePlanInfoServices = App.ServiceProvider.GetService(); _sidePanelComplateServices = App.ServiceProvider.GetService(); _backPanelComplateServices = App.ServiceProvider.GetService(); } /// /// 初始化下发生产计划,获取已拆分的计划进行下发 /// public void InitSendPlan() { Thread.Sleep(5000); var obj_sidePanel = PlcHelper.melsecList.FirstOrDefault(d => d.EquipName.Equals("SidePanelPlc")); var obj_backPanel = PlcHelper.melsecList.FirstOrDefault(d => d.EquipName.Equals("BackPanelPLC")); while (true) { var planInfos = _executePlanInfoServices.Query(d => d.ProductLineCode.Equals("1001") && d.ExecuteStatus == 1); if(planInfos != null) { if(planInfos.Count > 0) { ExecutePlanInfo planInfo = planInfos.First(); if(planInfo.PlanType == 1) //联合下发 { SendPlanTask(planInfo,obj_sidePanel,obj_backPanel); UpdatePlanTaskByComplate(planInfo); } else if(planInfo.PlanType == 2) { SendPlanTask_SidePanel(planInfo, obj_sidePanel); UpdatePlanTaskByComplate(planInfo); } else if(planInfo.PlanType == 3) { SendPlanTaskTo_BackPanel(planInfo, obj_backPanel); UpdatePlanTaskByComplate(planInfo); } } else { Console.WriteLine("未获取到需要下发的任务"); } } Thread.Sleep(3000); } } /// /// 根据完成记录更新生产计划 /// /// private void UpdatePlanTaskByComplate(ExecutePlanInfo planInfo) { try { lock (string.Empty) { bool isComplate = true; do { //等待计划执行完成 List sidePanelComplates = _sidePanelComplateServices.Query(x => x.ProductlineCode == "1001" && x.PlanCode == planInfo.TaskCode); int sumSidePanelAmount = sidePanelComplates.Sum(x => x.OutPutAmount); List backPanelComplates = _backPanelComplateServices.Query(x => x.ProductlineCode == "1001" && x.PlanCode == planInfo.TaskCode); int sumBackPanelAmount = backPanelComplates.Sum(x => x.OutPutAmount); Console.WriteLine($"当前计划:{planInfo.TaskCode};计划产量:{planInfo.PlanAmount};围板完成:{sumSidePanelAmount};背板完成:{sumBackPanelAmount}"); int sumAmount = 0; if(planInfo.PlanType == 1) { if (sumSidePanelAmount >= sumBackPanelAmount) { sumAmount = sumBackPanelAmount; } else { sumAmount = sumSidePanelAmount; } }else if(planInfo.PlanType == 2) { sumAmount = sumSidePanelAmount; } else { sumAmount = sumBackPanelAmount; } if (planInfo.PlanAmount - sumAmount == 0) { planInfo.ExecuteStatus = 3; isComplate = false; } planInfo.CompleteAmount = sumAmount; _executePlanInfoServices.UpdateExecutePlanInfo(planInfo); Thread.Sleep(5000); } while (isComplate); } }catch(Exception ex) { Console.WriteLine($"计划任务信息更新异常:{ex.Message}"); } } /// /// 联合下发 /// /// /// /// private void SendPlanTask(ExecutePlanInfo planInfo, PlcModel obj_sidePanel,PlcModel obj_backPanel) { try { Task.Run(() => { if (obj_sidePanel != null) { //计划编号10个字:D6000-D6009、物料编号10个字:D6010-D6019、计划数量1个字:D6020、应答字1个字D6021 obj_sidePanel.plc.WriteString("D6030", planInfo.TaskCode); string processNumber = GetProcessNumberBy(planInfo.MaterialCode); obj_sidePanel.plc.WriteString("D6010", "BCD/310NF"); obj_sidePanel.plc.WriteInt32("D6020", planInfo.PlanAmount); obj_sidePanel.plc.WriteInt32("D6021", 1); Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>等待围板设备应答。。。。。。"); //下发完成后读取PLC应答,应答后复位应答信号 #region PLC反馈信号逻辑处理 //循环读取PLC应答信号,PLC应答后复位应答信号、更新计划状态为执行中 bool isFlag = true; do { if (obj_sidePanel.plc.ReadInt32("D6021") == 2) { obj_sidePanel.plc.WriteInt32("D6021", 0); Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>收到围板设备应答信号,复位应答地址"); isFlag = false; } Thread.Sleep(2000); } while (isFlag); //更新计划状态为2执行中 planInfo.ExecuteStatus = 2; _executePlanInfoServices.UpdateExecutePlanInfo(planInfo); RefreshCurrentPlanInfoEvent?.Invoke(planInfo); #endregion //读取设备进度,完成后再次下发新任务 ReadDeviceComplate_SidePanel(obj_sidePanel); } }); Task.Run(() => { if (obj_backPanel != null) { //计划编号10个字:D6000-D6009、物料编号10个字:D6010-D6019、计划数量1个字:D6020、应答字1个字D6021 obj_backPanel.plc.WriteString("D6030", planInfo.TaskCode); string processNumber = GetProcessNumberBy(planInfo.MaterialCode); obj_backPanel.plc.WriteString("D6010", "BCD/310NF"); obj_backPanel.plc.WriteInt32("D6020", planInfo.PlanAmount); obj_backPanel.plc.WriteInt32("D6021", 1); Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>等待背板设备应答。。。。。。"); #region PLC反馈信号逻辑处理 //循环读取PLC应答信号,PLC应答后复位应答信号、更新计划状态为执行中 bool isFlag = true; do { if (obj_backPanel.plc.ReadInt32("D6021") == 2) { obj_backPanel.plc.WriteInt32("D6021", 0); Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>收到背板板设备应答信号,复位应答地址"); isFlag = false; } Thread.Sleep(2000); } while (isFlag); //更新计划状态为2执行中 planInfo.ExecuteStatus = 2; _executePlanInfoServices.UpdateExecutePlanInfo(planInfo); RefreshCurrentPlanInfoEvent?.Invoke(planInfo); #endregion //读取设备进度,完成后再次下发新任务 ReadDeviceComplate_BackPanel(obj_backPanel); } }); } catch (Exception ex) { MessageBox.Show($"围板⽣产计划下发异常:{ex.Message}", "提示", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly); } } /// /// 下发围板生产计划 /// /// /// public void SendPlanTask_SidePanel(ExecutePlanInfo planInfo, PlcModel obj_sidePanel) { try { Task.Run(() => { if (obj_sidePanel != null) { //计划编号10个字:D6000-D6009、物料编号10个字:D6010-D6019、计划数量1个字:D6020、应答字1个字D6021 obj_sidePanel.plc.WriteString("D6030", planInfo.TaskCode); string processNumber = GetProcessNumberBy(planInfo.MaterialCode); obj_sidePanel.plc.WriteString("D6010", "BCD/310NF"); obj_sidePanel.plc.WriteInt32("D6020", planInfo.PlanAmount); obj_sidePanel.plc.WriteInt32("D6021", 1); Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>等待围板设备应答。。。。。。"); //下发完成后读取PLC应答,应答后复位应答信号 #region PLC反馈信号逻辑处理 //循环读取PLC应答信号,PLC应答后复位应答信号、更新计划状态为执行中 bool isFlag = true; do { if (obj_sidePanel.plc.ReadInt32("D6021") == 2) { obj_sidePanel.plc.WriteInt32("D6021", 0); Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>收到围板设备应答信号,复位应答地址"); isFlag = false; } Thread.Sleep(2000); } while (isFlag); //更新计划状态为2执行中 planInfo.ExecuteStatus = 2; _executePlanInfoServices.UpdateExecutePlanInfo(planInfo); RefreshCurrentPlanInfoEvent?.Invoke(planInfo); #endregion //读取设备进度,完成后再次下发新任务 ReadDeviceComplate_SidePanel(obj_sidePanel); } }); } catch (Exception ex) { MessageBox.Show($"围板⽣产计划下发异常:{ex.Message}", "提示", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly); } } /// /// 读取围板生产数据 /// /// public void ReadDeviceComplate_SidePanel(PlcModel obj) { bool isFlag = true; try { do { //D6030 //计划编号:D6030-D6039,物料编号:D6040-D6049,计划完成数:D6050,计划下线数:D6051,设备状态:D6052-D6056,生产节拍:D6057-D6058 byte[] info = obj.plc.Read("D6030", 59); if(info == null) { Thread.Sleep(1000); continue; } //计划编号 string planCode = Encoding.ASCII.GetString(info.Skip(0).Take(20).ToArray()); //物料编号 string materialCode = Encoding.ASCII.GetString(info.Skip(20).Take(20).ToArray()); //完成数量 int complateAmount = short.Parse(bytesToHexStr(info.Skip(40).Take(1).ToArray(), 1), System.Globalization.NumberStyles.HexNumber); //下线数量 int offLineAmount = short.Parse(bytesToHexStr(info.Skip(41).Take(2).ToArray(), 2), System.Globalization.NumberStyles.HexNumber); //设备状态 int deviceStatus = short.Parse(bytesToHexStr(info.Skip(43).Take(2).ToArray(), 2), System.Globalization.NumberStyles.HexNumber); //生产节拍 int productionBeat = short.Parse(bytesToHexStr(info.Skip(51).Take(4).ToArray(), 4), System.Globalization.NumberStyles.HexNumber); Console.WriteLine($"围板设备数据读取====>>>>当前计划:{planCode},物料编号:{materialCode},完成数量:{complateAmount},下线数量:{offLineAmount},设备状态:{deviceStatus},生产节拍:{productionBeat}"); //添加完工记录 RecordSidePanelComplate sidePanelComplate = new RecordSidePanelComplate() { ProductlineCode = "1001", PlanCode = planCode.Substring(0, 16), //MaterialCode = string.IsNullOrEmpty(materialCode) ? "" : materialCode, MaterialCode = "BCD/310NF", CompleteAmount = complateAmount, OffLineAmount = offLineAmount, DeviceStatus = deviceStatus, ProductionBeat = productionBeat, RecordTime = DateTime.Now, IsFlag = 1 }; if(string.IsNullOrEmpty(planCode)) { Thread.Sleep(5000); continue; } //先查询该计划编号下的前一条完工记录,如果不存在本条记录产量为0 List sidePanelComplates = _sidePanelComplateServices.Query(x => x.ProductlineCode == "1001" && x.PlanCode == planCode.Substring(0, 16)); int lastComplateAmount = 0; //前一条完成记录的计划完成数量 int sumComplateAmount = 0; //当前计划总产量 if (sidePanelComplates != null) { if (sidePanelComplates.Count > 0) { sidePanelComplates = sidePanelComplates.OrderByDescending(x => x.RecordTime).ToList(); lastComplateAmount = sidePanelComplates.First().CompleteAmount; sidePanelComplate.OutPutAmount = complateAmount - lastComplateAmount; sumComplateAmount = sidePanelComplates.Sum(x => x.OutPutAmount) + sidePanelComplate.OutPutAmount; if (sidePanelComplate.OutPutAmount == 0) { Thread.Sleep(5000); continue; } else { List planInfos = _executePlanInfoServices.Query(x => x.TaskCode.Equals(planCode.Substring(0, 16)) && x.ExecuteStatus == 2); if(planInfos != null) { if(planInfos.Count > 0) { ExecutePlanInfo planInfo = planInfos.First(); if (planInfo != null) { if (planInfo.PlanAmount - sumComplateAmount == 0) { isFlag = false; Console.WriteLine($"围板计划执行完成,计划数量:{planInfo.PlanAmount};实际产量:{sumComplateAmount};差异值:{planInfo.PlanAmount - sumComplateAmount}"); } } } } } } } _sidePanelComplateServices.InsertSidePanelCimplate(sidePanelComplate); Thread.Sleep(5000); } while (isFlag); } catch (Exception e) { Console.WriteLine($"读取围板设备完成数据异常:{e.Message}"); } } /// /// 下发背板生产计划 /// /// /// public void SendPlanTaskTo_BackPanel(ExecutePlanInfo planInfo, PlcModel obj_backPanel) { try { Task.Run(() => { if (obj_backPanel != null) { //计划编号10个字:D6000-D6009、物料编号10个字:D6010-D6019、计划数量1个字:D6020、应答字1个字D6021 obj_backPanel.plc.WriteString("D6030", planInfo.TaskCode); string processNumber = GetProcessNumberBy(planInfo.MaterialCode); obj_backPanel.plc.WriteString("D6010", "BCD/310NF"); obj_backPanel.plc.WriteInt32("D6020", planInfo.PlanAmount); obj_backPanel.plc.WriteInt32("D6021", 1); Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>等待背板设备应答。。。。。。"); #region PLC反馈信号逻辑处理 //循环读取PLC应答信号,PLC应答后复位应答信号、更新计划状态为执行中 bool isFlag = true; do { if (obj_backPanel.plc.ReadInt32("D6021") == 2) { obj_backPanel.plc.WriteInt32("D6021", 0); Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>收到背板板设备应答信号,复位应答地址"); isFlag = false; } Thread.Sleep(2000); } while (isFlag); //更新计划状态为2执行中 planInfo.ExecuteStatus = 2; _executePlanInfoServices.UpdateExecutePlanInfo(planInfo); RefreshCurrentPlanInfoEvent?.Invoke(planInfo); #endregion //读取设备进度,完成后再次下发新任务 ReadDeviceComplate_BackPanel(obj_backPanel); } }); } catch (Exception ex) { MessageBox.Show($"背板⽣产计划下发异常:{ex.Message}", "提示", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly); } } /// /// 读取背板生产数据 /// /// public void ReadDeviceComplate_BackPanel(PlcModel obj) { bool isFlag = true; try { do { //计划编号:D6030-D6039,物料编号:D6040-D6049,计划完成数:D6050,计划下线数:D6051,设备状态:D6052-D6056,生产节拍:D6057-D6058 byte[] info = obj.plc.Read("D6030", 59); if (info == null) { Thread.Sleep(1000); continue; } //计划编号 string planCode = Encoding.ASCII.GetString(info.Skip(0).Take(20).ToArray()); //物料编号 string materialCode = Encoding.ASCII.GetString(info.Skip(20).Take(20).ToArray()); //完成数量 int complateAmount = short.Parse(bytesToHexStr(info.Skip(40).Take(1).ToArray(), 1), System.Globalization.NumberStyles.HexNumber); //下线数量 int offLineAmount = short.Parse(bytesToHexStr(info.Skip(41).Take(2).ToArray(), 2), System.Globalization.NumberStyles.HexNumber); //设备状态 int deviceStatus = short.Parse(bytesToHexStr(info.Skip(43).Take(2).ToArray(), 2), System.Globalization.NumberStyles.HexNumber); //生产节拍 int productionBeat = short.Parse(bytesToHexStr(info.Skip(51).Take(4).ToArray(), 4), System.Globalization.NumberStyles.HexNumber); Console.WriteLine($"背板设备数据读取====>>>>当前计划:{planCode},物料编号:{materialCode},完成数量:{complateAmount},下线数量:{offLineAmount},设备状态:{deviceStatus},生产节拍:{productionBeat}"); //添加完工记录 RecordBackPanelComplate backPanelComplate = new RecordBackPanelComplate() { ProductlineCode = "1001", PlanCode = planCode.Substring(0, 16), //MaterialCode = string.IsNullOrEmpty(materialCode) ? "" : materialCode, MaterialCode = "BCD/310NF", CompleteAmount = complateAmount, OffLineAmount = offLineAmount, DeviceStatus = deviceStatus, ProductionBeat = productionBeat, RecordTime = DateTime.Now, IsFlag = 1 }; if (string.IsNullOrEmpty(planCode)) { Thread.Sleep(5000); continue; } //先查询该计划编号下的前一条完工记录,如果不存在本条记录产量为0 List backPanelComplates = _backPanelComplateServices.Query(x => x.ProductlineCode == "1001" && x.PlanCode == planCode.Substring(0, 16)); int lastComplateAmount = 0; //前一条完成记录的计划完成数量 int sumComplateAmount = 0; //当前计划总产量 if (backPanelComplates != null) { if (backPanelComplates.Count > 0) { backPanelComplates = backPanelComplates.OrderByDescending(x => x.RecordTime).ToList(); lastComplateAmount = backPanelComplates.First().CompleteAmount; backPanelComplate.OutPutAmount = complateAmount - lastComplateAmount; sumComplateAmount = backPanelComplates.Sum(x => x.OutPutAmount) + backPanelComplate.OutPutAmount; if (backPanelComplate.OutPutAmount == 0) { Thread.Sleep(5000); continue; } else { List planInfos = _executePlanInfoServices.Query(x => x.TaskCode == planCode.Substring(0, 16) && x.ExecuteStatus == 2); if (planInfos != null) { if(planInfos.Count > 0) { ExecutePlanInfo planInfo = planInfos.First(); if (planInfo != null) { if (planInfo.PlanAmount - sumComplateAmount == 0) { isFlag = false; Console.WriteLine($"背板计划执行完成,计划数量:{planInfo.PlanAmount};实际产量:{sumComplateAmount};差异值:{planInfo.PlanAmount - sumComplateAmount}"); } } } } } } } _backPanelComplateServices.InsertBackPanelCimplate(backPanelComplate); Thread.Sleep(5000); } while (isFlag); } catch (Exception e) { Console.WriteLine($"读取背板设备完成数据异常:{e.Message}"); } } /// /// 通过物料编号获取工艺编号 /// /// /// private string GetProcessNumberBy(string materialCode) { return System.Guid.NewGuid().ToString("N").Substring(0,20); } public static string bytesToHexStr(byte[] bytes, int iLen)//e.g. { 0x01, 0x01} ---> " 01 01" { string returnStr = ""; if (bytes != null) { for (int i = 0; i < iLen; i++) { returnStr += bytes[i].ToString("X2"); } } return returnStr; } }