using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Log; using Aitex.Core.Util; using Aitex.Core.Utilities; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.WaferHolder; using CyberX8_Core; using System; using MECF.Framework.Common.ToolLayout; using MECF.Framework.Common.Persistent.Reservoirs; using CyberX8_RT.Modules.Reservoir; using Aitex.Core.RT.OperationCenter; using MECF.Framework.Common.RecipeCenter; using Aitex.Core.RT.RecipeCenter; using MECF.Framework.Common.SubstrateTrackings; using CyberX8_RT.Devices.Metal; using Aitex.Core.RT.Device; using CyberX8_RT.Devices.Reservoir; using MECF.Framework.Common.Routine; using MECF.Framework.Common.ProcessCell; using Aitex.Core.RT.SCCore; namespace CyberX8_RT.Modules.Metal { public class MetalEntity : Entity, IEntity, IModuleEntity { #region 常量 private const string STRATUS = "Stratus"; private const string AUTO = "Auto"; private const string MANUAL = "Manual"; private const string DISABLED= "Disabled"; private const string ENGINEERING = "Engineering"; private const string PRODUCTION = "Production"; #endregion #region 内部变量 /// /// 已经完成的Cycle次数 /// private int _achievedCycle = 0; /// /// Metal项 /// private MetalItem _metalItem; /// /// 持久化对象 /// private MetalPersistentValue _persistentValue; /// /// c&m Initialize routine /// private CompactEmbranceInitializeRoutine _compactEmbranceInitializeRoutine; /// /// C&M Runrecipe routine /// private CompactEmbranceRunRecipeRoutine _compactEmbranceRunRecipeRoutine; /// /// S&H Initialize Routine /// private StandardHotInitializeRoutine _standardHotInitializeRoutine; /// /// S&H RunRecipe Routine /// private StandardHotRunRecipeRoutine _standardHotRunRecipeRoutine; /// /// Current short test routine /// private CurrentShortTestRoutine _currentShortTestRoutine; /// /// 当前Recipe /// private DepRecipe _currentRecipe = null; /// /// recipe时间 /// private int _recipeTime; /// /// 循环次数 /// private int _cycle = 0; /// /// 运行Recipe面 /// private string _recipeSide = ""; /// /// 当前RunRecipe Routine /// private RoutineBase _currentRunRecipeRoutine; /// /// Runrecipe已经运行的时间 /// private int _runrecipeElapsedTime = 0; /// /// run recipe start time /// private DateTime _runRecipeStartTime; /// /// run recipe complete time /// private DateTime _runRecipeCompleteTime; #endregion #region 属性 /// /// 模块名称 /// public ModuleName Module { get; private set; } /// /// 初始化状态 /// public bool IsInit { get { return fsm.State == (int)MetalState.Init; } } /// /// 空闲状态 /// public bool IsIdle { get { return fsm.State == (int)MetalState.Idle; } } /// /// 是否发生错误 /// public bool IsError { get { return fsm.State == (int)MetalState.Error; } } /// /// 是否正在作业 /// public bool IsBusy { get { return fsm.State > (int)MetalState.Idle; } } /// /// 是否初始化完成 /// public bool IsInitialized { get { return fsm.State >= (int)MetalState.Initialized; } } /// /// 是否禁用 /// public bool IsDisable { get { return _persistentValue == null || _persistentValue.OperatingMode == DISABLED; } } /// /// 自动模式 /// public bool IsAuto { get { return _persistentValue!=null&&_persistentValue.OperatingMode == AUTO; } } /// /// 自动模式 /// public bool IsManual { get { return _persistentValue != null && _persistentValue.OperatingMode == MANUAL; } } /// /// 是否为工程模式 /// public bool IsEngineering { get { return _persistentValue != null && _persistentValue.RecipeOperatingMode == ENGINEERING; } } /// /// 是否为产品模式 /// public bool IsProduction { get { return _persistentValue != null && _persistentValue.RecipeOperatingMode == PRODUCTION; } } /// /// WaferHolder信息 /// public WaferHolderInfo WaferHolderInfo { get { return WaferHolderManager.Instance.GetWaferHolder(Module.ToString()); } } /// /// 已完成的RunRecipeCycle次数 /// public int AchievedCycle { get { return _achievedCycle; } } /// /// 当前状态机状态 /// public int State { get { return fsm.State; } } /// /// 当前Metal设置的WaferSize /// public int MetalWaferSize { get { return _persistentValue.MetalWaferSize; } } /// /// recipe时长 /// public int RecipeTime { get { return _recipeTime; } } /// /// 剩余时间 /// public override int TimeToReady { get { if (IsIdle) { return 0; } switch(fsm.State) { case (int)MetalState.RunReciping: return Math.Max(_recipeTime - fsm.ElapsedTime/1000, 0); default: return 0 ; } } } /// /// 用量 /// public MetalUsage MetalUsage { get { return MetalUsageManager.Instance.GetMetalUsage(Module.ToString()); } } #endregion /// /// 构造函数 /// /// public MetalEntity(ModuleName moduleName) { this.Module = moduleName; WaferManager.Instance.SubscribeLocation(Module, 2); InitialFsm(); } /// /// 初始化 /// /// protected override bool Init() { InitializeDATA(); InitializeParameter(); InitializeRoutine(); InitializeOperation(); return true; } /// /// 初始化参数 /// private void InitializeParameter() { _persistentValue = MetalPersistentManager.Instance.GetMetalPersistentValue(Module.ToString()); if (_persistentValue == null) { LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), "Persistent Value Object is not exist"); } _metalItem=MetalItemManager.Instance.GetMetalItem(Module.ToString()); } /// /// 初始化Routine /// private void InitializeRoutine() { _compactEmbranceInitializeRoutine = new CompactEmbranceInitializeRoutine(Module.ToString()); _standardHotInitializeRoutine=new StandardHotInitializeRoutine(Module.ToString()); _compactEmbranceRunRecipeRoutine=new CompactEmbranceRunRecipeRoutine(Module.ToString()); _standardHotRunRecipeRoutine=new StandardHotRunRecipeRoutine(Module.ToString()); _currentShortTestRoutine=new CurrentShortTestRoutine(Module.ToString()); } /// /// 初始化操作 /// private void InitializeOperation() { OP.Subscribe($"{Module}.InitializeAll", (cmd, args) => { return CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.Initialize); }); OP.Subscribe($"{Module}.CycleManualProcessRecipe", (cmd, args) => { DepRecipe recipe = RecipeFileManager.Instance.LoadGenericityRecipe(args[0].ToString()); if (recipe == null) { LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), $"{args[0]} recipe is null"); return false; } object[] objects = new object[args.Length]; objects[0] = recipe; for(int i = 1; i < args.Length; i++) { objects[i] = args[i]; } return CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.RunRecipe,objects); }); OP.Subscribe($"{Module}.CurrentShortTest", (cmd, args) => { return CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.CurrentShortTest); }); OP.Subscribe($"{Module}.UpdateMetalUsage", UpdateMetalUsageAction); OP.Subscribe($"{Module}.Abort", (cmd, args) => { return CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.Abort); }); } /// /// EnterInit /// public void EnterInit() { if ((MetalState)fsm.State != MetalState.Idle) return; else { CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.Init); } } /// 初始化状态机 /// private void InitialFsm() { fsm = new StateMachine(Module.ToString(), (int)MetalState.Init, 20); fsm.EnableRepeatedMsg(true); AnyStateTransition(MetalMsg.Error, EnterError, MetalState.Error); //Initialize AnyStateTransition(MetalMsg.Initialize, InitializeAll, MetalState.Initializing); Transition(MetalState.Initializing,FSM_MSG.TIMER,InitializeAllMonitor, MetalState.Initialized); //直接进入Idle Transition(MetalState.Initialized, FSM_MSG.TIMER, NullFunc, MetalState.Idle); //RunRecipe Transition(MetalState.Idle, MetalMsg.RunRecipe, RunRecipe, MetalState.RunReciping); Transition(MetalState.WaitForRunRecipe, MetalMsg.RunRecipe, RunRecipe, MetalState.RunReciping); Transition(MetalState.RunReciping, FSM_MSG.TIMER, RunRecipeMonitor, MetalState.Idle); Transition(MetalState.RunReciping, MetalMsg.Abort, AbortRecipe, MetalState.Abort); //Current Short Test Transition(MetalState.Idle, MetalMsg.CurrentShortTest, CurrentShortTest, MetalState.CurrentShortTesting); Transition(MetalState.CurrentShortTesting, FSM_MSG.TIMER, CurrentShortTestMonitor, MetalState.WaitCloseFlow); Transition(MetalState.WaitCloseFlow, MetalMsg.CloseFlowValve, CloseFlowValve, MetalState.WaitOpenFlow); Transition(MetalState.WaitOpenFlow, MetalMsg.OpenFlowValve, OpenFlowValve, MetalState.WaitForRunRecipe); //Enter Init Transition(MetalState.Idle, MetalMsg.Init, NullFunc, MetalState.Init); EnumLoop.ForEach((item) => { fsm.MapState((int)item, item.ToString()); }); EnumLoop.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); }); } /// /// 初始化DATA /// private void InitializeDATA() { InitializeSVID(); DATA.Subscribe($"{Module}.FsmState", () => ((MetalState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.WaferHolder", () => WaferHolderInfo, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AchievedCycle", () => AchievedCycle, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.IsInit", () => IsInit, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.IsIdle", () => IsIdle, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.IsError", () => IsError, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.IsBusy", () => IsBusy, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.IsDisable", () => IsDisable, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.CurrentRecipe", () => _currentRecipe != null ? _currentRecipe.Ppid : "", SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.MetalUsage", () => MetalUsage, SubscriptionAttribute.FLAG.IgnoreSaveDB); } /// /// 初始化SVID /// private void InitializeSVID() { DATA.Subscribe($"{Module}.State", () => ((MetalState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.LotID", () => (WaferHolderInfo != null ? WaferHolderInfo.LotId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.WSID", () => (WaferHolderInfo != null ? WaferHolderInfo.Id : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.LSAID", () => (WaferHolderInfo != null ? WaferHolderInfo.CrsAId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.LSBID", () => (WaferHolderInfo != null ? WaferHolderInfo.CrsBId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.ModuleRecipe", () => (_currentRecipe != null ? _currentRecipe.Ppid : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.SequenceRecipe", () => (WaferHolderInfo != null ? WaferHolderInfo.SequenceId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.WaferAID", () => (WaferHolderInfo != null ? WaferHolderInfo.WaferAId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.WaferBID", () => (WaferHolderInfo != null ? WaferHolderInfo.WaferBId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.TotalTime", () => _recipeTime, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.TimeRemain", () => _recipeTime != 0 && _currentRunRecipeRoutine != null ? (_recipeTime - Math.Round((double)_currentRunRecipeRoutine.ElapsedMilliseconds / 1000, 0)) : 0, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.Task", () => WaferHolderInfo != null ? WaferHolderInfo.CurrentControlJobId : "", SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.OperatingMode", () => _persistentValue != null ? _persistentValue.OperatingMode : "None", SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.TotalUsage", () => MetalUsage != null ? MetalUsage.TotalUsage : 0, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.TotalUsage.WarningLimit", () => SC.GetValue("Metal.MetalTotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.TotalUsage.FaultLimit", () => SC.GetValue("Metal.MetalTotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeAUsage",()=> MetalUsage!=null?MetalUsage.AnodeAUsage:0, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeAUsage.WarningLimit", () => SC.GetValue("Metal.AnodeATotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeAUsage.FaultLimit", () => SC.GetValue("Metal.AnodeATotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeBUsage", () => MetalUsage != null ? MetalUsage.AnodeBUsage:0, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeBUsage.WarningLimit", () => SC.GetValue("Metal.AnodeBTotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeBUsage.FaultLimit", () => SC.GetValue("Metal.AnodeBTotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.MembranceAUsage",()=> MetalUsage != null ? MetalUsage.MembranceAUsage:0, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.MembranceAUsage.WarningLimit", () => SC.GetValue("Metal.MembraneATotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.MembranceAUsage.FaultLimit", () => SC.GetValue("Metal.MembraneATotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.MembranceBUsage", () => MetalUsage != null ? MetalUsage.MembranceBUsage:0, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.MembranceBUsage.WarningLimit", () => SC.GetValue("Metal.MembraneBTotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.MembranceBUsage.FaultLimit", () => SC.GetValue("Metal.MembraneBTotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.TotalWafers", () => MetalUsage != null ? MetalUsage.TotalWafers:0, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.TotalWafers.WarningLimit", () => SC.GetValue("Metal.MetalTotalWafersWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.TotalWafers.FaultLimit", () => SC.GetValue("Metal.MetalTotalWafersFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeAWafers",()=> MetalUsage != null ? MetalUsage.AnodeAWafers:0, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeAWafers.WarningLimit", () => SC.GetValue("Metal.AnodeATotalWafersWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeAWafers.FaultLimit", () => SC.GetValue("Metal.AnodeATotalWafersFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeBWafers", () => MetalUsage != null ? MetalUsage.AnodeBWafers:0, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeBWafers.WarningLimit", () => SC.GetValue("Metal.AnodeBTotalWafersWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.AnodeBWafers.FaultLimit", () => SC.GetValue("Metal.AnodeBTotalWafersFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB); } /// /// 进入错误状态 /// /// /// private bool EnterError(object[] args) { if (State == (int)MetalState.RunReciping) { if (_metalItem.SubType == STRATUS) { _standardHotRunRecipeRoutine.Abort(); } else { _compactEmbranceRunRecipeRoutine.Abort(); } } return true; } /// /// UpdateMetalUsageAction /// /// /// /// private bool UpdateMetalUsageAction(string cmd, object[] args) { if (args.Length > 2) { MetalUsageManager.Instance.UpdateMetalUsageByManualOperation(args[0].ToString(), args[1].ToString(), args[2].ToString()); LOG.WriteLog(eEvent.INFO_METAL, Module.ToString(), $"New {args[1].ToString()} value {args[2].ToString()} was input"); } return true; } #region Initialize All /// /// 初始化 /// /// /// private bool InitializeAll(object[] param) { if (fsm.State ==(int)MetalState.Initializing) { LOG.WriteLog(eEvent.WARN_METAL, Module.ToString(), "state is Initializing,cannot do initialize"); return false; } if(!CheckReservoirInitialized()) { LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), "Reservoir is not initialized"); return false; } if ("Auto".Equals(_persistentValue.OperatingMode)) { if (!CheckReservoirIsAuto()) { LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), "Reservoir is not in Auto OperationMode"); return false; } } if (_metalItem.SubType==STRATUS) { return _standardHotInitializeRoutine.Start(_persistentValue) == RState.Running; } else { return _compactEmbranceInitializeRoutine.Start(_persistentValue) == RState.Running; } } /// /// 检验Reservoir是否Initialized /// /// private bool CheckReservoirInitialized() { string reservoir = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString()); ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(reservoir); if (reservoirEntity != null) { return reservoirEntity.IsInitialized; } return false; } /// /// 检验Reservoir是否Auto /// /// private bool CheckReservoirIsAuto() { string reservoir = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString()); ReservoirsPersistentValue reservoirsPersistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(reservoir); if ("Auto".Equals(reservoirsPersistentValue.OperatingMode)) { return true; } return false; } /// /// 初始化监控 /// /// /// private bool InitializeAllMonitor(object[] param) { RState rsstate= RState.Running; if (_metalItem.SubType == STRATUS) { rsstate = _standardHotInitializeRoutine.Monitor(); } else { rsstate = _compactEmbranceInitializeRoutine.Monitor() ; } if(rsstate==RState.End) { return true; } else if(rsstate==RState.Failed||rsstate==RState.Timeout) { PostMsg(MetalMsg.Error); return false; } return false; } #endregion #region RunRecipe /// /// Run Recipe /// /// /// private bool RunRecipe(object[] param) { DepRecipe recipe = param[0] as DepRecipe; _recipeSide = param[1].ToString(); _cycle = (int)param[2]; _runrecipeElapsedTime = 0; bool result = false; if (_metalItem.SubType == STRATUS) { _currentRunRecipeRoutine = _standardHotRunRecipeRoutine; result= _standardHotRunRecipeRoutine.Start(recipe,_recipeSide) == RState.Running; } else { _currentRunRecipeRoutine = _compactEmbranceRunRecipeRoutine; result= _compactEmbranceRunRecipeRoutine.Start(recipe,_recipeSide) == RState.Running; } if(result) { if (WaferHolderInfo != null) { WaferHolderInfo.MetalModuleName = Module; } _recipeTime = recipe.CalculateRecipeTotalTime(); _currentRecipe = recipe; if (WaferHolderInfo != null) { LOG.WriteLog(eEvent.INFO_METAL, Module.ToString(), $"{WaferHolderInfo?.Id} {string.Join(",", WaferHolderInfo.SchedulerModules)}"); } _runRecipeStartTime = DateTime.Now; if (WaferHolderInfo != null && _currentRecipe != null) { FaModuleNotifier.Instance.NotifyWaferShuttleRecipeStart(WaferHolderInfo, _currentRecipe.Ppid); } } return result; } /// /// RunRecipe监控 /// /// /// private bool RunRecipeMonitor(object[] param) { RState rsstate = RState.Running; if (_metalItem.SubType == STRATUS) { rsstate = _standardHotRunRecipeRoutine.Monitor(); } else { rsstate = _compactEmbranceRunRecipeRoutine.Monitor(); } if (Singleton.Instance.IsAutoRunning&&_runrecipeElapsedTime!=TimeToReady) { _runrecipeElapsedTime = TimeToReady; LOG.WriteLog(eEvent.INFO_METAL, Module.ToString(), $"{WaferHolderInfo?.Id} {Module} RunRecipe TimeToReady {TimeToReady}s."); } if (rsstate == RState.End) { _recipeTime = 0; if (WaferHolderInfo != null) { double anodeAUsage = GetAnodeAUsage(); double anodeBUsage = GetAnodeBUsage(); MetalUsageManager.Instance.UpdateMetalUsage(Module.ToString(), _recipeSide, anodeAUsage, anodeBUsage); //CMM Usage if(_metalItem.SubType == STRATUS) { string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString()); StandardHotReservoirDevice resDevice = DEVICE.GetDevice(reservoirName); resDevice.SetExportCMMUsage(); } WaferHolderInfo.LastMetalRecipeCompleteTime = DateTime.Now; } _runrecipeElapsedTime = 0; //记录LotTrack _runRecipeCompleteTime = DateTime.Now; int timeLength = (int)(_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds; if (_metalItem.SubType == STRATUS) { _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2"); MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _standardHotRunRecipeRoutine.MetalLotTrackDatas, _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType); } else { _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2"); MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _compactEmbranceRunRecipeRoutine.MetalLotTrackDatas, _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType); } if (WaferHolderInfo != null && _currentRecipe != null) { FaModuleNotifier.Instance.NotifyWaferShuttleRecipeEnd(WaferHolderInfo, _currentRecipe.Ppid, timeLength); } return true; } else if (rsstate == RState.Failed || rsstate == RState.Timeout) { _recipeTime = 0; if (WaferHolderInfo != null) { double anodeAUsage = GetAnodeAUsage(); double anodeBUsage = GetAnodeBUsage(); MetalUsageManager.Instance.UpdateMetalUsage(Module.ToString(), _recipeSide, anodeAUsage, anodeBUsage); //CMMUsage if (_metalItem.SubType == STRATUS) { string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString()); StandardHotReservoirDevice resDevice = DEVICE.GetDevice(reservoirName); resDevice.SetExportCMMUsage(); } } _runrecipeElapsedTime = 0; if (WaferHolderInfo != null && _currentRecipe != null) { WaferHolderInfo.LastMetalRecipeCompleteTime = DateTime.Now; } PostMsg(MetalMsg.Error); //记录LotTrack _runRecipeCompleteTime = DateTime.Now; if (_metalItem.SubType == STRATUS) { _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2"); MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _standardHotRunRecipeRoutine.MetalLotTrackDatas, _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType); } else { _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2"); MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _compactEmbranceRunRecipeRoutine.MetalLotTrackDatas, _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType); } if (WaferHolderInfo != null && _currentRecipe != null) { FaModuleNotifier.Instance.NotifyWaferShuttleRecipeFailed(WaferHolderInfo, _currentRecipe.Ppid); } return false; } return false; } /// /// 获取A面使用的电量 /// /// private double GetAnodeAUsage() { if(_metalItem.SubType == STRATUS) { return Math.Round(_standardHotRunRecipeRoutine.AnodeAUsage,3); } else { return Math.Round(_compactEmbranceRunRecipeRoutine.AnodeAUsage,3); } } /// /// 获取B面使用的电量 /// /// private double GetAnodeBUsage() { if (_metalItem.SubType == STRATUS) { return Math.Round(_standardHotRunRecipeRoutine.AnodeBUsage, 3); } else { return Math.Round(_compactEmbranceRunRecipeRoutine.AnodeBUsage, 3); } } /// /// Abort Recipe /// /// /// public bool AbortRecipe(object[] param) { _runRecipeCompleteTime = DateTime.Now; if (_metalItem.SubType == STRATUS) { _standardHotRunRecipeRoutine.Abort(); _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2"); MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _standardHotRunRecipeRoutine.MetalLotTrackDatas, _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType); } else { _compactEmbranceRunRecipeRoutine.Abort(); _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2"); MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _compactEmbranceRunRecipeRoutine.MetalLotTrackDatas, _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType); } return true; } #endregion #region Current Short Test /// /// Current Short Test /// /// /// private bool CurrentShortTest(object[] param) { return _currentShortTestRoutine.Start() == RState.Running; } /// /// Current Short test监控 /// /// /// private bool CurrentShortTestMonitor(object[] param) { RState rsstate = _currentShortTestRoutine.Monitor(); if (rsstate == RState.End) { return true; } else if (rsstate == RState.Failed || rsstate == RState.Timeout) { PostMsg(MetalMsg.Error); return false; } return false; } #endregion #region Close Flow Valve /// /// 关闭Flow Valve /// /// /// private bool CloseFlowValve(object[] param) { if(_metalItem.SubType==STRATUS) { StandardHotMetalDevice device = DEVICE.GetDevice(Module.ToString()); if (device!=null) { return device.SwitchToBypass("", null); } return false; } else { CompactMembranMetalDevice device=DEVICE.GetDevice(Module.ToString()); if(device!=null) { string reservoir= ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString()); CompactMembranReservoirDevice reservoirDevice = DEVICE.GetDevice(reservoir); if (reservoirDevice != null) { bool result = reservoirDevice.CAByPassOn("", null); if(result) { return device.CellFlowValveOff("", null); } } } return false; } } #endregion #region Open Flow Valve /// /// 打开Flow Valve /// /// /// private bool OpenFlowValve(object[] param) { if (_metalItem.SubType == STRATUS) { StandardHotMetalDevice device = DEVICE.GetDevice(Module.ToString()); if (device != null) { bool result = device.SwitchToFlow("", null); if (result) { return device.PumpOnOperation("",null); } } return false; } else { CompactMembranMetalDevice device = DEVICE.GetDevice(Module.ToString()); if (device != null) { string reservoir = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString()); CompactMembranReservoirDevice reservoirDevice = DEVICE.GetDevice(reservoir); if (reservoirDevice != null) { bool result = reservoirDevice.CAByPassOff("", null); if (result) { return device.CellFlowValveOn("", null); } } } return false; } } #endregion public bool Check(int msg, out string reason, params object[] args) { reason = ""; return true; } public bool CheckAcked(int msg) { return true; } public int Invoke(string function, params object[] args) { switch (function) { case "HomeAll": if (IsIdle) { return (int)FSM_MSG.NONE; } if (CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.Initialize)) { return (int)MetalMsg.Initialize; } else { return (int)FSM_MSG.NONE; } } return (int)FSM_MSG.NONE; } } public enum MetalMsg { NONE, Error, ResumeError, Initialize, Manual, Auto, CurrentShortTest, CloseFlowValve, OpenFlowValve, RunRecipe, Abort, Init } }