| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087 | using Aitex.Core.RT.Log;using Aitex.Core.Util;using MECF.Framework.Common.Equipment;using MECF.Framework.Common.SubstrateTrackings;using MECF.Framework.Common.WaferHolder;using CyberX8_Core;using CyberX8_RT.Modules.Loader;using CyberX8_RT.Modules.PUF;using CyberX8_RT.Modules;using CyberX8_RT.Schedulers;using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Documents;using Aitex.Core.Common;using MECF.Framework.Common.CommonData;using MECF.Framework.Common.Jobs;using Aitex.Core.RT.Fsm;using MECF.Framework.Common.RecipeCenter;using MECF.Framework.Common.ToolLayout;using Aitex.Core.RT.Routine;using CyberX8_RT.Schedulers.Transporter;using CyberX8_RT.Modules.Rinse;namespace CyberX8_RT.Dispatch{    public enum WaferHolderTaskState    {        Created,        Processing,        End,        Error,        Canceled    }    /// <summary>    /// WaferHolder    /// </summary>    /// <param name="info"></param>    /// <param name="schedulerSequence"></param>    public delegate void WaferHolderSchedulerComplete(WaferHolderInfo info, SchedulerSequence schedulerSequence);    /// <summary>    /// WaferHolderTask完成    /// </summary>    /// <param name="id"></param>    public delegate void WaferHolderTaskComplete(string id);    public class WaferHolderTask    {        #region 常量         private const string PWT = "PWT";        #endregion        #region 内部变量        /// <summary>        /// 调度步骤        /// </summary>        private List<SchedulerSequence> _schedulerSequences;        /// <summary>        /// 当前步骤索引        /// </summary>        private int _currentSequenceIndex = 0;        /// <summary>        /// PUF实例        /// </summary>        private PUFEntity _puf1Entity;        /// <summary>        /// PUF实例        /// </summary>        private PUFEntity _puf2Entity;        /// <summary>        /// 是否开始执行        /// </summary>        private bool _isStart = false;        /// <summary>        /// 暂停时的索引        /// </summary>        private int _pausedIndex = -1;        /// <summary>        /// 错误上升触发        /// </summary>        private R_TRIG _sequenceErrorTigger = new R_TRIG();        /// <summary>        /// Sequence类型        /// </summary>        private string _sequenceType = "";        /// <summary>        /// FA回复        /// </summary>        private SchedulerFACallback _schedulerFACallback = new SchedulerFACallback();        #endregion        #region 属性        /// <summary>        /// ID         /// </summary>        public string ID { get;private set; }           /// <summary>        /// WaferHolder属性        /// </summary>        public WaferHolderInfo WaferHolderInfo { get;private set; }        /// <summary>        /// Process Job信息        /// </summary>        public ProcessJobInfo ProcessJobInfo { get;private set; }        /// <summary>        /// 状态        /// </summary>        public WaferHolderTaskState State { get; private set; }        /// <summary>        /// 步骤完成事件        /// </summary>        public event WaferHolderSchedulerComplete OnSchedulerComplete;        /// <summary>        /// 任务完成事件        /// </summary>        public event WaferHolderTaskComplete OnTaskComplete;        /// <summary>        /// 调度集合        /// </summary>        public List<SchedulerSequence> SchedulerSequences { get { return _schedulerSequences; } }        #endregion        /// <summary>        /// 构造函数        /// </summary>        /// <param name="waferHolderInfo"></param>        /// <param name="schedulerSequences"></param>        public WaferHolderTask(WaferHolderInfo waferHolderInfo,ProcessJobInfo processJobInfo)        {            ID=Guid.NewGuid().ToString();            WaferHolderInfo=waferHolderInfo;            WaferHolderInfo.Status = WaferHolderStatus.Normal;            if (processJobInfo != null)            {                WaferHolderInfo.SequenceId = processJobInfo.SequenceRecipe.Ppid;                WaferHolderInfo.SequenceRecipe = processJobInfo.SequenceRecipe;                _sequenceType = processJobInfo.SequenceRecipe.SequenceType;                WaferHolderInfo.CurrentControlJobId = processJobInfo.ControlJobName;                WaferHolderInfo.LotId = processJobInfo.LotName;            }            else            {                AnalyseProductionProcessJobInfo();            }            ProcessJobInfo=processJobInfo;            State = WaferHolderTaskState.Created;            _puf1Entity = Singleton<RouteManager>.Instance.GetModule<PUFEntity>(ModuleName.PUF1.ToString());            _puf2Entity = Singleton<RouteManager>.Instance.GetModule<PUFEntity>(ModuleName.PUF2.ToString());        }        /// <summary>        /// 初始化调度步骤        /// </summary>        /// <param name="schedulers"></param>        public void InitialSchedulers(List<SchedulerSequence> schedulers)        {            _schedulerSequences = schedulers;        }        /// <summary>        /// 分析生产片的ProcessJob信息        /// </summary>        private void AnalyseProductionProcessJobInfo()        {            if (!string.IsNullOrEmpty(WaferHolderInfo.WaferAId))            {                WaferInfo waferAInfo = WaferManager.Instance.GetWaferByWaferId(WaferHolderInfo.WaferAId);                if (waferAInfo != null && waferAInfo.WaferType == WaferType.Production)                {                    ProcessJobInfo = waferAInfo.ProcessJob;                    _sequenceType = ProcessJobInfo.SequenceRecipe.SequenceType;                    WaferHolderInfo.CurrentControlJobId = ProcessJobInfo.ControlJobName;                    WaferHolderInfo.LotId = ProcessJobInfo.LotName;                    WaferHolderInfo.SequenceRecipe = ProcessJobInfo.SequenceRecipe;                    return;                }            }            if (!string.IsNullOrEmpty(WaferHolderInfo.WaferBId))            {                WaferInfo waferBInfo = WaferManager.Instance.GetWaferByWaferId(WaferHolderInfo.WaferBId);                if (waferBInfo != null && waferBInfo.WaferType == WaferType.Production)                {                    ProcessJobInfo = waferBInfo.ProcessJob;                    _sequenceType = ProcessJobInfo.SequenceRecipe.SequenceType;                    WaferHolderInfo.CurrentControlJobId = ProcessJobInfo.ControlJobName;                    WaferHolderInfo.LotId = ProcessJobInfo.LotName;                    WaferHolderInfo.SequenceRecipe = ProcessJobInfo.SequenceRecipe;                }            }        }        /// <summary>        /// 执行        /// </summary>        public void Run()        {            if(_currentSequenceIndex>=_schedulerSequences.Count)            {                State = WaferHolderTaskState.End;                if(OnTaskComplete!=null)                {                    OnTaskComplete(ID);                }                FaModuleNotifier.Instance.NotifyWaferShuttleJobEnd(WaferHolderInfo);                LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"WaferHolder {WaferHolderInfo.Id} task complete");                return;            }            if (!_isStart)            {                bool preCondition = CheckStartCondition();                if (!preCondition)                {                    return;                }                LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"{WaferHolderInfo.Id} prepare Start {_currentSequenceIndex + 1} sequence");                _isStart = true;                if (WaferHolderInfo.SchedulerModules == null)                {                    WaferHolderInfo.SchedulerModules = new List<string>();                }                WaferHolderInfo.SchedulerModules.Clear();            }            SchedulerSequence sequence = _schedulerSequences[_currentSequenceIndex];            //暂停中            if (sequence.State == RState.Init && _currentSequenceIndex >= _pausedIndex && _pausedIndex != -1)            {                return;            }            if (_currentSequenceIndex == _schedulerSequences.Count - 1 && sequence.State == RState.End)            {                State=WaferHolderTaskState.End;                if (OnTaskComplete != null)                {                    OnTaskComplete(ID);                }                FaModuleNotifier.Instance.NotifyWaferShuttleJobEnd(WaferHolderInfo);                LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"WaferHolder {WaferHolderInfo.Id} task complete");                return;            }            if(_currentSequenceIndex<_schedulerSequences.Count)            {                if(sequence.State==RState.Init)                {                    if(sequence.SchedulerModule==null)                    {                        return;                    }                    if(!BufferWaferHolderJudgeResource(sequence))                    {                        return;                    }                    string reason = "";                    bool sequeceCondition = sequence.SchedulerModule.CheckPrecondition(_schedulerSequences, _currentSequenceIndex, sequence.Parameters,WaferHolderInfo.Id,ref reason);                    if (sequeceCondition)                    {                        bool result = sequence.SchedulerModule.RunProcess(sequence.Recipe,sequence.Parameters, sequence.SynchronousModuleMessages);                        if (result)                        {                            if (State == WaferHolderTaskState.Created)                            {                                State = WaferHolderTaskState.Processing;                                FaModuleNotifier.Instance.NotifyWaferShuttleJobStart(WaferHolderInfo);                            }                            sequence.State = RState.Running;                            sequence.StartTime = DateTime.Now;                            LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"{WaferHolderInfo.Id} Start {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module}");                        }                        else                        {                                                       if (sequence.ModuleName == ModuleName.Transporter1&&sequence.NextModuleType==ModuleType.Metal)                            {                                if (!CheckAfterMetalAvaible())                                {                                    LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"{WaferHolderInfo.Id} {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module} has no avaible metal");                                    TransporterAction action = sequence.Parameters as TransporterAction;                                    if (action.ActionMsg == Modules.Transporter.TransporterMSG.Transfer)                                    {                                        WaferHolderMoveItem waferHolderMoveItem = action.Parameter as WaferHolderMoveItem;                                        waferHolderMoveItem.DestModuleType = ModuleType.Dryer;                                        waferHolderMoveItem.DestModule = ModuleName.Unknown;                                        LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"{WaferHolderInfo.Id} {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module} next sequence changed to dryer");                                    }                                }                            }                        }                    }                    else                    {                        _sequenceErrorTigger.CLK = !sequeceCondition;                        if (_sequenceErrorTigger.Q)                        {                            LOG.WriteLog(eEvent.EV_SEQUENCE, "System", $"{WaferHolderInfo.Id} Start {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module} failed,{reason}");                        }                    }                }                else if(sequence.State==RState.Running)                {                    sequence.SchedulerModule.MonitorProcess(sequence,false);                    _sequenceErrorTigger.CLK = sequence.SchedulerModule.IsError;                    if (sequence.SchedulerModule.IsError)                    {                        //用于LoadTransporter取的WaferHolder Id不一致,则取消当前WaferHolderTask                        if (sequence.ModuleName == ModuleName.Transporter2)                        {                            LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"{WaferHolderInfo.Id} {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module} failed,task canceled");                            State = WaferHolderTaskState.Canceled;                            return;                        }                        if (_sequenceErrorTigger.Q)                        {                            AnalyseSchedulerErrorState(sequence);                        }                    }                    else if(sequence.SchedulerModule.IsIdle)                    {                        sequence.EndTime = DateTime.Now;                        sequence.State = RState.End;                        sequence.ProcessMilliSeconds=sequence.EndTime.Subtract(sequence.StartTime).TotalMilliseconds;                        if(sequence.IsProcessSequece)                        {                            UpdateWaferHolderProcessingStatus();                        }                        if(sequence.IsLastProcessSequence)                        {                            UpdateWaferHolderProcessComplete();                        }                        if (OnSchedulerComplete != null)                        {                            OnSchedulerComplete(WaferHolderInfo, sequence);                        }                        UpdateLoaderToBufferWaferHolderToloaderStatus(sequence);                        LOG.WriteLog(eEvent.EV_SEQUENCE, "System", $"{WaferHolderInfo.Id} {_currentSequenceIndex + 1} sequence {sequence.ModuleName} complete, time length {sequence.ProcessMilliSeconds}");                        _currentSequenceIndex++;                         AutoChangeLoaderTransporterScheduler();                        //检验rinse后面是否存在可用的Metal                        if (sequence.ModuleType == ModuleType.Rinse)                        {                            AnalyseRinseAfterMetalAvaible(sequence);                        }                        else if (sequence.ModuleType == ModuleType.Prewet)                        {                            AnalysePrewetAfterMetalAvaible(sequence);                        }                    }                }                else if (sequence.State == RState.End)                {                    LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} {_currentSequenceIndex + 1} sequence is End");                    _currentSequenceIndex++;                }            }        }        /// <summary>        /// 更新任务结束        /// </summary>        public void UpdateDryerLastSchedulerComplete()        {            SchedulerSequence sequence = _schedulerSequences[_currentSequenceIndex];            sequence.EndTime = DateTime.Now;            sequence.State = RState.End;            sequence.ProcessMilliSeconds = sequence.EndTime.Subtract(sequence.StartTime).TotalMilliseconds;            LOG.WriteLog(eEvent.EV_SEQUENCE, "System", $"{WaferHolderInfo.Id} {_currentSequenceIndex+1} sequence {sequence.ModuleName} complete, time length {sequence.ProcessMilliSeconds}");            State = WaferHolderTaskState.End;            if (OnTaskComplete != null)            {                OnTaskComplete(ID);            }            LOG.WriteLog(eEvent.EV_SEQUENCE, "Sequence", $"WaferHolder {WaferHolderInfo.Id} task complete");        }        /// <summary>        /// 更新从Loader到Buffer的WaferHolder更新为不可以拉回至Loader        /// </summary>        /// <param name="sequence"></param>        private void UpdateLoaderToBufferWaferHolderToloaderStatus(SchedulerSequence sequence)        {            string currentLocation = WaferHolderInfo.CurrentLocation;            if(!Enum.TryParse(currentLocation,out ModuleName locationName))            {                return;            }            if (!ModuleHelper.IsBuffer(locationName))            {                return;            }            if (sequence.ModuleName == ModuleName.Transporter2)            {                TransporterAction transporterAction = sequence.Parameters as TransporterAction;                if (transporterAction.ActionMsg == Modules.Transporter.TransporterMSG.Transfer)                {                    WaferHolderMoveItem waferHolderMoveItem = transporterAction.Parameter as WaferHolderMoveItem;                    if (waferHolderMoveItem.SourceModule == ModuleName.Loader1 && waferHolderMoveItem.DestModuleType == ModuleType.Buffer)                    {                        WaferHolderInfo.IsToLoader = false;                        LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} IsToLoader Changed to false;");                    }                    else if (waferHolderMoveItem.DestModuleType == ModuleType.Buffer && waferHolderMoveItem.SourceModuleType != ModuleType.Loader)                    {                        WaferHolderInfo.IsToLoader = true;                        LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} IsToLoader Changed to true;");                    }                }            }        }        /// <summary>        /// 分析错误状态下的调度        /// </summary>        private void AnalyseSchedulerErrorState(SchedulerSequence sequence)        {            if (sequence.ModuleType == ModuleType.Prewet)            {                AnalyseSchedulerPrewetErrorState(sequence);            }            else if (sequence.ModuleType == ModuleType.Dryer)            {                AnalyseSchedulerDryerErrorState(sequence);            }            else if (sequence.ModuleType == ModuleType.Rinse)            {                RinseItem rinseItem = RinseItemManager.Instance.GetRinseItem(sequence.ModuleName.ToString());                if (rinseItem == null)                {                    return;                }                if (rinseItem.SubType != PWT)                {                    AnalyseSchedulerRinseErrorState(sequence);                }                else                {                    AnalyseSchedulerPrewetErrorState(sequence);                }            }            else if (sequence.ModuleType == ModuleType.Metal)            {                AnalyseSchedulerMetalErrorState(sequence);            }        }        /// <summary>        /// 判定Buffer中WaferHolder的后面工序是否存在可用资源,不存在的话,则Task直接结束        /// </summary>        /// <param name="sequence"></param>        private bool BufferWaferHolderJudgeResource(SchedulerSequence sequence)        {            string currentLocation = WaferHolderInfo.CurrentLocation;            if (Enum.TryParse(currentLocation, out ModuleName moduleName))            {                //当前WaferHolder处于Buffer中,当前步骤不是第一步,当前调度模块为transporter2                if (ModuleHelper.IsBuffer(moduleName)&&_currentSequenceIndex!=0&&sequence.ModuleName==ModuleName.Transporter2)                {                    if (!SchedulerSequenceRecipeManager.Instance.ExistAvaibleProcessCell(WaferHolderInfo.SequenceRecipe, false))                    {                        for (int i = _currentSequenceIndex; i < _schedulerSequences.Count; i++)                        {                            SchedulerSequence item = _schedulerSequences[i];                            item.State = RState.End;                        }                        _currentSequenceIndex = _schedulerSequences.Count - 1;                        LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} exist no avaible cell");                        WaferHolderInfo.IsToLoader = true;                        LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} IsToLoader Changed to true");                        RemoveWaferHolderSRDScheduler();                        UpdateWaferHolderMisProcessedStatus();                        return false;                    }                }            }            return true;        }        /// <summary>        /// 检验Prewet后面的Metal是否存在可用        /// </summary>        private void AnalysePrewetAfterMetalAvaible(SchedulerSequence schedulerSequence)        {            //获取可用的Metal以及Rinse                        if (!CheckAfterMetalAvaible())            {                LOG.WriteLog(eEvent.WARN_SCHEDULER, "System", $"{WaferHolderInfo.Id} has no avaible metal after prewet");                SkipAfterMetal(schedulerSequence,true);                RemoveWaferHolderSRDScheduler();                UpdateWaferHolderMisProcessedStatus();                //SchedulerSequence nextSchedulerSequence = _schedulerSequences[_currentSequenceIndex];                //if (nextSchedulerSequence.ModuleName != ModuleName.Transporter1)                //{                //    return;                //}                //WaferHolderMoveItem waferHolderMoveItem = nextSchedulerSequence.Parameters as WaferHolderMoveItem;                //waferHolderMoveItem.DestModuleType = ModuleType.Dryer;                //waferHolderMoveItem.DestModule = ModuleName.Unknown;            }        }        /// <summary>        /// 检验Rinse后面的Metal是否存在可用        /// </summary>        /// <returns></returns>        private void AnalyseRinseAfterMetalAvaible(SchedulerSequence schedulerSequence)        {                        //获取可用的Metal以及Rinse                        if(!CheckAfterMetalAvaible())            {                LOG.WriteLog(eEvent.WARN_SCHEDULER, "System", $"{WaferHolderInfo.Id} has no avaible metal after rinse");                SkipAfterMetal(schedulerSequence,true);                RemoveWaferHolderSRDScheduler();                UpdateWaferHolderMisProcessedStatus();            }        }        /// <summary>        /// 检验后续Metal可用性        /// </summary>        /// <returns></returns>        private bool CheckAfterMetalAvaible()        {            for (int i = _currentSequenceIndex + 1; i < _schedulerSequences.Count; i++)            {                SchedulerSequence sequence = _schedulerSequences[i];                if (sequence.ModuleType != ModuleType.Metal)                {                    continue ;                }                if (sequence.Recipe == null || !(sequence.Recipe is DepRecipe))                {                    continue;                }                DepRecipe depRecipe = (DepRecipe)sequence.Recipe;                bool result= SchedulerSequenceManager.Instance.CalculateAvaibleMetalCellByChemistry(depRecipe.Chemistry, sequence.SequenceType,sequence.WaferSize);                if (!result)                {                    return false;                }            }            return true;        }        #region Analyse ErrorState Scheduler        /// <summary>        /// Prewet出错重新调度        /// </summary>        /// <param name="sequence"></param>        private void AnalyseSchedulerPrewetErrorState(SchedulerSequence sequence)        {            SkipAfterSchedulerToDry(ModuleName.Transporter2);            sequence.State = RState.End;            sequence.EndTime = DateTime.Now;            sequence.ProcessMilliSeconds= sequence.EndTime.Subtract(sequence.StartTime).TotalMilliseconds;            RemoveWaferHolderSRDScheduler();            UpdateWaferHolderMisProcessedStatus();            LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Prewet meet error,scheduler changed to transporter2");        }        /// <summary>        /// 路过后面调度直接至Dryer        /// </summary>        private void SkipAfterSchedulerToDry(ModuleName transporterName)        {            for (int i = _currentSequenceIndex=1; i < _schedulerSequences.Count; i++)            {                SchedulerSequence item = _schedulerSequences[i];                if (item.ModuleName != ModuleName.Transporter1)                {                    item.State = RState.End;                    item.ProcessMilliSeconds = 0;                }                else                {                    if (item.Parameters is TransporterAction)                    {                        TransporterAction action= (TransporterAction)item.Parameters;                        if (action.ActionMsg == Modules.Transporter.TransporterMSG.Transfer)                        {                            WaferHolderMoveItem waferHolderMoveItem = action.Parameter as WaferHolderMoveItem;                            if (waferHolderMoveItem.DestModuleType == ModuleType.Dryer)                            {                                _currentSequenceIndex = i;                                item.SchedulerModule = SchedulerManager.Instance.GetScheduler(transporterName);                                waferHolderMoveItem.SourceModule = ModuleName.Prewet1;                                waferHolderMoveItem.SourceModuleType = ModuleType.Prewet;                                break;                            }                            else                            {                                item.State = RState.End;                                item.ProcessMilliSeconds = 0;                            }                        }                    }                }            }        }        /// <summary>        /// Dryer出错重新调度,上一步调度修改为transporter2,同时tranporter2搬运源目标为当前Module,目标类型也是Dryer        /// </summary>        /// <param name="sequence"></param>        private void AnalyseSchedulerDryerErrorState(SchedulerSequence sequence)        {            if (SchedulerSequenceManager.Instance.GetAvaibleModuleCell(_sequenceType,ModuleType.Dryer)!=ModuleName.Unknown)            {                sequence.State = RState.Init;                SchedulerSequence preSchedulerSequence = GetPreSchedulerSequence();                preSchedulerSequence.State = RState.Init;                preSchedulerSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(ModuleName.Transporter2);                TransporterAction action = preSchedulerSequence.Parameters as TransporterAction;                if (action.ActionMsg != Modules.Transporter.TransporterMSG.Transfer)                {                    return;                }                WaferHolderMoveItem waferHolderMoveItem = action.Parameter as WaferHolderMoveItem;                waferHolderMoveItem.SourceModule = waferHolderMoveItem.DestModule;                waferHolderMoveItem.SourceModuleType = waferHolderMoveItem.DestModuleType;                waferHolderMoveItem.DestModuleType = waferHolderMoveItem.DestModuleType;                waferHolderMoveItem.DestModule = ModuleName.Unknown;                sequence.SchedulerModule = null;                _currentSequenceIndex--;                LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Dryer meet error,rescheduler changed to transporter2");            }            else            {                LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Dryer meet error,rescheduler has no avaible dryer");            }        }        /// <summary>        /// Rinse出错重新调度,回退至上一步调度        /// </summary>        /// <param name="sequence"></param>        private void AnalyseSchedulerRinseErrorState(SchedulerSequence sequence)        {            ModuleName metalName = SchedulerSequenceManager.Instance.GetPreMetalModuleName(_currentSequenceIndex, _schedulerSequences);            if (metalName == ModuleName.Unknown)            {                return;            }            if (SchedulerSequenceManager.Instance.GetAvaibleModuleCell(_sequenceType, ModuleType.Rinse,metalName) != ModuleName.Unknown)            {                sequence.State = RState.Init;                SchedulerSequence preSchedulerSequence = GetPreSchedulerSequence();                preSchedulerSequence.State = RState.Init;                TransporterAction action = preSchedulerSequence.Parameters as TransporterAction;                if (action.ActionMsg != Modules.Transporter.TransporterMSG.Transfer)                {                    return;                }                WaferHolderMoveItem waferHolderMoveItem = action.Parameter as WaferHolderMoveItem;                waferHolderMoveItem.SourceModule = waferHolderMoveItem.DestModule;                waferHolderMoveItem.SourceModuleType = waferHolderMoveItem.DestModuleType;                waferHolderMoveItem.DestModuleType = waferHolderMoveItem.DestModuleType;                waferHolderMoveItem.DestModule = ModuleName.Unknown;                sequence.SchedulerModule = null;                _currentSequenceIndex--;                LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Rinse meet error,scheduler changed to transporter1");            }            else            {                LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Rinse meet error,rescheduler has no avaible rinse");            }        }        /// <summary>        /// Metal出错重新调度,回退至上一步调度        /// </summary>        /// <param name="sequence"></param>        private void AnalyseSchedulerMetalErrorState(SchedulerSequence sequence)        {            //当前步骤结束,WaferHolder状态            UpdateWaferHolderErrorStatus();            sequence.EndTime = DateTime.Now;            sequence.ProcessMilliSeconds= sequence.EndTime.Subtract(sequence.StartTime).TotalMilliseconds;            sequence.State = RState.End;            LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Metal meet error,rescheduler changed to next module");            //跳过后面的metal            SkipAfterMetal(sequence,false);            //移除SRD调度            RemoveWaferHolderSRDScheduler();            _currentSequenceIndex++;        }        /// <summary>        /// 跳过后面的Metal        /// </summary>        private void SkipAfterMetal(SchedulerSequence schedulerSequence,bool isSetLastSequenceSourceModule)        {            int startIndex = -1;            int endIndex = -1;            //从下一个Metal直到碰到Dryer            for (int i = _currentSequenceIndex + 1; i < _schedulerSequences.Count; i++)            {                SchedulerSequence item = _schedulerSequences[i];                if (item.ModuleType == ModuleType.Metal && startIndex == -1)                {                    startIndex = i;                }                if (item.ModuleType == ModuleType.Dryer)                {                    endIndex = i - 1;//Dryer前一步骤为Transporter,保留Dryer前面的transporter                    break;                }            }            //将后面的Metal的步骤直接跳过,包含gh g 后面的transporter            if (startIndex != -1)            {                for (int i = startIndex - 1; i < endIndex; i++)                {                    SchedulerSequence item = _schedulerSequences[i];                    item.State = RState.End;                    LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} skip {i+1} sequence {item.ModuleType}");                }            }            //是否设置最后调度的源模块            if (isSetLastSequenceSourceModule)            {                SchedulerSequence lastSchedulerSequence = _schedulerSequences[endIndex];                if (lastSchedulerSequence.ModuleType == ModuleType.Transporter)                {                    TransporterAction action = lastSchedulerSequence.Parameters as TransporterAction;                    if (action.ActionMsg != Modules.Transporter.TransporterMSG.Transfer)                    {                        return;                    }                    WaferHolderMoveItem waferHolderMoveItem = action.Parameter as WaferHolderMoveItem;                    if (schedulerSequence.SchedulerModule != null)                    {                        waferHolderMoveItem.SourceModule = schedulerSequence.ModuleName;                        waferHolderMoveItem.SourceModuleType = schedulerSequence.ModuleType;                    }                }            }        }        /// <summary>        /// 移除SRD调度        /// </summary>        private void RemoveWaferHolderSRDScheduler()        {            WaferTask waferATask = WaferTaskManager.Instance.GetWaferTask(WaferHolderInfo.WaferAId);            if (waferATask != null)            {                waferATask.RemoveSrdScheduler();            }            WaferTask waferBTask = WaferTaskManager.Instance.GetWaferTask(WaferHolderInfo.WaferBId);            if (waferBTask != null)            {                waferBTask.RemoveSrdScheduler();            }        }        #endregion        /// <summary>        /// 自动更新LoaderTransporter的工序        /// </summary>        private void AutoChangeLoaderTransporterScheduler()        {            if(_currentSequenceIndex>=_schedulerSequences.Count)            {                return;            }            if(_currentSequenceIndex+2>=_schedulerSequences.Count)            {                return;            }            SchedulerSequence schedulerSequence = _schedulerSequences[_currentSequenceIndex];            if (schedulerSequence == null)            {                return;            }            if(schedulerSequence.ModuleName==ModuleName.Transporter2)            {                if (schedulerSequence.Parameters == null || !(schedulerSequence.Parameters is TransporterAction))                {                    return;                }                TransporterAction action = (TransporterAction)schedulerSequence.Parameters;                if (action.ActionMsg != Modules.Transporter.TransporterMSG.Transfer)                {                    return;                }                WaferHolderMoveItem waferHolderMoveItem = (WaferHolderMoveItem)action.Parameter;                if(waferHolderMoveItem.DestModuleType!=ModuleType.Buffer)                {                    return;                }                SchedulerSequence nextSchedulerSequence = _schedulerSequences[_currentSequenceIndex + 1];                if(nextSchedulerSequence.ModuleName!=ModuleName.Transporter2)                {                    return;                }                if(nextSchedulerSequence.Parameters==null||!(nextSchedulerSequence.Parameters is TransporterAction))                {                    return;                }                TransporterAction nextAction = nextSchedulerSequence.Parameters as TransporterAction;                if (nextAction.ActionMsg != Modules.Transporter.TransporterMSG.Transfer)                {                    return;                }                WaferHolderMoveItem nextWaferHolderMoveItem = (WaferHolderMoveItem)nextAction.Parameter;                if(nextWaferHolderMoveItem.DestModule==ModuleName.Unknown)                {                    if (ProcessJobInfo != null && ProcessJobInfo.SequenceRecipe != null)                    {                        //后面不存在资源,搬运至Buffer中,而不是进后面cell                        if (!SchedulerSequenceRecipeManager.Instance.ExistAvaibleProcessCell(ProcessJobInfo.SequenceRecipe, false))                        {                            return;                        }                    }                    if (CheckBufferHasUnProcessedWaferHolder())                    {                        return;                    }                    //若Buffer后面的cell存在资源,则直接搬运至Cell中                    ModuleName avaibleModuleName = SchedulerSequenceManager.Instance.GetAvaibleEmptyModuleCell(nextWaferHolderMoveItem.DestModuleType,_sequenceType);                    if(avaibleModuleName==ModuleName.Unknown)                    {                        return;                    }                    else                    {                        schedulerSequence.State = RState.End;                        _currentSequenceIndex++;                        nextWaferHolderMoveItem.DestModule = avaibleModuleName;                        nextWaferHolderMoveItem.SourceModule = ModuleName.Loader1;                        nextWaferHolderMoveItem.SourceModuleType = ModuleType.Loader;                        UpdateNextSequenceModule(_currentSequenceIndex + 1,avaibleModuleName);                      }                }                //下一步是QDR                else if (nextWaferHolderMoveItem.DestModuleType == ModuleType.Rinse && nextWaferHolderMoveItem.DestModule != ModuleName.Unknown)                {                    RinseEntity rinseEntity = Singleton<RouteManager>.Instance.GetModule<RinseEntity>(nextWaferHolderMoveItem.DestModule.ToString());                    if (rinseEntity != null && rinseEntity.IsAuto && rinseEntity.IsIdle && rinseEntity.WaferHolderInfo == null)                    {                        schedulerSequence.State = RState.End;                        _currentSequenceIndex++;                        nextWaferHolderMoveItem.SourceModule = ModuleName.Loader1;                        nextWaferHolderMoveItem.SourceModuleType = ModuleType.Loader;                        UpdateNextSequenceModule(_currentSequenceIndex + 1, nextWaferHolderMoveItem.DestModule);                    }                }                else if(nextWaferHolderMoveItem.DestModule==ModuleName.Loader1)                {                    LoaderEntity loaderEntity = Singleton<RouteManager>.Instance.GetModule<LoaderEntity>(ModuleName.Loader1.ToString());                    if(loaderEntity==null)                    {                        return;                    }                    if(loaderEntity.WaferHolderInfo!=null)                    {                        return;                    }                    if(loaderEntity.IsBusy)                    {                        return;                    }                    schedulerSequence.State = RState.End;                    _currentSequenceIndex++;                    nextWaferHolderMoveItem.SourceModule = waferHolderMoveItem.SourceModule;                    nextWaferHolderMoveItem.SourceModuleType = waferHolderMoveItem.SourceModuleType;                }            }        }        /// <summary>        /// 检验Buffer中是否存在未处理的WaferHolder        /// </summary>        /// <returns></returns>        private bool CheckBufferHasUnProcessedWaferHolder()        {            List<string> bufferModules = BufferItemManager.Instance.InstalledModules;            foreach (string module in bufferModules)            {                WaferHolderInfo item = WaferHolderManager.Instance.GetWaferHolder(module);                if (item == null)                {                    continue;                }                if (string.IsNullOrEmpty(item.WaferAId))                {                    continue;                }                if (string.IsNullOrEmpty(item.WaferBId))                {                    continue;                }                WaferInfo waferA=WaferManager.Instance.GetWaferByWaferId(item.WaferAId);                if (waferA == null)                {                    continue;                }                if (waferA.ProcessState == EnumWaferProcessStatus.Idle&&waferA.WaferType==WaferType.Production)                {                    return true;                }                WaferInfo waferB = WaferManager.Instance.GetWaferByWaferId(item.WaferBId);                if(waferB == null)                {                    continue;                }                if (waferB.ProcessState == EnumWaferProcessStatus.Idle && waferB.WaferType == WaferType.Production)                {                    return true;                }            }            return false;        }        /// <summary>        /// 更新下一工序的调度模块        /// </summary>        /// <param name="sequenceIndex"></param>        /// <param name="moduleName"></param>        private void UpdateNextSequenceModule(int sequenceIndex,ModuleName moduleName)        {            if(sequenceIndex<_schedulerSequences.Count)            {                SchedulerSequence schedulerSequence = _schedulerSequences[sequenceIndex];                if(schedulerSequence!=null&&schedulerSequence.SchedulerModule==null)                {                    schedulerSequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(moduleName);                    schedulerSequence.ModuleName = moduleName;                }            }        }        /// <summary>        /// 更新WaferHolder工序完成Wafer状态        /// </summary>        private void UpdateWaferHolderProcessComplete()        {            if (WaferHolderInfo.Status != WaferHolderStatus.Completed)            {                UpdateWaferHolderWaferProcessStatus(EnumWaferProcessStatus.Completed);                WaferHolderInfo.Status = WaferHolderStatus.Completed;                LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Status changed to {WaferHolderInfo.Status}");            }            MaterialTrackerManager.Instance.UpdateModuleMaterial(WaferHolderInfo.CurrentLocation);        }        /// <summary>        /// 更新WaferHolder工序正在加工        /// </summary>        private void UpdateWaferHolderProcessingStatus()        {            if (WaferHolderInfo.Status == WaferHolderStatus.Normal)            {                UpdateWaferHolderWaferProcessStatus(EnumWaferProcessStatus.InProcess);                WaferHolderInfo.Status = WaferHolderStatus.Processing;                LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferHolderInfo.Id} Status changed to {WaferHolderInfo.Status}");                MaterialTrackerManager.Instance.UpdateModuleMaterial(WaferHolderInfo.CurrentLocation);            }        }        /// <summary>        /// 更新WaferHolder工序错误状态        /// </summary>        /// <param name="sequence"></param>        private void UpdateWaferHolderErrorStatus()        {            UpdateWaferHolderWaferProcessStatus(EnumWaferProcessStatus.Failed);            WaferHolderInfo.Status = WaferHolderStatus.Failed;            MaterialTrackerManager.Instance.UpdateModuleMaterial(WaferHolderInfo.CurrentLocation);        }        /// <summary>        /// 更新WaferHolder工序MisProcessed状态        /// </summary>        /// <param name="sequence"></param>        private void UpdateWaferHolderMisProcessedStatus()        {            UpdateWaferHolderWaferProcessStatus(EnumWaferProcessStatus.MisProcessed);            WaferHolderInfo.Status = WaferHolderStatus.MisProcessed;            MaterialTrackerManager.Instance.UpdateModuleMaterial(WaferHolderInfo.CurrentLocation);        }        /// <summary>        /// 更新WaferHolder处理状态        /// </summary>        /// <param name="sequence"></param>        /// <param name="processStatus"></param>        private void UpdateWaferHolderWaferProcessStatus(EnumWaferProcessStatus processStatus)        {            if (Enum.TryParse(WaferHolderInfo.CurrentLocation, out ModuleName moduleName))            {                if (!string.IsNullOrEmpty(WaferHolderInfo.WaferAId))                {                    WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(WaferHolderInfo.WaferAId);                    if (waferInfo != null && waferInfo.WaferType == WaferType.Production)                    {                        WaferManager.Instance.UpdateWaferProcessStatus(moduleName, 0, processStatus);                        LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{waferInfo.WaferID} status changed to {processStatus}");                    }                }                if (!string.IsNullOrEmpty(WaferHolderInfo.WaferBId))                {                    WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(WaferHolderInfo.WaferBId);                    if (waferInfo != null && waferInfo.WaferType == WaferType.Production)                    {                        WaferManager.Instance.UpdateWaferProcessStatus(moduleName, 1, processStatus);                        LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{waferInfo.WaferID} status changed to {processStatus}");                    }                }            }        }        /// <summary>        /// 检验前置条件        /// </summary>        /// <returns></returns>        private bool CheckStartCondition()        {            LoaderEntity loaderEntity = Singleton<RouteManager>.Instance.GetModule<LoaderEntity>(ModuleName.Loader1.ToString());                       if (loaderEntity.WaferHolderInfo != null)            {                return false;            }            //if (ProcessJobInfo != null)            //{            //    if (!SchedulerSequenceRecipeManager.Instance.ExistAvaibleProcessCell(ProcessJobInfo.SequenceRecipe, false))            //    {            //        _currentSequenceIndex = _schedulerSequences.Count;            //        LOG.WriteLog(eEvent.WARN_SCHEDULER, "System", $"WaferHolder {WaferHolderInfo.Id} start scheduler meet no avaible cell");            //        return false;            //    }            //}            return true;        }        /// <summary>        /// 释放资源        /// </summary>        public void Dispose()        {            _schedulerSequences.Clear();        }        /// <summary>        /// 暂停        /// </summary>        public void Pause()        {            _pausedIndex = _currentSequenceIndex;        }        /// <summary>        /// 恢复        /// </summary>        public void Resume()        {            _pausedIndex = -1;        }        /// <summary>        /// 获取当前调度阶段        /// </summary>        /// <returns></returns>        public SchedulerSequence GetCurrentSchedulerSequence()        {            return GetSchedulerSequenceByIndex(_currentSequenceIndex);        }        /// <summary>        /// 获取前一个调度阶段        /// </summary>        /// <returns></returns>        public SchedulerSequence GetPreSchedulerSequence()        {            return GetSchedulerSequenceByIndex(_currentSequenceIndex-1);        }        /// <summary>        /// 根据索引获取调度阶段对象        /// </summary>        /// <param name="index"></param>        /// <returns></returns>        private SchedulerSequence GetSchedulerSequenceByIndex(int index)        {            if (index == -1 || index >= _schedulerSequences.Count)            {                return null;            }            return _schedulerSequences[index];        }        /// <summary>        /// 是否调度完成Loader调度        /// </summary>        /// <returns></returns>        public bool IsNotPassLoader()        {            return _currentSequenceIndex <= 1;        }    }}
 |