| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802 | 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;        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.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;                                    }                                    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;                                    }                                    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);        }         }}
 |