308 lines
13 KiB
C#
308 lines
13 KiB
C#
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.有NG,2.没锁,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.有NG,2.没锁,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();
|
||
}
|
||
}
|
||
}
|