RecipeFileManager.cs 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows.Forms.VisualStyles;
  6. using System.Xml.Schema;
  7. using System.Xml;
  8. using System.IO;
  9. using Aitex.Core.RT.Log;
  10. using System.Text.RegularExpressions;
  11. using Aitex.Common.Util;
  12. using Aitex.Core.RT.Event;
  13. using Aitex.Core.Util;
  14. using Aitex.Core.Utilities;
  15. using Aitex.Core.WCF;
  16. using MECF.Framework.Common.OperationCenter;
  17. using MECF.Framework.Common.Properties;
  18. using MECF.Framework.Common.RecipeCenter;
  19. namespace Aitex.Core.RT.RecipeCenter
  20. {
  21. public class RecipeFileManager : Singleton<RecipeFileManager>
  22. {
  23. //sequence文件 统一放在 Recipes/Sequence 文件夹下面
  24. public const string SequenceFolder = "Sequence";
  25. public const string SourceModule = "Recipe";
  26. private bool _recipeIsValid;
  27. private List<string> _validationErrors = new List<string>();
  28. private List<string> _validationWarnings = new List<string>();
  29. private Dictionary<int, Dictionary<string, string>> _recipeItems;
  30. IRecipeFileContext _rcpContext;
  31. private ISequenceFileContext _seqContext;
  32. IEapMapFileContext _eapMapContext;
  33. public void Initialize(IRecipeFileContext context, IEapMapFileContext eapMapContext = null)
  34. {
  35. Initialize(context, null, true, eapMapContext);
  36. }
  37. public void Initialize(IRecipeFileContext context, bool enableService, IEapMapFileContext eapMapContext = null)
  38. {
  39. Initialize(context, null, enableService, eapMapContext);
  40. }
  41. public void Initialize(IRecipeFileContext rcpContext, ISequenceFileContext seqContext, bool enableService, IEapMapFileContext eapMapContext = null)
  42. {
  43. _rcpContext = rcpContext == null ? new DefaultRecipeFileContext() : rcpContext;
  44. _seqContext = seqContext == null ? new DefaultSequenceFileContext() : seqContext;
  45. _eapMapContext = eapMapContext == null ? new DefaultEapMapFileContext() : eapMapContext;
  46. CultureSupported.UpdateCoreCultureResource(CultureSupported.English);
  47. if (enableService)
  48. {
  49. Singleton<WcfServiceManager>.Instance.Initialize(new Type[]
  50. {
  51. typeof(RecipeService)
  52. });
  53. }
  54. var dir = string.Format("{0}{1}\\", PathManager.GetRecipeDir(), SequenceFolder);
  55. DirectoryInfo di = new DirectoryInfo(dir);
  56. if (!di.Exists)
  57. {
  58. di.Create();
  59. }
  60. InitMapConvert();
  61. }
  62. private void ValidationEventHandler(object sender, ValidationEventArgs e)
  63. {
  64. switch (e.Severity)
  65. {
  66. case XmlSeverityType.Error:
  67. _validationErrors.Add(e.Message);
  68. _recipeIsValid = false;
  69. break;
  70. case XmlSeverityType.Warning:
  71. _validationWarnings.Add(e.Message);
  72. break;
  73. }
  74. }
  75. /// <summary>
  76. /// XML schema checking
  77. /// </summary>
  78. /// <param name="chamId"></param>
  79. /// <param name="recipeName"></param>
  80. /// <param name="recipeContent"></param>
  81. /// <param name="reason"></param>
  82. /// <returns></returns>
  83. public bool ValidateRecipe(string chamberId, string recipeName, string recipeContent, out List<string> reason)
  84. {
  85. try
  86. {
  87. XmlDocument document = new XmlDocument();
  88. document.LoadXml(recipeContent);
  89. MemoryStream schemaStream = new MemoryStream(ASCIIEncoding.ASCII.GetBytes(GetRecipeSchema(chamberId)));
  90. XmlReader xmlSchemaReader = XmlReader.Create(schemaStream);
  91. XmlSchema schema1 = XmlSchema.Read(xmlSchemaReader, ValidationEventHandler);
  92. document.Schemas.Add(schema1);
  93. document.LoadXml(recipeContent);
  94. ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
  95. _recipeIsValid = true;
  96. _validationErrors = new List<string>();
  97. _validationWarnings = new List<string>();
  98. // Validates recipe.
  99. document.Validate(eventHandler);
  100. }
  101. catch (Exception ex)
  102. {
  103. LOG.Write(ex.Message);
  104. _recipeIsValid = false;
  105. }
  106. if (!_recipeIsValid && _validationErrors.Count == 0)
  107. {
  108. _validationErrors.Add(Resources.RecipeFileManager_ValidateRecipe_XMLSchemaValidateFailed);
  109. }
  110. reason = _validationErrors;
  111. return _recipeIsValid;
  112. }
  113. /// <summary>
  114. /// 检查变量ramp rate
  115. /// </summary>
  116. /// <param name="stepNo"></param>
  117. /// <param name="rampEnable"></param>
  118. /// <param name="varName"></param>
  119. /// <param name="rampTime"></param>
  120. /// <param name="maxRampUpRate"></param>
  121. /// <param name="maxRampDownRate"></param>
  122. /// <returns>False:check ok, True: check failed</returns>
  123. public bool CheckRampRate(int stepNo, string rampEnable, string varName, string rampTime, double maxRampUpRate, double maxRampDownRate)
  124. {
  125. try
  126. {
  127. if (stepNo <= 0)
  128. return false;
  129. if (varName == "AZone.Setpoint" || varName == "BZone.Setpoint" || varName == "CZone.Setpoint" || varName == "DZone.Setpoint")
  130. {
  131. string curStepHeatCtrlMode = _recipeItems[stepNo]["Heater.Mode"];
  132. string lastStepHeatCtrlMode = _recipeItems[stepNo - 1]["Heater.Mode"];
  133. if (curStepHeatCtrlMode != lastStepHeatCtrlMode)
  134. return false;
  135. }
  136. bool isRampEnable = bool.Parse(rampEnable);
  137. string[] timeStr = rampTime.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
  138. double hh = 0;
  139. double mm = 0;
  140. double ss = 0;
  141. if (timeStr.Length == 3)
  142. {
  143. hh = double.Parse(timeStr[0]);
  144. mm = double.Parse(timeStr[1]);
  145. ss = double.Parse(timeStr[2]);
  146. }
  147. else if (timeStr.Length == 2)
  148. {
  149. mm = double.Parse(timeStr[0]);
  150. ss = double.Parse(timeStr[1]);
  151. }
  152. else if (timeStr.Length == 1)
  153. {
  154. ss = double.Parse(timeStr[0]);
  155. }
  156. double totalTimeSec = hh * 3600 + mm * 60 + ss;
  157. double diff = double.Parse(_recipeItems[stepNo][varName]) - double.Parse(_recipeItems[stepNo - 1][varName]);
  158. if (!isRampEnable || totalTimeSec <= 0)
  159. {
  160. //jump
  161. if (diff != 0) return true;
  162. return false;
  163. }
  164. else
  165. {
  166. double rampRate = diff / totalTimeSec;
  167. if ((rampRate > 0 && rampRate >= maxRampUpRate) ||
  168. (rampRate < 0 && rampRate <= -maxRampDownRate))
  169. return true;
  170. return false;
  171. }
  172. }
  173. catch (Exception ex)
  174. {
  175. LOG.Write(ex.Message);
  176. return true;
  177. }
  178. }
  179. private object _locker = new object();
  180. /// <summary>
  181. /// Check recipe content
  182. /// </summary>
  183. /// <param name="chamId"></param>
  184. /// <param name="recipeContent"></param>
  185. /// <param name="reasons"></param>
  186. /// <returns></returns>
  187. public bool CheckRecipe(string chamberId, string recipeContent, out List<string> reasons)
  188. {
  189. lock (_locker)
  190. {
  191. reasons = new List<string>();
  192. //add recipe content validation here
  193. try
  194. {
  195. var xmlFormat = new XmlDocument();
  196. xmlFormat.LoadXml(GetRecipeFormatXml(chamberId));
  197. var mfcDic = new Dictionary<string, double>(); //name + scale
  198. var pcDic = new Dictionary<string, double>(); //name + scale
  199. foreach (XmlElement mfc in xmlFormat.SelectNodes("/TableRecipeFormat/Catalog/Group/Step[@DeviceType='MFC']"))
  200. {
  201. mfcDic.Add(mfc.Attributes["ControlName"].Value, Convert.ToDouble(mfc.Attributes["Max"].Value));
  202. }
  203. foreach (XmlElement pc in xmlFormat.SelectNodes("/TableRecipeFormat/Catalog/Group/Step[@DeviceType='PC']"))
  204. {
  205. pcDic.Add(pc.Attributes["ControlName"].Value, Convert.ToDouble(pc.Attributes["Max"].Value));
  206. }
  207. //var spindleMaxSpeed = Convert.ToDouble(xmlFormat.SelectSingleNode("/TableRecipeFormat/Catalog/Group/Step[@ControlName='Spindle.Speed']").Attributes["Max"].Value);
  208. var xmlRecipe = new XmlDocument();
  209. xmlRecipe.LoadXml(recipeContent);
  210. //read in all recipe items
  211. _recipeItems = new Dictionary<int, Dictionary<string, string>>();
  212. var stepElements = xmlRecipe.SelectNodes("/TableRecipeData/Step");
  213. for (int stepNo = 0; stepNo < stepElements.Count; stepNo++)
  214. {
  215. var stepElement = stepElements[stepNo] as XmlElement;
  216. var step = new Dictionary<string, string>();
  217. _recipeItems[stepNo] = step;
  218. foreach (XmlAttribute att1 in stepElement.Attributes)
  219. {
  220. step.Add(att1.Name, att1.Value);
  221. }
  222. foreach (XmlElement subNd1 in stepElement.ChildNodes)
  223. {
  224. foreach (XmlAttribute att2 in subNd1.Attributes)
  225. {
  226. step.Add(att2.Name, att2.Value);
  227. }
  228. foreach (XmlElement subNd2 in subNd1.ChildNodes)
  229. {
  230. foreach (XmlAttribute att3 in subNd2.Attributes)
  231. {
  232. step.Add(att3.Name, att3.Value);
  233. }
  234. foreach (XmlElement subNd3 in subNd2.ChildNodes)
  235. {
  236. foreach (XmlAttribute att4 in subNd3.Attributes)
  237. {
  238. step.Add(att4.Name, att4.Value);
  239. }
  240. }
  241. }
  242. }
  243. }
  244. #region check loop control
  245. for (int j = 0; j < _recipeItems.Count; j++)
  246. {
  247. var loopStr = _recipeItems[j]["Loop"];
  248. bool isLoopStart = Regex.IsMatch(loopStr, @"^Loop\x20\d+$");
  249. bool isLoopEnd = Regex.IsMatch(loopStr, @"^Loop End$");
  250. bool isNullOrEmpty = string.IsNullOrWhiteSpace(loopStr);
  251. if (!isLoopEnd && !isLoopStart && !isNullOrEmpty)
  252. {
  253. string reason = string.Format("Value '{0}' not valid", loopStr);
  254. reasons.Add(string.Format("第{0}步,{1}.", j + 1, reason));
  255. }
  256. if (isLoopEnd)
  257. {
  258. string reason = "Loop Start 缺失";
  259. reasons.Add(string.Format("第{0}步,{1}.", j + 1, reason));
  260. }
  261. else if (isLoopStart)
  262. {
  263. for (int k = j + 1; k < _recipeItems.Count; k++)
  264. {
  265. var loopStr2 = _recipeItems[k]["Loop"];
  266. bool isCurStepLoopStart = Regex.IsMatch(loopStr2, @"^Loop\x20\d+$");
  267. bool isCurStepLoopEnd = Regex.IsMatch(loopStr2, @"^Loop End$");
  268. isNullOrEmpty = string.IsNullOrWhiteSpace(loopStr2);
  269. if (!isCurStepLoopEnd && !isCurStepLoopStart && !isNullOrEmpty)
  270. {
  271. string reason = string.Format("Value '{0}' not valid", loopStr2);
  272. reasons.Add(string.Format("第{0}步,{1}.", k + 1, reason));
  273. }
  274. else if (isCurStepLoopStart)
  275. {
  276. string reason = "前面循环没有结束,不能设置新的Loop Start标志";
  277. reasons.Add(string.Format("第{0}步,{1}.", k + 1, reason));
  278. }
  279. else if (isCurStepLoopEnd)
  280. {
  281. j = k;
  282. break;
  283. }
  284. if (k == _recipeItems.Count - 1)
  285. {
  286. j = k;
  287. string reason = "Loop End 缺失";
  288. reasons.Add(string.Format("第{0}步,{1}.", k + 1, reason));
  289. }
  290. }
  291. }
  292. }
  293. #endregion
  294. //check mfc range
  295. for (int stepNo = 0; stepNo < _recipeItems.Count; stepNo++)
  296. {
  297. foreach (var mfcName in mfcDic.Keys)
  298. {
  299. if (_recipeItems[stepNo].ContainsKey(mfcName))
  300. {
  301. var mfcSetpoint = Convert.ToDouble(_recipeItems[stepNo][mfcName]);
  302. if (mfcSetpoint < 0 || mfcSetpoint > mfcDic[mfcName])
  303. {
  304. reasons.Add(string.Format("第{0}步,{1}设定{2},超出 0~{3}sccm范围.", stepNo + 1, mfcName, mfcSetpoint, mfcDic[mfcName]));
  305. }
  306. }
  307. }
  308. //check pc range
  309. foreach (var pcName in pcDic.Keys)
  310. {
  311. if (_recipeItems[stepNo].ContainsKey(pcName))
  312. {
  313. var pcSetpoint = Convert.ToDouble(_recipeItems[stepNo][pcName]);
  314. if (pcSetpoint < 0 || pcSetpoint > pcDic[pcName])
  315. {
  316. reasons.Add(string.Format("第{0}步,{1}设定{2},超出 0~{3}mbar范围.", stepNo + 1, pcName, pcSetpoint, pcDic[pcName]));
  317. }
  318. }
  319. }
  320. }
  321. #region recipe parameter validation
  322. //reading predefined varaible
  323. var recipePredfine = new Dictionary<string, string>();
  324. foreach (XmlElement nd in xmlFormat.SelectNodes("/TableRecipeFormat/Validation/Predefine/Item"))
  325. {
  326. recipePredfine.Add(nd.Attributes["VarName"].Value, nd.Attributes["Value"].Value);
  327. }
  328. //lua validation
  329. //using (var lua = new LuaInterface.Lua())
  330. //{
  331. // //is special recipe?
  332. // bool IsSpecialRecipe = true;
  333. // {
  334. // for (int stepIndex = 0; stepIndex < _recipeItems.Count; stepIndex++)
  335. // {
  336. // if (_recipeItems[stepIndex]["Heater.Mode"] != "CurrentControl" ||
  337. // _recipeItems[stepIndex]["AZone.Setpoint"] != "0" ||
  338. // _recipeItems[stepIndex]["BZone.Setpoint"] != "0" ||
  339. // _recipeItems[stepIndex]["CZone.Setpoint"] != "0" ||
  340. // (_recipeItems[stepIndex].ContainsKey("DZone.Setpoint") && _recipeItems[stepIndex]["DZone.Setpoint"] != "0"))
  341. // {
  342. // IsSpecialRecipe = false;
  343. // break;
  344. // }
  345. // }
  346. // }
  347. // lua.DoString(string.Format("IsProductionRecipe={0};", (!IsSpecialRecipe).ToString().ToLower()));
  348. // //set get ramp rate function
  349. // lua.RegisterFunction("CheckRampRate", this, GetType().GetMethod("CheckRampRate"));
  350. // for (int stepIndex = 0; stepIndex < _recipeItems.Count; stepIndex++)
  351. // {
  352. // //reading var from current recipe step
  353. // foreach (var varName in _recipeItems[stepIndex].Keys)
  354. // {
  355. // string varValueString = _recipeItems[stepIndex][varName];
  356. // double varValue;
  357. // if (double.TryParse(varValueString, out varValue))
  358. // lua.DoString(string.Format("{0}={1};", varName.Replace(".", "_"), varValueString));
  359. // else
  360. // lua.DoString(string.Format("{0}=\"{1}\";", varName.Replace(".", "_"), varValueString));
  361. // }
  362. // //reading predefined variables in recipe
  363. // foreach (var key in recipePredfine.Keys)
  364. // {
  365. // string varValueString = recipePredfine[key];
  366. // double varValue;
  367. // if (double.TryParse(varValueString, out varValue))
  368. // lua.DoString(string.Format("{0}={1};", key, varValue));
  369. // else
  370. // lua.DoString(string.Format("{0}=\"{1}\";", key, varValueString));
  371. // }
  372. // //set stepNo
  373. // lua.DoString(string.Format("StepNo={0};", stepIndex));
  374. // //reading validation rules
  375. // var validationRules = new List<Tuple<string, string, string>>();
  376. // foreach (XmlElement nd in xmlFormat.SelectNodes("/TableRecipeFormat/Validation/Restriction/Rule"))
  377. // {
  378. // string varName = nd.Attributes["VarName"].Value;
  379. // string checkCondition = nd.Attributes["CheckCondition"].Value.Replace("&lt;", "<").Replace("&gt;", ">");
  380. // string message = nd.Attributes["Message"].Value.Replace("'", "\"");
  381. // validationRules.Add(new Tuple<string, string, string>(varName, checkCondition, message));
  382. // }
  383. // //do valation
  384. // foreach (var rule in validationRules)
  385. // {
  386. // lua.DoString(string.Format("if {0} then hasErr=1 else hasErr=0 end", rule.Item2));
  387. // bool hasError = ((int)lua.GetNumber("hasErr")) == 1;
  388. // if (hasError)
  389. // {
  390. // lua.DoString(string.Format("message=string.format({0});", rule.Item3));
  391. // string reason = lua.GetString("message");
  392. // reasons.Add(string.Format("第{0}步,{1}.", stepIndex + 1, reason));
  393. // }
  394. // }
  395. // }
  396. //}
  397. #endregion
  398. }
  399. catch (Exception ex)
  400. {
  401. reasons.Add(Resources.RecipeFileManager_CheckRecipe_RecipeValidationFailed + ex.Message);
  402. LOG.Write(ex);
  403. return false;
  404. }
  405. return reasons.Count == 0;
  406. }
  407. }
  408. /// <summary>
  409. /// This method will be invoked by two places:
  410. /// (1) Load a recipe from server to GUI for editing (do not need validation when loading, do validation when saving);
  411. /// (2) Load a recipe from recipe engine to run process(always do a validation before run recipe);
  412. /// </summary>
  413. /// <param name="recipeName"></param>
  414. /// <param name="needValidation">indicate whether a recipe format validation is needed or not</param>
  415. /// <returns></returns>
  416. public string LoadRecipe(string chamberId, string recipeName, bool needValidation)
  417. {
  418. string rcp = string.Empty;
  419. try
  420. {
  421. using (StreamReader fs = new StreamReader(GenerateRecipeFilePath(chamberId, recipeName)))
  422. {
  423. rcp = fs.ReadToEnd();
  424. fs.Close();
  425. }
  426. //if (needValidation)
  427. //{
  428. // List<string> reason;
  429. // if (!ValidateRecipe(chamberId, recipeName, rcp, out reason))
  430. // {
  431. // rcp = string.Empty;
  432. // LOG.Write("校验recipe file 出错, " + string.Join(",", reason.ToArray()));
  433. // }
  434. //}
  435. }
  436. catch (Exception ex)
  437. {
  438. LOG.Write(ex, $"load recipe file failed, {recipeName}");
  439. rcp = string.Empty;
  440. }
  441. return rcp;
  442. }
  443. /// <summary>
  444. /// Get recipe list
  445. /// </summary>
  446. /// <param name="chamId"></param>
  447. /// <param name="includingUsedRecipe"></param>
  448. /// <returns></returns>
  449. public IEnumerable<string> GetRecipes(string chamberId, bool includingUsedRecipe)
  450. {
  451. return _rcpContext.GetRecipes(chamberId, includingUsedRecipe);
  452. }
  453. /// <summary>
  454. /// Get recipe list in xml format
  455. /// </summary>
  456. /// <param name="chamId"></param>
  457. /// <param name="includingUsedRecipe"></param>
  458. /// <returns></returns>
  459. public string GetXmlRecipeList(string chamberId, bool includingUsedRecipe)
  460. {
  461. XmlDocument doc = new XmlDocument();
  462. var baseFolderPath = getRecipeDirPath(chamberId);
  463. DirectoryInfo curFolderInfo = new DirectoryInfo(baseFolderPath);
  464. doc.AppendChild(GenerateRecipeList(chamberId, curFolderInfo, doc, includingUsedRecipe));
  465. return doc.OuterXml;
  466. }
  467. public void SaveRecipeHistory(string chamberId, string recipeName, string recipeContent, bool needSaveAs = true)
  468. {
  469. try
  470. {
  471. if (!string.IsNullOrEmpty(recipeName) && needSaveAs)
  472. {
  473. string newRecipeName = string.Format("HistoryRecipe\\{0}\\{1}", DateTime.Now.ToString("yyyyMM"), recipeName);
  474. SaveRecipe(chamberId, newRecipeName, recipeContent, true, false);
  475. LOG.Write(string.Format("{0}通知TM保存工艺程序{1}", chamberId, recipeName));
  476. }
  477. }
  478. catch (Exception ex)
  479. {
  480. LOG.Write(ex, string.Format("保存{0}工艺程序{1}发生错误", chamberId, recipeName));
  481. }
  482. }
  483. /// <summary>
  484. /// generate recipe list information in current directory
  485. /// </summary>
  486. /// <param name="chamId"></param>
  487. /// <param name="currentDir"></param>
  488. /// <param name="doc"></param>
  489. /// <returns></returns>
  490. XmlElement GenerateRecipeList(string chamberId, DirectoryInfo currentDir, XmlDocument doc, bool includingUsedRecipe)
  491. {
  492. int trimLength = getRecipeDirPath(chamberId).Length;
  493. XmlElement folderEle = doc.CreateElement("Folder");
  494. folderEle.SetAttribute("Name", currentDir.FullName.Substring(trimLength));
  495. DirectoryInfo[] dirInfos = currentDir.GetDirectories();
  496. foreach (DirectoryInfo dirInfo in dirInfos)
  497. {
  498. if (!includingUsedRecipe && dirInfo.Name == "HistoryRecipe")
  499. continue;
  500. folderEle.AppendChild(GenerateRecipeList(chamberId, dirInfo, doc, includingUsedRecipe));
  501. }
  502. FileInfo[] fileInfos = currentDir.GetFiles("*.rcp");
  503. foreach (FileInfo fileInfo in fileInfos)
  504. {
  505. XmlElement fileNd = doc.CreateElement("File");
  506. string fileStr = fileInfo.FullName.Substring(trimLength).TrimStart(new char[] { '\\' }); ;
  507. fileStr = fileStr.Substring(0, fileStr.LastIndexOf("."));
  508. fileNd.SetAttribute("Name", fileStr);
  509. folderEle.AppendChild(fileNd);
  510. }
  511. return folderEle;
  512. }
  513. /// <summary>
  514. /// Delete a recipe by recipe name
  515. /// </summary>
  516. /// <param name="chamId"></param>
  517. /// <param name="recipeName"></param>
  518. /// <returns></returns>
  519. public bool DeleteRecipe(string chamberId, string recipeName)
  520. {
  521. try
  522. {
  523. File.Delete(GenerateRecipeFilePath(chamberId, recipeName));
  524. InfoDialog(string.Format(Resources.RecipeFileManager_DeleteRecipe_RecipeFile0DeleteSucceeded, recipeName));
  525. }
  526. catch (Exception ex)
  527. {
  528. LOG.Write(ex, "删除recipe file 出错");
  529. WarningDialog(string.Format(Resources.RecipeFileManager_DeleteRecipe_RecipeFile0DeleteFailed, recipeName));
  530. return false;
  531. }
  532. return true;
  533. }
  534. /// <summary>
  535. /// Rename recipe
  536. /// </summary>
  537. /// <param name="chamId"></param>
  538. /// <param name="oldName"></param>
  539. /// <param name="newName"></param>
  540. /// <returns></returns>
  541. public bool RenameRecipe(string chamId, string oldName, string newName)
  542. {
  543. try
  544. {
  545. if (File.Exists(GenerateRecipeFilePath(chamId, newName)))
  546. {
  547. WarningDialog(string.Format(Resources.RecipeFileManager_RenameRecipe_RecipeFile0FileExisted, oldName));
  548. return false;
  549. }
  550. else
  551. {
  552. File.Move(GenerateRecipeFilePath(chamId, oldName), GenerateRecipeFilePath(chamId, newName));
  553. InfoDialog(string.Format(Resources.RecipeFileManager_RenameRecipe_RecipeFile0Renamed, oldName, newName));
  554. }
  555. }
  556. catch (Exception ex)
  557. {
  558. LOG.Write(ex, "重命名recipe file 出错");
  559. WarningDialog(string.Format(Resources.RecipeFileManager_RenameRecipe_RecipeFile0RenameFailed, oldName, newName));
  560. return false;
  561. }
  562. return true;
  563. }
  564. //private void EventInfo(string message)
  565. //{
  566. // _rcpContext.PostInfoEvent(message);
  567. //}
  568. //private void EventWarning(string message)
  569. //{
  570. // _rcpContext.PostWarningEvent(message);
  571. //}
  572. //private void EventAlarm(string message)
  573. //{
  574. // _rcpContext.PostAlarmEvent(message);
  575. //}
  576. private void InfoDialog(string message)
  577. {
  578. _rcpContext.PostInfoDialogMessage(message);
  579. }
  580. private void WarningDialog(string message)
  581. {
  582. _rcpContext.PostWarningDialogMessage(message);
  583. }
  584. //private void AlarmDialog(string message)
  585. //{
  586. // _rcpContext.PostAlarmDialogMessage(message);
  587. //}
  588. private void EventDialog(string message, List<string> reason)
  589. {
  590. string msg = message;
  591. foreach (var r in reason)
  592. {
  593. msg += "\r\n" + r;
  594. }
  595. _rcpContext.PostDialogEvent(msg);
  596. }
  597. /// <summary>
  598. /// get recipe's file path
  599. /// </summary>
  600. /// <param name="recipeName"></param>
  601. /// <returns></returns>
  602. private string GenerateRecipeFilePath(string chamId, string recipeName)
  603. {
  604. return getRecipeDirPath(chamId) + recipeName + ".rcp";
  605. }
  606. private string GenerateSequenceFilePath(string chamId, string recipeName)
  607. {
  608. return getRecipeDirPath(chamId) + recipeName + ".seq";
  609. }
  610. /// <summary>
  611. /// get recipe's dir path
  612. /// </summary>
  613. /// <param name="recipeName"></param>
  614. /// <returns></returns>
  615. private string getRecipeDirPath(string chamId)
  616. {
  617. var dir = string.Format("{0}{1}\\", PathManager.GetRecipeDir(), chamId);
  618. DirectoryInfo di = new DirectoryInfo(dir);
  619. if (!di.Exists) di.Create();
  620. return dir;
  621. }
  622. /// <summary>
  623. /// delete a recipe folder
  624. /// </summary>
  625. /// <param name="chamId"></param>
  626. /// <param name="folderName"></param>
  627. /// <returns></returns>
  628. public bool DeleteFolder(string chamId, string folderName)
  629. {
  630. try
  631. {
  632. Directory.Delete(getRecipeDirPath(chamId) + folderName, true);
  633. InfoDialog(string.Format(Resources.RecipeFileManager_DeleteFolder_RecipeFolder0DeleteSucceeded, folderName));
  634. }
  635. catch (Exception ex)
  636. {
  637. LOG.Write(ex, "删除recipe folder 出错");
  638. WarningDialog(string.Format("recipe folder {0} delete failed", folderName));
  639. return false;
  640. }
  641. return true;
  642. }
  643. /// <summary>
  644. /// save as recipe content
  645. /// </summary>
  646. /// <param name="chamId"></param>
  647. /// <param name="recipeName"></param>
  648. /// <param name="recipeContent"></param>
  649. /// <returns></returns>
  650. public bool SaveAsRecipe(string chamId, string recipeName, string recipeContent)
  651. {
  652. var path = GenerateRecipeFilePath(chamId, recipeName);
  653. if (File.Exists(path))
  654. {
  655. WarningDialog(string.Format(Resources.RecipeFileManager_SaveAsRecipe_RecipeFile0savefailed, recipeName));
  656. return false;
  657. }
  658. return SaveRecipe(chamId, recipeName, recipeContent, true, true);
  659. }
  660. /// <summary>
  661. /// save recipe content
  662. /// </summary>
  663. /// <param name="chamId"></param>
  664. /// <param name="recipeName"></param>
  665. /// <param name="recipeContent"></param>
  666. /// <returns></returns>
  667. public bool SaveRecipe(string chamId, string recipeName, string recipeContent, bool clearBarcode, bool notifyUI)
  668. {
  669. //validate recipe format when saving a recipe file
  670. //var reasons1 = new List<string>();
  671. //var reasons2 = new List<string>();
  672. //ValidateRecipe(chamId, recipeName, recipeContent, out reasons1);
  673. //CheckRecipe(chamId, recipeContent, out reasons2);
  674. //reasons1.AddRange(reasons2);
  675. //if (reasons1.Count > 0)
  676. //{
  677. // EventDialog(string.Format( Resources.RecipeFileManager_SaveRecipe_SaveRecipeContentError, recipeName), reasons1);
  678. //}
  679. bool ret = true;
  680. try
  681. {
  682. var path = GenerateRecipeFilePath(chamId, recipeName);
  683. FileInfo fi = new FileInfo(path);
  684. if (!fi.Directory.Exists)
  685. fi.Directory.Create();
  686. XmlDocument xml = new XmlDocument();
  687. xml.LoadXml(recipeContent);
  688. XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8);
  689. writer.Formatting = Formatting.Indented;
  690. xml.Save(writer);
  691. writer.Close();
  692. if (notifyUI)
  693. {
  694. InfoDialog(string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveCompleted, recipeName));
  695. }
  696. else
  697. {
  698. EV.PostMessage("System", EventEnum.GeneralInfo, string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveCompleted, recipeName));
  699. }
  700. }
  701. catch (Exception ex)
  702. {
  703. LOG.Write(ex, "保存recipe file 出错");
  704. if (notifyUI)
  705. {
  706. WarningDialog(string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveFailed, recipeName));
  707. }
  708. ret = false;
  709. }
  710. return ret;
  711. }
  712. /// <summary>
  713. /// create a new recipe folder
  714. /// </summary>
  715. /// <param name="chamId"></param>
  716. /// <param name="folderName"></param>
  717. /// <returns></returns>
  718. public bool CreateFolder(string chamId, string folderName)
  719. {
  720. try
  721. {
  722. Directory.CreateDirectory(getRecipeDirPath(chamId) + folderName);
  723. InfoDialog(string.Format(Resources.RecipeFileManager_CreateFolder_RecipeFolder0Created, folderName));
  724. }
  725. catch (Exception ex)
  726. {
  727. LOG.Write(ex, "create recipe folder failed");
  728. WarningDialog(string.Format(Resources.RecipeFileManager_CreateFolder_RecipeFolder0CreateFailed, folderName));
  729. return false;
  730. }
  731. return true;
  732. }
  733. /// <summary>
  734. /// move recipe file
  735. /// </summary>
  736. /// <param name="chamId"></param>
  737. /// <param name="recipeName"></param>
  738. /// <returns></returns>
  739. public bool MoveRecipeFile(string chamId, string recipeName, string tragetFolderName, bool clearBarcode, bool notifyUI)
  740. {
  741. bool ret = true;
  742. try
  743. {
  744. var path = getRecipeDirPath(chamId);
  745. string fullFileName = path + recipeName + ".rcp";
  746. string tragetFullFilePath = path + tragetFolderName;
  747. File.Move(fullFileName, tragetFullFilePath + "\\" + recipeName.Split('\\')[recipeName.Split('\\').Length - 1] + ".rcp");
  748. if (notifyUI)
  749. {
  750. InfoDialog(string.Format(Resources.RecipeFileManager_MoveRecipe_RecipeFile0MoveCompleted, recipeName));
  751. }
  752. else
  753. {
  754. EV.PostMessage("System", EventEnum.GeneralInfo, string.Format(Resources.RecipeFileManager_MoveRecipe_RecipeFile0MoveCompleted, recipeName));
  755. }
  756. }
  757. catch (Exception ex)
  758. {
  759. LOG.Write(ex, "移动 recipe file 出错");
  760. if (notifyUI)
  761. {
  762. WarningDialog(string.Format(Resources.RecipeFileManager_MoveRecipe_RecipeFile0MoveFailed, recipeName));
  763. }
  764. ret = false;
  765. }
  766. return ret;
  767. }
  768. /// <summary>
  769. /// Rename recipe folder name
  770. /// </summary>
  771. /// <param name="chamId"></param>
  772. /// <param name="oldName"></param>
  773. /// <param name="newName"></param>
  774. /// <returns></returns>
  775. public bool RenameFolder(string chamId, string oldName, string newName)
  776. {
  777. try
  778. {
  779. string oldPath = getRecipeDirPath(chamId) + oldName;
  780. string newPath = getRecipeDirPath(chamId) + newName;
  781. Directory.Move(oldPath, newPath);
  782. InfoDialog(string.Format(Resources.RecipeFileManager_RenameFolder_RecipeFolder0renamed, oldName, newName));
  783. }
  784. catch (Exception ex)
  785. {
  786. LOG.Write(ex, "Rename recipe folder failed");
  787. WarningDialog(string.Format(Resources.RecipeFileManager_RenameFolder_RecipeFolder0RenameFailed, oldName, newName));
  788. return false;
  789. }
  790. return true;
  791. }
  792. private string GetRecipeBody(string chamberId, string nodePath)
  793. {
  794. if (_rcpContext == null)
  795. return string.Empty;
  796. string schema = _rcpContext.GetRecipeDefiniton(chamberId);
  797. XmlDocument dom = new XmlDocument();
  798. dom.LoadXml(schema);
  799. XmlNode node = dom.SelectSingleNode(nodePath);
  800. return node.OuterXml;
  801. }
  802. /// <summary>
  803. /// get reactor's recipe format define file
  804. /// </summary>
  805. /// <param name="chamId"></param>
  806. /// <returns></returns>
  807. public string GetRecipeFormatXml(string chamberId)
  808. {
  809. return GetRecipeBody(chamberId, "/Aitex/TableRecipeFormat");
  810. }
  811. /// <summary>
  812. /// get reactor's template recipe file
  813. /// </summary>
  814. /// <param name="chamId"></param>
  815. /// <returns></returns>
  816. public string GetRecipeTemplate(string chamberId)
  817. {
  818. if (_rcpContext != null)
  819. return _rcpContext.GetRecipeTemplate(chamberId);
  820. return GetRecipeBody(chamberId, "/Aitex/TableRecipeData");
  821. }
  822. /// <summary>
  823. /// get reactor's template recipe file
  824. /// </summary>
  825. /// <param name="chamId"></param>
  826. /// <returns></returns>
  827. public string GetRecipeSchema(string chamberId)
  828. {
  829. if (_rcpContext == null)
  830. return string.Empty;
  831. string schema = _rcpContext.GetRecipeDefiniton(chamberId);
  832. XmlDocument dom = new XmlDocument();
  833. dom.LoadXml(schema);
  834. XmlNode node = dom.SelectSingleNode("/Aitex/TableRecipeSchema");
  835. return node.InnerXml;
  836. }
  837. public string GetRecipeByBarcode(string chamberId, string barcode)
  838. {
  839. try
  840. {
  841. string recipePath = PathManager.GetRecipeDir() + chamberId + "\\";
  842. var di = new DirectoryInfo(recipePath);
  843. var fis = di.GetFiles("*.rcp", SearchOption.AllDirectories);
  844. XmlDocument xml = new XmlDocument();
  845. foreach (var fi in fis)
  846. {
  847. string str = fi.FullName.Substring(recipePath.Length);
  848. if (!str.Contains("HistoryRecipe\\"))
  849. {
  850. xml.Load(fi.FullName);
  851. if (xml.SelectSingleNode(string.Format("/TableRecipeData[@Barcode='{0}']", barcode)) != null)
  852. {
  853. return str.Substring(0, str.LastIndexOf('.'));
  854. }
  855. }
  856. }
  857. return string.Empty;
  858. }
  859. catch (Exception ex)
  860. {
  861. LOG.Write(ex);
  862. return string.Empty;
  863. }
  864. }
  865. #region Sequence
  866. private string GetSequenceConfig(string nodePath)
  867. {
  868. if (_seqContext == null)
  869. return string.Empty;
  870. string schema = _seqContext.GetConfigXml();
  871. XmlDocument dom = new XmlDocument();
  872. dom.LoadXml(schema);
  873. XmlNode node = dom.SelectSingleNode(nodePath);
  874. return node.OuterXml;
  875. }
  876. public string GetSequence(string sequenceName, bool needValidation)
  877. {
  878. return GetSequence(sequenceName, needValidation, true);
  879. }
  880. public string GetSequence(string sequenceName, bool needValidation, bool isEap = false)
  881. {
  882. string seq = string.Empty;
  883. try
  884. {
  885. using (StreamReader fs = new StreamReader(GenerateSequenceFilePath(SequenceFolder, sequenceName)))
  886. {
  887. seq = fs.ReadToEnd();
  888. fs.Close();
  889. }
  890. if (isEap)
  891. {
  892. seq = PMToEapConvert(seq, isEap);
  893. }
  894. if (needValidation && !_seqContext.Validation(seq))
  895. {
  896. EV.PostWarningLog(SourceModule, $"Read {sequenceName} failed, validation failed");
  897. seq = string.Empty;
  898. }
  899. }
  900. catch (Exception ex)
  901. {
  902. LOG.Write(ex);
  903. EV.PostWarningLog(SourceModule, $"Read {sequenceName} failed, " + ex.Message);
  904. seq = string.Empty;
  905. }
  906. return seq;
  907. }
  908. public List<string> GetSequenceNameList()
  909. {
  910. var result = new List<string>();
  911. try
  912. {
  913. string recipePath = PathManager.GetRecipeDir() + SequenceFolder + "\\";
  914. var di = new DirectoryInfo(recipePath);
  915. var fis = di.GetFiles("*.seq", SearchOption.AllDirectories);
  916. foreach (var fi in fis)
  917. {
  918. string str = fi.FullName.Substring(recipePath.Length);
  919. str = str.Substring(0, str.LastIndexOf('.'));
  920. result.Add(str);
  921. }
  922. }
  923. catch (Exception ex)
  924. {
  925. LOG.Write(ex);
  926. EV.PostWarningLog(SourceModule, "Get sequence list failed, " + ex.Message);
  927. }
  928. return result;
  929. }
  930. public bool DeleteSequence(string sequenceName)
  931. {
  932. try
  933. {
  934. File.Delete(GenerateSequenceFilePath(SequenceFolder, sequenceName));
  935. EV.PostInfoLog(SourceModule, $"sequence {sequenceName} deleted");
  936. }
  937. catch (Exception ex)
  938. {
  939. LOG.Write(ex);
  940. EV.PostWarningLog(SourceModule, $"delete {sequenceName} failed, " + ex.Message);
  941. return false;
  942. }
  943. return true;
  944. }
  945. public bool SaveSequence(string sequenceName, string sequenceContent, bool notifyUI)
  946. {
  947. bool ret = true;
  948. try
  949. {
  950. var path = GenerateSequenceFilePath(SequenceFolder, sequenceName);
  951. FileInfo fi = new FileInfo(path);
  952. if (!fi.Directory.Exists)
  953. {
  954. fi.Directory.Create();
  955. }
  956. XmlDocument xml = new XmlDocument();
  957. xml.LoadXml(sequenceContent);
  958. EapToPMConvert(xml);
  959. XmlTextWriter writer = new XmlTextWriter(path, null);
  960. writer.Formatting = Formatting.Indented;
  961. xml.Save(writer);
  962. writer.Close();
  963. if (notifyUI)
  964. {
  965. EV.PostPopDialogMessage(EventLevel.Information, "Save Complete", $"Sequence {sequenceName} saved ");
  966. }
  967. else
  968. {
  969. EV.PostInfoLog(SourceModule, $"Sequence {sequenceName} saved ");
  970. }
  971. }
  972. catch (Exception ex)
  973. {
  974. LOG.Write(ex);
  975. EV.PostWarningLog(SourceModule, $"save sequence {sequenceName} failed, " + ex.Message);
  976. if (notifyUI)
  977. {
  978. EV.PostPopDialogMessage(EventLevel.Alarm, "Save Error", $"save sequence {sequenceName} failed, " + ex.Message);
  979. }
  980. ret = false;
  981. }
  982. return ret;
  983. }
  984. public bool SaveAsSequence(string sequenceName, string sequenceContent)
  985. {
  986. var path = GenerateSequenceFilePath(SequenceFolder, sequenceName);
  987. if (File.Exists(path))
  988. {
  989. EV.PostWarningLog(SourceModule, $"save sequence {sequenceName} failed, already exist");
  990. return false;
  991. }
  992. return SaveSequence(sequenceName, sequenceContent, false);
  993. }
  994. public bool RenameSequence(string oldName, string newName)
  995. {
  996. try
  997. {
  998. if (File.Exists(GenerateSequenceFilePath(SequenceFolder, newName)))
  999. {
  1000. EV.PostWarningLog(SourceModule, $"{newName} already exist, rename failed");
  1001. return false;
  1002. }
  1003. else
  1004. {
  1005. File.Move(GenerateSequenceFilePath(SequenceFolder, oldName), GenerateSequenceFilePath(SequenceFolder, newName));
  1006. EV.PostInfoLog(SourceModule, $"sequence {oldName} renamed to {newName}");
  1007. }
  1008. }
  1009. catch (Exception ex)
  1010. {
  1011. LOG.Write(ex);
  1012. EV.PostWarningLog(SourceModule, $"rename {oldName} failed, " + ex.Message);
  1013. return false;
  1014. }
  1015. return true;
  1016. }
  1017. public string GetSequenceFormatXml()
  1018. {
  1019. return GetSequenceConfig("/Aitex/TableSequenceFormat");
  1020. }
  1021. private const string PMSelectionValue = "PMSelection";
  1022. private const string PositionValue = "Position";
  1023. private const string PMValue = "PM";
  1024. private const char commaChar = ',';
  1025. public string GetEapMapXml()
  1026. {
  1027. return _eapMapContext.GetConfigXml();
  1028. }
  1029. private string PMToEapConvert(string seq, bool isEap)
  1030. {
  1031. if (!string.IsNullOrWhiteSpace(seq) && isEap)
  1032. {
  1033. var pmToEapConvert = GetPMToEapConvert();
  1034. if(pmToEapConvert == null)
  1035. {
  1036. return seq;
  1037. }
  1038. XmlDocument doc = new XmlDocument();
  1039. doc.LoadXml(seq);
  1040. XmlNodeList nodes = doc.SelectNodes("Aitex/TableSequenceData/Step");
  1041. foreach (XmlNode node in nodes)
  1042. {
  1043. switch (node.Attributes[PositionValue].Value)
  1044. {
  1045. case PMValue:
  1046. {
  1047. var pMSelectionValues = node.Attributes[PMSelectionValue].Value.Split(commaChar);
  1048. for (int i = 0; i < pMSelectionValues.Length; i++)
  1049. {
  1050. if (pmToEapConvert.ContainsKey(pMSelectionValues[i]))
  1051. {
  1052. pMSelectionValues[i] = pmToEapConvert[pMSelectionValues[i]];
  1053. }
  1054. }
  1055. node.Attributes[PMSelectionValue].Value = string.Join(commaChar.ToString(), pMSelectionValues);
  1056. break;
  1057. }
  1058. }
  1059. }
  1060. using (var ms = new MemoryStream())
  1061. using (var writer = new XmlTextWriter(ms, null))
  1062. {
  1063. writer.Formatting = Formatting.Indented;
  1064. doc.Save(writer);
  1065. return Encoding.UTF8.GetString(ms.ToArray());
  1066. }
  1067. }
  1068. return seq;
  1069. }
  1070. private void EapToPMConvert(XmlDocument doc)
  1071. {
  1072. if(doc != null)
  1073. {
  1074. var eapToPMConvert = GetEapToPMConvert();
  1075. if(eapToPMConvert == null)
  1076. {
  1077. return;
  1078. }
  1079. XmlNodeList nodes = doc.SelectNodes("Aitex/TableSequenceData/Step");
  1080. foreach (XmlNode node in nodes)
  1081. {
  1082. switch (node.Attributes[PositionValue].Value)
  1083. {
  1084. case PMValue:
  1085. {
  1086. var pMSelectionValues = node.Attributes[PMSelectionValue].Value.Split(commaChar);
  1087. for(int i=0;i< pMSelectionValues.Length; i++)
  1088. {
  1089. if (eapToPMConvert.ContainsKey(pMSelectionValues[i]))
  1090. {
  1091. pMSelectionValues[i] = eapToPMConvert[pMSelectionValues[i]];
  1092. }
  1093. }
  1094. node.Attributes[PMSelectionValue].Value = string.Join(commaChar.ToString(), pMSelectionValues);
  1095. break;
  1096. }
  1097. }
  1098. }
  1099. }
  1100. }
  1101. private Dictionary<string, string> _mapPMToEapConvert;
  1102. private Dictionary<string, string> _mapEapToPMConvert;
  1103. public Dictionary<string, string> GetEapToPMConvert()
  1104. {
  1105. if (_mapEapToPMConvert == null || _mapEapToPMConvert.Count == 0)
  1106. {
  1107. if (InitMapConvert())
  1108. {
  1109. return _mapEapToPMConvert;
  1110. }
  1111. }
  1112. return _mapEapToPMConvert;
  1113. }
  1114. public Dictionary<string, string> GetPMToEapConvert()
  1115. {
  1116. if(_mapPMToEapConvert == null || _mapPMToEapConvert.Count == 0)
  1117. {
  1118. if (InitMapConvert())
  1119. {
  1120. return _mapPMToEapConvert;
  1121. }
  1122. }
  1123. return _mapPMToEapConvert;
  1124. }
  1125. private bool InitMapConvert()
  1126. {
  1127. try
  1128. {
  1129. if (_mapPMToEapConvert == null)
  1130. {
  1131. _mapPMToEapConvert = new Dictionary<string, string>();
  1132. }
  1133. if (_mapEapToPMConvert == null)
  1134. {
  1135. _mapEapToPMConvert = new Dictionary<string, string>();
  1136. }
  1137. var returnDic = new Dictionary<string, string>();
  1138. var formatContent = GetEapMapXml();
  1139. XmlDocument doc = new XmlDocument();
  1140. doc.LoadXml(formatContent);
  1141. XmlNodeList nodes = doc.SelectNodes("Aitex/EAPMap/Item");
  1142. const string nameValue = "Name";
  1143. const string eAPNameValue = "EAPName";
  1144. foreach (XmlNode node in nodes)
  1145. {
  1146. switch (node.Attributes[nameValue].Value)
  1147. {
  1148. case "PMMap":
  1149. XmlNodeList multiitems = node.SelectNodes("Selection");
  1150. foreach (XmlNode item in multiitems)
  1151. {
  1152. _mapPMToEapConvert[item.Attributes[nameValue].Value] = item.Attributes[eAPNameValue].Value;
  1153. _mapEapToPMConvert[item.Attributes[eAPNameValue].Value] = _mapPMToEapConvert[item.Attributes[nameValue].Value];
  1154. }
  1155. break;
  1156. }
  1157. }
  1158. }
  1159. catch(Exception ex)
  1160. {
  1161. LOG.Write(ex, "Sequence Map exception");
  1162. return false;
  1163. }
  1164. return true;
  1165. }
  1166. internal bool DeleteSequenceFolder(string folderName)
  1167. {
  1168. try
  1169. {
  1170. Directory.Delete(PathManager.GetRecipeDir() + SequenceFolder + "\\" + folderName, true);
  1171. EV.PostInfoLog(SourceModule, "Folder " + folderName + "deleted");
  1172. }
  1173. catch (Exception ex)
  1174. {
  1175. LOG.Write(ex, "delete sequence folder exception");
  1176. EV.PostWarningLog(SourceModule, $"can not delete folder {folderName}, {ex.Message}");
  1177. return false;
  1178. }
  1179. return true;
  1180. }
  1181. internal bool CreateSequenceFolder(string folderName)
  1182. {
  1183. try
  1184. {
  1185. Directory.CreateDirectory(PathManager.GetRecipeDir() + SequenceFolder + "\\" + folderName);
  1186. EV.PostInfoLog(SourceModule, "Folder " + folderName + "created");
  1187. }
  1188. catch (Exception ex)
  1189. {
  1190. LOG.Write(ex, "sequence folder create exception");
  1191. EV.PostWarningLog(SourceModule, $"can not create folder {folderName}, {ex.Message}");
  1192. return false;
  1193. }
  1194. return true;
  1195. }
  1196. internal bool RenameSequenceFolder(string oldName, string newName)
  1197. {
  1198. try
  1199. {
  1200. string oldPath = PathManager.GetRecipeDir() + SequenceFolder + "\\" + oldName;
  1201. string newPath = PathManager.GetRecipeDir() + SequenceFolder + "\\" + newName;
  1202. Directory.Move(oldPath, newPath);
  1203. EV.PostInfoLog(SourceModule, $"rename folder from {oldName} to {newName}");
  1204. }
  1205. catch (Exception ex)
  1206. {
  1207. LOG.Write(ex, "rename sequence folder failed");
  1208. EV.PostWarningLog(SourceModule, $"can not rename folder {oldName}, {ex.Message}");
  1209. return false;
  1210. }
  1211. return true;
  1212. }
  1213. public string GetXmlSequenceList(string chamberId)
  1214. {
  1215. XmlDocument doc = new XmlDocument();
  1216. DirectoryInfo curFolderInfo = new DirectoryInfo(PathManager.GetRecipeDir() + SequenceFolder + "\\");
  1217. doc.AppendChild(GenerateSequenceList(chamberId, curFolderInfo, doc));
  1218. return doc.OuterXml;
  1219. }
  1220. XmlElement GenerateSequenceList(string chamberId, DirectoryInfo currentDir, XmlDocument doc)
  1221. {
  1222. int trimLength = (PathManager.GetRecipeDir() + SequenceFolder + "\\").Length;
  1223. XmlElement folderEle = doc.CreateElement("Folder");
  1224. folderEle.SetAttribute("Name", currentDir.FullName.Substring(trimLength));
  1225. DirectoryInfo[] dirInfos = currentDir.GetDirectories();
  1226. foreach (DirectoryInfo dirInfo in dirInfos)
  1227. {
  1228. folderEle.AppendChild(GenerateSequenceList(chamberId, dirInfo, doc));
  1229. }
  1230. FileInfo[] fileInfos = currentDir.GetFiles("*.seq");
  1231. foreach (FileInfo fileInfo in fileInfos)
  1232. {
  1233. XmlElement fileNd = doc.CreateElement("File");
  1234. string fileStr = fileInfo.FullName.Substring(trimLength).TrimStart(new char[] { '\\' }); ;
  1235. fileStr = fileStr.Substring(0, fileStr.LastIndexOf("."));
  1236. fileNd.SetAttribute("Name", fileStr);
  1237. folderEle.AppendChild(fileNd);
  1238. }
  1239. return folderEle;
  1240. }
  1241. #endregion
  1242. }
  1243. }