| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806 | using Aitex.Core.Common;using Aitex.Core.RT.Event;using Aitex.Core.RT.Log;using Aitex.Core.RT.OperationCenter;using Aitex.Core.RT.Routine;using Aitex.Core.RT.SCCore;using Aitex.Core.Util;using MECF.Framework.Common.DBCore;using MECF.Framework.Common.Equipment;using MECF.Framework.Common.Alarms;using MECF.Framework.Common.Event;using MECF.Framework.Common.SubstrateTrackings;using System;using System.Collections.Generic;using FurnaceRT.Equipments.PMs.Routines;using System.Diagnostics;using MECF.Framework.Common.DataCenter;using System.Runtime.Remoting.Metadata.W3cXsd2001;using FurnaceRT.Equipments.Systems;using MECF.Framework.Common.CommonData.EnumData;namespace FurnaceRT.Equipments.PMs.RecipeExecutions{    public enum RecipeContinueMode    {        None,        WaferReturnAndJobStop,        RecipeCompleted,        StepContinue,        StepRestart,        RecipeRestart,        NextStep,    }    public class Process : PMBaseRoutine    {        enum RecipeRunningState        {            Error,            RecipeCompleted,            ExecStep,            TimeWait,            ConditionWait,            StepCompleted,            Paused,        }        enum RecipeAlaramAction        {            None,            JumpAbortRecipe,            JumpStep,            JumpStepCancelCallLoop,            Abort,            Hold,            IgnoreAlaram,        }        private object _recipeLocker = new object();        private RecipeRunningState _state = RecipeRunningState.ExecStep;        private RecipeRunningState _pausedState = RecipeRunningState.ExecStep;        private double _curStepElpasedTimeBeforePaused;        private double _holdTimeElpasedTime;        private double _waferTimeElpasedTimeBeforPaused;        //Add by SSH,20250930,判断recipe是否执行结束,给job使用        public bool IsRecipeCompleted { get { return _state == RecipeRunningState.RecipeCompleted || _state == RecipeRunningState.Error; } }        private double _totalElpasedTime;        public RecipeContinueMode ContinueAction { get; set; }        public DateTime _recipeStartTime        {            get;            private set;        }        public string CurrentRecipeContent { get; private set; }        public int _currentStepNumber;        private int _currentSubRecipeStepNumber;        private bool _loopEnd;        public int CurStepTotalLoopCount        {            get;            private set;        }        public int CurSubRecipeStepTotalLoopCount        {            get;            private set;        }        public double CurStepTotalTime        {            get            {                if (PMModule.RecipeRunningInfo.RecipeStepList == null || PMModule.RecipeRunningInfo.RecipeStepList.Count == 0 || _state == RecipeRunningState.RecipeCompleted || _state == RecipeRunningState.Error)                    return 0;                return PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime * 1000;            }        }        public int CurrentLoopCount        {            get;            private set;        }        public int CurrentAbortRecipeLoopCount        {            get;            private set;        }        public int CurrentSubRecipeLoopCount        {            get;            private set;        }        public bool IsExecuteAbort        {            get;            private set;        }        public bool IsSubReciep        {            get;            private set;        }        public int AlarmConditionJumpStep { get; set; } = -1;        private DeviceTimer _stepTimer = new DeviceTimer();        private DeviceTimer _holdTimer = new DeviceTimer();        private RecipeFACallback _faCallback;        private RecipeDBCallback _dbCallback;        private Fdc _fdc;        private ModuleName _doModule = ModuleName.PM1;        private bool IsJumpStepCancelCallLoop;        private int _jumpStepNumber;        private int _showStepNo;        private int _subRecipeStartStepNumber;        private RecipeAlaramAction _alarmAction = RecipeAlaramAction.None;        public List<string> _alarmNames        {            private set;            get;        }        private R_TRIG _trigHeaterBottomToleranceAlarm = new R_TRIG();        private R_TRIG _trigHeaterBottomToleranceWarning = new R_TRIG();        private R_TRIG _trigHeaterCenterBottomToleranceAlarm = new R_TRIG();        private R_TRIG _trigHeaterCenterBottomToleranceWarning = new R_TRIG();        private R_TRIG _trigHeaterCenterToleranceAlarm = new R_TRIG();        private R_TRIG _trigHeaterCenterToleranceWarning = new R_TRIG();        private R_TRIG _trigHeaterCenterTopToleranceAlarm = new R_TRIG();        private R_TRIG _trigHeaterCenterTopToleranceWarning = new R_TRIG();        private R_TRIG _trigHeaterTopToleranceAlarm = new R_TRIG();        private R_TRIG _trigHeaterTopToleranceWarning = new R_TRIG();        private R_TRIG _trigPressureToleranceAlarm = new R_TRIG();        private R_TRIG _trigPressureToleranceWarning = new R_TRIG();        private R_TRIG _trigInputSignalTimeOutAlarm = new R_TRIG();        private R_TRIG _trigTemperatureConvergenceTimeOutAlarm = new R_TRIG();        private R_TRIG _trigReachTempTimeOutAlarm = new R_TRIG();        private R_TRIG _trigPressureConvergenceTimeOutAlarm = new R_TRIG();        private R_TRIG _trigReachPressureTimeOutAlarm = new R_TRIG();        private R_TRIG _trigAutoProfileTimeOutAlarm = new R_TRIG();        private Dictionary<string, R_TRIG> _trigMfcToleranceAlarms;        private Dictionary<string, R_TRIG> _trigMfcToleranceWarnings;        private R_TRIG _trigBoatMoveToLoadPositionTimeout = new R_TRIG();        private R_TRIG _trigHeaterProfileFinish = new R_TRIG();        private R_TRIG _trigLeakCheckFinish = new R_TRIG();        private R_TRIG _trigBoatWaitCondition = new R_TRIG();        private R_TRIG _trigAPCWaitCondition = new R_TRIG();        private R_TRIG _trigAUXWaitCondition = new R_TRIG();        private R_TRIG _trigHeaterWaitCondition = new R_TRIG();        private R_TRIG _trigMFCWaitCondition = new R_TRIG();        private string _infoHeaterProfileFinish = "";        private string _infoAUXWaitCondition = "";        private string _infoHeaterWaitCondition = "";        private string _infoMFCWaitCondition = "";        private Dictionary<int, Tuple<bool, int>> _callSubSteps = new Dictionary<int, Tuple<bool, int>>();        private bool _isJumpStep = false;        public Process(ModuleName module, PMModule pm) : base(module, pm)        {            Module = module.ToString();            Name = "Process";            _trigMfcToleranceAlarms = new Dictionary<string, R_TRIG>()            {                {"MFC61", new R_TRIG() },                {"MFC13", new R_TRIG() },                {"MFC14", new R_TRIG() },                {"MFC15", new R_TRIG() },                {"MFC16", new R_TRIG() },                {"MFC24", new R_TRIG() },                {"MFC25", new R_TRIG() },                {"MFC26", new R_TRIG() },                {"MFC34", new R_TRIG() },                {"MFC35", new R_TRIG() },                {"MFC36", new R_TRIG() },                {"MFC90", new R_TRIG() },                {"MFC91", new R_TRIG() },                {"MFC84", new R_TRIG() },            };            _trigMfcToleranceWarnings = new Dictionary<string, R_TRIG>()            {                {"MFC61", new R_TRIG() },                {"MFC13", new R_TRIG() },                {"MFC14", new R_TRIG() },                {"MFC15", new R_TRIG() },                {"MFC16", new R_TRIG() },                {"MFC24", new R_TRIG() },                {"MFC25", new R_TRIG() },                {"MFC26", new R_TRIG() },                {"MFC34", new R_TRIG() },                {"MFC35", new R_TRIG() },                {"MFC36", new R_TRIG() },                {"MFC90", new R_TRIG() },                {"MFC91", new R_TRIG() },                {"MFC84", new R_TRIG() },            };            _faCallback = new RecipeFACallback();            _dbCallback = new RecipeDBCallback();            _fdc = new Fdc(Module);        }        public override Result Start(params object[] param)        {            CurStepTotalLoopCount = 0;            _currentSubRecipeStepNumber = CurSubRecipeStepTotalLoopCount = 0;            if (AlarmConditionJumpStep > 0)                _currentStepNumber = AlarmConditionJumpStep;            else                _currentStepNumber = PMModule.IsJobProcess ? 1 : 0; // 如果是从Job Process开始,从1开始,跳过standby step            AlarmConditionJumpStep = -1;            PMModule.RecipeRunningInfo.InnerId = Guid.NewGuid();            PMModule.RecipeRunningInfo.BeginTime = DateTime.Now;            PMModule.RecipeRunningInfo.TotalTime = CalcRecipeTime();            if (PMModule.RecipeRunningInfo.TotalTime < 0)                return Result.FAIL;            IsSubReciep = false;            IsExecuteAbort = false;            IsJumpStepCancelCallLoop = false;            PMModule.IsPaused = false;            PMModule.IsHeaterProfile = false;            PMModule.IsHeaterProfileSuccess = false;            PMModule.IsMainRecipeComplete = false;            _loopEnd = false;            _isJumpStep = false;            _curStepElpasedTimeBeforePaused = 0;            _waferTimeElpasedTimeBeforPaused = 0;            _totalElpasedTime = 0;            _holdTimeElpasedTime = 0;            _jumpStepNumber = 0;            _showStepNo = 0;            _state = RecipeRunningState.ExecStep;            _alarmAction = RecipeAlaramAction.None;            _alarmNames = new List<string>();            _subRecipeStartStepNumber = 1;            _callSubSteps.Clear();            PMModule.InitAlarmCondition(PMModule.RecipeRunningInfo.Head.AlarmCondition);            PMModule.InitLeakCheck(PMModule.RecipeRunningInfo.Head.LeakCheck);            PMModule.InitN2PurgeMode(PMModule.RecipeRunningInfo.Head.N2PurgeModeStr);            ResetTrig();            Notify($"Start");            _faCallback.RecipeStart(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName);            _dbCallback.RecipeStart(PMModule.Module, 0, PMModule.RecipeRunningInfo.InnerId.ToString(), PMModule.RecipeRunningInfo.RecipeName, GetDBRecipeType(PMModule.RecipeRunningInfo.ExecRecipeType), (int)PMModule.RecipeExecEntryEnumValue);            _dbCallback.RecipeUpdateStatus(PMModule.RecipeRunningInfo.InnerId.ToString(), "InProcess");            _fdc.Reset();            WaferManager.Instance.UpdateWaferProcessStatus(ModuleHelper.Converter(Module), 0, EnumWaferProcessStatus.InProcess);            PMModule.ResetFDCRecipeStepName();            PMModule.HeaterEnable(true);            #region 把pj_id更新到process表            //从原来退出process挪到此处写入,是为了避免多个job手动abort掉当前job,而recipe继续执行导致的pj_id更新错误            var firstPjId = Singleton<EquipmentManager>.Instance.GetFirstPJId();            UpdateProcessDataPJid(firstPjId);            #endregion            PMModule.RecipeExecEntryEnumValue = RecipeExecEntryEnum.None;            return Result.RUN;        }        public override Result Monitor()        {            if (!PMModule.CheckEnableRunProcess(out string reason))            {                PMModule.CheckEnableRunProcessAlarm.Set(reason);                return Result.FAIL;            }            //MonitorRecipeAlaramAction();            //if (IsExecuteAbort)            //    return Result.DONE;            MonitorRecipePause();            CheckTolerance();            List<RecipeStep> curSteps;            if ((IsSubReciep || PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].IsCallSubStep) && !_isJumpStep)            {                curSteps = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps;                if (!_callSubSteps.ContainsKey(_currentStepNumber))                    _callSubSteps.Add(_currentStepNumber, Tuple.Create(false, 0));                if (PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].IsCallSubStep)                    _callSubSteps[_currentStepNumber] = Tuple.Create(true, PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeLoopCount);                if (!IsSubReciep)                {                    PMModule.RecipeRunningInfo.SubRecipeCurrentLoopCount = 1;                    PMModule.RecipeRunningInfo.SubRecipeLoopCount = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeLoopCount;                    PMModule.RecipeRunningInfo.SubRecipeTable = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeTableInfo;                }                PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].IsCallSubStep = false;                IsSubReciep = true;            }            else            {                PMModule.RecipeRunningInfo.SubRecipeTable = string.Empty;                curSteps = PMModule.RecipeRunningInfo.RecipeStepList;                PMModule.RecipeRunningInfo.SubRecipeLoopCount = 0;            }            lock (_recipeLocker)            {                try                {                    switch (_state)                    {                        case RecipeRunningState.ExecStep:                            {                                PMModule.IsWait = false;                                _loopEnd = false;                                if (!_holdTimer.IsIdle())                                {                                    _holdTimeElpasedTime += _holdTimer.GetElapseTime();                                    _holdTimer.Stop();                                }                                PMModule.ResetToleranceChecker();                                _curStepElpasedTimeBeforePaused = 0;                                ContinueAction = RecipeContinueMode.None;                                if (IsSubReciep)                                {                                    if (curSteps[_currentSubRecipeStepNumber].IsLoopStartStep)                                    {                                        CurrentSubRecipeLoopCount++;                                        PMModule.RecipeRunningInfo.IsLooping = true;                                        PMModule.RecipeRunningInfo.LoopCountCurrent = CurrentSubRecipeLoopCount - 1;//即使不循环,本身也有一次。本身的一次不算,所以减1                                        PMModule.RecipeRunningInfo.LoopCountSet = curSteps[_currentSubRecipeStepNumber].LoopCount - 1;//即使不循环,本身也有一次。本身的一次不算,所以减1                                    }                                    if (curSteps[_currentSubRecipeStepNumber].IsJumpStep)                                    {                                        _currentSubRecipeStepNumber = curSteps[_currentSubRecipeStepNumber].JumpStepNo;                                    }                                    PMModule.SetFDCRecipeStepName(IsSubReciep, curSteps[_currentSubRecipeStepNumber].StepName, (_currentSubRecipeStepNumber + 1).ToString());                                    RecipeExec("Sub recipe", curSteps, _currentSubRecipeStepNumber, _curStepElpasedTimeBeforePaused, _currentSubRecipeStepNumber + 1);                                }                                else                                {                                    if (curSteps[_currentStepNumber].IsLoopStartStep)                                    {                                        CurrentLoopCount++;                                        PMModule.RecipeRunningInfo.IsLooping = true;                                        PMModule.RecipeRunningInfo.LoopCountCurrent = CurrentLoopCount - 1;//即使不循环,本身也有一次。本身的一次不算,所以减1                                        PMModule.RecipeRunningInfo.LoopCountSet = curSteps[_currentStepNumber].LoopCount - 1;//即使不循环,本身也有一次。本身的一次不算,所以减1                                    }                                    if (curSteps[_currentStepNumber].IsJumpStep)                                    {                                        curSteps[_currentStepNumber].IsJumpStep = false;//只执行一次                                        _currentStepNumber = curSteps[_currentStepNumber].JumpStepNo;                                    }                                    PMModule.SetFDCRecipeStepName(IsSubReciep, curSteps[_currentStepNumber].StepName, _currentStepNumber.ToString());                                    RecipeExec("Main recipe", curSteps, _currentStepNumber, _curStepElpasedTimeBeforePaused);                                }                            }                            break;                        case RecipeRunningState.TimeWait:                            //if (PMModule.IsPaused)                            //{                            //    _state = RecipeRunningState.Paused;                            //    break;                            //}                            var leakCheck = PMModule.CheckLeakCheckFinish();                            _trigLeakCheckFinish.CLK = !leakCheck;                            if (_trigLeakCheckFinish.Q)                                LOG.Write($"Wait condition:leak check");                            if (_stepTimer.IsTimeout())                            {                                var heaterProfile = PMModule.CheckHeaterProfileFinish(out reason);                                _trigHeaterProfileFinish.CLK = !heaterProfile || _infoHeaterProfileFinish != reason;                                if (_trigHeaterProfileFinish.Q)                                    LOG.Write($"Wait condition:heater profile--{reason}");                                _infoHeaterProfileFinish = reason;                                var boatWaitCondition = PMModule.CheckBoatWaitCondition(out reason);                                _trigBoatWaitCondition.CLK = !boatWaitCondition;                                if (_trigBoatWaitCondition.Q)                                    LOG.Write($"Wait condition:boat--{reason}");                                var apcWaitCondition = PMModule.CheckAPCWaitCondition(out reason);                                _trigAPCWaitCondition.CLK = !apcWaitCondition;                                if (_trigAPCWaitCondition.Q)                                    LOG.Write($"Wait condition:APC--{reason}");                                var auxWaitCondition = PMModule.CheckAUXWaitCondition(out reason);                                _trigAUXWaitCondition.CLK = !auxWaitCondition || _infoAUXWaitCondition != reason;                                if (_trigAUXWaitCondition.Q)                                    LOG.Write($"Wait condition:heater profile--{reason}");                                _infoAUXWaitCondition = reason;                                var heaterWaitCondition = PMModule.CheckHeaterWaitCondition(out reason);                                _trigHeaterWaitCondition.CLK = !heaterWaitCondition || _infoHeaterWaitCondition != reason;                                if (_trigHeaterWaitCondition.Q)                                    LOG.Write($"Wait condition:heater--{reason}");                                _infoHeaterWaitCondition = reason;                                var mfcWaitCondition = PMModule.CheckMFCWaitCondition(out reason);                                _trigMFCWaitCondition.CLK = !mfcWaitCondition || _infoMFCWaitCondition != reason;                                if (_trigMFCWaitCondition.Q)                                    LOG.Write($"Wait condition:MFC--{reason}");                                _infoMFCWaitCondition = reason;                                if (heaterProfile &&                                    leakCheck &&                                    boatWaitCondition &&                                    apcWaitCondition &&                                    auxWaitCondition &&                                    heaterWaitCondition &&                                    mfcWaitCondition)                                {                                    _state = RecipeRunningState.StepCompleted;                                }                                else                                {                                    PMModule.IsWait = true;                                }                            }                            else                            {                                PMModule.CheckHeaterProfileFinish(out reason);                                PMModule.CheckBoatWaitCondition(out reason);                                PMModule.CheckAPCWaitCondition(out reason);                                PMModule.CheckAUXWaitCondition(out reason);                                PMModule.CheckHeaterWaitCondition(out reason);                                PMModule.CheckMFCWaitCondition(out reason);                            }                            break;                        case RecipeRunningState.ConditionWait:                            {                                if (!PMModule.CheckBoatState() && !PMModule.IsBoatMoveToLoadPosition)                                    break;                                var heaterProfile = PMModule.CheckHeaterProfileFinish(out reason);                                _trigHeaterProfileFinish.CLK = !heaterProfile || _infoHeaterProfileFinish != reason;                                if (_trigHeaterProfileFinish.Q)                                    LOG.Write($"Wait condition:heater profile--{reason}");                                _infoHeaterProfileFinish = reason;                                leakCheck = PMModule.CheckLeakCheckFinish();                                _trigLeakCheckFinish.CLK = !leakCheck;                                if (_trigLeakCheckFinish.Q)                                    LOG.Write($"Wait condition:leak check");                                var boatWaitCondition = PMModule.CheckBoatWaitCondition(out reason);                                _trigBoatWaitCondition.CLK = !boatWaitCondition;                                if (_trigBoatWaitCondition.Q)                                    LOG.Write($"Wait condition:boat--{reason}");                                var apcWaitCondition = PMModule.CheckAPCWaitCondition(out reason);                                _trigAPCWaitCondition.CLK = !apcWaitCondition;                                if (_trigAPCWaitCondition.Q)                                    LOG.Write($"Wait condition:APC--{reason}");                                var auxWaitCondition = PMModule.CheckAUXWaitCondition(out reason);                                _trigAUXWaitCondition.CLK = !auxWaitCondition || _infoAUXWaitCondition != reason;                                if (_trigAUXWaitCondition.Q)                                    LOG.Write($"Wait condition:heater profile--{reason}");                                _infoAUXWaitCondition = reason;                                var heaterWaitCondition = PMModule.CheckHeaterWaitCondition(out reason);                                _trigHeaterWaitCondition.CLK = !heaterWaitCondition || _infoHeaterWaitCondition != reason;                                if (_trigHeaterWaitCondition.Q)                                    LOG.Write($"Wait condition:heater--{reason}");                                _infoHeaterWaitCondition = reason;                                var mfcWaitCondition = PMModule.CheckMFCWaitCondition(out reason);                                _trigMFCWaitCondition.CLK = !mfcWaitCondition || _infoMFCWaitCondition != reason;                                if (_trigMFCWaitCondition.Q)                                    LOG.Write($"Wait condition:MFC--{reason}");                                _infoMFCWaitCondition = reason;                                if (heaterProfile &&                                    leakCheck &&                                    boatWaitCondition &&                                    apcWaitCondition &&                                    auxWaitCondition &&                                    heaterWaitCondition &&                                    mfcWaitCondition)                                {                                    _state = RecipeRunningState.StepCompleted;                                }                                if (_stepTimer.IsTimeout())                                {                                    if (PMModule.IsBoatMoveToLoadPosition)                                    {                                        _trigBoatMoveToLoadPositionTimeout.CLK = !boatWaitCondition;                                        if (_trigBoatMoveToLoadPositionTimeout.Q)                                            PMModule.BoatMoveToLoadPositionTimeoutWarning.Set();                                    }                                    //_trigInputSignalTimeOutAlarm.CLK = !PMModule.CheckExternalSensorCondition();                                    //if (_trigInputSignalTimeOutAlarm.Q)                                    //    PMModule.InputSignalTimeOutAlarm.Set();                                    //_trigTemperatureConvergenceTimeOutAlarm.CLK = !PMModule.CheckTempStabilizeCondition();                                    //if (_trigTemperatureConvergenceTimeOutAlarm.Q)                                    //    PMModule.TemperatureConvergenceTimeOutAlarm.Set();                                    //_trigReachTempTimeOutAlarm.CLK = !PMModule.CheckReachTempCondition();                                    //if (_trigReachTempTimeOutAlarm.Q)                                    //    PMModule.TemperatureConvergenceTimeOutAlarm.Set("Reach temp condition timeout");                                    //_trigPressureConvergenceTimeOutAlarm.CLK = !PMModule.CheckPressureStablilizeCondition();                                    //if (_trigPressureConvergenceTimeOutAlarm.Q)                                    //    PMModule.PressureConvergenceTimeOutAlarm.Set();                                    //_trigReachPressureTimeOutAlarm.CLK = !PMModule.CheckReachPressureCondition();                                    //if (_trigReachPressureTimeOutAlarm.Q)                                    //    PMModule.PressureConvergenceTimeOutAlarm.Set("Reach pressure condition timeout");                                    //_trigAutoProfileTimeOutAlarm.CLK = !PMModule.CheckFinishAutoProfileCondition();                                    //if (_trigAutoProfileTimeOutAlarm.Q)                                    //    PMModule.AutoProfileTimeOutAlarm.Set();                                    //_state = RecipeRunningState.StepCompleted;                                }                                else                                {                                    _trigBoatMoveToLoadPositionTimeout.RST = true;                                }                            }                            break;                        case RecipeRunningState.Paused:                            if (!_stepTimer.IsIdle())                            {                                _curStepElpasedTimeBeforePaused += _stepTimer.GetElapseTime();                                _stepTimer.Stop();                            }                            if (_holdTimer.IsIdle())                                _holdTimer.Start(0);                            switch (ContinueAction)                            {                                case RecipeContinueMode.None:                                    break;                                case RecipeContinueMode.StepContinue:                                    if (!_holdTimer.IsIdle())                                    {                                        _holdTimeElpasedTime += _holdTimer.GetElapseTime();                                        _holdTimer.Stop();                                    }                                    _state = RecipeRunningState.ExecStep;                                    _stepTimer.Stop();                                    break;                            }                            break;                        case RecipeRunningState.StepCompleted:                            {                                ResetTrig();                                //CloseAllValve();                                _curStepElpasedTimeBeforePaused = 0;                                var stepName = "";                                var stepTime = (float)_stepTimer.GetElapseTime() / 1000;//sec                                var thickness = 0.0f;                                if (IsSubReciep)                                {                                    stepName = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].StepName;                                    float.TryParse(PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].FilmThickFormula, out thickness);                                    //放在前面,stepnumber后面会被更新                                    if (!_isJumpStep)                                    {                                        _faCallback.RecipeStepEnd(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName, _currentSubRecipeStepNumber + 1);                                        _dbCallback.RecipeStepEnd(PMModule.RecipeRunningInfo.InnerId.ToString(), _currentSubRecipeStepNumber + 1, _fdc.DataList, SC.GetStringValue("PM1.TempCorrection"), SC.GetStringValue("PM1.Heater.PID"));                                    }                                    _fdc.Stop();                                    _totalElpasedTime += curSteps[_currentSubRecipeStepNumber].StepTime;                                    _subRecipeStartStepNumber++;                                    if (_loopEnd)                                    {                                        _currentSubRecipeStepNumber++;                                        CurrentSubRecipeLoopCount = 0;                                        PMModule.RecipeRunningInfo.IsLooping = false;                                        PMModule.RecipeRunningInfo.LoopCountCurrent = 0;                                        PMModule.RecipeRunningInfo.LoopCountSet = 0;                                    }                                    else                                    {                                        SubRecipeLoopEndCheck(curSteps);                                    }                                    if (_currentSubRecipeStepNumber >= curSteps.Count)                                    {                                        PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeLoopCount--;                                        if (PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeLoopCount > 0)                                        {                                            IsSubReciep = true;                                        }                                        else                                        {                                            IsSubReciep = false;                                        }                                        _currentSubRecipeStepNumber = 0;                                        CurrentSubRecipeLoopCount = 0;                                        //// sub recipe执行完后,检查下是否在main recipe的loop内                                        //RecipeLoopEndCheck();                                        //if (_currentStepNumber >= PMModule.RecipeRunningInfo.RecipeStepList.Count)                                        //{                                        //    _currentStepNumber = PMModule.RecipeRunningInfo.RecipeStepList.Count - 1;                                        //    _state = RecipeRunningState.RecipeCompleted;                                        //}                                    }                                    _state = RecipeRunningState.ExecStep;                                    _stepTimer.Stop();                                }                                else                                {                                    stepName = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepName;                                    float.TryParse(PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].FilmThickFormula, out thickness);                                    //放在前面,stepnumber后面会被更新                                    if (!_isJumpStep)                                    {                                        _faCallback.RecipeStepEnd(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName, _currentStepNumber);                                        _dbCallback.RecipeStepEnd(PMModule.RecipeRunningInfo.InnerId.ToString(), _currentStepNumber, _fdc.DataList, SC.GetStringValue("PM1.TempCorrection"), SC.GetStringValue("PM1.Heater.PID"));                                    }                                    _fdc.Stop();                                    if (_currentStepNumber >= 0 && !IsSubReciep)                                    {                                        _totalElpasedTime += PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime;                                    }                                    if (IsSubReciep)                                        IsSubReciep = false;                                    if (_loopEnd)                                    {                                        _currentStepNumber++;                                        CurrentLoopCount = 0;                                        CurrentAbortRecipeLoopCount = 0;                                        CurrentSubRecipeLoopCount = 0;                                        PMModule.RecipeRunningInfo.IsLooping = false;                                        PMModule.RecipeRunningInfo.LoopCountCurrent = 0;                                        PMModule.RecipeRunningInfo.LoopCountSet = 0;                                    }                                    else                                    {                                        RecipeLoopEndCheck(PMModule.RecipeRunningInfo.RecipeStepList);                                    }                                    if (_currentStepNumber >= PMModule.RecipeRunningInfo.RecipeStepList.Count - 1)                                    {                                        for (int i = 0; i < SC.GetValue<int>($"Boat.SlotCount"); i++)                                        {                                            if (!WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(Module), i))                                                continue;                                            var wafer = WaferManager.Instance.GetWafer(ModuleHelper.Converter(Module), i);                                            if (wafer.ProcessState == EnumWaferProcessStatus.Completed ||                                                wafer.ProcessState == EnumWaferProcessStatus.Idle)                                                continue;                                            WaferManager.Instance.UpdateWaferProcessStatus(ModuleHelper.Converter(Module), i, EnumWaferProcessStatus.Completed);                                        }                                        PMModule.IsMainRecipeComplete = true;                                    }                                    if (_currentStepNumber >= PMModule.RecipeRunningInfo.RecipeStepList.Count)                                    {                                        _currentStepNumber = PMModule.RecipeRunningInfo.RecipeStepList.Count - 1;                                        _state = RecipeRunningState.RecipeCompleted;                                    }                                    else                                    {                                        _state = RecipeRunningState.ExecStep;                                        _stepTimer.Stop();                                    }                                }                                if (!_isJumpStep)                                {                                    var wafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(Module));                                    for (int i = 0; i < wafers.Length; i++)                                    {                                        if (WaferManager.Instance.CheckNoWafer(ModuleHelper.Converter(Module), i))                                            continue;                                        var useCount = wafers[i].UseCount;                                        var useTime = wafers[i].UseTime + (float)stepTime;                                        var useThick = wafers[i].UseThick + thickness;                                        WaferManager.Instance.UpdateWaferStatistics(ModuleHelper.Converter(Module), i, useCount, (float)Math.Round(useTime, 1), useThick);                                    }                                    PMModule.UpdateRecipeThickness(PMModule.RecipeRunningInfo.RecipeName, thickness);                                    PMModule.UpdateRecipeStepFre(stepName);                                    PMModule.UpdateRecipeStepRunTime(stepName, Math.Round(stepTime, 1));                                    PMModule.UpdateRecipeStepGroupThickness(stepName, thickness);                                    PMModule.UpdateBoatTotalThickness(thickness);                                }                            }                            _isJumpStep = false;                            if (PMModule.IsPaused)                            {                                _state = RecipeRunningState.Paused;                                break;                            }                            break;                        case RecipeRunningState.RecipeCompleted:                            {                                var wafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(Module));                                for (int i = 0; i < wafers.Length; i++)                                {                                    if (WaferManager.Instance.CheckNoWafer(ModuleHelper.Converter(Module), i))                                        continue;                                    var useCount = wafers[i].UseCount + 1;                                    var useTime = wafers[i].UseTime;                                    var useThick = wafers[i].UseThick;                                    WaferManager.Instance.UpdateWaferStatistics(ModuleHelper.Converter(Module), i, useCount, (float)Math.Round(useTime, 1), useThick);                                }                                PMModule.UpdateSEDWafer(WaferManager.Instance.GetAllWafers());                                if (PMModule.IsHeaterProfile && !PMModule.IsHeaterProfileSuccess)                                    EV.PostWarningLog(PMModule.Module, "Auto profile failed");                                PMModule.UpdateRecipeFre(PMModule.RecipeRunningInfo.RecipeName);                                Notify("End");                                return Result.DONE;                            }                        case RecipeRunningState.Error:                            {                                return Result.DONE;                            }                        default:                            break;                    }                }                catch (Exception ex)                {                    LOG.Write(ex);                    return Result.FAIL;                }            }            MonitorRecipeRunInfo();            return Result.RUN;        }        private void MonitorRecipeRunInfo()        {            PMModule.IsHolded = _state == RecipeRunningState.Paused;            double elapseTime;            double totalElapseTime;            double holdTotalElapseTime;            var step = 0;            if (IsSubReciep)            {                if (PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps != null)                {                    if (_stepTimer.IsIdle())                    {                        elapseTime = (_curStepElpasedTimeBeforePaused / 1000) < 1 ? 0 : _curStepElpasedTimeBeforePaused / 1000;                    }                    else                    {                        elapseTime = ((_curStepElpasedTimeBeforePaused + _stepTimer.GetElapseTime()) / 1000) < 1 ? 0 : (_curStepElpasedTimeBeforePaused + _stepTimer.GetElapseTime()) / 1000;                    }                    if (elapseTime > PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].StepTime)                        elapseTime = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].StepTime;                    totalElapseTime = _totalElpasedTime + elapseTime > PMModule.RecipeRunningInfo.TotalTime ? PMModule.RecipeRunningInfo.TotalTime : _totalElpasedTime + elapseTime;                    if (_holdTimer.IsIdle())                    {                        holdTotalElapseTime = _holdTimeElpasedTime / 1000;                    }                    else                    {                        holdTotalElapseTime = (_holdTimeElpasedTime + _holdTimer.GetElapseTime()) / 1000;                    }                    PMModule.RecipeRunningInfo.StepElapseTime = elapseTime;                    PMModule.RecipeRunningInfo.TotalElapseTime = totalElapseTime;                    PMModule.RecipeRunningInfo.HoldTime = holdTotalElapseTime;                    PMModule.RecipeRunningInfo.StepTime = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].StepTime;                    PMModule.RecipeRunningInfo.RecipeName = $"Sub/{PMModule.RecipeRunningInfo.Head.SubRecipe}-{PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeTableInfo}-{PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].StepName}";                    PMModule.RecipeRunningInfo.ExecRecipeType = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].RecipeType;                    PMModule.RecipeRunningInfo.SubRecipeCurrentLoopCount = PMModule.RecipeRunningInfo.SubRecipeLoopCount - PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeLoopCount + 1;                    PMModule.RecipeRunningInfo.SubRecipeName = PMModule.RecipeRunningInfo.Head.SubRecipe;                    PMModule.RecipeRunningInfo.SubRecipeTable = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeTableInfo;                    step = _currentSubRecipeStepNumber;                    if (_state == RecipeRunningState.Paused)                    {                        //pause之后,当前step执行完,显示的step要保持hold住的这一步的                        step--;                        if (step < 0)                            step = 0;                    }                    PMModule.RecipeRunningInfo.StepNumber = step + 1; //CurStepNum start from 0                    PMModule.RecipeRunningInfo.StepName = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[step].StepName;                    if (PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[step].IsLoopEndStep)                        PMModule.RecipeRunningInfo.NextStepName = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps.Count > PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].LoopStartStep ?                            PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[step].LoopStartStep].StepName : "";                    else                    {                        if (PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps.Count > step + 1)                        {                            PMModule.RecipeRunningInfo.NextStepName = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[step + 1].StepName;                        }                        else                        {                            if (PMModule.RecipeRunningInfo.SubRecipeCurrentLoopCount < PMModule.RecipeRunningInfo.SubRecipeLoopCount)                            {                                //sub 下一个循环                                PMModule.RecipeRunningInfo.NextStepName = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[0].StepName;                            }                            else                            {                                //sub执行结束                                if (PMModule.RecipeRunningInfo.RecipeStepList.Count > _currentStepNumber)                                {                                    PMModule.RecipeRunningInfo.NextStepName = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepName;                                }                            }                        }                    }                    if (PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].StepName.ToLower() == "standby")                    {                        PMModule.StringProcessFlowState = PMModule.ProcessFlowState.Standby.ToString();                    }                    else                    {                        PMModule.StringProcessFlowState = PMModule.ProcessFlowState.Run.ToString();                    }                }                return;            }            if (_stepTimer.IsIdle())            {                elapseTime = (_curStepElpasedTimeBeforePaused / 1000) < 1 ? 0 : _curStepElpasedTimeBeforePaused / 1000;            }            else            {                elapseTime = ((_curStepElpasedTimeBeforePaused + _stepTimer.GetElapseTime()) / 1000) < 1 ? 0 : (_curStepElpasedTimeBeforePaused + _stepTimer.GetElapseTime()) / 1000;            }            if (elapseTime > PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime)                elapseTime = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime;            totalElapseTime = _totalElpasedTime + elapseTime > PMModule.RecipeRunningInfo.TotalTime ? PMModule.RecipeRunningInfo.TotalTime : _totalElpasedTime + elapseTime;            if (_holdTimer.IsIdle())            {                holdTotalElapseTime = _holdTimeElpasedTime / 1000;            }            else            {                holdTotalElapseTime = (_holdTimeElpasedTime + _holdTimer.GetElapseTime()) / 1000;            }            PMModule.RecipeRunningInfo.StepElapseTime = elapseTime;            PMModule.RecipeRunningInfo.TotalElapseTime = totalElapseTime;            PMModule.RecipeRunningInfo.HoldTime = holdTotalElapseTime;            PMModule.RecipeRunningInfo.StepTime = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime;            PMModule.RecipeRunningInfo.RecipeName = PMModule.RecipeRunningInfo.MainRecipeName;            PMModule.RecipeRunningInfo.ExecRecipeType = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeType;            if (_state == RecipeRunningState.RecipeCompleted)            {                PMModule.RecipeRunningInfo.HoldTime = 0;            }            step = _currentStepNumber;            if (_state == RecipeRunningState.Paused)            {                //pause之后,当前step执行完,显示的step要保持hold住的这一步的                step--;                if (step < 0)                    step = 0;            }            if (PMModule.RecipeRunningInfo.RecipeStepList[0].StepName.ToLower() == "standby")            {                PMModule.RecipeRunningInfo.StepNumber = step; //CurStepNum start from 0            }            else            {                PMModule.RecipeRunningInfo.StepNumber = step + 1; //CurStepNum start from 0            }            PMModule.RecipeRunningInfo.StepName = PMModule.RecipeRunningInfo.RecipeStepList[_showStepNo].StepName;            if (PMModule.RecipeRunningInfo.RecipeStepList[step].IsLoopEndStep)                PMModule.RecipeRunningInfo.NextStepName = PMModule.RecipeRunningInfo.RecipeStepList.Count > PMModule.RecipeRunningInfo.RecipeStepList[step].LoopStartStep ? PMModule.RecipeRunningInfo.RecipeStepList[PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].LoopStartStep].StepName : "";            else                PMModule.RecipeRunningInfo.NextStepName = PMModule.RecipeRunningInfo.RecipeStepList.Count > step + 1 ? PMModule.RecipeRunningInfo.RecipeStepList[step + 1].StepName : "";            if (PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepName.ToLower() == "standby")            {                PMModule.StringProcessFlowState = PMModule.ProcessFlowState.Standby.ToString();            }            else if (PMModule.RecipeRunningInfo.RecipeStepList.Count - 1 == _currentStepNumber)            {                PMModule.StringProcessFlowState = PMModule.ProcessFlowState.End.ToString();            }            else            {                PMModule.StringProcessFlowState = PMModule.ProcessFlowState.Run.ToString();            }        }        private void MonitorRecipeAlaramAction()        {            if (_state != RecipeRunningState.TimeWait && _state != RecipeRunningState.ConditionWait)                return;            if (_alarmNames.Count == 0)                return;            int group = -1, temp = 0;            string iAlarmConditionTable = "1:";            if (IsSubReciep)            {                for (int i = 0; i < _alarmNames.Count; i++)                {                    iAlarmConditionTable = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].AlarmConditionTable;                    temp = (int)Singleton<EventManager>.Instance.AlarmDic[iAlarmConditionTable.ToString()][_alarmNames[i]].Group;                    if (!PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].AlarmActionSets.ContainsKey(temp))                        continue;                    var type = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].AlarmActionSets[temp].ProcessingType;                    if (temp >= group && (group == -1 || type != "Ignore Alarm"))                        group = temp;                }            }            else            {                for (int i = 0; i < _alarmNames.Count; i++)                {                    iAlarmConditionTable = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].AlarmConditionTable;                    temp = (int)Singleton<EventManager>.Instance.AlarmDic[iAlarmConditionTable.ToString()][_alarmNames[i]].Group;                    if (!PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].AlarmActionSets.ContainsKey(temp))                        continue;                    var type = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].AlarmActionSets[temp].ProcessingType;                    if (temp >= group && (group == -1 || type != "Ignore Alarm"))                        group = temp;                }            }            _alarmNames.Clear();            if (group == -1)                return;            string alarmAction = "", alarmDetails = "";            List<RecipeStep> abortRecipes = new List<RecipeStep>();            if (IsSubReciep)            {                alarmAction = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].AlarmActionSets[group].ProcessingType;                alarmDetails = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].AlarmActionSets[group].ProcessingDetails;                abortRecipes = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].AlarmActionSets[group].AbortRecipeStepList;            }            else            {                alarmAction = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].AlarmActionSets[group].ProcessingType;                alarmDetails = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].AlarmActionSets[group].ProcessingDetails;                abortRecipes = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].AlarmActionSets[group].AbortRecipeStepList;            }            switch (alarmAction)            {                case "Jump Abort Recipe":                    alarmDetails = alarmDetails.Replace("Abort Recipe/", string.Empty);                    Abort();                    _alarmAction = RecipeAlaramAction.JumpAbortRecipe;                    break;                case "Jump Step":                    alarmDetails = alarmDetails.Replace("Jump Step/", string.Empty);                    _jumpStepNumber = PMModule.RecipeRunningInfo.RecipeStepList.FindIndex(x => x.StepName == alarmDetails);                    _alarmAction = RecipeAlaramAction.JumpStep;                    _state = RecipeRunningState.StepCompleted;                    break;                case "Jump Step(Cancel Call Loop)":                    alarmDetails = alarmDetails.Replace("Jump Step(Cancel Call Loop)/", string.Empty);                    _jumpStepNumber = PMModule.RecipeRunningInfo.RecipeStepList.FindIndex(x => x.StepName == alarmDetails);                    _alarmAction = RecipeAlaramAction.JumpStepCancelCallLoop;                    IsJumpStepCancelCallLoop = true;                    _state = RecipeRunningState.StepCompleted;                    break;                case "Abort":                    IsExecuteAbort = true;                    break;                case "Hold":                    PMModule.IsPaused = true;                    ContinueAction = RecipeContinueMode.None;                    _alarmAction = RecipeAlaramAction.Hold;                    break;                case "Ignore Alarm":                    _alarmAction = RecipeAlaramAction.IgnoreAlaram;                    break;                default:                    _alarmAction = RecipeAlaramAction.IgnoreAlaram;                    break;            }        }        private void MonitorRecipePause()        {            if (_state != RecipeRunningState.TimeWait && _state != RecipeRunningState.ConditionWait)                return;            //if (PMModule.IsPaused)            //{            //    _state = RecipeRunningState.Paused;            //}        }        public override void Abort()        {            //PMModule.AbortRecipe();//暂时这么做            PMModule.RecipeRunningInfo.IsLooping = false;            PMModule.RecipeRunningInfo.LoopCountCurrent = 0;            PMModule.RecipeRunningInfo.LoopCountSet = 0;            IsExecuteAbort = true;            IsSubReciep = false;            PMModule.IsPaused = false;            PMModule.IsHeaterProfile = false;            PMModule.IsHeaterProfileSuccess = false;            if (!_holdTimer.IsIdle())            {                _holdTimeElpasedTime += _holdTimer.GetElapseTime();                _holdTimer.Stop();            }            CurrentLoopCount = 0;            CurrentAbortRecipeLoopCount = 0;            CurrentSubRecipeLoopCount = 0;            _state = RecipeRunningState.RecipeCompleted;//暂时这么做            //更新步次结束时间            _dbCallback.RecipeStepEnd(PMModule.RecipeRunningInfo.InnerId.ToString(), IsSubReciep ? _currentSubRecipeStepNumber + 1 : _currentStepNumber, _fdc.DataList, SC.GetStringValue("PM1.TempCorrection"), SC.GetStringValue("PM1.Heater.PID"));            return;//暂时这么做            //_totalElpasedTime = 0;            PMModule.RecipeRunningInfo.BeginTime = DateTime.Now;            double total = 0;            for (int i = 0; i < PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].AbortRecipeSteps.Count; i++)            {                total += PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].AbortRecipeSteps[i].StepTime;            }            PMModule.RecipeRunningInfo.TotalTime = _totalElpasedTime + total;            ResetTrig();            //PMModule.ResetToleranceAlarm();            //PMModule.ResetToleranceAlarmChecker();            PMModule.ExecuteAbortRecipeWarning.Set($"from recipe name:{PMModule.RecipeRunningInfo.RecipeName} step:{_currentStepNumber} start execute abort recipe.");            _state = RecipeRunningState.ExecStep;        }        public void UpdateProcessDataPJid(string pjId)        {            _dbCallback.RecipeUpdatePjId(PMModule.RecipeRunningInfo.InnerId.ToString(), pjId);        }        public void ExitProcess()        {            if (_state == RecipeRunningState.RecipeCompleted)            {                PMModule.StringProcessFlowState = PMModule.ProcessFlowState.Standby.ToString();                _faCallback.RecipeComplete(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName);                _dbCallback.RecipeComplete(PMModule.RecipeRunningInfo.InnerId.ToString());                _fdc.Stop();            }            else            {                if (PMModule.IsExcuteIdleRecipe)                {                    _faCallback.RecipeComplete(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName);                    _dbCallback.RecipeComplete(PMModule.RecipeRunningInfo.InnerId.ToString());                    _fdc.Stop();                }                else                {                    _faCallback.RecipeFailed(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName);                    _dbCallback.RecipeFailed(PMModule.RecipeRunningInfo.InnerId.ToString());                    _fdc.Stop();                };            }        }        public void PauseRecipe()        {            PMModule.IsPaused = true;            ContinueAction = RecipeContinueMode.None;        }        public void ContinueRecipe()        {            PMModule.IsPaused = false;            ContinueAction = RecipeContinueMode.StepContinue;        }        public void SkipCurrentRecipeStep()        {            if (_state == RecipeRunningState.ConditionWait || _state == RecipeRunningState.TimeWait || _state == RecipeRunningState.Paused)            {                _state = RecipeRunningState.StepCompleted;                _loopEnd = true;                PMModule.RecipeRunningInfo.IsLooping = false;                PMModule.RecipeRunningInfo.LoopCountCurrent = 0;                PMModule.RecipeRunningInfo.LoopCountSet = 0;                PMModule.IsPaused = false;                if (!_holdTimer.IsIdle())                {                    _holdTimeElpasedTime += _holdTimer.GetElapseTime();                    _holdTimer.Stop();                }            }            if (IsSubReciep)            {                ResetLoop(PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps, _currentSubRecipeStepNumber);            }            else            {                ResetLoop(PMModule.RecipeRunningInfo.RecipeStepList, _currentStepNumber);            }        }        private void ResetLoop(List<RecipeStep> checkRecipeSeps, int currentStepNumber)        {            if (checkRecipeSeps == null)                return;            var hasLoopStart = false;            for (int i = currentStepNumber; i >= 0; i--)            {                if (checkRecipeSeps[i].IsLoopStartStep)                {                    hasLoopStart = true;                    break;                }                if (checkRecipeSeps[i].IsLoopEndStep)                {                    hasLoopStart = false;//前面有end,说明没有循环                    break;                }            }            if (hasLoopStart)            {                for (int i = currentStepNumber; i < checkRecipeSeps.Count; i++)                {                    if (checkRecipeSeps[i].IsLoopStartStep)                    {                        break;//没有循环                    }                    if (checkRecipeSeps[i].IsLoopEndStep)                    {                        checkRecipeSeps[i].IsLoopEndStep = false;//跳出skip step之间的循环                        break;                    }                }            }        }        public void LeakCheckRetry()        {            JumpCurrentRecipeStep(_currentStepNumber - 1, PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber - 1].StepName);        }        public void JumpCurrentRecipeStep(int stepNumber, string stepName, bool isAlarmConditionCall = false)        {            PMModule.StopLeakCheckTimer();            LOG.Write($"Jump to step stepNumber={stepNumber} stepName={stepName}, currentStepNumber={_currentStepNumber}");            if (_state == RecipeRunningState.ConditionWait || _state == RecipeRunningState.TimeWait ||                _state == RecipeRunningState.Paused || _state == RecipeRunningState.ExecStep)            {                _loopEnd = true;                PMModule.RecipeRunningInfo.IsLooping = false;                PMModule.RecipeRunningInfo.LoopCountCurrent = 0;                PMModule.RecipeRunningInfo.LoopCountSet = 0;                CurrentLoopCount = 0;                CurrentAbortRecipeLoopCount = 0;                CurrentSubRecipeLoopCount = 0;                IsSubReciep = false;                if (IsSubReciep)                {                    _faCallback.RecipeStepEnd(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName, _currentSubRecipeStepNumber + 1);                    _dbCallback.RecipeStepEnd(PMModule.RecipeRunningInfo.InnerId.ToString(), _currentSubRecipeStepNumber + 1, _fdc.DataList, SC.GetStringValue("PM1.TempCorrection"), SC.GetStringValue("PM1.Heater.PID"));                    ResetLoop(PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps, _currentSubRecipeStepNumber);                }                else                {                    _faCallback.RecipeStepEnd(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName, _currentStepNumber);                    _dbCallback.RecipeStepEnd(PMModule.RecipeRunningInfo.InnerId.ToString(), _currentStepNumber, _fdc.DataList, SC.GetStringValue("PM1.TempCorrection"), SC.GetStringValue("PM1.Heater.PID"));                    ResetLoop(PMModule.RecipeRunningInfo.RecipeStepList, _currentStepNumber);                }                if (_callSubSteps != null)                {                    foreach (var key in _callSubSteps.Keys)                    {                        if (PMModule.RecipeRunningInfo.RecipeStepList.Count > key)                        {                            PMModule.RecipeRunningInfo.RecipeStepList[key].IsCallSubStep = _callSubSteps[key].Item1;                            PMModule.RecipeRunningInfo.RecipeStepList[key].SubRecipeLoopCount = _callSubSteps[key].Item2;                        }                    }                    _currentSubRecipeStepNumber = CurSubRecipeStepTotalLoopCount = 0;                }                _isJumpStep = true;                _currentStepNumber = stepNumber - 1;                if (_currentStepNumber < 0)                    _currentStepNumber = 0;                _totalElpasedTime = RefreshElpasedTime();                _state = RecipeRunningState.StepCompleted;                PMModule.IsPaused = false;                if (!_holdTimer.IsIdle())                {                    _holdTimeElpasedTime += _holdTimer.GetElapseTime();                    _holdTimer.Stop();                }            }        }        private double RefreshElpasedTime()        {            double total = 0;            try            {                for (int i = 0; i < _currentStepNumber; i++)                {                    if (!PMModule.RecipeRunningInfo.RecipeStepList[i].IsJumpStep)                    {                        if (PMModule.RecipeRunningInfo.RecipeStepList[i].IsLoopEndStep)                        {                            int iLoopStartStep = PMModule.RecipeRunningInfo.RecipeStepList[i].LoopStartStep;                            for (int j = 0; j < PMModule.RecipeRunningInfo.RecipeStepList[i].LoopCount; j++)                            {                                for (int m = iLoopStartStep; m <= i; m++)                                {                                    if (PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps != null && PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps.Count > _currentSubRecipeStepNumber)                                    {                                        total += SubRecipeCalTotalTime(i) * PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeLoopCount;                                    }                                    total += PMModule.RecipeRunningInfo.RecipeStepList[m].StepTime;                                }                            }                        }                        else                        {                            if (PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps != null &&                                PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps.Count > _currentSubRecipeStepNumber)                            {                                total += SubRecipeCalTotalTime(i) * PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeLoopCount;                            }                            total += PMModule.RecipeRunningInfo.RecipeStepList[i].StepTime;                        }                    }                }            }            catch (Exception ex)            {                LOG.Write(ex);                return -1;            }            return (int)total;        }        public void RespondAlarm(string name)        {            if (!_alarmNames.Contains(name))                _alarmNames.Add(name);        }        protected int CalcRecipeTime()        {            double total = 0;            int iStart = PMModule.IsJobProcess ? 1 : 0;            try            {                for (int i = iStart; i < PMModule.RecipeRunningInfo.RecipeStepList.Count; i++)                //for (int i = PMModule.RecipeRunningInfo.RecipeStepList.Count - 1; i <= iStart; i--)                {                    if (!PMModule.RecipeRunningInfo.RecipeStepList[i].IsJumpStep)                    {                        if (PMModule.RecipeRunningInfo.RecipeStepList[i].IsLoopEndStep)                        {                            int iLoopStartStep = PMModule.RecipeRunningInfo.RecipeStepList[i].LoopStartStep;                            total += PMModule.RecipeRunningInfo.RecipeStepList[i].StepTime;                            for (int j = 0; j < PMModule.RecipeRunningInfo.RecipeStepList[i].LoopCount - 1; j++)                            {                                for (int m = iLoopStartStep; m <= i; m++)                                {                                    if (PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps != null && PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps.Count > _currentSubRecipeStepNumber)                                    {                                        total += SubRecipeCalTotalTime(i) * PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeLoopCount;                                    }                                    total += PMModule.RecipeRunningInfo.RecipeStepList[m].StepTime;                                }                            }                        }                        else                        {                            if (PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps != null && PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps.Count > _currentSubRecipeStepNumber)                            {                                total += SubRecipeCalTotalTime(i) * PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeLoopCount;                            }                            total += PMModule.RecipeRunningInfo.RecipeStepList[i].StepTime;                        }                    }                    else                    {                        i = PMModule.RecipeRunningInfo.RecipeStepList[i].JumpStepNo - 1;// -1是因为i++                    }                }            }            catch (Exception ex)            {                LOG.Write(ex);                return -1;            }            return (int)total;        }        private int AbortRecipeCalTotalTime()        {            double total = 0;            List<RecipeStep> abortRecipeSteps;            abortRecipeSteps = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].AbortRecipeSteps;            try            {                for (int i = 0; i < abortRecipeSteps.Count; i++)                {                    if (!abortRecipeSteps[i].IsJumpStep)                    {                        if (abortRecipeSteps[i].IsLoopStartStep)                        {                            int iLoopEndStep = 0;                            for (int j = 0; j < abortRecipeSteps[i].LoopCount; j++)                            {                                for (int m = i; m < abortRecipeSteps.Count; m++)                                {                                    total += abortRecipeSteps[m].StepTime;                                    if (abortRecipeSteps[m].IsLoopEndStep)                                    {                                        iLoopEndStep = m;                                        break;                                    }                                }                            }                            i = iLoopEndStep;                        }                        else                        {                            total += abortRecipeSteps[i].StepTime;                        }                    }                    else                    {                        i = abortRecipeSteps[i].JumpStepNo - 1;// -1是因为i++                    }                }            }            catch (Exception ex)            {                LOG.Write(ex);                return -1;            }            return (int)total;        }        public void SetContinue(string continueMode)        {            switch (continueMode)            {                case "Step continue":                    ContinueAction = RecipeContinueMode.StepContinue;                    break;                case "Step restart":                    ContinueAction = RecipeContinueMode.StepRestart;                    break;                case "Next step":                    ContinueAction = RecipeContinueMode.NextStep;                    break;                case "Recipe restart":                    ContinueAction = RecipeContinueMode.RecipeRestart;                    break;                case "Recipe complete":                    ContinueAction = RecipeContinueMode.RecipeCompleted;                    break;                case "Wafer return and job stop":                    ContinueAction = RecipeContinueMode.WaferReturnAndJobStop;                    break;            }            PMModule.ResetToleranceChecker();        }        private double SubRecipeCalTotalTime(int currentStepNumber)        {            double total = 0;            for (int k = _currentSubRecipeStepNumber; k < PMModule.RecipeRunningInfo.RecipeStepList[currentStepNumber].SubRecipeSteps.Count; k++)            {                if (!PMModule.RecipeRunningInfo.RecipeStepList[currentStepNumber].SubRecipeSteps[k].IsJumpStep)                {                    if (PMModule.RecipeRunningInfo.RecipeStepList[currentStepNumber].SubRecipeSteps[k].IsLoopEndStep)                    {                        int iSystemLoopStartStep = PMModule.RecipeRunningInfo.RecipeStepList[currentStepNumber].SubRecipeSteps[k].LoopStartStep;                        total += PMModule.RecipeRunningInfo.RecipeStepList[currentStepNumber].SubRecipeSteps[k].StepTime;                        for (int n = 0; n < PMModule.RecipeRunningInfo.RecipeStepList[currentStepNumber].SubRecipeSteps[k].LoopCount - 1; n++)                        {                            for (int l = iSystemLoopStartStep; l <= k; l++)                            {                                total += PMModule.RecipeRunningInfo.RecipeStepList[currentStepNumber].SubRecipeSteps[l].StepTime;                            }                        }                    }                    else                    {                        total += PMModule.RecipeRunningInfo.RecipeStepList[currentStepNumber].SubRecipeSteps[k].StepTime;                    }                }                else                {                    k = PMModule.RecipeRunningInfo.RecipeStepList[currentStepNumber].SubRecipeSteps[k].JumpStepNo - 1;// -1是因为k++                }            }            return total;        }        private void SubRecipeLoopEndCheck(List<RecipeStep> recipeSteps)        {            if (_alarmAction == RecipeAlaramAction.JumpStep || _alarmAction == RecipeAlaramAction.JumpStepCancelCallLoop)            {                _currentSubRecipeStepNumber = _jumpStepNumber;                _alarmAction = RecipeAlaramAction.None;                _alarmNames.Clear();                return;            }            if (recipeSteps[_currentSubRecipeStepNumber].IsLoopEndStep)            {                if (IsJumpStepCancelCallLoop)                {                    _currentSubRecipeStepNumber++;                    IsJumpStepCancelCallLoop = false;                    return;                }                //重新读取循环的设定次数                CurSubRecipeStepTotalLoopCount = recipeSteps[_currentSubRecipeStepNumber].LoopCount;                if (CurrentSubRecipeLoopCount >= CurSubRecipeStepTotalLoopCount)                {                    CurrentSubRecipeLoopCount = CurSubRecipeStepTotalLoopCount = 0;                    _currentSubRecipeStepNumber++;                    PMModule.RecipeRunningInfo.IsLooping = false;                    PMModule.RecipeRunningInfo.LoopCountCurrent = 0;                    PMModule.RecipeRunningInfo.LoopCountSet = 0;                }                else                {                    _currentSubRecipeStepNumber = recipeSteps[_currentSubRecipeStepNumber].LoopStartStep;                }            }            else            {                _currentSubRecipeStepNumber++;            }        }        private void RecipeLoopEndCheck(List<RecipeStep> recipeSteps)        {            if (_alarmAction == RecipeAlaramAction.JumpStep || _alarmAction == RecipeAlaramAction.JumpStepCancelCallLoop)            {                _currentStepNumber = _jumpStepNumber;                _alarmAction = RecipeAlaramAction.None;                _alarmNames.Clear();                return;            }            if (recipeSteps[_currentStepNumber].IsLoopEndStep)            {                if (IsJumpStepCancelCallLoop)                {                    _currentStepNumber++;                    IsJumpStepCancelCallLoop = false;                    return;                }                //重新读取循环的设定次数                CurStepTotalLoopCount = recipeSteps[_currentStepNumber].LoopCount;                if (CurrentLoopCount >= CurStepTotalLoopCount)                {                    CurrentLoopCount = CurStepTotalLoopCount = 0;                    _currentStepNumber++;                    PMModule.RecipeRunningInfo.IsLooping = false;                    PMModule.RecipeRunningInfo.LoopCountCurrent = 0;                    PMModule.RecipeRunningInfo.LoopCountSet = 0;                }                else                {                    _currentStepNumber = recipeSteps[_currentStepNumber].LoopStartStep;                }            }            else            {                _currentStepNumber++;            }        }        private void CheckTolerance()        {            //foreach (var key in _trigMfcToleranceAlarms.Keys)            //{            //    if (PMModule.GasMFCs.ContainsKey(key) && _trigMfcToleranceWarnings.ContainsKey(key))            //    {            //        _trigMfcToleranceAlarms[key].CLK = PMModule.GasMFCs[key].CheckToleranceAlarm();            //        if (_trigMfcToleranceAlarms[key].Q)            //            PMModule.GasMFCs[key].SetToleranceAlarm();            //        _trigMfcToleranceWarnings[key].CLK = PMModule.GasMFCs[key].CheckToleranceWarning();            //        if (_trigMfcToleranceWarnings[key].Q && !_trigMfcToleranceAlarms[key].Q)            //            PMModule.GasMFCs[key].SetToleranceWarning();            //    }            //}            //_trigHeaterBottomToleranceAlarm.CLK = PMModule.CheckHeaterBottomToleranceAlaram();            //if (_trigHeaterBottomToleranceAlarm.Q)            //    PMModule.SetHeaterBottomToleranceAlaram();            //_trigHeaterBottomToleranceWarning.CLK = PMModule.CheckHeaterBottomToleranceWarning();            //if (_trigHeaterBottomToleranceWarning.Q && !_trigHeaterBottomToleranceAlarm.Q)            //    PMModule.SetHeaterBottomToleranceWarning();            //_trigHeaterCenterBottomToleranceAlarm.CLK = PMModule.CheckHeaterCenterBottomToleranceAlaram();            //if (_trigHeaterCenterBottomToleranceAlarm.Q)            //    PMModule.SetHeaterCenterBottomToleranceAlaram();            //_trigHeaterCenterBottomToleranceWarning.CLK = PMModule.CheckHeaterCenterBottomToleranceWarning();            //if (_trigHeaterCenterBottomToleranceWarning.Q && !_trigHeaterCenterBottomToleranceAlarm.Q)            //    PMModule.SetHeaterCenterBottomToleranceWarning();            //_trigHeaterCenterToleranceAlarm.CLK = PMModule.CheckHeaterCenterToleranceAlaram();            //if (_trigHeaterCenterToleranceAlarm.Q)            //    PMModule.SetHeaterCenterToleranceAlaram();            //_trigHeaterCenterToleranceWarning.CLK = PMModule.CheckHeaterCenterToleranceWarning();            //if (_trigHeaterCenterToleranceWarning.Q && !_trigHeaterCenterToleranceAlarm.Q)            //    PMModule.SetHeaterCenterToleranceWarning();            //_trigHeaterCenterTopToleranceAlarm.CLK = PMModule.CheckHeaterCenterTopToleranceAlaram();            //if (_trigHeaterCenterTopToleranceAlarm.Q)            //    PMModule.SetHeaterCenterTopToleranceAlaram();            //_trigHeaterCenterTopToleranceWarning.CLK = PMModule.CheckHeaterCenterTopToleranceWarning();            //if (_trigHeaterCenterTopToleranceWarning.Q && !_trigHeaterCenterTopToleranceAlarm.Q)            //    PMModule.SetHeaterCenterTopToleranceWarning();            //_trigHeaterTopToleranceAlarm.CLK = PMModule.CheckHeaterTopToleranceAlaram();            //if (_trigHeaterTopToleranceAlarm.Q)            //    PMModule.SetHeaterTopToleranceAlaram();            //_trigHeaterTopToleranceWarning.CLK = PMModule.CheckHeaterTopToleranceWarning();            //if (_trigHeaterTopToleranceWarning.Q && !_trigHeaterTopToleranceAlarm.Q)            //    PMModule.SetHeaterTopToleranceWarning();            //_trigPressureToleranceAlarm.CLK = PMModule.CheckPressureToleranceAlaram();            //if (_trigPressureToleranceAlarm.Q)            //    PMModule.SetPressureToleranceAlaram();            //_trigPressureToleranceWarning.CLK = PMModule.CheckPressureToleranceWarning();            //if (_trigPressureToleranceWarning.Q && !_trigPressureToleranceAlarm.Q)            //    PMModule.SetPressureToleranceWarning();        }        private void ResetTrig()        {            PMModule.ResetAlarmCondition();            foreach (var key in _trigMfcToleranceAlarms.Keys)            {                if (_trigMfcToleranceWarnings.ContainsKey(key))                {                    _trigMfcToleranceAlarms[key].RST = true;                    _trigMfcToleranceWarnings[key].RST = true;                }            }            _trigHeaterBottomToleranceAlarm.RST = true;            _trigHeaterBottomToleranceWarning.RST = true;            _trigHeaterCenterBottomToleranceAlarm.RST = true;            _trigHeaterCenterBottomToleranceWarning.RST = true;            _trigHeaterCenterToleranceAlarm.RST = true;            _trigHeaterCenterToleranceWarning.RST = true;            _trigHeaterCenterTopToleranceAlarm.RST = true;            _trigHeaterCenterTopToleranceWarning.RST = true;            _trigHeaterTopToleranceAlarm.RST = true;            _trigHeaterTopToleranceWarning.RST = true;            _trigPressureToleranceAlarm.RST = true;            _trigPressureToleranceWarning.RST = true;            _trigInputSignalTimeOutAlarm.RST = true;            _trigTemperatureConvergenceTimeOutAlarm.RST = true;            _trigReachTempTimeOutAlarm.RST = true;            _trigPressureConvergenceTimeOutAlarm.RST = true;            _trigReachPressureTimeOutAlarm.RST = true;            _trigAutoProfileTimeOutAlarm.RST = true;            _trigHeaterProfileFinish.RST = true;            _trigLeakCheckFinish.RST = true;            _trigBoatWaitCondition.RST = true;            _trigAPCWaitCondition.RST = true;            _trigAUXWaitCondition.RST = true;            _trigHeaterWaitCondition.RST = true;            _trigMFCWaitCondition.RST = true;            _infoHeaterProfileFinish = "";            _infoAUXWaitCondition = "";            _infoHeaterWaitCondition = "";            _infoMFCWaitCondition = "";        }        private int GetDBRecipeType(string recipeTypeName)        {            if (string.IsNullOrEmpty(recipeTypeName))                return (int)RecipeTypeEnum.none;            if (Enum.TryParse<RecipeTypeEnum>(recipeTypeName, true, out var result))                return (int)result;            return (int)RecipeTypeEnum.none;        }        private void RecipeExec(string type, List<RecipeStep> curSteps, int currentStepNumber, double curStepElpasedTimeBeforePaused, int otherRecipeStartStepNumber = 0)        {            var reason = "";            _stepTimer.Start(curSteps[currentStepNumber].StepTime * 1000 - curStepElpasedTimeBeforePaused);            _showStepNo = currentStepNumber;            Notify($"{type} running step {currentStepNumber + 1}:{curSteps[currentStepNumber].StepName}");            var stopwatch = new Stopwatch();            stopwatch.Start();            //执行工艺程序命令            foreach (var recipeCmd in curSteps[currentStepNumber].RecipeCommands.Keys)            {                if (!OP.CanDoOperation($"{_doModule}.{recipeCmd}", out reason, curSteps[currentStepNumber].RecipeCommands[recipeCmd]))                {                    if (!OP.CanDoOperation($"{Module}.{recipeCmd}", out reason, curSteps[currentStepNumber].RecipeCommands[recipeCmd]))                    {                        if (!OP.CanDoOperation($"{ModuleName.System}.{recipeCmd}", out reason, curSteps[currentStepNumber].RecipeCommands[recipeCmd]))                        {                            PMModule.CheckCanDoOperationAlarm.Set($"Can not execute {recipeCmd}, {reason}");                            return;                        }                        else                        {                            OP.DoOperation($"{ModuleName.System}.{recipeCmd}", out string reason1, 0, curSteps[currentStepNumber].RecipeCommands[recipeCmd]);                        }                    }                    else                    {                        OP.DoOperation($"{Module}.{recipeCmd}", out string reason1, 0, curSteps[currentStepNumber].RecipeCommands[recipeCmd]);                    }                }                else                {                    OP.DoOperation($"{_doModule}.{recipeCmd}", out string reason1, 0, curSteps[currentStepNumber].RecipeCommands[recipeCmd]);                }            }            LOG.Write($"step exec time {stopwatch.ElapsedMilliseconds}");            if (curSteps[currentStepNumber].EndBy == EnumEndByCondition.ByTime && !PMModule.IsBoatMoveToLoadPosition)                _state = RecipeRunningState.TimeWait;            else                _state = RecipeRunningState.ConditionWait;            _faCallback.RecipeStepStart(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName, otherRecipeStartStepNumber != 0 ? otherRecipeStartStepNumber : currentStepNumber);            if (type == "Sub recipe")                _dbCallback.RecipeStepStart(PMModule.RecipeRunningInfo.InnerId.ToString(), _currentStepNumber, PMModule.RecipeRunningInfo.RecipeStepList.Count > _currentStepNumber ? PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepName : "",                    PMModule.RecipeRunningInfo.RecipeStepList.Count > _currentStepNumber ? (float)PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime : 0,                    $"{(otherRecipeStartStepNumber != 0 ? otherRecipeStartStepNumber : currentStepNumber)}", curSteps[currentStepNumber].StepName, (float)curSteps[currentStepNumber].StepTime,                    $"{PMModule.RecipeRunningInfo.SubRecipeCurrentLoopCount}/{PMModule.RecipeRunningInfo.SubRecipeLoopCount}");            else                _dbCallback.RecipeStepStart(PMModule.RecipeRunningInfo.InnerId.ToString(), otherRecipeStartStepNumber != 0 ? otherRecipeStartStepNumber : currentStepNumber,                    curSteps[currentStepNumber].StepName, (float)curSteps[currentStepNumber].StepTime, "", "", 0, "");            _fdc.Start(curSteps[currentStepNumber].RecipeCommands);        }    }}
 |