using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Xml; using Aitex.Common.Util; using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.Log; using Aitex.Core.RT.RecipeCenter; using Aitex.Core.RT.SCCore; using SicModules.PMs.RecipeExecutions; using static Aitex.Core.RT.Device.PmDevices.DicMode; namespace SicModules.PMs.Routines.EditableRoutine { public class EditableRoutineParser { public static bool Parse(string routineName, string module, out RecipeHead recipeHead, out List recipeData, out string reason) { reason = string.Empty; recipeHead = new RecipeHead(); recipeData = new List(); string content = RecipeFileManager.Instance.LoadRecipe("", routineName, false); if (string.IsNullOrEmpty(content)) { reason = $"{routineName} is not a valid routine file"; return false; } try { //获取工艺程序文件中允许的命令字符串列表 //目的:如果工艺程序文件中含有规定之外的命令,则被禁止执行 HashSet recipeAllowedCommands = new HashSet(); XmlDocument rcpFormatDoc = new XmlDocument(); string recipeSchema = PathManager.GetCfgDir() + @"\Recipe\Sic\Routine\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); } //获取工艺程序文件中所有步的内容 XmlDocument rcpDataDoc = new XmlDocument(); rcpDataDoc.LoadXml(content); XmlNode nodeModule = rcpDataDoc.SelectSingleNode($"/Aitex/TableRecipeData/Module[@Name='{module}']"); if (nodeModule == null) { reason = $"Routine file does not contains step content for {module}"; return false; } XmlElement nodeConfig = nodeModule.SelectSingleNode($"Config") as XmlElement; recipeHead.ProcessPurgeCount = (nodeConfig != null && nodeConfig.HasAttribute("StepNo")) ? nodeConfig.Attributes["StepNo"].Value : ""; XmlNodeList stepNodeList = nodeModule.SelectNodes($"Step"); for (int i = 0; i < stepNodeList.Count; i++) { var recipeStep = new RecipeStep(); recipeData.Add(recipeStep); XmlElement stepNode = stepNodeList[i] as XmlElement; Dictionary dic = new Dictionary(); //遍历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"]; recipeStep.StepTime = Convert.ToDouble(dic["Time"]); //转换成enum recipeStep.EndBy = (EnumEndByCondition)Enum.Parse(typeof(EnumEndByCondition), dic["EndBy"]); recipeStep.LoopCount = 0; recipeStep.IsLoopStartStep = false; recipeStep.IsLoopEndStep = false; int.TryParse(dic["LoopTimes"], out recipeStep.LoopCount); if (dic.ContainsKey("LoopStart")) { bool.TryParse(dic["LoopStart"], out recipeStep.IsLoopStartStep); } if (dic.ContainsKey("LoopEnd")) { bool.TryParse(dic["LoopEnd"], out recipeStep.IsLoopEndStep); } //特殊处理 if (dic.ContainsKey("V33.GVTurnValve")) { if (dic["V33.GVTurnValve"] == "H2") { dic["V33.GVTurnValve"] = "True"; } else if (dic["V33.GVTurnValve"] == "Ar") { dic["V33.GVTurnValve"] = "False"; } } if (dic.ContainsKey("V64.GVTurnValve")) { if (dic["V64.GVTurnValve"] == "H2") { dic["V64.GVTurnValve"] = "True"; } else if (dic["V64.GVTurnValve"] == "Close") { dic["V64.GVTurnValve"] = "False"; } } if (dic.ContainsKey("V65.GVTurnValve")) { if (dic["V65.GVTurnValve"] == "Ar") { dic["V65.GVTurnValve"] = "True"; } else if (dic["V65.GVTurnValve"] == "Close") { dic["V65.GVTurnValve"] = "False"; } } if (dic.ContainsKey("V68.GVTurnValve")) { if (dic["V68.GVTurnValve"] == "Ar") { dic["V68.GVTurnValve"] = "True"; } else if (dic["V68.GVTurnValve"] == "Close") { dic["V68.GVTurnValve"] = "False"; } } dic = dic.ToDictionary(k => k.Key, v => v.Value == "Open" ? "True" : (v.Value == "Close" ? "False" : v.Value)); // 阀门 dic = dic.ToDictionary(k => k.Key, v => v.Value == "Enable" ? "True" : (v.Value == "Disable" ? "False" : v.Value)); // Enable // 蝶阀 if (dic["TV.SetMode"] == "Position") { dic["TV.SetMode"] = PressureCtrlMode.TVPositionCtrl.ToString(); } else if (dic["TV.SetMode"] == "Pressure") { dic["TV.SetMode"] = PressureCtrlMode.TVPressureCtrl.ToString(); } else if (dic["TV.SetMode"] == "Close") { dic["TV.SetMode"] = PressureCtrlMode.TVClose.ToString(); } else { dic["TV.SetMode"] = "Hold"; } // PSU and SCR HeaterControlMode PSUControlMode = (HeaterControlMode)Enum.Parse(typeof(HeaterControlMode), dic["TC1.SetHeaterMode"]); HeaterControlMode SCRControlMode = (HeaterControlMode)Enum.Parse(typeof(HeaterControlMode), dic["TC2.SetHeaterMode2"]); dic["TC1.SetHeaterMode"] = ((int)PSUControlMode).ToString(); dic["TC2.SetHeaterMode2"] = ((int)SCRControlMode).ToString(); //if (PSUControlMode == HeaterControlMode.Power) //{ // dic.Remove("TC1.SetL1TargetSP"); // dic.Remove("TC1.SetL2TargetSP"); // dic.Remove("TC1.SetL3TargetSP"); //} if (SCRControlMode == HeaterControlMode.Power) { dic.Remove("TC2.SetL3TargetSP"); } dic.Remove("StepNo"); dic.Remove("Name"); dic.Remove("Time"); dic.Remove("EndBy"); dic.Remove("LoopStart"); dic.Remove("LoopEnd"); dic.Remove("LoopTimes"); //if(dic.ContainsKey("V64.GVTurnValve")) //{ // dic.Remove("V64.GVTurnValve"); //} //if (dic.ContainsKey("V65.GVTurnValve")) //{ // dic.Remove("V65.GVTurnValve"); //} //if (dic.ContainsKey("V66.GVTurnValve")) //{ // dic.Remove("V66.GVTurnValve"); //} //if (dic.ContainsKey("V67.GVTurnValve")) //{ // dic.Remove("V67.GVTurnValve"); //} foreach (string key in dic.Keys) { if (dic[key] != "Hold") { recipeStep.RecipeCommands.Add(key, dic[key]); } } } } catch (Exception ex) { LOG.Write(ex); reason = $"Routine file content not valid, {routineName}, {ex.Message}"; return false; } return true; } } }