You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AUCMA_SCADA/Aucma.Core.SheetMetal/Business/SheetMetalPlanTaskHandle.cs

406 lines
19 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
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;
namespace Aucma.Core.SheetMetal.Business;
/// <summary>
/// 箱壳计划任务处理
/// </summary>
public class SheetMetalPlanTaskHandle
{
/// <summary>
/// 刷新当前正在执行的计划
/// </summary>
public delegate void RefreshCurrentPlanInfo(ExecutePlanInfo planInfo);
public event RefreshCurrentPlanInfo RefreshCurrentPlanInfoEvent;
protected readonly IExecutePlanInfoServices? _executePlanInfoServices;
protected readonly IRecordSidePanelComplateServices _sidePanelComplateServices;
public HwPLc.PlcModel plc1 = null;
public SheetMetalPlanTaskHandle()
{
_executePlanInfoServices =
App.ServiceProvider.GetService<IExecutePlanInfoServices>();
_sidePanelComplateServices = App.ServiceProvider.GetService<IRecordSidePanelComplateServices>();
}
/// <summary>
/// 下发围板生产计划
/// </summary>
/// <param name="planInfo"></param>
/// <param name="obj"></param>
public void SendPlanTask_WB(ExecutePlanInfo planInfo, PlcModel obj)
{
Thread.Sleep(5000);
try
{
lock (string.Empty)
{
if (obj != null)
{
//计划编号10个字D6000-D6009、物料编号10个字D6010-D6019、计划数量1个字D6020、应答字1个字D6021
obj.plc.WriteString("D6000", planInfo.TaskCode);
string processNumber = GetProcessNumberBy(planInfo.MaterialCode);
obj.plc.WriteString("D6010", "BCD/310NF");
obj.plc.WriteInt32("D6020", planInfo.PlanAmount);
obj.plc.WriteInt32("D6021", 1);
Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>等待围板设备应答。。。。。。");
//下发完成后读取PLC应答应答后复位应答信号
#region PLC反馈信号逻辑处理
//循环读取PLC应答信号PLC应答后复位应答信号、更新计划状态为执行中
bool isFlag = true;
do
{
if (obj.plc.ReadInt32("D6021") == 2)
{
obj.plc.WriteInt32("D6021", 0);
Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>收到围板设备应答信号,复位应答地址");
isFlag = false;
}
Thread.Sleep(2000);
} while (isFlag);
//更新计划状态为2执行中
planInfo.ExecuteStatus = 2;
//SheetMetalPlanTaskHandle handle = new SheetMetalPlanTaskHandle();
//plc1 = PlcHelper.melsecList.FirstOrDefault(d => d.EquipName.Equals("OldMelsecPlc1"));
//handle.SendPlanTask_WB(list, plc1);
_executePlanInfoServices.UpdateExecutePlanInfo(planInfo);
RefreshCurrentPlanInfoEvent?.Invoke(planInfo);
#endregion
//读取设备进度,完成后再次下发新任务
ReadDeviceComplate_WB(obj);
}
}
}
catch (Exception ex)
{
MessageBox.Show($"围板⽣产计划下发异常:{ex.Message}", "提示", MessageBoxButton.OK, MessageBoxImage.Error,
MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly);
}
}
/// <summary>
/// 读取围板生产数据
/// </summary>
/// <param name="obj"></param>
public void ReadDeviceComplate_WB(PlcModel obj)
{
bool isFlag = true;
try
{
do
{
//计划编号D6030-D6039物料编号D6040-D6049计划完成数D6050计划下线数D6051设备状态D6052-D6056,生产节拍D6057-D6058
byte[] info = obj.plc.Read("D6030", 59);
//计划编号
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,
MaterialCode = materialCode,
CompleteAmount = complateAmount,
OffLineAmount = offLineAmount,
DeviceStatus = deviceStatus,
ProductionBeat = productionBeat,
RecordTime = DateTime.Now
};
//先查询该计划编号下的前一条完工记录如果不存在本条记录产量为0
List<RecordSidePanelComplate> sidePanelComplates = _sidePanelComplateServices.Query(x => x.ProductlineCode == "1001" && x.PlanCode == planCode);
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
{
if (sumComplateAmount > 0)
{
ExecutePlanInfo planInfo = _executePlanInfoServices.Query(x => x.TaskCode.Equals(planCode.Substring(0, 13)) && x.ExecuteStatus == 2).FirstOrDefault();
if (planInfo != null)
{
if (sumComplateAmount > planInfo.CompleteAmount)
{
if (planInfo.PlanAmount - sumComplateAmount == 0)
{
Console.WriteLine($"计划:{planCode},执行完成!!!");
planInfo.CompleteAmount = sumComplateAmount;
planInfo.ExecuteStatus = 3;
_executePlanInfoServices.UpdateExecutePlanInfo(planInfo);
isFlag = false;
}
else
{
Console.WriteLine(
$"设备当前计划:{planCode},计划数量:{planInfo.PlanAmount},实际完成:{sumComplateAmount},差异:{planInfo.PlanAmount - sumComplateAmount}");
planInfo.CompleteAmount = sumComplateAmount;
_executePlanInfoServices.UpdateExecutePlanInfo(planInfo);
}
RefreshCurrentPlanInfoEvent?.Invoke(planInfo);
}
}
}
}
}
}
_sidePanelComplateServices.InsertSidePanelCimplate(sidePanelComplate);
Thread.Sleep(5000);
} while (isFlag);
}
catch (Exception e)
{
Console.WriteLine($"读取设备完成数据异常:{e.Message}");
}
}
/// <summary>
/// 下发背板生产计划
/// </summary>
/// <param name="planInfo"></param>
/// <param name="obj"></param>
public void SendPlanTaskTo_BB(ExecutePlanInfo planInfo, PlcModel obj)
{
Thread.Sleep(5000);
try
{
lock (string.Empty)
{
if (obj != null)
{
//计划编号10个字D6000-D6009、物料编号10个字D6010-D6019、计划数量1个字D6020、应答字1个字D6021
obj.plc.WriteString("D6000", planInfo.TaskCode);
string processNumber = GetProcessNumberBy(planInfo.MaterialCode);
obj.plc.WriteString("D6010", "BCD/310NF");
obj.plc.WriteInt32("D6020", planInfo.PlanAmount);
obj.plc.WriteInt32("D6021", 1);
Console.WriteLine($"{DateTime.Now.ToString("HH:m:s")}===>等待背板设备应答。。。。。。");
#region PLC反馈信号逻辑处理
//循环读取PLC应答信号PLC应答后复位应答信号、更新计划状态为执行中
bool isFlag = true;
do
{
if (obj.plc.ReadInt32("D6021") == 2)
{
obj.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_BB(obj);
}
else
{
return;
}
}
}
catch (Exception ex)
{
MessageBox.Show($"背板⽣产计划下发异常:{ex.Message}", "提示", MessageBoxButton.OK, MessageBoxImage.Error,
MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly);
}
}
/// <summary>
/// 读取背板生产数据
/// </summary>
/// <param name="obj"></param>
public void ReadDeviceComplate_BB(PlcModel obj)
{
bool isFlag = true;
try
{
do
{
//计划编号D6030-D6039物料编号D6040-D6049计划完成数D6050计划下线数D6051设备状态D6052-D6056,生产节拍D6057-D6058
byte[] info = obj.plc.Read("D6030", 59);
//计划编号
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 = "1002",
PlanCode = planCode,
MaterialCode = materialCode,
CompleteAmount = complateAmount,
OffLineAmount = offLineAmount,
DeviceStatus = deviceStatus,
ProductionBeat = productionBeat,
RecordTime = DateTime.Now
};
//先查询该计划编号下的前一条完工记录如果不存在本条记录产量为0
List<RecordSidePanelComplate> sidePanelComplates = _sidePanelComplateServices.Query(x => x.ProductlineCode == "1002" && x.PlanCode == planCode);
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
{
if (sumComplateAmount > 0)
{
ExecutePlanInfo planInfo = _executePlanInfoServices.Query(x=>x.TaskCode.Equals(planCode.Substring(0,13)) && x.ExecuteStatus == 2).FirstOrDefault();
if (planInfo != null)
{
if (sumComplateAmount > planInfo.CompleteAmount)
{
if (planInfo.PlanAmount - sumComplateAmount == 0)
{
Console.WriteLine($"计划:{planCode},执行完成!!!");
planInfo.CompleteAmount = sumComplateAmount;
planInfo.ExecuteStatus = 3;
_executePlanInfoServices.UpdateExecutePlanInfo(planInfo);
isFlag = false;
}
else
{
Console.WriteLine(
$"设备当前计划:{planCode},计划数量:{planInfo.PlanAmount},实际完成:{sumComplateAmount},差异:{planInfo.PlanAmount - sumComplateAmount}");
planInfo.CompleteAmount = sumComplateAmount;
_executePlanInfoServices.UpdateExecutePlanInfo(planInfo);
}
RefreshCurrentPlanInfoEvent?.Invoke(planInfo);
}
}
}
}
}
}
_sidePanelComplateServices.InsertSidePanelCimplate(sidePanelComplate);
Thread.Sleep(5000);
} while (isFlag);
}
catch (Exception e)
{
Console.WriteLine($"读取设备完成数据异常:{e.Message}");
}
}
/// <summary>
/// 通过物料编号获取工艺编号
/// </summary>
/// <param name="materialCode"></param>
/// <returns></returns>
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;
}
}