Files
6098/Cowain.Bake.Main/Station/BakingStation.cs

308 lines
13 KiB
C#
Raw Normal View History

using Cowain.Bake.BLL;
using Cowain.Bake.Common;
using Cowain.Bake.Common.Core;
using Cowain.Bake.Common.Enums;
using Cowain.Bake.Common.Interface;
using Cowain.Bake.Communication.Interface;
using Cowain.Bake.Main.Common;
using Cowain.Bake.Model.Models;
using Opc.Ua;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Unity;
namespace Cowain.Bake.Main.Station
{
public class BakingStation : IServerManager
{
public string Name { get; set; }
readonly StoveProcessParam processParam = null;
public IUnityContainer _unityContainer { get; set; }
readonly CmdFactories cmdFactories;
readonly CancellationTokenSource cts = new CancellationTokenSource();
public BakingStation(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
processParam = _unityContainer.Resolve<StoveProcessParam>();
cmdFactories = _unityContainer.Resolve<CmdFactories>();
Start();
}
public void Start()
{
Task.Run(async () =>
{
while (!cts.Token.IsCancellationRequested)
{
try
{
if (Global.AppExit)
{
return;
}
await Task.Delay(6 * 1000);
List<ExCavityInfoModel> details = _unityContainer.Resolve<CavityInfoService>().GetAllExInfo().Where(
x => x.Type == (int)EStationType.Stove
&& x.Enable == true
&& x.CavityEnable == true).ToList();
//ProcessEndBaking(details);
ProcessStartBaking(details);
}
catch (Exception ex)
{
LogHelper.Instance.Error("BakingStation:Start:工艺参数,异常" + ex.ToString());
_unityContainer.Resolve<LogService>().AddLog("BakingStation:Start:工艺参数,异常" + ex.Message, E_LogType.Debug.ToString());
//throw;
}
}
}, cts.Token);
}
void ProcessStartBaking(List<ExCavityInfoModel> stoveDetails)
{
List<bool> bakeFlag = new List<bool>();
bool[] bakeEnable = new bool[Global.STOVE_MAX_LAYERS];
List<ExCavityInfoModel> layers = null;
var stoves = stoveDetails.GroupBy(p => new { p.StationId }).Select(s => s.FirstOrDefault()).ToList();
foreach (var stove in stoves) //烘烤以层为单位,所以以层为单位循环,这样简单
{
var conf = _unityContainer.Resolve<DeviceConfigService>().GetConfig(stove.StationId);
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(conf.Name);
if (null == plc || !plc.IsConnect)
{
continue;
}
//远程/本地模式 //0 / 空闲 1 / 待机 2 / 停止 3 / 工作 4 / 保压
if (!CommonFun.Instance.IsStoveQualified(plc, stove.StationId, 1, false))//工作当中就退出
{
continue;
}
layers = stoveDetails.Where(x => x.StationId == stove.StationId).OrderBy(x => x.Layer).ToList();//一炉子的夹具信息
bakeFlag.Clear();
//一层的夹具信息
foreach (var detail in layers)
{
//bakeFlag = new bool[layers.Count]; //每一层有多少个可以烘烤的层
if (0 == detail.PalletId)
{
continue;
}
if (0 != detail.PalletId && !detail.IsLoad) //有托盘,无信号
{
LogHelper.Instance.Error($"有夹具,却没有信号或者没有读到信号,machineId:{stove.StationId},layer:{stove.Layer}");
continue;
}
if (detail.PalletStatus != (int)EPalletStatus.Advisable
&& detail.PalletStatus != (int)EPalletStatus.TestNG)
{
continue;
}
bakeEnable[detail.Layer] = true;
//if (detail.LastFlag ?? false)
//{
// bakeFlag = Enumerable.Repeat(true, layers.Count).ToArray();
// //break; //为了bakeEnable所以不退出
//}
bakeFlag.Add(true);
//bakeFlag[detail.Layer - 1] = true;
}
if (0 == bakeFlag.Count)
{
continue;
}
//因为当每个夹具都放水的时候,可能存在一个要复烘,一个不需要,这个时候就有为false
if (bakeFlag.Count != layers.Count // (bakeFlag.Contains(false))
&& null == layers.Find(x => x.LastFlag == true)) //不是最后一盘
{
//复烘逻辑:1.有NG2.没锁3.无有其它盘
var failPallet = layers.Where(x => x.PalletStatus == (int)EPalletStatus.TestNG).ToList();
if (0 == failPallet.Count) //没有测试NG的
{
continue;
}
if (layers.Any(x => x.Lock)) //有锁,也就是还有回炉的夹具
{
continue;
}
int countPallets = layers.Where(x => x.PalletId != 0 && x.IsLoad == true && x.PalletStatus != (int)EPalletStatus.BlankOver).Count();
if (failPallet.Count != countPallets)//有其它状态盘,如烘烤完成,也不开始烘烤
{
continue;
}
//复烘逻辑满足:1.有NG2.没锁3.无有其它状态盘
}
//if (!IsCanBaking(plc, stove.StationId, stove.Layer))
//{
// continue;
//}
#region
//清料时,可能为会空,
ExCavityInfoModel palletProceParam = stoveDetails.Where(x => !string.IsNullOrEmpty(x.JobNum)
&& x.PalletId != 0 && x.StationId == stove.StationId).FirstOrDefault();
if (!processParam.SendStoveProcessParam(plc, palletProceParam)) //成功了要改变夹具状态 EPalletStatus.
{
continue;
}
//启动烤炉自动流程/下发工艺参数完成信号(开始烘烤)
if (!cmdFactories.StartBaking(plc, stove.StationId, bakeEnable))
{
continue;
}
//去复位“烘烤完成”
cmdFactories.ResetEndBaking(stove.StationId);
//托盘绑定烤箱位置
List<int> ids = layers.Select(x => x.PalletId).ToList(); //修改夹具状态
LogHelper.Instance.Info($"下发工艺参数成功!工站:{stove.Name},工单:{stove.JobNum},托盘号:{JsonSerializer.Serialize(ids)}");
int updateResult = _unityContainer.Resolve<PalletInfoService>().UpdateStartBakingInfo(
layers.Where(x => x.PalletStatus == (int)EPalletStatus.Advisable
|| x.PalletStatus == (int)EPalletStatus.TestNG).ToList()); //托盘绑定烤箱位置,状态,时间
if (updateResult <= 0)
{
LogHelper.Instance.Warn($"修改夹具{string.Join(",", ids)}状态失败!");
}
#endregion
}
}
bool IsCanBaking(IPLCDevice plc, int mainCode, int layer)
{
return true;
}
public void TrigEndBaking(DataValue data, Variable node)
{
if (!((bool)data.WrappedValue.Value))
{
return;
}
List<ExCavityInfoModel> stoveCavitys = _unityContainer.Resolve<CavityInfoService>().GetAllExInfo().Where(
x => x.Type == (int)EStationType.Stove
&& x.Enable == true
&& x.CavityEnable == true
&& x.StationId == node.StationId).ToList();
if (0 == stoveCavitys.Count)
{
LogHelper.Instance.Error($"{node.StationId}#炉没有可能的腔体,烘烤完成失效!");
return;
}
int[] ids = stoveCavitys.Where(x =>
x.PalletStatus == (int)EPalletStatus.Bake
&& x.PalletId != 0).Select(x => x.PalletId).ToArray(); //修改夹具状态,BlankOver清料时会有这状态
if (0 == ids.Count())
{
LogHelper.Instance.Error($"{node.StationId}#炉没有找到【烘烤中】的腔体,烘烤完成失效!");
return;
}
int updateResult = _unityContainer.Resolve<PalletInfoService>().UpdateBakingOverTime(ids);
if (updateResult <= 0)
{
LogHelper.Instance.Warn($"修改夹具为烘烤完成,{string.Join(",", ids)}状态失败!");
};
}
//void ProcessEndBaking(List<ExCavityInfoModel> stoveDetails)
//{
// bool[] bakeFlag = new bool[Global.STOVE_LAYERS];
// List<ExCavityInfoModel> layers = null;
// var stoves = stoveDetails.GroupBy(p => new { p.StationId }).Select(s => s.FirstOrDefault()).ToList();
// foreach (var stove in stoves) //烘烤以炉子为单位,所以以炉子为单位循环,这样简单
// {
// Array.Clear(bakeFlag, 0, Global.STOVE_LAYERS);
// var conf = _unityContainer.Resolve<DeviceConfigService>().GetConfig(stove.StationId);
// IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(conf.Name);
// if (null == plc || !plc.IsConnect)
// {
// continue;
// }
// //远程/本地模式 //0 / 空闲 1 / 待机 2 / 停止 3 / 工作 4 / 保压
// if (!CommonFun.Instance.IsStoveQualified(plc, stove.StationId, 1, false)) //工作当中就退出
// {
// continue;
// }
// //烘烤完成信号
// var resultBool = plc.GetValue<bool>(EStoveSignal.BakingMark.ToString(), stove.StationId); //stove.Layer
// if (!resultBool.IsSuccess || !resultBool.Content)
// {
// continue;
// }
// layers = stoveDetails.Where(x => x.StationId == stove.StationId).OrderBy(x => x.Layer).ToList();//一个炉子的夹具信息
// foreach (var detail in layers)
// {
// //只有在烘烤中的,才会有烘烤完成
// if (detail.PalletStatus != (int)EPalletStatus.Bake //detail.PalletStatus != (int)EPalletStatus.Advisable
// || 0 == detail.PalletId) //detail.PalletStatus != (int)EPalletStatus.Bake
// {
// continue;
// }
// if (detail.LastFlag ?? false)
// {
// bakeFlag = Enumerable.Repeat(true, Global.STOVE_LAYERS).ToArray();
// break;
// }
// bakeFlag[detail.Number - 1] = true;
// }
// if (bakeFlag.Contains(true)) //有假表示有夹具。
// {
// int[] ids = layers.Where(x =>
// x.PalletStatus == (int)EPalletStatus.Bake
// && x.PalletId != 0).Select(x => x.PalletId).ToArray(); //修改夹具状态,BlankOver清料时会有这状态
// int updateResult = _unityContainer.Resolve<PalletInfoService>().UpdateBakingOverTime(ids);
// if (updateResult <= 0)
// {
// LogHelper.Instance.Warn($"修改夹具{string.Join(",", ids)}状态失败!");
// };
// }
// }
//}
public void Stop()
{
// 在需要取消任务的时候,调用以下代码:
cts.Cancel();
}
}
}