Browse Source

fix abortRecipe/idleRecipe 数据不正确/process log无法展示导出 问题

jiangjy 1 day ago
parent
commit
62d9d4f4ff

+ 19 - 7
FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessExportAllViewModel.cs

@@ -231,7 +231,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
 
             RecipeDatas.ToList().ForEach(recipe =>
             {
-                QueryStep(recipe.StartTime, recipe.EndTime);
+                QueryStep(recipe);
             });
 
             if (StepInfo != null && StepInfo.Count > 0)
@@ -291,15 +291,24 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
         }
 
 
-        public void QueryStep(DateTime starTime, DateTime endTime)//, string recipeName去掉查询recipeName名称,有嵌套调用
+        public void QueryStep(ProcessHistoryLot historyLot)//, string recipeName去掉查询recipeName名称,有嵌套调用
         {
-            starTime = starTime.AddMinutes(-1);
-            endTime = endTime.AddMinutes(1);
+            string sql = string.Empty;
+            DataTable dbData = new DataTable();
 
-            string sql = $"SELECT * FROM \"process_data\" where (\"process_begin_time\" >= '{starTime:yyyy/MM/dd HH:mm:ss.fff}' and \"process_end_time\" <= '{endTime:yyyy/MM/dd HH:mm:ss.fff}') order by \"process_begin_time\" DESC;";
-
-            DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql);
+            if (!string.IsNullOrEmpty(historyLot.PjId))
+            {
+                sql = $"SELECT * FROM process_data where pj_id='{historyLot.PjId}'";
+                dbData = QueryDataClient.Instance.Service.QueryData(sql);
+            }
 
+            if (dbData == null || dbData.Rows.Count == 0)
+            {
+                DateTime starTime = historyLot.StartTime.AddMinutes(-1);
+                DateTime endTime = historyLot.EndTime.AddMinutes(1);
+                sql = $"SELECT * FROM \"process_data\" where (\"process_begin_time\" >= '{starTime:yyyy/MM/dd HH:mm:ss.fff}' and \"process_end_time\" <= '{endTime:yyyy/MM/dd HH:mm:ss.fff}') order by \"process_begin_time\" DESC;";
+                dbData = QueryDataClient.Instance.Service.QueryData(sql);
+            }
             if (dbData != null && dbData.Rows.Count > 0)
             {
                 List<ProcessDataLot> ProcessDataLotList = new List<ProcessDataLot>();
@@ -323,6 +332,9 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
                     }
                     ProcessDataLotList.Add(item);
                 }
+                if (ProcessDataLotList.Count == 0) { LOG.Warning($"QueryStep:No process data({sql})"); return; }
+    
+
                 //   Annotations.Add(VerLine(Media.Brushes.Blue, ProcessDataLotList[0].ProcessBeginTime, Media.Brushes.Blue, $"{ProcessDataLotList[0].RecipeName}"));
 
                 //Annotations.Add(VerLine(Media.Brushes.Blue, ProcessDataLotList[0].ProcessEndTime, Media.Brushes.Blue, $"Recipe End"));

+ 45 - 12
Furnace/FurnaceRT/Equipments/PMs/PMModule.cs

@@ -1051,8 +1051,6 @@ namespace FurnaceRT.Equipments.PMs
             _processRoutine?.Abort();
             IsWait = false;
             IsJobProcess = false;
-
-
             _recipeRunningInfo.RecipeName = param[0].ToString();
             var recipeType = param[1].ToString();
             var tableID = 1;
@@ -1076,7 +1074,7 @@ namespace FurnaceRT.Equipments.PMs
             RecipeRunningInfo.MainRecipeName = _recipeRunningInfo.RecipeName;
             RecipeRunningInfo.Head = recipeHead;
             RecipeRunningInfo.RecipeStepList = recipeSteps;
-
+            RecipeRunningInfo.RecipeName = _recipeRunningInfo.RecipeName;
             Result ret = StartRoutine(_preprocessRoutine);
             if (ret == Result.FAIL || ret == Result.DONE)
                 return false;
@@ -1093,7 +1091,7 @@ namespace FurnaceRT.Equipments.PMs
                 PreprocessStartFailedWarning.Set($"boat is not ready");
                 return false;
             }
-
+            Singleton<EquipmentManager>.Instance.EndPj("AbnormalEnd");
             _recipeRunningInfo.RecipeName = SC.ContainsItem("System.Recipe.Idle Recipe") ? SC.GetStringValue("System.Recipe.Idle Recipe") : string.Empty;
             if (!RecipeParser.Parse(_recipeRunningInfo.RecipeName, ModuleName.PM1.ToString(), out var recipeHead, out var recipeSteps, out string reason, "Idle"))
             {
@@ -1113,6 +1111,8 @@ namespace FurnaceRT.Equipments.PMs
             RecipeRunningInfo.MainRecipeName = _recipeRunningInfo.RecipeName;
             RecipeRunningInfo.Head = recipeHead;
             RecipeRunningInfo.RecipeStepList = recipeSteps;
+            RecipeRunningInfo.RecipeName = _recipeRunningInfo.RecipeName;
+            RecipeRunningInfo.ExecRecipeType = recipeSteps.Count > 0 ? recipeSteps[0].RecipeType : string.Empty;
 
             Result ret = StartRoutine(_preprocessRoutine);
             if (ret == Result.FAIL || ret == Result.DONE)
@@ -1172,7 +1172,6 @@ namespace FurnaceRT.Equipments.PMs
                 var firstPjId = Singleton<EquipmentManager>.Instance.GetFirstPJId();
 
                 Singleton<EquipmentManager>.Instance.EndPj();
-                _processRoutine.UpdateProcessDataPJid(firstPjId);
             }
 
 
@@ -1296,7 +1295,10 @@ namespace FurnaceRT.Equipments.PMs
         private bool FsmRecipeAbort(object[] param)
         {
             Singleton<EquipmentManager>.Instance.EndPj("Recipe Abort");
+            var firstPjId = Singleton<EquipmentManager>.Instance.GetFirstPJId();
+            _processRoutine.UpdateProcessDataPJid(firstPjId);
             _processRoutine.Abort();
+
             IsWait = false;
             IsJobProcess = false;
 
@@ -1315,16 +1317,47 @@ namespace FurnaceRT.Equipments.PMs
                     return false;
                 }
             }
+            var recipeType = recipeSteps.Count > 0 ? recipeSteps[0].RecipeType : string.Empty;
+            var recipeTable = "";
 
-            RecipeRunningInfo.MainRecipeName = recipeName;
-            RecipeRunningInfo.Head = recipeHead;
-            RecipeRunningInfo.RecipeStepList = recipeSteps;
 
-            Result ret = StartRoutine(_processRoutine);
-            if (ret == Result.FAIL || ret == Result.DONE)
-                return false;
+            if (!string.IsNullOrEmpty(_recipeRunningInfo.Head.AbortRecipe))
+            {
+                var currectStep = _recipeRunningInfo.RecipeStepList[_processRoutine._currentStepNumber];
+                if (string.IsNullOrEmpty(currectStep.AbortRecipeTableInfo))
+                {
+                    if (!RecipeParser.ParseTables(_recipeRunningInfo.Head.AbortRecipe, Module, out var recipeData, out reason, "Abort"))
+                    {
+                        ExecuteAbortRecipeFailAlarm.Set($"Load abort recipe {recipeName} failed, {reason}");
+                        return false;
+                    }
+                    else
+                    {
+                        recipeTable = recipeData.FirstOrDefault().Key.ToString();
+                    }
+                }
+                else
+                {
+                    recipeTable = currectStep.AbortRecipeTableInfo.Split(':').FirstOrDefault();
+                }
+            }
+            else
+            {
+                if (!RecipeParser.ParseTables(SC.GetStringValue("System.Recipe.Abort Recipe"), Module, out var recipeData, out reason, "Abort"))
+                {
+                    ExecuteAbortRecipeFailAlarm.Set($"Load abort recipe {recipeName} failed, {reason}");
+                    return false;
+                }
+                else
+                {
+                    recipeTable = recipeData.FirstOrDefault().Key.ToString();
 
-            return ret == Result.RUN;
+                }
+
+            }
+
+            CheckToPostMessage((int)MSG.RunOtherRecipe, recipeName, recipeType, recipeTable);
+            return true;
         }
 
         private bool FsmStartPostProcess(object[] param)

+ 1 - 0
Furnace/FurnaceRT/Equipments/PMs/RecipeExecutions/PreProcess.cs

@@ -381,6 +381,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                 PMModule.RecipeRunningInfo.MainRecipeName = _recipeName;
                 PMModule.RecipeRunningInfo.Head = recipeHead;
                 PMModule.RecipeRunningInfo.RecipeStepList = recipeSteps;
+                PMModule.RecipeRunningInfo.ExecRecipeType = recipeSteps.Count > 0 ? recipeSteps[0].RecipeType : string.Empty;
             }
 
 

+ 9 - 1
Furnace/FurnaceRT/Equipments/PMs/RecipeExecutions/Process.cs

@@ -16,6 +16,7 @@ using FurnaceRT.Equipments.PMs.Routines;
 using System.Diagnostics;
 using MECF.Framework.Common.DataCenter;
 using System.Runtime.Remoting.Metadata.W3cXsd2001;
+using FurnaceRT.Equipments.Systems;
 
 namespace FurnaceRT.Equipments.PMs.RecipeExecutions
 {
@@ -78,7 +79,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
         public string CurrentRecipeContent { get; private set; }
 
 
-        private int _currentStepNumber;
+        public int _currentStepNumber;
 
         private int _currentSubRecipeStepNumber;
 
@@ -304,6 +305,13 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
             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
+
             return Result.RUN;
         }
 

+ 948 - 1
Furnace/FurnaceRT/Equipments/PMs/RecipeExecutions/RecipeParser.cs

@@ -9,6 +9,7 @@ using Aitex.Core.RT.RecipeCenter;
 using Aitex.Core.RT.SCCore;
 using MECF.Framework.Common.Equipment;
 using System.IO;
+using MECF.Framework.UI.Client.CenterViews.Editors.Recipe;
 
 namespace FurnaceRT.Equipments.PMs.RecipeExecutions
 {
@@ -203,7 +204,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                         recipeHead.TempCorrect = nodeConfig.HasAttribute("Combination.TempCorrection") ? nodeConfig.Attributes["Combination.TempCorrection"].Value : "";
                         recipeHead.TempPID = nodeConfig.HasAttribute("Combination.TempPID") ? nodeConfig.Attributes["Combination.TempPID"].Value : "";
                         recipeHead.ProfileCondition = nodeConfig.HasAttribute("Combination.ProfileCondition") ? nodeConfig.Attributes["Combination.ProfileCondition"].Value : "";
-                        if(nodeConfig.HasAttribute("N2PurgeMode"))
+                        if (nodeConfig.HasAttribute("N2PurgeMode"))
                         {
                             recipeHead.IsN2PurgeMode = nodeConfig.Attributes["N2PurgeMode"].Value.Replace(" ", "").ToLower() == "n2purge";
                             recipeHead.N2PurgeModeStr = nodeConfig.Attributes["N2PurgeMode"].Value;
@@ -1212,5 +1213,951 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                 }
             }
         }
+        public static bool ParseTables(string recipeFile, string module, out Dictionary<int, List<RecipeStep>> recipeDatas, out string reason, string recipeType)
+        {
+            reason = string.Empty;
+
+            recipeDatas = new Dictionary<int, List<RecipeStep>>();
+
+            string content = string.Empty;
+            if (recipeType != "Process" && recipeType != "Idle" && recipeType != "Reset")
+            {
+                if (!File.Exists($"{PathManager.GetRecipeDir()}\\{SC.GetStringValue("System.Recipe.SupportedChamberType")}\\{SC.GetStringValue($"System.Recipe.Supported{recipeType}Type")}\\{recipeFile}.rcp"))
+                    return true;
+            }
+
+            content = RecipeFileManager.Instance.LoadRecipe($"{SC.GetStringValue("System.Recipe.SupportedChamberType")}\\{SC.GetStringValue($"System.Recipe.Supported{recipeType}Type")}", recipeFile, false);
+
+            if (string.IsNullOrEmpty(content))
+            {
+                reason = $"{recipeFile} is not a valid recipe file";
+                return false;
+            }
+
+            try
+            {
+                //获取工艺程序文件中允许的命令字符串列表
+                //目的:如果工艺程序文件中含有规定之外的命令,则被禁止执行
+                HashSet<string> recipeAllowedCommands = new HashSet<string>();
+                XmlDocument rcpFormatDoc = new XmlDocument();
+                string recipeSchema = PathManager.GetCfgDir() + $@"\Recipe\Furnace\Process\{SC.GetStringValue("System.SetUp.ToolType")}\RecipeFormat.xml";
+                rcpFormatDoc.Load(recipeSchema);
+                XmlNodeList rcpItemNodeList = rcpFormatDoc.SelectNodes("/Aitex/TableRecipeFormat/Catalog/Group/Step");
+                foreach (XmlElement item in rcpItemNodeList)
+                    recipeAllowedCommands.Add(item.Attributes["ControlName"].Value);
+
+                recipeAllowedCommands.Add("Temperature.ControlMode");
+                recipeAllowedCommands.Add("Temperature.Correct");
+                recipeAllowedCommands.Add("Temperature.PID");
+                recipeAllowedCommands.Add("ConditionCheck");
+                recipeAllowedCommands.Add("EventSetting");
+                recipeAllowedCommands.Add("FilmThickFormula");
+                recipeAllowedCommands.Add("FilmThickCoefficientA");
+                recipeAllowedCommands.Add("FilmThickCoefficientB");
+                recipeAllowedCommands.Add("AlarmTableIndex");
+                recipeAllowedCommands.Add("RFSwitch");
+                recipeAllowedCommands.Add("RFSetpoint");
+                recipeAllowedCommands.Add("ForwardPowerAlarmWatchTable");
+                recipeAllowedCommands.Add("PrAlarmWatchTable");
+                recipeAllowedCommands.Add("PIAlarmWatchTable");
+                recipeAllowedCommands.Add("C1Setpoint");
+                recipeAllowedCommands.Add("C2Setpoint");
+                recipeAllowedCommands.Add("C1AlarmWatchTable");
+                recipeAllowedCommands.Add("C2AlarmWatchTable");
+                recipeAllowedCommands.Add("VppAlarmWatchTable");
+                recipeAllowedCommands.Add("VdcAlarmWatchTable");
+                recipeAllowedCommands.Add("PressureSonserValue");
+                recipeAllowedCommands.Add("PressureValveAngle");
+                recipeAllowedCommands.Add("PressureSettingVG");
+                recipeAllowedCommands.Add("PressCommand");
+                recipeAllowedCommands.Add("PressValue");
+                recipeAllowedCommands.Add("PressureAlarmTableNo");
+                recipeAllowedCommands.Add("AbortRecipeTableIndex");
+                recipeAllowedCommands.Add("AlarmConditionTable");
+                recipeAllowedCommands.Add("LoaderCommand");
+                recipeAllowedCommands.Add("LoaderValue");
+                for (int i = 1; i < 11; i++)
+                {
+                    recipeAllowedCommands.Add($"AlarmAction.{i}");
+                    recipeAllowedCommands.Add($"AlarmDetails.{i}");
+                }
+
+                for (int i = 1; i < 60; i++)
+                {
+                    recipeAllowedCommands.Add($"MFC{i}.Flow.Set");
+                    recipeAllowedCommands.Add($"MFC{i}.Flow.SetUnit");
+                    recipeAllowedCommands.Add($"MFC{i}.Flow.Ramprate");
+                    recipeAllowedCommands.Add($"MFC{i}.Flow.RamprateUnit");
+                    recipeAllowedCommands.Add($"MFC{i}.Flow.Check");
+                    recipeAllowedCommands.Add($"MFC{i}.Flow.High");
+                    recipeAllowedCommands.Add($"MFC{i}.Flow.Low");
+                    recipeAllowedCommands.Add($"MFC{i}.Flow.Unit");
+                }
+
+                for (int i = 1; i < 200; i++)
+                {
+                    recipeAllowedCommands.Add($"AUX.{i}.Set");
+                    recipeAllowedCommands.Add($"AUX.{i}.Check");
+                    recipeAllowedCommands.Add($"AUX.{i}.High");
+                    recipeAllowedCommands.Add($"AUX.{i}.Low");
+                    recipeAllowedCommands.Add($"AUX.{i}.CheckUnit");
+                }
+
+                recipeAllowedCommands.Add("HeaterU.ZoneName");
+                recipeAllowedCommands.Add("HeaterU.Set");
+                recipeAllowedCommands.Add("HeaterU.SetUnit");
+                recipeAllowedCommands.Add("HeaterU.Ramprate");
+                recipeAllowedCommands.Add("HeaterU.RamprateUnit");
+                recipeAllowedCommands.Add("HeaterU.Check");
+                recipeAllowedCommands.Add("HeaterU.High");
+                recipeAllowedCommands.Add("HeaterU.Low");
+                recipeAllowedCommands.Add("HeaterU.Unit");
+
+                recipeAllowedCommands.Add("HeaterCU.ZoneName");
+                recipeAllowedCommands.Add("HeaterCU.Set");
+                recipeAllowedCommands.Add("HeaterCU.SetUnit");
+                recipeAllowedCommands.Add("HeaterCU.Ramprate");
+                recipeAllowedCommands.Add("HeaterCU.RamprateUnit");
+                recipeAllowedCommands.Add("HeaterCU.Check");
+                recipeAllowedCommands.Add("HeaterCU.High");
+                recipeAllowedCommands.Add("HeaterCU.Low");
+                recipeAllowedCommands.Add("HeaterCU.Unit");
+
+                recipeAllowedCommands.Add("HeaterC.ZoneName");
+                recipeAllowedCommands.Add("HeaterC.Set");
+                recipeAllowedCommands.Add("HeaterC.SetUnit");
+                recipeAllowedCommands.Add("HeaterC.Ramprate");
+                recipeAllowedCommands.Add("HeaterC.RamprateUnit");
+                recipeAllowedCommands.Add("HeaterC.Check");
+                recipeAllowedCommands.Add("HeaterC.High");
+                recipeAllowedCommands.Add("HeaterC.Low");
+                recipeAllowedCommands.Add("HeaterC.Unit");
+
+                recipeAllowedCommands.Add("HeaterCL.ZoneName");
+                recipeAllowedCommands.Add("HeaterCL.Set");
+                recipeAllowedCommands.Add("HeaterCL.SetUnit");
+                recipeAllowedCommands.Add("HeaterCL.Ramprate");
+                recipeAllowedCommands.Add("HeaterCL.RamprateUnit");
+                recipeAllowedCommands.Add("HeaterCL.Check");
+                recipeAllowedCommands.Add("HeaterCL.High");
+                recipeAllowedCommands.Add("HeaterCL.Low");
+                recipeAllowedCommands.Add("HeaterCL.Unit");
+
+                recipeAllowedCommands.Add("HeaterL.ZoneName");
+                recipeAllowedCommands.Add("HeaterL.Set");
+                recipeAllowedCommands.Add("HeaterL.SetUnit");
+                recipeAllowedCommands.Add("HeaterL.Ramprate");
+                recipeAllowedCommands.Add("HeaterL.RamprateUnit");
+                recipeAllowedCommands.Add("HeaterL.Check");
+                recipeAllowedCommands.Add("HeaterL.High");
+                recipeAllowedCommands.Add("HeaterL.Low");
+                recipeAllowedCommands.Add("HeaterL.Unit");
+
+                recipeAllowedCommands.Add("Loader.Command");
+                recipeAllowedCommands.Add("Loader.Speed1");
+                recipeAllowedCommands.Add("Loader.Speed2");
+                recipeAllowedCommands.Add("Loader.Speed3");
+                recipeAllowedCommands.Add("Loader.RPM");
+
+                recipeAllowedCommands.Add("Press.Command");
+                recipeAllowedCommands.Add("Press.PID");
+                recipeAllowedCommands.Add("Press.Set");
+                recipeAllowedCommands.Add("Press.SlowVacSet");
+                recipeAllowedCommands.Add("Press.ValveAngleSet");
+                recipeAllowedCommands.Add("Press.IsWait");
+                recipeAllowedCommands.Add("Press.LowWait");
+                recipeAllowedCommands.Add("Press.HighWait");
+                recipeAllowedCommands.Add("Press.WaitUnit");
+                recipeAllowedCommands.Add("Press.WaitPress");
+
+                //获取工艺程序文件中所有步的内容
+                XmlDocument rcpDataDoc = new XmlDocument();
+                rcpDataDoc.LoadXml(content);
+
+                XmlNodeList tablesNodeList = rcpDataDoc.SelectNodes("//Tables/Table");
+                if (tablesNodeList == null || tablesNodeList.Count == 0)
+                {
+                    reason = "No Table nodes found.";
+                    return false;
+                }
+
+                for (int x = 0; x < tablesNodeList.Count; x++)
+                {
+                    XmlNode tableNode = tablesNodeList[x];
+
+                    // 获取当前 Table 下的所有 Step 节点
+                    XmlNodeList stepNodes = tableNode.SelectNodes("Step");
+                    #region 
+                    string strLoopEndStep, strJumpStep;
+                    strLoopEndStep = strJumpStep = string.Empty;
+                    var recipeData = new List<RecipeStep>();
+
+                    for (int i = 0; i < stepNodes.Count; i++)
+                    {
+                        var recipeStep = new RecipeStep();
+                        recipeStep.RecipeType = recipeType;
+                        recipeData.Add(recipeStep);
+
+                        XmlElement stepNode = stepNodes[i] as XmlElement;
+                        Dictionary<string, string> dic = new Dictionary<string, string>();
+
+                        //遍历Step节点
+                        foreach (XmlAttribute att in stepNode.Attributes)
+                        {
+                            if (recipeAllowedCommands.Contains(att.Name))
+                            {
+                                dic.Add(att.Name, att.Value);
+                            }
+                        }
+                        //遍历Step子节点中所有的attribute属性节点
+                        foreach (XmlElement subStepNode in stepNode.ChildNodes)
+                        {
+                            foreach (XmlAttribute att in subStepNode.Attributes)
+                            {
+                                if (recipeAllowedCommands.Contains(att.Name))
+                                {
+                                    dic.Add(att.Name, att.Value);
+                                }
+                            }
+                            //遍历Step子节点的子节点中所有的attribute属性节点
+                            foreach (XmlElement subsubStepNode in subStepNode.ChildNodes)
+                            {
+                                foreach (XmlAttribute att in subsubStepNode.Attributes)
+                                {
+                                    if (recipeAllowedCommands.Contains(att.Name))
+                                    {
+                                        dic.Add(att.Name, att.Value);
+                                    }
+                                }
+                            }
+                        }
+
+                        recipeStep.StepName = dic["Name"];
+
+                        if (dic["Name"] == strLoopEndStep)
+                        {
+                            recipeStep.IsLoopEndStep = true;
+                            strLoopEndStep = string.Empty;
+                        }
+                        recipeStep.IsJumpStep = false;
+
+                        if (dic.ContainsKey("Command"))
+                        {
+                            string commandStr = dic["Command"];
+                            if (commandStr.Contains("CallSystemRecipe"))
+                            {
+                            }
+                            else if (commandStr.ToUpper().StartsWith("CALL"))
+                            {
+                                int subTableID = 0;
+                                var subPara = commandStr.Replace("CALL", "").Replace("[", "").Replace("]", "").Split('*');
+                                if (subPara != null && subPara.Length > 1)
+                                {
+                                    int.TryParse(subPara[0], out int loopCount);
+                                    var tablePara = subPara[1].Split(':');
+                                    if (tablePara != null && tablePara.Length > 1)
+                                    {
+                                        int.TryParse(tablePara[0], out subTableID);
+                                        if (subTableID > 0)
+                                        {
+                                            recipeStep.IsCallSubStep = true;
+                                            recipeStep.SubRecipeLoopCount = loopCount;
+                                        }
+                                    }
+                                    recipeStep.SubRecipeTableInfo = subPara[1];
+                                }
+
+
+                            }
+                            else if (commandStr.ToUpper().StartsWith("LOOP"))
+                            {
+                                recipeStep.IsLoopEndStep = true;
+                                var loopPara = commandStr.Replace("LOOP", "").Replace("[", "").Replace("]", "").Split('*');
+                                if (loopPara != null && loopPara.Length > 1)
+                                {
+                                    int.TryParse(loopPara[0], out int loopCount);
+                                    recipeStep.LoopCount = loopCount + 1;//加1是因为第一次从正常的start-》end的执行算是一次循环,所以要额外加1
+
+                                    int loopStartStep = -1;
+                                    for (int index = 0; index < recipeData.Count; index++)
+                                    {
+                                        if (recipeData[index].StepName == loopPara[1])
+                                        {
+                                            loopStartStep = index;
+                                            break;
+                                        }
+                                    }
+                                    if (loopStartStep < 0)
+                                    {
+                                        reason = $"Recipe file does not contains LOOP step {loopPara[1]}";
+                                        return false;
+                                    }
+                                    if (loopPara[1] != null)
+                                    {
+                                        if (loopStartStep < 0 ||
+                                            (recipeType == "Process" && loopStartStep == 0))//Process recipe的standby不参与循环
+                                            recipeStep.IsLoopEndStep = false;
+                                        else
+                                        {
+                                            recipeStep.LoopStartStep = loopStartStep;
+                                            if (recipeData.Count > loopStartStep)
+                                            {
+                                                recipeData[loopStartStep].IsLoopStartStep = true;
+                                                recipeData[loopStartStep].LoopCount = loopCount + 1;
+
+                                                recipeStep.LoopEndStep = recipeType == "Process" ? i + 1 : i;//Process recipe包含standby,从0开始;其他recipe不包含standby
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                            else if (commandStr.ToUpper().StartsWith("JUMP"))
+                            {
+                                var jumpPara = commandStr.Replace("Jump:", string.Empty).Replace("[", "").Replace("]", "");//JumpStepNo
+                                if (jumpPara != null)
+                                {
+                                    //int.TryParse(jumpPara[0], out int jumpStepNo);
+
+                                    //recipeStep.JumpStepNo = recipeType == "Process" ? jumpStepNo : jumpStepNo - 1;//Process recipe包含standby,从0开始;其他recipe不包含standby
+                                    recipeStep.IsJumpStep = true;
+                                    recipeStep.JumpStepName = jumpPara;
+                                }
+                            }
+                        }
+
+                        if (dic.ContainsKey("AbortRecipeTableIndex"))
+                        {
+                            if (dic["AbortRecipeTableIndex"].ToLower() != "none")
+                            {
+                                recipeStep.AbortRecipeTableInfo = dic["AbortRecipeTableIndex"];
+                            }
+                            recipeStep.AbortRecipeSteps = null;
+
+                        }
+
+                        if (dic.ContainsKey("EventSetting"))
+                        {
+                            string eventSettingStr = dic["EventSetting"];
+                            if (eventSettingStr.ToLower() == "start")
+                            {
+                                recipeStep.IsTimeMeasurementStartStep = true;
+                            }
+                            else if (eventSettingStr.ToLower() == "stop")
+                            {
+                                recipeStep.IsTimeMeasurementStopStep = true;
+                            }
+                        }
+
+                        if (dic.ContainsKey("FilmThickFormula"))
+                        {
+                            recipeStep.FilmThickFormula = dic["FilmThickFormula"];
+                        }
+
+                        if (dic.ContainsKey("FilmThickCoefficientA"))
+                        {
+                            recipeStep.FilmThickCoefficientA = float.Parse(dic["FilmThickCoefficientA"]);
+                        }
+
+                        if (dic.ContainsKey("FilmThickCoefficientB"))
+                        {
+                            recipeStep.FilmThickCoefficientB = float.Parse(dic["FilmThickCoefficientB"]);
+                        }
+
+                        if (dic.ContainsKey("AlarmConditionTable"))
+                        {
+                            recipeStep.AlarmConditionTable = dic["AlarmConditionTable"];
+                        }
+
+                        for (int j = 1; j < 11; j++)
+                        {
+                            string tempType = "Ignore Alarm";
+                            string tempDetails = "";
+                            if (dic.ContainsKey($"AlarmAction.{j}"))
+                            {
+                                tempType = dic[$"AlarmAction.{j}"];
+                            }
+                            if (dic.ContainsKey($"AlarmDetails.{j}"))
+                            {
+                                tempDetails = dic[$"AlarmDetails.{j}"];
+                            }
+                            recipeStep.AlarmActionSets.Add(j, new AlarmActions()
+                            {
+                                ProcessingType = tempType,
+                                ProcessingDetails = tempDetails
+                            });
+                        }
+
+                        //if(dic.ContainsKey("Loop"))
+                        //{
+                        //    string loopStr = dic["Loop"];
+                        //    recipeStep.IsLoopStartStep = System.Text.RegularExpressions.Regex.Match(loopStr, @"Loop\x20\d+\s*$").Success;
+                        //    recipeStep.IsLoopEndStep = System.Text.RegularExpressions.Regex.Match(loopStr, @"Loop End$").Success;
+                        //    if (recipeStep.IsLoopStartStep)
+                        //        recipeStep.LoopCount = Convert.ToInt32(loopStr.Replace("Loop", string.Empty));
+                        //    else
+                        //        recipeStep.LoopCount = 0;
+                        //}
+
+                        //recipe time
+                        if (dic["Name"].ToLower() == "standby")
+                        {
+                            if (DateTime.TryParse(dic["Time"], out DateTime time))
+                            {
+                                recipeStep.StepTime = time.Second + time.Minute * 60 + time.Hour * 3600 + time.Millisecond / 1000.0;
+                            }
+                            else if (float.TryParse(dic["Time"], out float timeInSec))
+                            {
+                                recipeStep.StepTime = timeInSec;
+                                recipeStep.EndBy = EnumEndByCondition.ByTime;
+                            }
+                            else
+                            {
+                                recipeStep.StepTime = 0;
+                                recipeStep.EndBy = EnumEndByCondition.ByStandbyFactor;
+                            }
+                        }
+                        else
+                        {
+                            if (System.Text.RegularExpressions.Regex.Match(dic["Time"], @"[a-zA-Z]").Success)
+                            {
+                                if (SC.ContainsItem($"{module}.RecipeEditParameter.StepTime.{dic["Time"]}"))
+                                {
+                                    var time = DateTime.Parse(SC.GetStringValue($"{module}.RecipeEditParameter.StepTime.{dic["Time"]}"));
+                                    recipeStep.StepTime = time.Second + time.Minute * 60 + time.Hour * 3600;
+                                }
+                                else
+                                {
+                                    reason = $"Configuration does not contains step time config {dic["Time"]}";
+                                    return false;
+                                }
+                            }
+                            else
+                            {
+                                if (DateTime.TryParse(dic["Time"], out DateTime time))
+                                {
+                                    recipeStep.StepTime = time.Second + time.Minute * 60 + time.Hour * 3600 + time.Millisecond / 1000.0;
+                                }
+                                else if (float.TryParse(dic["Time"], out float timeInSec))
+                                {
+                                    recipeStep.StepTime = timeInSec;
+                                }
+                                else
+                                {
+                                    reason = $"Step time {dic["Time"]} is invalid";
+                                    return false;
+                                }
+                            }
+
+                            if (dic["ConditionCheck"].ToLower() == "none")
+                            {
+                                recipeStep.EndBy = EnumEndByCondition.ByTime;
+                            }
+                            else
+                            {
+                                recipeStep.EndBy = EnumEndByCondition.ByStandbyFactor;
+                            }
+                        }
+
+                        //ReplaceControlName(ref dic, "GasLineMFC1.Flow", "MFC1.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC2.Flow", "MFC2.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC3.Flow", "MFC3.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC4.Flow", "MFC4.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC5.Flow", "MFC5.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC6.Flow", "MFC6.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC7.Flow", "MFC7.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC8.Flow", "MFC8.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC9.Flow", "MFC9.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC10.Flow", "MFC10.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC11.Flow", "MFC11.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC12.Flow", "MFC12.SetParameters");
+                        //ReplaceControlName(ref dic, "GasLineMFC51.Flow", "MFC51.SetParameters");
+
+                        AddParameter(ref dic, "MFC1.SetParameters", new string[8] { "MFC1.Flow.Set", "MFC1.Flow.Ramprate", "MFC1.Flow.SetUnit", "MFC1.Flow.RamprateUnit", "MFC1.Flow.Check", "MFC1.Flow.High", "MFC1.Flow.Low", "MFC1.Flow.Unit" });
+                        AddParameter(ref dic, "MFC2.SetParameters", new string[8] { "MFC2.Flow.Set", "MFC2.Flow.Ramprate", "MFC2.Flow.SetUnit", "MFC2.Flow.RamprateUnit", "MFC2.Flow.Check", "MFC2.Flow.High", "MFC2.Flow.Low", "MFC2.Flow.Unit" });
+                        AddParameter(ref dic, "MFC3.SetParameters", new string[8] { "MFC3.Flow.Set", "MFC3.Flow.Ramprate", "MFC3.Flow.SetUnit", "MFC3.Flow.RamprateUnit", "MFC3.Flow.Check", "MFC3.Flow.High", "MFC3.Flow.Low", "MFC3.Flow.Unit" });
+                        AddParameter(ref dic, "MFC4.SetParameters", new string[8] { "MFC4.Flow.Set", "MFC4.Flow.Ramprate", "MFC4.Flow.SetUnit", "MFC4.Flow.RamprateUnit", "MFC4.Flow.Check", "MFC4.Flow.High", "MFC4.Flow.Low", "MFC4.Flow.Unit" });
+                        AddParameter(ref dic, "MFC5.SetParameters", new string[8] { "MFC5.Flow.Set", "MFC5.Flow.Ramprate", "MFC5.Flow.SetUnit", "MFC5.Flow.RamprateUnit", "MFC5.Flow.Check", "MFC5.Flow.High", "MFC5.Flow.Low", "MFC5.Flow.Unit" });
+                        AddParameter(ref dic, "MFC6.SetParameters", new string[8] { "MFC6.Flow.Set", "MFC6.Flow.Ramprate", "MFC6.Flow.SetUnit", "MFC6.Flow.RamprateUnit", "MFC6.Flow.Check", "MFC6.Flow.High", "MFC6.Flow.Low", "MFC6.Flow.Unit" });
+                        AddParameter(ref dic, "MFC7.SetParameters", new string[8] { "MFC7.Flow.Set", "MFC7.Flow.Ramprate", "MFC7.Flow.SetUnit", "MFC7.Flow.RamprateUnit", "MFC7.Flow.Check", "MFC7.Flow.High", "MFC7.Flow.Low", "MFC7.Flow.Unit" });
+                        AddParameter(ref dic, "MFC8.SetParameters", new string[8] { "MFC8.Flow.Set", "MFC8.Flow.Ramprate", "MFC8.Flow.SetUnit", "MFC8.Flow.RamprateUnit", "MFC8.Flow.Check", "MFC8.Flow.High", "MFC8.Flow.Low", "MFC8.Flow.Unit" });
+                        AddParameter(ref dic, "MFC9.SetParameters", new string[8] { "MFC9.Flow.Set", "MFC9.Flow.Ramprate", "MFC9.Flow.SetUnit", "MFC9.Flow.RamprateUnit", "MFC9.Flow.Check", "MFC9.Flow.High", "MFC9.Flow.Low", "MFC9.Flow.Unit" });
+                        AddParameter(ref dic, "MFC10.SetParameters", new string[8] { "MFC10.Flow.Set", "MFC10.Flow.Ramprate", "MFC10.Flow.SetUnit", "MFC10.Flow.RamprateUnit", "MFC10.Flow.Check", "MFC10.Flow.High", "MFC10.Flow.Low", "MFC10.Flow.Unit" });
+                        AddParameter(ref dic, "MFC11.SetParameters", new string[8] { "MFC11.Flow.Set", "MFC11.Flow.Ramprate", "MFC11.Flow.SetUnit", "MFC11.Flow.RamprateUnit", "MFC11.Flow.Check", "MFC11.Flow.High", "MFC11.Flow.Low", "MFC11.Flow.Unit" });
+                        AddParameter(ref dic, "MFC12.SetParameters", new string[8] { "MFC12.Flow.Set", "MFC12.Flow.Ramprate", "MFC12.Flow.SetUnit", "MFC12.Flow.RamprateUnit", "MFC12.Flow.Check", "MFC12.Flow.High", "MFC12.Flow.Low", "MFC12.Flow.Unit" });
+                        AddParameter(ref dic, "MFC13.SetParameters", new string[8] { "MFC13.Flow.Set", "MFC13.Flow.Ramprate", "MFC13.Flow.SetUnit", "MFC13.Flow.RamprateUnit", "MFC13.Flow.Check", "MFC13.Flow.High", "MFC13.Flow.Low", "MFC13.Flow.Unit" });
+                        AddParameter(ref dic, "MFC14.SetParameters", new string[8] { "MFC14.Flow.Set", "MFC14.Flow.Ramprate", "MFC14.Flow.SetUnit", "MFC14.Flow.RamprateUnit", "MFC14.Flow.Check", "MFC14.Flow.High", "MFC14.Flow.Low", "MFC14.Flow.Unit" });
+                        AddParameter(ref dic, "MFC15.SetParameters", new string[8] { "MFC15.Flow.Set", "MFC15.Flow.Ramprate", "MFC15.Flow.SetUnit", "MFC15.Flow.RamprateUnit", "MFC15.Flow.Check", "MFC15.Flow.High", "MFC15.Flow.Low", "MFC15.Flow.Unit" });
+                        AddParameter(ref dic, "MFC16.SetParameters", new string[8] { "MFC16.Flow.Set", "MFC16.Flow.Ramprate", "MFC16.Flow.SetUnit", "MFC16.Flow.RamprateUnit", "MFC16.Flow.Check", "MFC16.Flow.High", "MFC16.Flow.Low", "MFC16.Flow.Unit" });
+                        AddParameter(ref dic, "MFC17.SetParameters", new string[8] { "MFC17.Flow.Set", "MFC17.Flow.Ramprate", "MFC17.Flow.SetUnit", "MFC17.Flow.RamprateUnit", "MFC17.Flow.Check", "MFC17.Flow.High", "MFC17.Flow.Low", "MFC17.Flow.Unit" });
+                        AddParameter(ref dic, "MFC31.SetParameters", new string[8] { "MFC31.Flow.Set", "MFC31.Flow.Ramprate", "MFC31.Flow.SetUnit", "MFC31.Flow.RamprateUnit", "MFC31.Flow.Check", "MFC31.Flow.High", "MFC31.Flow.Low", "MFC31.Flow.Unit" });
+                        AddParameter(ref dic, "MFC32.SetParameters", new string[8] { "MFC32.Flow.Set", "MFC32.Flow.Ramprate", "MFC32.Flow.SetUnit", "MFC32.Flow.RamprateUnit", "MFC32.Flow.Check", "MFC32.Flow.High", "MFC32.Flow.Low", "MFC32.Flow.Unit" });
+                        //AddParameter(ref dic, "MFC51.SetParameters", new string[8] { "MFC51.Flow.Set",  "MFC51.Flow.Ramprate", "MFC51.Flow.SetUnit", "MFC51.Flow.RamprateUnit", "MFC51.Flow.Check", "MFC51.Flow.High", "MFC51.Flow.Low", "MFC51.Flow.Unit" });
+
+                        ReplaceControlName(ref dic, "MFM57Flow", "MFM57.SetParameters");
+                        ReplaceControlName(ref dic, "MFM1Flow", "MFM1.SetParameters");
+                        ReplaceControlName(ref dic, "MFM6Flow", "MFM6.SetParameters");
+                        ReplaceControlName(ref dic, "MFM7Flow", "MFM7.SetParameters");
+                        ReplaceControlName(ref dic, "MFM8Flow", "MFM8.SetParameters");
+                        ReplaceControlName(ref dic, "MFM9Flow", "MFM9.SetParameters");
+                        ReplaceControlName(ref dic, "MFM11Flow", "MFM11.SetParameters");
+                        ReplaceControlName(ref dic, "MFM12Flow", "MFM12.SetParameters");
+                        ReplaceControlName(ref dic, "MFM13Flow", "MFM13.SetParameters");
+                        ReplaceControlName(ref dic, "MFM16Flow", "MFM16.SetParameters");
+
+                        ReplaceControlName(ref dic, "ConditionCheck", "SetConditionCheck");
+
+                        ReplaceControlName(ref dic, "Command", "SetCommand");
+
+                        if (dic.ContainsKey("AlarmConditionTable"))
+                            ReplaceControlName(ref dic, "AlarmConditionTable", "SetAlarmConditionTable");
+
+                        //ReplaceControlName(ref dic, "Heater2", "ZoneU.SetParameters");
+                        //ReplaceControlName(ref dic, "Heater4", "ZoneCU.SetParameters");
+                        //ReplaceControlName(ref dic, "Heater6", "ZoneC.SetParameters");
+                        //ReplaceControlName(ref dic, "Heater8", "ZoneCL.SetParameters");
+                        //ReplaceControlName(ref dic, "Heater10", "ZoneL.SetParameters");
+                        var controlMode = dic["Temperature.ControlMode"];
+                        var correct = dic["Temperature.Correct"];
+                        var PID = dic["Temperature.PID"];
+                        //AddParameter(ref dic, "ZoneU.SetParameters", controlMode, correct, PID);
+                        //AddParameter(ref dic, "ZoneCU.SetParameters", controlMode, correct, PID);
+                        //AddParameter(ref dic, "ZoneC.SetParameters", controlMode, correct, PID);
+                        //AddParameter(ref dic, "ZoneCL.SetParameters", controlMode, correct, PID);
+                        //AddParameter(ref dic, "ZoneL.SetParameters", controlMode, correct, PID);
+
+                        AddParameter(ref dic, "HeaterU.SetParameters", new string[9] { "HeaterU.ZoneName", "HeaterU.Set", "HeaterU.SetUnit", "HeaterU.Ramprate", "HeaterU.RamprateUnit", "HeaterU.Check", "HeaterU.High", "HeaterU.Low", "HeaterU.Unit" });
+                        AddParameterValue(ref dic, "HeaterU.SetParameters", new string[8] { controlMode, correct, PID, "", "", "", dic["ValveAV91"], dic["BWR"] });
+
+                        AddParameter(ref dic, "HeaterCU.SetParameters", new string[9] { "HeaterCU.ZoneName", "HeaterCU.Set", "HeaterCU.SetUnit", "HeaterCU.Ramprate", "HeaterCU.RamprateUnit", "HeaterCU.Check", "HeaterCU.High", "HeaterCU.Low", "HeaterCU.Unit" });
+                        AddParameterValue(ref dic, "HeaterCU.SetParameters", new string[8] { controlMode, correct, PID, "", "", "", dic["ValveAV91"], dic["BWR"] });
+
+                        AddParameter(ref dic, "HeaterC.SetParameters", new string[9] { "HeaterC.ZoneName", "HeaterC.Set", "HeaterC.SetUnit", "HeaterC.Ramprate", "HeaterC.RamprateUnit", "HeaterC.Check", "HeaterC.High", "HeaterC.Low", "HeaterC.Unit" });
+                        AddParameterValue(ref dic, "HeaterC.SetParameters", new string[8] { controlMode, correct, PID, "", "", "", dic["ValveAV91"], dic["BWR"] });
+
+                        AddParameter(ref dic, "HeaterCL.SetParameters", new string[9] { "HeaterCL.ZoneName", "HeaterCL.Set", "HeaterCL.SetUnit", "HeaterCL.Ramprate", "HeaterCL.RamprateUnit", "HeaterCL.Check", "HeaterCL.High", "HeaterCL.Low", "HeaterCL.Unit" });
+                        AddParameterValue(ref dic, "HeaterCL.SetParameters", new string[8] { controlMode, correct, PID, "", "", "", dic["ValveAV91"], dic["BWR"] });
+
+                        AddParameter(ref dic, "HeaterL.SetParameters", new string[9] { "HeaterL.ZoneName", "HeaterL.Set", "HeaterL.SetUnit", "HeaterL.Ramprate", "HeaterL.RamprateUnit", "HeaterL.Check", "HeaterL.High", "HeaterL.Low", "HeaterL.Unit" });
+                        AddParameterValue(ref dic, "HeaterL.SetParameters", new string[8] { controlMode, correct, PID, "", "", "", dic["ValveAV91"], dic["BWR"] });
+
+                        AddParameter(ref dic, "APC.SetParameters", new string[10] { "Press.Command", "Press.PID", "Press.Set", "Press.SlowVacSet", "Press.ValveAngleSet", "Press.IsWait", "Press.LowWait", "Press.HighWait", "Press.WaitUnit", "Press.WaitPress" });//APC
+                        AddParameterValue(ref dic, "APC.SetParameters", new string[2] { "", dic["ValveAV71"] });//APC
+
+                        AddParameter(ref dic, "SetBoatMotion", new string[5] { "Loader.Command", "Loader.Speed1", "Loader.Speed2", "Loader.Speed3", "Loader.RPM" });//Boat
+
+                        List<string> auxCommands = new List<string>();
+                        for (int k = 1; k < 200; k++)
+                        {
+                            if (!dic.ContainsKey($"AUX.{k}.Set"))
+                                continue;
+                            auxCommands.Add($"{k},{dic[$"AUX.{k}.Set"]},{dic[$"AUX.{k}.Check"]},{dic[$"AUX.{k}.High"]},{dic[$"AUX.{k}.Low"]},{dic[$"AUX.{k}.CheckUnit"]}");
+                            dic.Remove($"AUX.{k}.Set");
+                            dic.Remove($"AUX.{k}.Check");
+                            dic.Remove($"AUX.{k}.High");
+                            dic.Remove($"AUX.{k}.Low");
+                            dic.Remove($"AUX.{k}.CheckUnit");
+                        }
+                        dic.Add("AUX.SetParameters", string.Join(";", auxCommands));
+
+                        //ReplaceControlName(ref dic, "RFSwitch", "RfPower.SetParameters");
+                        //AddParameter(ref dic, "RfPower.SetParameters", dic["RFSetpoint"], dic["ForwardPowerAlarmWatchTable"], dic["PrAlarmWatchTable"], dic["PIAlarmWatchTable"]);
+
+                        //ReplaceControlName(ref dic, "C1Setpoint", "RfMatch.SetParameters");
+                        //AddParameter(ref dic, "RfMatch.SetParameters", dic["C2Setpoint"], dic["C1AlarmWatchTable"], dic["C2AlarmWatchTable"], dic["VppAlarmWatchTable"]);
+                        AddValveParameter(ref dic, "SetValves", new string[159] {
+                      "ValveAV1",
+                      "ValveAV2",
+                      "ValveAV3",
+                      "ValveAV4",
+                      "ValveAV5",
+                      "ValveAV6",
+                      "ValveAV7",
+                      "ValveAV8",
+                      "ValveAV9",
+                      "ValveAV10",
+                      "ValveAV11",
+                      "ValveAV12",
+                      "ValveAV13",
+                      "ValveAV14",
+                      "ValveAV15",
+                      "ValveAV16",
+                      "ValveAV17",
+                      "ValveAV18",
+                      "ValveAV19",
+                      "ValveAV20",
+                      "ValveAV21",
+                      "ValveAV22",
+                      "ValveAV23",
+                      "ValveAV24",
+                      "ValveAV25",
+                      "ValveAV26",
+                      "ValveAV27",
+                      "ValveAV28",
+                      "ValveAV29",
+                      "ValveAV30",
+                      "ValveAV31",
+                      "ValveAV32",
+                      "ValveAV33",
+                      "ValveAV34",
+                      "ValveAV35",
+                      "ValveAV36",
+                      "ValveAV37",
+                      "ValveAV38",
+                      "ValveAV39",
+                      "ValveAV40",
+                      "ValveAV41",
+                      "ValveAV42",
+                      "ValveAV43",
+                      "ValveAV44",
+                      "ValveAV45",
+                      "ValveAV46",
+                      "ValveAV47",
+                      "ValveAV48",
+                      "ValveAV49",
+                      "ValveAV50",
+                      "ValveAV51",
+                      "ValveAV52",
+                      "ValveAV53",
+                      "ValveAV54",
+                      "ValveAV55",
+                      "ValveAV56",
+                      "ValveAV57",
+                      "ValveAV58",
+                      "ValveAV59",
+                      "ValveAV60",
+                      "ValveAV61",
+                      "ValveAV62",
+                      "ValveAV63",
+                      "ValveAV64",
+                      "ValveAV65",
+                      "ValveAV66",
+                      "ValveAV67",
+                      "ValveAV68",
+                      "ValveAV69",
+                      "ValveAV70",
+                      "ValveAV71",
+                      "ValveAV72",
+                      "ValveAV73",
+                      "ValveAV74",
+                      "ValveAV75",
+                      "ValveAV76",
+                      "ValveAV77",
+                      "ValveAV78",
+                      "ValveAV79",
+                      "ValveAV80",
+                      "ValveAV81",
+                      "ValveAV82",
+                      "ValveAV83",
+                      "ValveAV84",
+                      "ValveAV85",
+                      "ValveAV86",
+                      "ValveAV87",
+                      "ValveAV88",
+                      "ValveAV89",
+                      "ValveAV90",
+                      "ValveAV91",
+                      "ValveAV92",
+                      "ValveAV93",
+                      "ValveAV94",
+                      "ValveAV95",
+                      "ValveAV96",
+                      "ValveAV97",
+                      "ValveAV98",
+                      "ValveAV99",
+                      "ValveAV100",
+                      "ValveAV101",
+                      "ValveAV102",
+                      "ValveAV103",
+                      "ValveAV104",
+                      "ValveAV105",
+                      "ValveAV106",
+                      "ValveAV107",
+                      "ValveAV108",
+                      "ValveAV109",
+                      "ValveAV110",
+                      "ValveAV111",
+                      "ValveAV112",
+                      "ValveAV113",
+                      "ValveAV114",
+                      "ValveAV115",
+                      "ValveAV116",
+                      "ValveAV117",
+                      "ValveAV118",
+                      "ValveAV119",
+                      "ValveAV120",
+                      "ValveAV121",
+                      "ValveAV122",
+                      "ValveAV123",
+                      "ValveAV124",
+                      "ValveAV125",
+                      "ValveAV126",
+                      "ValveAV127",
+                      "ValveAV128",
+                      "ValveAV129",
+                      "ValveAV130",
+                      "ValveAV131",
+                      "ValveAV132",
+                      "ValveAV133",
+                      "ValveAV134",
+                      "ValveAV135",
+                      "ValveAV136",
+                        "DPR",
+                        "AGV",
+                        "AGV2",
+                        "MBP",
+                        "MBP1",
+                        "MBP2",
+                        "DP",
+                        "BWR",
+                        "F2Cln",
+                        "HFCln",
+                        "CEXH",
+                        "DEPO",
+                        "HTR1",
+                        "HTR2",
+                        "HTR3",
+                        "DP1",
+                        "DP2",
+                        "HMNT",
+                        "CMNT",
+                        "HREF",
+                        "CREF",
+                        "HZERO",
+                        "CZERO"
+                    });
+
+                        //dic.Remove("SetValves");
+                        //dic.Remove("HeaterU.SetParameters");
+                        //dic.Remove("HeaterCU.SetParameters");
+                        //dic.Remove("HeaterC.SetParameters");
+                        //dic.Remove("HeaterCL.SetParameters");
+                        //dic.Remove("HeaterL.SetParameters");
+                        //dic.Remove("MFC1.SetParameters");
+                        //dic.Remove("MFC2.SetParameters");
+                        //dic.Remove("MFC3.SetParameters");
+                        //dic.Remove("MFC4.SetParameters");
+                        //dic.Remove("MFC5.SetParameters");
+                        //dic.Remove("MFC6.SetParameters");
+                        //dic.Remove("MFC7.SetParameters");
+                        //dic.Remove("MFC8.SetParameters");
+                        //dic.Remove("MFC9.SetParameters");
+                        //dic.Remove("MFC10.SetParameters");
+                        //dic.Remove("MFC11.SetParameters");
+                        //dic.Remove("MFC12.SetParameters");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV1");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV2");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV3");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV4");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV5");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV6");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV7");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV8");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV9");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV10");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV11");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV12");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV13");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV14");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV15");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV16");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV17");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV18");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV19");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV20");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV21");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV22");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV23");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV24");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV25");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV26");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV27");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV28");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV29");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV30");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV31");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV32");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV33");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV34");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV35");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV36");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV37");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV38");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV39");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV52");
+                        ////ReplaceControlNameForValve(ref dic, "ValveAV54");
+                        ////ReplaceControlNameForValve(ref dic, "ValveAV56");
+                        ////ReplaceControlNameForValve(ref dic, "ValveAV57");
+                        ////ReplaceControlNameForValve(ref dic, "ValveAV58");
+                        ////ReplaceControlNameForValve(ref dic, "ValveAV59");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV60");
+                        ////ReplaceControlNameForValve(ref dic, "ValveAV65");
+                        ////ReplaceControlNameForValve(ref dic, "ValveAV66");
+                        ////ReplaceControlNameForValve(ref dic, "ValveAV68");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV71");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV72");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV73");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV74");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV75");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV77");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV81");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV82");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV83");
+                        //ReplaceControlNameForValve(ref dic, "ValveAV91");
+                        dic.Remove("StepNo");
+                        dic.Remove("Name");
+                        dic.Remove("EndBy");
+                        dic.Remove("Time");
+                        dic.Remove("ZAxisPosition");
+                        dic.Remove("ZAxisSpeed");
+                        dic.Remove("RotatePosition");
+                        dic.Remove("RotateSpeed");
+                        dic.Remove("RotateDirection");
+                        dic.Remove("Heater1");
+                        dic.Remove("Heater2");
+                        dic.Remove("Heater3");
+                        dic.Remove("Heater4");
+                        dic.Remove("Heater5");
+                        dic.Remove("ValveAV54");
+                        dic.Remove("ValveAV56");
+                        dic.Remove("ValveAV57");
+                        dic.Remove("ValveAV58");
+                        dic.Remove("ValveAV59");
+                        dic.Remove("ValveAV65");
+                        dic.Remove("ValveAV66");
+                        dic.Remove("ValveAV68");
+                        dic.Remove("ExternalOn");
+                        dic.Remove("ExternalOff");
+                        dic.Remove("ExternalSensor");
+                        dic.Remove("TempStabilize");
+                        dic.Remove("FinishAutoProfile");
+                        dic.Remove("ReachTempWait");
+                        dic.Remove("ReachTemp");
+                        dic.Remove("TempUpper");
+                        dic.Remove("TempLower");
+                        dic.Remove("ReachPressureWait");
+                        dic.Remove("ReachPressure");
+                        dic.Remove("PressureUpper");
+                        dic.Remove("PressureLower");
+                        dic.Remove("PressureStabilize");
+                        dic.Remove("External.Out1");
+                        dic.Remove("External.Out2");
+                        dic.Remove("External.Out3");
+                        dic.Remove("External.Out4");
+                        dic.Remove("External.Out5");
+                        dic.Remove("External.Out6");
+
+                        dic.Remove("RFSwitch");
+                        dic.Remove("RFSetpoint");
+                        dic.Remove("ForwardPowerAlarmWatchTable");
+                        dic.Remove("PrAlarmWatchTable");
+                        dic.Remove("PIAlarmWatchTable");
+
+                        dic.Remove("C1Setpoint");
+                        dic.Remove("C2Setpoint");
+                        dic.Remove("C1AlarmWatchTable");
+                        dic.Remove("C2AlarmWatchTable");
+                        dic.Remove("VppAlarmWatchTable");
+                        dic.Remove("VdcAlarmWatchTable");
+                        dic.Remove("AbortRecipeTableIndex");
+
+                        dic.Remove("Temperature.ControlMode");
+                        dic.Remove("Temperature.Correct");
+                        dic.Remove("Temperature.PID");
+                        dic.Remove("Temperature.Profile");
+                        dic.Remove("Temperature.Stabilize");
+                        dic.Remove("Temperature.TempReadyCond");
+
+                        dic.Remove("FilmThickFormula");
+                        dic.Remove("FilmThickCoefficientA");
+                        dic.Remove("FilmThickCoefficientB");
+
+                        dic.Remove("APC.SetPressure");
+                        dic.Remove("PressureSettingVG");
+                        dic.Remove("PressureSonserValue");
+                        dic.Remove("PressureValveAngle");
+                        dic.Remove("PressureAlarmTableNo");
+
+                        dic.Remove("EventSetting");
+                        dic.Remove("AlarmTableIndex");
+                        dic.Remove("AlarmDetails.1");
+                        dic.Remove("AlarmAction.1");
+                        dic.Remove("AlarmDetails.2");
+                        dic.Remove("AlarmAction.2");
+                        dic.Remove("AlarmDetails.3");
+                        dic.Remove("AlarmAction.3");
+                        dic.Remove("AlarmDetails.4");
+                        dic.Remove("AlarmAction.4");
+                        dic.Remove("AlarmDetails.5");
+                        dic.Remove("AlarmAction.5");
+                        dic.Remove("AlarmDetails.6");
+                        dic.Remove("AlarmAction.6");
+                        dic.Remove("AlarmDetails.7");
+                        dic.Remove("AlarmAction.7");
+                        dic.Remove("AlarmDetails.8");
+                        dic.Remove("AlarmAction.8");
+                        dic.Remove("AlarmDetails.9");
+                        dic.Remove("AlarmAction.9");
+                        dic.Remove("AlarmDetails.10");
+                        dic.Remove("AlarmAction.10");
+
+                        //List<string> mfcCheckInstall = new List<string>()
+                        //{
+                        //    "MfcN1",
+                        //    "MfcN2",
+                        //    "MfcN3",
+                        //    "MfcH1",
+                        //    "MfcJ1",
+                        //    "MfcXN1",
+                        //};
+                        //foreach(var mfc in mfcCheckInstall)
+                        //{
+                        //    if (!SC.GetValue<bool>($"PM1.MFC.{mfc}.IsMFCInstalled"))
+                        //        dic.Remove($"{mfc}.SetParameters");
+                        //}
+
+                        foreach (string key in dic.Keys)
+                            recipeStep.RecipeCommands.Add(key, dic[key]);
+                    }
+
+                    for (int i = 0; i < recipeData.Count; i++)
+                    {
+                        if (recipeData[i].IsJumpStep)
+                        {
+                            bool findJumpStep = false;
+                            for (int j = 0; j < recipeData.Count; j++)
+                            {
+                                if (recipeData[j].StepName == recipeData[i].JumpStepName)
+                                {
+                                    recipeData[i].JumpStepNo = j;
+                                    findJumpStep = true;
+                                    break;
+                                }
+                            }
+
+                            if (!findJumpStep)
+                            {
+                                reason = $"Recipe file does not contains jump step {recipeData[i].JumpStepName}";
+                                return false;
+                            }
+                        }
+                    }
+                    #endregion
+                    recipeDatas.Add(x + 1, recipeData);
+                }
+
+
+
+
+            }
+            catch (Exception ex)
+            {
+                LOG.Write(ex);
+
+                reason = $"Recipe file content not valid, {recipeFile}, {ex.Message}";
+                return false;
+            }
+            return true;
+        }
+
     }
 }

+ 5 - 0
Furnace/FurnaceRT/Equipments/Systems/EquipmentManager.cs

@@ -1813,6 +1813,11 @@ namespace FurnaceRT.Equipments.Systems
         {
             return _auto.GetFirstPJStatus();
         }
+
+        public void PjFinished(string endStatus = "Normal")
+        {
+            _auto.PjFinished(endStatus);
+        }
         #region FA
 
         private bool FsmFAJobCommand(object[] param)

+ 1 - 1
Furnace/FurnaceUI/Views/Recipes/RecipeJobViewModel.cs

@@ -954,7 +954,7 @@ namespace FurnaceUI.Views.Recipes
                     prefix = GetPrefix(CurrentFileNode.PrefixPath, CurrentFileNode);
                 }
             }
-            if (RecipeFileList.Find(a => a.Name == recipeName.ToLower()) != null)
+            if (RecipeFileList!=null&&RecipeFileList.Find(a => a.Name == recipeName.ToLower()) != null)
             {
                 DialogBox.ShowWarning($"Can not create {recipeName}, Recipe with the same name already exist.");
                 return;

+ 1 - 1
Furnace/FurnaceUI/Views/Recipes/RecipeLayoutViewModel.cs

@@ -944,7 +944,7 @@ namespace FurnaceUI.Views.Recipes
                     prefix = GetPrefix(CurrentFileNode.PrefixPath, CurrentFileNode);
                 }
             }
-            if (RecipeFileList.Find(a => a.Name == recipeName.ToLower()) != null)
+            if (RecipeFileList != null && RecipeFileList.Find(a => a.Name == recipeName.ToLower()) != null)
             {
                 DialogBox.ShowWarning($"Can not create {recipeName}, Recipe with the same name already exist.");
                 return;

+ 2 - 2
Furnace/FurnaceUI/Views/Recipes/RecipeViewModel.cs

@@ -492,7 +492,7 @@ namespace FurnaceUI.Views.Recipes
                 //获取目录
                 prefix = GetPrefix(CurrentFileNode.PrefixPath, CurrentFileNode);
             }
-            if (RecipeFileList.Find(a => a.Name == recipeName.ToLower()) != null)
+            if (RecipeFileList != null && RecipeFileList.Find(a => a.Name == recipeName.ToLower()) != null)
             {
                 return;
             }
@@ -2223,7 +2223,7 @@ namespace FurnaceUI.Views.Recipes
             {
                 recipeEditViewModel.SelectedStepName = oldStepName;
             }
-            bool? bret = (windowManager as WindowManager)?.ShowDialogWithTitle(recipeEditViewModel,this, null, $"Recipe Edit");
+            bool? bret = (windowManager as WindowManager)?.ShowDialogWithTitle(recipeEditViewModel, this, null, $"Recipe Edit");
             if (recipeEditViewModel.CurrentRecipe != null && recipeEditViewModel.selectStep != null)
             {
                 oldPrefix = recipeEditViewModel.CurrentRecipe.PrefixPath;