using Aitex.Common.Util;
using Aitex.Core.RT.ConfigCenter;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.RecipeCenter;
using CyberX8_Core;
using CyberX8_RT.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CyberX8_RT.Modules.Prewet;
using MECF.Framework.Common.CommonData;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.SCCore;
using CyberX8_RT.Modules.Rinse;
namespace CyberX8_RT.Schedulers.Prewet
{
public class SchedulerPrewet : SchedulerModule
{
private enum PrewetOperation
{
None,
RunRecipe,
WaitForPick,
Keepwet
}
#region 内部变量
///
/// Prewet实体
///
private PrewetEntity _prewetEntity;
///
/// keep wet次数
///
private int _keepwetCount = 0;
///
/// keep wet限制次数
///
private int _keepwetLimit = 0;
///
/// 当前操作
///
private PrewetOperation _currentOperation=PrewetOperation.None;
#endregion
#region 属性
///
/// 是否空闲
///
public override bool IsIdle
{
get { return _state == RState.End; }
}
///
/// 是否错误
///
public override bool IsError
{
get { return _state == RState.Failed || _state == RState.Timeout; }
}
#endregion
///
/// 构造函数
///
///
public SchedulerPrewet(ModuleName moduleName) : base(moduleName.ToString())
{
_prewetEntity = Singleton.Instance.GetModule(moduleName.ToString());
}
///
/// 执行
///
///
///
public override bool RunProcess(object recipe, object parameter, List syncModuleMessages)
{
if (!(recipe is PwtRecipe))
{
_state = RState.Failed;
LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), "recipe is invalid");
return false;
}
_keepwetCount = 0;
_keepwetLimit = SC.GetValue("Prewet.KeepWetMaxLimit");
PwtRecipe pwtRecipe = (PwtRecipe)recipe;
bool result = _prewetEntity.CheckToPostMessage(eEvent.ERR_PREWET, Module.ToString(), (int)PrewetMsg.RunRecipe, pwtRecipe,1);
if (result)
{
_state = RState.Running;
_currentOperation = PrewetOperation.RunRecipe;
}
return result;
}
///
/// 监控执行
///
///
public override bool MonitorProcess(SchedulerSequence schedulerSequence, bool hasMatchWafer)
{
bool exsitEnableCell = false;
if (_prewetEntity.IsError)
{
_state=RState.Failed;
return true;
}
if (_prewetEntity.State == (int)PrewetState.WaitForPick || (_prewetEntity.IsIdle && _prewetEntity.WaferHolderInfo == null))
{
_state = RState.End;
_currentOperation = PrewetOperation.None;
return true;
}
if (_prewetEntity.State==(int)PrewetState.RunRecipeComplete&&_currentOperation==PrewetOperation.RunRecipe)
{
CheckNextModuleCondition(schedulerSequence,ref exsitEnableCell);
}
else if((_prewetEntity.State==(int)PrewetState.DelayKeepwetComplete)&&_currentOperation==PrewetOperation.Keepwet)
{
if(_keepwetCount>_keepwetLimit)
{
LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"keepwet count {_keepwetCount} over limit {_keepwetLimit}");
_state = RState.Failed;
}
else
{
CheckNextModuleTimeToReady(schedulerSequence,ref exsitEnableCell);
}
}
else if (_prewetEntity.State == (int)PrewetState.DelayKeepweting && _currentOperation == PrewetOperation.Keepwet)
{
CheckNextModuleTimeToReady(schedulerSequence, ref exsitEnableCell);
}
return true;
}
///
/// 检验下一个
///
///
///
private void CheckNextModuleCondition(SchedulerSequence sequence,ref bool existEnableCell)
{
PwtRecipe pwtRecipe = (PwtRecipe)sequence.Recipe;
if(!pwtRecipe.KeepWet)
{
NotifyPrewetReadyForPick("prewet no keepwet");
return;
}
CheckNextModuleTimeToReady(sequence,ref existEnableCell);
}
///
/// 检验下一模块剩余时间
///
///
private void CheckNextModuleTimeToReady(SchedulerSequence sequence,ref bool existEnableCell)
{
int idleKeepwetPauseBetweenScanSeconds = SC.GetValue("Prewet.IdleKeepwetPauseBetweenScanSeconds");
ModuleType nextModuleType = sequence.NextModuleType;
if (nextModuleType == ModuleType.Metal)
{
if (!(sequence.NextRecipe is DepRecipe))
{
NotifyPrewetReadyForPick("sequence nextRecipe is not deprecipe");
}
else
{
DepRecipe depRecipe = sequence.NextRecipe as DepRecipe;
ModuleName moduleName = SchedulerSequenceManager.Instance.CalculateAvaibleMetalCellByChemistry(depRecipe.Chemistry, "",sequence.SequenceType,ref existEnableCell);
if (moduleName != ModuleName.Unknown)
{
IModuleEntity moduleEntity = Singleton.Instance.GetModule(moduleName.ToString());
if (SchedulerSequenceManager.Instance.CheckMetalCellRecipeTimeAvaible(moduleEntity, depRecipe))
{
if (moduleEntity.IsIdle)
{
NotifyPrewetReadyForPick($"{moduleEntity.Module} Is idle");
}
else
{
NotifyPrewetReadyForPick($"{moduleEntity.Module} remain seconds {moduleEntity.TimeToReady}");
}
}
else
{
NotifyPrewetKeepWet();
}
}
else
{
if (existEnableCell)
{
NotifyPrewetKeepWet();
}
else
{
NotifyPrewetReadyForPick($"no enable metal");
}
}
}
}
else
{
ModuleName moduleName = SchedulerSequenceManager.Instance.GetAvaibleEmptyModuleCell(nextModuleType,sequence.SequenceType);
if (moduleName != ModuleName.Unknown)
{
IModuleEntity moduleEntity = Singleton.Instance.GetModule(moduleName.ToString());
if (moduleEntity.IsIdle)
{
NotifyPrewetReadyForPick($"{moduleEntity.Module} is idle");
}
else
{
if (moduleEntity.TimeToReady <= idleKeepwetPauseBetweenScanSeconds)
{
NotifyPrewetReadyForPick($"{moduleEntity.Module} remain seconds {moduleEntity.TimeToReady}");
}
else
{
NotifyPrewetKeepWet();
}
}
}
else
{
NotifyPrewetKeepWet();
}
}
}
///
/// 通知Prewet准备Process for pick
///
private void NotifyPrewetReadyForPick(string reason)
{
bool result= _prewetEntity.CheckToPostMessage(eEvent.ERR_PREWET, Module.ToString(),
(int)PrewetMsg.PrepareToPick);
if (result)
{
_currentOperation = PrewetOperation.WaitForPick;
LOG.WriteLog(eEvent.INFO_PREWET, Module.ToString(), reason);
}
}
///
/// 通知Prewet准备Keep Wet
///
private void NotifyPrewetKeepWet()
{
if (_prewetEntity.State == (int)PrewetState.DelayKeepweting)
{
return;
}
bool result= _prewetEntity.CheckToPostMessage(eEvent.ERR_PREWET, ModuleName.Prewet1.ToString(),
(int)PrewetMsg.DelayKeepwet);
if(result)
{
if (_currentOperation != PrewetOperation.Keepwet)
{
_currentOperation = PrewetOperation.Keepwet;
}
_keepwetCount++;
}
}
///
/// 检验前置条件
///
///
///
///
public override bool CheckPrecondition(List schedulerSequences, int sequenceIndex, object parameter,string materialId,ref string reason)
{
if (_state == RState.Running)
{
reason = "scheduler module is already running";
return false;
}
if (_prewetEntity.State!=(int)PrewetState.WaitForPlace)
{
reason = "prewet state is not WaitForPlace";
return false;
}
if(_prewetEntity.WaferHolderInfo==null)
{
reason = "prewet has no wafer shuttle";
return false;
}
if (_prewetEntity.WaferHolderInfo.Id != materialId)
{
reason = $"{_prewetEntity.Module} wafer shuttle {_prewetEntity.WaferHolderInfo.Id} is not matched with {materialId}";
return false;
}
_currentOperation = PrewetOperation.None;
return true;
}
}
}