123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939 |
- using System;
- using System.Collections.Generic;
- using System.Xml;
- using Aitex.Core.RT.Device;
- using Aitex.Core.RT.Event;
- using Aitex.Core.RT.Job;
- using Aitex.Core.RT.Log;
- using Aitex.Core.RT.RecipeCenter;
- using Aitex.Core.RT.Routine;
- using Aitex.Core.Util;
- using Aitex.Core.RT.SCCore;
- using Aitex.Platform;
- using Aitex.RT.Properties;
- using Aitex.Triton160.Common;
- using Aitex.Triton160.RT.Device;
- using Aitex.Triton160.RT.Module;
- namespace Aitex.Triton160.RT.Routine.Process
- {
- public class Process : CommonRoutine
- {
- /// <summary>
- /// 工艺程序运行引擎状态定义
- /// </summary>
- enum RecipeEngineState
- {
- Error,
- RecipeCompleted,
- ExecStep,
- TimeWait,
- ConditionWait,
- StepCompleted,
- Paused,
- }
- enum CycleCountResetFlag
- {
- ResetByDay,
- ResetByRecipe,
- }
- /// <summary>
- /// 工艺程序数据
- /// </summary>
- private object _lockerTotalCycle = new object();
- private Dictionary<string, int> _recipeTotalCycle = new Dictionary<string, int>();
- //public bool IsAtmRecipeRun { private set; get; }
- private DeviceTimer _beginPauseTimer = new DeviceTimer();
- /// <summary>
- /// 防止工艺程序运行线程和外部更新工艺程序数据的线程并发进行
- /// </summary>
- private object _recipeLocker = new object();
- /// <summary>
- /// 当前工艺执行引擎的状态
- /// </summary>
- private RecipeEngineState _state = RecipeEngineState.ExecStep;
- private RecipeEngineState _pausedState = RecipeEngineState.ExecStep;
- private DeviceTimer _estimatedTimeCalcTimer = new DeviceTimer();//用于定时计算工艺程序估计的结束时间
- private int _currentRecipeCycleCount = 0;
- private string _previousRecipeName;
- private string _processCompleteInfo;
- private bool _isProcessCompleted;
- public DateTime RecipeStartTime
- {
- get;
- private set;
- }
- public int RecipeChangeNo
- {
- get;
- private set;
- }
- public string CurrentRecipeBaseName { get; private set; }
- public string CurrentRecipeRunningName { get; private set; }
- public string CurrentRecipeContent { get; private set; }
- public string CurrentLotName
- {
- get; set;
- }
- public string CurrentJobName
- {
- get;
- set;
- }
- private List<RecipeStep> _recipeStepList = new List<RecipeStep>();
- public List<RecipeStep> CurrentRecipeStepList
- {
- get
- {
- return _recipeStepList;
- }
- set
- {
- _recipeStepList = value;
- }
- }
- public RecipeHead CurrentRecipeHead
- {
- get; set;
- }
- public int CurStepNum
- {
- get;
- private set;
- }
- public int CurStepTotalLoopCount
- {
- get;
- private set;
- }
- public double CurStepTotalTime
- {
- get
- {
- if (_recipeStepList == null || _recipeStepList.Count == 0 || _state == RecipeEngineState.RecipeCompleted || _state == RecipeEngineState.Error)
- return 0;
- return _recipeStepList[CurStepNum].StepTime * 1000;
- }
- }
- public int CurrentLoopCount
- {
- get;
- private set;
- }
- private DeviceTimer StepTimer = new DeviceTimer();
- public bool IsPaused
- {
- private set;
- get;
- }
- public string CurStepComment
- {
- get
- {
- if (_recipeStepList == null || _recipeStepList.Count == 0)
- return String.Empty;
- return _recipeStepList[CurStepNum].StepName;
- }
- }
- public double CurStepLeftTime
- {
- get
- {
- if (IsPaused)
- return StepTimer.GetTotalTime() - StepTimer.GetElapseTime() + _beginPauseTimer.GetElapseTime();
- //return Math.Max(0,StepTimer.GetTotalTime() - StepTimer.GetElapseTime());
- return StepTimer.GetTotalTime() - StepTimer.GetElapseTime();
- }
- }
- public double CurStepElpasedTime
- {
- get
- {
- if (_recipeStepList == null || _recipeStepList.Count == 0 || _state == RecipeEngineState.RecipeCompleted || _state == RecipeEngineState.Error)
- return 0;
- return StepTimer.GetElapseTime();
- }
- }
- public double CurStepTotalRfTime
- {
- get
- {
- if (_recipeStepList == null || _recipeStepList.Count == 0 || _state == RecipeEngineState.RecipeCompleted || _state == RecipeEngineState.Error)
- return 0;
- if (_recipeStepList[CurStepNum].RecipeCommands.ContainsKey("Rf.SetPower") &&
- !string.IsNullOrEmpty(_recipeStepList[CurStepNum].RecipeCommands["Rf.SetPower"]) &&
- (Convert.ToDouble(_recipeStepList[CurStepNum].RecipeCommands["Rf.SetPower"]) > 0.1))
- return CurStepTotalTime;
- return 0;
- }
- }
- public int TotalCycle
- {
- get
- {
- if (string.IsNullOrEmpty(DateTimeRecipeBaseName))
- return 0;
- var ResetFlag = (int)SC.GetValue<double>(SCName.ProcessConfig_RecipeCycleCouterFlag);
- lock (_lockerTotalCycle)
- {
- if (ResetFlag == (int)CycleCountResetFlag.ResetByDay)
- {
- if (_recipeTotalCycle.ContainsKey(DateTimeRecipeBaseName))
- return _recipeTotalCycle[DateTimeRecipeBaseName];
- }
- else
- {
- return _currentRecipeCycleCount;
- }
- }
- return 0;
- }
- }
- public string DateTimeRecipeBaseName
- {
- get
- {
- if (string.IsNullOrEmpty(CurrentRecipeBaseName))
- return "";
- return DateTime.Now.ToString("yyyyMMdd") + CurrentRecipeBaseName;
- }
- }
- public double PausedTime
- {
- get
- {
- return IsPaused ? _beginPauseTimer.GetElapseTime() : 0;
- }
- }
- public double EstimatedTotalLeftTime
- {
- get;
- private set;
- }
- public int RecipeTotalStepNum
- {
- get
- {
- return _recipeStepList.Count;
- }
- }
- public Process(string module, string name)
- {
- Module = module;
- Name = name;
- Display = Resources.Process_Process_Process;
- RecipeStartTime = new DateTime(0);
- EstimatedTotalLeftTime = 0;
- }
- public bool Initialize()
- {
- InitCommon();
- CalcEstimatedRecipeEndTime();
- return true;
- }
- public Result Start(params object[] param)
- {
- RecipeStartTime = DateTime.Now;
- CurrentRecipeBaseName = (string)param[0];
- if (String.Equals(_previousRecipeName,CurrentRecipeBaseName))
- _currentRecipeCycleCount++;
- else
- {
- _currentRecipeCycleCount = 1;
- _previousRecipeName = CurrentRecipeBaseName;
- }
- CurrentRecipeRunningName = (string)param[1];
- RecipeChangeNo = (int)param[2];
- CurrentLotName = (string)param[3];
- CurrentRecipeContent = (string)param[4];
- CurrentRecipeHead = (RecipeHead)param[5];
- CurrentRecipeStepList = (List<RecipeStep>)param[6];
- CurrentJobName = (string)param[7];
- lock (_lockerTotalCycle)
- {
- if (_recipeTotalCycle.ContainsKey(DateTimeRecipeBaseName))
- _recipeTotalCycle[DateTimeRecipeBaseName] += 1;
- else
- {
- _recipeTotalCycle[DateTimeRecipeBaseName] = 1;
- }
- List<string> keys = new List<string>();
- foreach (KeyValuePair<string, int> item in _recipeTotalCycle)
- {
- if (!item.Key.StartsWith(DateTime.Now.ToString("yyyyMMdd")))
- keys.Add(item.Key);
- }
- foreach (string key in keys)
- {
- _recipeTotalCycle.Remove(key);
- }
- }
- CurStepNum = CurStepTotalLoopCount = 0;
- _estimatedTimeCalcTimer.Start(1000);
- //TmService.NotifySusceptorStatusChanged(RecipeName, SusceptorStatus.InProcessing); //@AAA
- EV.PostSoundMessage(String.Format("Run Recipe {0}", CurrentRecipeRunningName));
- EV.PostMessage(Module, EventEnum.RecipeStart, Module, CurrentRecipeRunningName);
- //更新当前的工艺状态到数据库中
- Singleton<PMEntity>.Instance.CurrentRunningJob.JobResult = JobStatus.InProcessing;
- Singleton<ProcessRecorder>.Instance.UpdateProcessStatus(Singleton<PMEntity>.Instance.CurrentRunningJob.RecipeRunId, JobStatus.InProcessing);
- _state = RecipeEngineState.ExecStep;
- return Result.RUN;
- }
- public void PopProcessEndDialog()
- {
- if(_isProcessCompleted)
- {
- if (_trigExitMessage.Q)
- {
- EV.PostPopDialogMessage(EventLevel.InformationNoDelay, string.Format(Resources.Process_Exit_0RecipeCompletelyRun, Module), _processCompleteInfo);
- }
- }
- else
- {
- EV.PostPopDialogMessage(EventLevel.Warning, string.Format(Resources.Process_Exit_0RecipeWasAborted, Module), _processCompleteInfo);
- }
- }
- /// <summary>
- /// quiting current state
- /// </summary>
- /// <param name="nextState"></param>
- public void Exit()
- {
- if (DeviceModel.PressureControl != null)
- {
- DeviceModel.PressureControl.EnableTolerance = false;
- }
- var ts = DateTime.Now - RecipeStartTime;
- var totalTime = string.Format("{0}:{1}:{2}", Convert.ToInt32(ts.TotalHours), ts.Minutes, ts.Seconds);
- JobInfo job = Singleton<PMEntity>.Instance.CurrentRunningJob;
- _isProcessCompleted = _state == RecipeEngineState.RecipeCompleted;
- if (_isProcessCompleted)
- {
- //正常工艺运行结束
- Singleton<ProcessRecorder>.Instance.AddRecord(job.RecipeRunId, CarrierDataType.ProcessNormalEnd, totalTime, "recipe finished");
- _processCompleteInfo = string.Format(Resources.Process_Exit_Recipe0RNStartTime1RNEndTime2RNTotalTime3,
- CurrentRecipeRunningName, RecipeStartTime.ToString("yyyy/MM/dd HH:mm:ss"),
- DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), totalTime);
- EV.PostMessage(Module, EventEnum.ProcessSuccEnd, Module, _processCompleteInfo);
- _trigExitMessage.CLK = true;
-
- job.JobResult = JobStatus.Processed;
- }
- else
- {
- //人为终止工艺运行结束
- Singleton<ProcessRecorder>.Instance.AddRecord(job.RecipeRunId, CarrierDataType.PostProcessErrorEnd, totalTime, "recipe aborted");
- string _processCompleteInfo = string.Format(Resources.Process_Exit_Recipe0RNStartTime1RNEndTime2RNTotalTime3,
- CurrentRecipeRunningName, RecipeStartTime.ToString("yyyy/MM/dd HH:mm:ss"),
- DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), totalTime);
- EV.PostMessage(Module, EventEnum.RecipeAborted, Module, _processCompleteInfo);
- //TmProxy.NotifyProcessEnded(false);
- //Update susceptor information
- job.JobResult = JobStatus.Troubled;
- }
- if((int)SC.GetValue<double>(SCName.ProcessConfig_ProcessFinishedReminderFlag) == 0)
- {
- PopProcessEndDialog();
- }
- job.ProcessEndTime = DateTime.Now;
- //重置工艺程序名
- CurrentRecipeRunningName = string.Empty;
- CurrentLotName = string.Empty;
- //stop all ramping when quiting processing state
- StopRamp();
- }
- private void CheckPressureStability()
- {
- //如果有ThrottleValve 就检查Throttle Valve的tolerance
- if (DeviceModel.PressureControl != null)
- {
- DeviceModel.PressureControl.EnableTolerance =
- (DeviceModel.MfcGas1 != null && DeviceModel.MfcGas1.SetPoint > 0.001) ||
- (DeviceModel.MfcGas2 != null && DeviceModel.MfcGas2.SetPoint > 0.001) ||
- (DeviceModel.MfcGas3 != null && DeviceModel.MfcGas3.SetPoint > 0.001) ||
- (DeviceModel.MfcGas4 != null && DeviceModel.MfcGas4.SetPoint > 0.001) ||
- (DeviceModel.MfcGas5 != null && DeviceModel.MfcGas5.SetPoint > 0.001);
- }
- }
- /// <summary>
- /// 工艺程序运行引擎放于此处
- /// </summary>
- public Result Monitor()
- {
- string reason = string.Empty;
- CalcEstimatedRecipeEndTime();
- //检查软件互锁是否强制停止运行工艺程序
- //if (!doRoutineRunning.Value)
- //{
- // if (!doRoutineRunning.Check(true, out reason))
- // {
- // EV.PostMessage(Module, EventEnum.RecipeAbortedByInterlock, Module, reason);
- // return Result.FAIL; // Reactor.PostEvent(new AlarmHandleCommand("软件互锁"));
- // }
- //}
- //工艺程序运行监控,自动打开阀门如果对应的MFC设定设置大于0
- if (DeviceModel.ValveMfc1 != null && DeviceModel.MfcGas1 != null)
- DeviceModel.ValveMfc1.TurnValve(DeviceModel.MfcGas1.SetPoint > 0, out reason);
- if (DeviceModel.ValveMfc2 != null && DeviceModel.MfcGas2 != null)
- DeviceModel.ValveMfc2.TurnValve(DeviceModel.MfcGas2.SetPoint > 0, out reason);
- if (DeviceModel.ValveMfc3 != null && DeviceModel.MfcGas3 != null)
- DeviceModel.ValveMfc3.TurnValve(DeviceModel.MfcGas3.SetPoint > 0, out reason);
- if (DeviceModel.ValveMfc4 != null && DeviceModel.MfcGas4 != null)
- DeviceModel.ValveMfc4.TurnValve(DeviceModel.MfcGas4.SetPoint > 0, out reason);
- if (DeviceModel.ValveMfc5 != null && DeviceModel.MfcGas5 != null)
- DeviceModel.ValveMfc5.TurnValve(DeviceModel.MfcGas5.SetPoint > 0, out reason);
- if (DeviceModel.ValveProcessGasFinal != null)
- {
- DeviceModel.ValveProcessGasFinal.TurnValve(
- (DeviceModel.MfcGas1 != null && DeviceModel.MfcGas1.SetPoint > 0)
- || (DeviceModel.MfcGas2 != null && DeviceModel.MfcGas2.SetPoint > 0)
- || (DeviceModel.MfcGas3 != null && DeviceModel.MfcGas3.SetPoint > 0)
- || (DeviceModel.MfcGas4 != null && DeviceModel.MfcGas4.SetPoint > 0)
- || (DeviceModel.MfcGas5 != null && DeviceModel.MfcGas5.SetPoint > 0), out reason);
- }
- //工艺程序运行引擎
- lock (_recipeLocker)
- {
- try
- {
- switch (_state)
- {
- case RecipeEngineState.ExecStep:
- {
- //工艺程序循环设置
- if (_recipeStepList[CurStepNum].IsLoopStartStep)
- {
- CurStepTotalLoopCount = _recipeStepList[CurStepNum].LoopCount;
- if (CurStepTotalLoopCount == 0)
- {
- CurrentLoopCount = 0;
- }
- else
- {
- CurrentLoopCount++;
- }
- }
- //当前工艺程序步的定时器设定
- StepTimer.Start(_recipeStepList[CurStepNum].StepTime * 1000);
- Singleton<ProcessRecorder>.Instance.AddRecord(Singleton<PMEntity>.Instance.CurrentRunningJob.RecipeRunId, CarrierDataType.RecipeStepStart, (CurStepNum + 1).ToString(), string.Format(Resources.Process_Monitor_RecipeRunningStartStep01, CurStepNum + 1, _recipeStepList[CurStepNum].StepName));
- //发送信息到用户界面
- EV.PostMessage(Module, EventEnum.RecipeStepStart, Module, CurrentRecipeRunningName, CurStepNum + 1, _recipeStepList[CurStepNum].StepName);
- //执行工艺程序命令
- foreach (var recipeCmd in _recipeStepList[CurStepNum].RecipeCommands.Keys)
- {
- if (!DEVICE.CanDo(recipeCmd))
- {
- EV.PostMessage(Module, EventEnum.RecipeItemUnknow, Module, recipeCmd);
- }
- else
- {
- var rampTime_ms = (int)(_recipeStepList[CurStepNum].StepTime * 1000);
- if (_recipeStepList[CurStepNum].IsJumpStep)
- rampTime_ms = 0;
- DEVICE.Do(recipeCmd, rampTime_ms, false, _recipeStepList[CurStepNum].RecipeCommands[recipeCmd]);
- }
- }
- //if (string.IsNullOrEmpty(_recipeStepList[CurStepNum].EndBy) || String.Compare(_recipeStepList[CurStepNum].EndBy, "None", true) == 0)
- {
- _state = RecipeEngineState.TimeWait;
- }
- //else
- //{
- // _state = RecipeEngineState.ConditionWait;
- //}
- }
- break;
- case RecipeEngineState.TimeWait:
- CheckPressureStability();
- if (StepTimer.IsTimeout())
- {
- _state = RecipeEngineState.StepCompleted;
- }
- break;
- case RecipeEngineState.ConditionWait:
- {
- //var endbyCondition = (EndByCondition)Enum.Parse(typeof(EndByCondition), _recipeStepList[CurStepNum].EndBy, true);
- //var endbyValue = Convert.ToDouble(_recipeStepList[CurStepNum].EndByValue);
- //if (isStepEndby(endbyCondition, endbyValue))
- {
- _state = RecipeEngineState.StepCompleted;
- }
- }
- break;
- case RecipeEngineState.Paused:
- break;
- case RecipeEngineState.StepCompleted:
- {
- //发送新的一步开始的信息到用户界面
- EV.PostMessage(Module, EventEnum.RecipeStepComplete, Module, CurrentRecipeRunningName, CurStepNum + 1);
- //添加石墨盘信息
- Singleton<ProcessRecorder>.Instance.AddRecord(Singleton<PMEntity>.Instance.CurrentRunningJob.RecipeRunId, CarrierDataType.RecipeStepNormalEnd, (CurStepNum + 1).ToString(), string.Format("recipe running:end step {0}", CurStepNum + 1));
- //判断是否当前步循环终止
- if (_recipeStepList[CurStepNum].IsLoopEndStep)
- {
- //重新读取循环的设定次数
- for (int nn = CurStepNum; nn >= 0; nn--)
- {
- if (_recipeStepList[nn].IsLoopStartStep)
- {
- CurStepTotalLoopCount = _recipeStepList[nn].LoopCount;
- break;
- }
- }
- if (CurrentLoopCount >= CurStepTotalLoopCount)
- {
- CurrentLoopCount = CurStepTotalLoopCount = 0;
- CurStepNum++;
- }
- else
- {
- int n = CurStepNum - 1;
- int next = -1;
- while (n >= 0)
- {
- if (_recipeStepList[n].IsLoopStartStep)
- {
- next = n;
- break;
- }
- n--;
- }
- if (next == -1)
- throw new Exception("Loop End control error");
- CurStepNum = next;
- }
- }
- else
- {
- CurStepNum++;
- }
- if (CurStepNum >= _recipeStepList.Count)
- {
- //EV.PostMessage(Module, EventEnum.RecipeComplete, Module, RecipeName);
- CurStepNum = _recipeStepList.Count - 1;
- _state = RecipeEngineState.RecipeCompleted;
- return Result.DONE;
- }
- else
- {
- _state = RecipeEngineState.ExecStep;
- }
- }
- break;
- case RecipeEngineState.RecipeCompleted:
- {
- return Result.DONE;
- }
- case RecipeEngineState.Error:
- return Result.FAIL;
- default:
- break;
- }
- }
- catch (Exception ex)
- {
- EV.PostMessage(Module, EventEnum.RecipeProcessException, Module, CurStepNum + 1, "语法错误");
- LOG.Write(ex);
- return Result.FAIL;
- }
- }
- return Result.RUN;
- }
- /// <summary>
- /// 暂停工艺程序运行
- /// </summary>
- public void PauseRecipe()
- {
- if (_state != RecipeEngineState.TimeWait && _state != RecipeEngineState.ConditionWait)
- return;
- if (!IsPaused)
- {
- string reason = String.Empty;
- IsPaused = true;
- _pausedState = _state;
- _state = RecipeEngineState.Paused;
- _beginPauseTimer.Start(0);
- Singleton<ProcessRecorder>.Instance.AddRecord(Singleton<PMEntity>.Instance.CurrentRunningJob.RecipeRunId, CarrierDataType.RecipeStepPaused, CurStepNum.ToString(), string.Format(Resources.Process_PauseRecipe_工艺运行中当前第0步暂停, CurStepNum + 1));
- EV.PostMessage(Module, EventEnum.RecipePaused, Module, CurrentRecipeRunningName, CurStepNum + 1);
- //pause mfc
- //pause pc
- StopRamp();
- }
- }
- /// <summary>
- /// 恢复工艺程序运行
- /// </summary>
- public void ResumeRecipe()
- {
- if (IsPaused)
- {
- //update current recipe step time
- string recipeXml = CurrentRecipeContent;
- int currentStepNo = CurStepNum;
- XmlDocument xmlDoc = new XmlDocument();
- xmlDoc.LoadXml(recipeXml);
- var stepNodes = xmlDoc.SelectNodes("/TableRecipeData/Step");
- if (currentStepNo >= 0 && currentStepNo < stepNodes.Count)
- {
- var curStepNode = stepNodes[currentStepNo] as XmlElement;
- var curStepNewTime = CurStepTotalTime + PausedTime;
- if (curStepNewTime < 0)
- curStepNewTime = 0;
- TimeSpan tspan = new TimeSpan(0, 0, 0, 0, (int)curStepNewTime);
- var timeString = string.Format("{0}:{1}:{2}", ((int)tspan.TotalHours).ToString("00"), tspan.Minutes.ToString("00"), tspan.Seconds.ToString("00"));
- curStepNode.SetAttribute("Time", timeString);
- LOG.Write(string.Format("执行Resume命令,将当前第{0}步时间修改为{1}", currentStepNo, timeString));
- UpdateRecipe(xmlDoc.OuterXml);
- }
- //Resume recipe
- IsPaused = false;
- _state = _pausedState;
- Singleton<ProcessRecorder>.Instance.AddRecord(Singleton<PMEntity>.Instance.CurrentRunningJob.RecipeRunId, CarrierDataType.RecipeStepResume, CurStepNum.ToString(), string.Format("工艺运行中:当前第{0}步,取消暂停", CurStepNum + 1));
- EV.PostMessage(Module, EventEnum.RecipeResumed, Module, CurrentRecipeRunningName, CurStepNum + 1);
- //resume recipe
- double stepElapsedTime = StepTimer.GetElapseTime() - _beginPauseTimer.GetElapseTime();
- double stepLeftTime = StepTimer.GetTotalTime() - stepElapsedTime;
- if (stepLeftTime < 0)
- stepLeftTime = 0;
- //更新当前步的定时器时间
- StepTimer.Restart(StepTimer.GetTotalTime() + _beginPauseTimer.GetElapseTime());
- //重新执行当前工艺程序步
- foreach (var recipeCmd in _recipeStepList[CurStepNum].RecipeCommands.Keys)
- {
- if (!DEVICE.CanDo(recipeCmd))
- {
- EV.PostMessage(Module, EventEnum.RecipeItemUnknow, Module, recipeCmd);
- }
- else
- {
- var rampTime_ms = (int)(_recipeStepList[CurStepNum].StepTime * 1000);
- if (_recipeStepList[CurStepNum].IsJumpStep)
- rampTime_ms = 0;
- DEVICE.Do(recipeCmd, rampTime_ms, false, _recipeStepList[CurStepNum].RecipeCommands[recipeCmd]);
- }
- }
- }
- }
- /// <summary>
- /// 终止工艺程序运行
- /// </summary>
- public void AbortRecipe()
- {
- ResumeRecipe();
- _state = RecipeEngineState.RecipeCompleted;
- CalcEstimatedRecipeEndTime();
- StopRamp();
- //send informational event
- Singleton<ProcessRecorder>.Instance.AddRecord(Singleton<PMEntity>.Instance.CurrentRunningJob.RecipeRunId, CarrierDataType.RecipeStepResume, CurStepNum.ToString(), string.Format("recipe running:aborted in step {0}", CurStepNum + 1));
- EV.PostMessage(Module, EventEnum.RecipeAborted, Module, Resources.Process_AbortRecipe_UserAbortedRecipe);
- }
- /// <summary>
- /// 跳至工艺程序下一步
- /// </summary>
- public void SkipCurrentRecipeStep()
- {
- if (_state == RecipeEngineState.Paused)
- {
- EV.PostMessage(Module, EventEnum.ReactorCmdReject, Module, "Pause Recipe", "Skip to next step");
- return;
- }
- try
- {
- //update current recipe step time
- string recipeXml = CurrentRecipeContent;
- int currentStepNo = CurStepNum;
- XmlDocument xmlDoc = new XmlDocument();
- xmlDoc.LoadXml(recipeXml);
- var stepNodes = xmlDoc.SelectNodes("/TableRecipeData/Step");
- if (currentStepNo >= 0 && currentStepNo < stepNodes.Count)
- {
- var curStepNode = stepNodes[currentStepNo] as XmlElement;
- var curStepElapsedTime = CurStepTotalTime - CurStepLeftTime;//ms
- if (curStepElapsedTime < 0)
- curStepElapsedTime = 0;
- TimeSpan tspan = new TimeSpan(0, 0, 0, 0, (int)curStepElapsedTime);
- var timeString = string.Format("{0}:{1}:{2}", ((int)tspan.TotalHours).ToString("00"), tspan.Minutes.ToString("00"), tspan.Seconds.ToString("00"));
- curStepNode.SetAttribute("Time", timeString);
- LOG.Write(string.Format("step skipped,step {0} time changed to {1}", currentStepNo, timeString));
- //recipe update command
- UpdateRecipe(xmlDoc.OuterXml);
- }
- }
- catch (Exception ex)
- {
- LOG.Write(ex);
- }
- if (_state == RecipeEngineState.ConditionWait || _state == RecipeEngineState.TimeWait)
- {
- _state = RecipeEngineState.StepCompleted;
- //send informational event
- EV.PostMessage(Module, EventEnum.RecipeStepSkipped, Module, CurrentRecipeRunningName, CurStepNum + 1);
- Singleton<ProcessRecorder>.Instance.AddRecord(Singleton<PMEntity>.Instance.CurrentRunningJob.RecipeRunId, CarrierDataType.RecipeStepJump, CurStepNum.ToString(), string.Format("Recipe Running:current step {0},skip to next step", CurStepNum + 1));
- }
- }
- public bool UpdateRecipe(string newRecipeContent)
- {
- lock (_recipeLocker)
- {
- RecipeHead head = null;
- List<RecipeStep> newRecipeData = null;
- if (!Recipe.Parse(newRecipeContent, out head, out newRecipeData))
- {
- EV.PostMessage(Module, EventEnum.ReadRecipeFail, Module, CurrentRecipeRunningName);
- return false;
- }
- else
- {
- string oldRecipeName = CurrentRecipeRunningName;
- CurrentRecipeRunningName = string.Format("{0}-{1}-({2})", DateTime.Now.ToString("yyyyMMddHHmmss"), CurrentRecipeBaseName, RecipeChangeNo++);
- //update local recipe data
- _recipeStepList = newRecipeData;
- CurrentRecipeContent = newRecipeContent;
- Singleton<ProcessRecorder>.Instance.UpdateProcessRecipeName(Singleton<PMEntity>.Instance.CurrentRunningJob.RecipeRunId, CurrentRecipeRunningName);
- //update susceptor recipe name
- //Susceptor sus = SusceptorManager.Instance.GetSystemSusceptors()[ModuleName.System];
- //if (sus != null)
- //{
- // sus.RecipeName = RecipeName;
- // SusceptorManager.Instance.Persist();
- //}
- //send informational event
- EV.PostMessage(Module, EventEnum.RecipeUpdated, Module, oldRecipeName, CurStepNum + 1, CurrentRecipeRunningName);
- Singleton<ProcessRecorder>.Instance.AddRecord(Singleton<PMEntity>.Instance.CurrentRunningJob.RecipeRunId, CarrierDataType.RecipeUpdated, CurStepNum.ToString(), string.Format("工艺运行中:当前第{0}步,更新程序:{1}", CurStepNum + 1, CurrentRecipeRunningName));
- //notify recipe change event to TM
- RecipeFileManager.Instance.SaveRecipeHistory(ModuleName.System.ToString(), CurrentRecipeRunningName, CurrentRecipeContent);
- }
- }
- return true;
- }
- /// <summary>
- /// Status name
- /// </summary>
- /// <returns></returns>
- public override string ToString()
- {
- return "recipe running";
- }
- protected void sendRecipeStopToSmart()
- {
- ///工艺停止发送StreamOffCommand
- // NotifierSmart.SendCommand("StreamOffCommand", Reactor.ChamId);
- }
- /// <summary>
- /// 工艺程序估计结束时间计算
- /// </summary>
- protected void CalcEstimatedRecipeEndTime()
- {
- try
- {
- //(*计算当前工艺程序预计所需的总时间,从当前步开始计算剩余步的估算时间+已经既成事实的时间 => 总的估计时间,采用该种方式进行总工艺时间理论上最为精确*)
- if (!_estimatedTimeCalcTimer.IsTimeout())
- return;
- _estimatedTimeCalcTimer.Start(1000);
- EstimatedTotalLeftTime = 0;
- if (_state == RecipeEngineState.RecipeCompleted)
- return;
- if (!(CurStepNum >= 0 && CurStepNum <= _recipeStepList.Count - 1))
- return;
- if (CurStepLeftTime > 0)
- {
- EstimatedTotalLeftTime = CurStepLeftTime;
- }
- int nextBegin = CurStepNum;
- //(*判断当前是否处于循环之中*)
- bool IsInLoop = false;
- int iNum1 = 0;
- int iNum2 = 0;
- //int j=i;
- for (int j = CurStepNum; j < _recipeStepList.Count; j++)
- {
- if (_recipeStepList[j].IsLoopEndStep)
- {
- iNum2 = j;
- IsInLoop = true;
- break;
- }
- else if (j > CurStepNum && _recipeStepList[j].IsLoopStartStep)
- {
- IsInLoop = false;
- break;
- }
- }
- if (IsInLoop)
- {
- //(*当前步处于循环中*)
- iNum1 = CurStepNum;
- for (int j = CurStepNum; j >= 0; j--)
- {
- if (_recipeStepList[j].IsLoopStartStep)
- {
- iNum1 = j;
- break;
- }
- }
- for (int j = CurStepNum + 1; j <= iNum2; j++)
- {
- EstimatedTotalLeftTime += _recipeStepList[j].StepTime * 1000 * (_recipeStepList[iNum1].LoopCount - CurrentLoopCount + 1);
- }
- for (int j = iNum1; j <= CurStepNum; j++)
- {
- EstimatedTotalLeftTime += _recipeStepList[j].StepTime * 1000 * (_recipeStepList[iNum1].LoopCount - CurrentLoopCount);
- }
- nextBegin = iNum2 + 1;
- }
- else
- {
- nextBegin++;
- }
- //(*当前步处于循环外*)
- for (int j = nextBegin; j < _recipeStepList.Count; j++)
- {
- if (_recipeStepList[j].IsLoopStartStep)
- {
- //j=i;
- iNum1 = j;
- iNum2 = j + 1;
- double lr1 = 0;
- for (int m = j; m < _recipeStepList.Count; m++)
- {
- lr1 += _recipeStepList[m].StepTime * 1000;
- if (_recipeStepList[m].IsLoopEndStep)
- {
- iNum2 = m;
- break;
- }
- }
- EstimatedTotalLeftTime = EstimatedTotalLeftTime + lr1 * _recipeStepList[iNum1].LoopCount;
- j = iNum2;
- }
- else
- {
- EstimatedTotalLeftTime += _recipeStepList[j].StepTime * 1000;
- }
- //END_WHILE
- }
- }
- catch (Exception ex)
- {
- LOG.Write(ex);
- }
- }
- }
- }
|