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

308 lines
13 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();
}
}
}