| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 | 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 内部变量        /// <summary>        /// Prewet实体        /// </summary>        private PrewetEntity _prewetEntity;        /// <summary>        /// keep wet次数        /// </summary>        private int _keepwetCount = 0;        /// <summary>        /// keep wet限制次数        /// </summary>        private int _keepwetLimit = 0;        /// <summary>        /// 当前操作        /// </summary>        private PrewetOperation _currentOperation=PrewetOperation.None;        #endregion        #region 属性        /// <summary>        /// 是否空闲        /// </summary>        public override bool IsIdle        {            get { return _state == RState.End; }        }        /// <summary>        /// 是否错误        /// </summary>        public override bool IsError        {            get { return _state == RState.Failed || _state == RState.Timeout; }        }        #endregion        /// <summary>        /// 构造函数        /// </summary>        /// <param name="module"></param>        public SchedulerPrewet(ModuleName moduleName) : base(moduleName.ToString())        {            _prewetEntity = Singleton<RouteManager>.Instance.GetModule<PrewetEntity>(moduleName.ToString());        }        /// <summary>        /// 执行        /// </summary>        /// <param name="parameter"></param>        /// <returns></returns>        public override bool RunProcess(object recipe, object parameter, List<SchedulerSyncModuleMessage> 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<int>("Prewet.KeepWetMaxLimit");            PwtRecipe pwtRecipe = (PwtRecipe)recipe;            bool result = _prewetEntity.CheckToPostMessage<PrewetState, PrewetMsg>(eEvent.ERR_PREWET, Module.ToString(), (int)PrewetMsg.RunRecipe, pwtRecipe,1);            if (result)            {                _state = RState.Running;                _currentOperation = PrewetOperation.RunRecipe;            }            return result;        }        /// <summary>        /// 监控执行        /// </summary>        /// <returns></returns>        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;        }        /// <summary>        /// 检验下一个        /// </summary>        /// <param name="sequence"></param>        /// <returns></returns>        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);        }        /// <summary>        /// 检验下一模块剩余时间        /// </summary>        /// <param name="sequence"></param>        private void CheckNextModuleTimeToReady(SchedulerSequence sequence,ref bool existEnableCell)        {            int idleKeepwetPauseBetweenScanSeconds = SC.GetValue<int>("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<RouteManager>.Instance.GetModule<IModuleEntity>(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<RouteManager>.Instance.GetModule<IModuleEntity>(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();                }            }        }        /// <summary>        /// 通知Prewet准备Process for pick        /// </summary>        private void NotifyPrewetReadyForPick(string reason)        {            bool result= _prewetEntity.CheckToPostMessage<PrewetState, PrewetMsg>(eEvent.ERR_PREWET, Module.ToString(),                (int)PrewetMsg.PrepareToPick);            if (result)            {                _currentOperation = PrewetOperation.WaitForPick;                LOG.WriteLog(eEvent.INFO_PREWET, Module.ToString(), reason);            }        }        /// <summary>        /// 通知Prewet准备Keep Wet        /// </summary>        private void NotifyPrewetKeepWet()        {            if (_prewetEntity.State == (int)PrewetState.DelayKeepweting)            {                return;            }            bool result= _prewetEntity.CheckToPostMessage<PrewetState, PrewetMsg>(eEvent.ERR_PREWET, ModuleName.Prewet1.ToString(),                (int)PrewetMsg.DelayKeepwet);            if(result)            {                if (_currentOperation != PrewetOperation.Keepwet)                {                    _currentOperation = PrewetOperation.Keepwet;                }                _keepwetCount++;            }        }        /// <summary>        /// 检验前置条件        /// </summary>        /// <param name="sequenceIndex"></param>        /// <param name="parameter"></param>        /// <returns></returns>        public override bool CheckPrecondition(List<SchedulerSequence> 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;        }    }}
 |