InterlockManager.cs 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Windows;
  8. using System.Xml;
  9. using Aitex.Core.RT.DataCenter;
  10. using Aitex.Core.RT.Event;
  11. using Aitex.Core.RT.Log;
  12. using Aitex.Core.RT.SCCore;
  13. using Aitex.Core.Util;
  14. using MECF.Framework.Common.Equipment;
  15. using MECF.Framework.Common.Event;
  16. namespace Aitex.Core.RT.IOCore
  17. {
  18. public class InterlockManager : Singleton<InterlockManager>, IAlarmHandler
  19. {
  20. private List<InterlockAction> _actions = new List<InterlockAction>();
  21. private Dictionary<InterlockLimit, List<InterlockAction>> _dicLimit = new Dictionary<InterlockLimit, List<InterlockAction>>();//and condition
  22. private Dictionary<InterlockAction, List<InterlockLimit>> _dicActionOrLimit = new Dictionary<InterlockAction, List<InterlockLimit>>();
  23. //private Dictionary<InterlockLimit, List<InterlockAction>> _dicUserDefineLimit = new Dictionary<InterlockLimit, List<InterlockAction>>();//and condition
  24. //private Dictionary<InterlockAction, List<InterlockLimit>> _dicUserDefineActionOrLimit = new Dictionary<InterlockAction, List<InterlockLimit>>();
  25. private string _interlockFile;
  26. #region userDefineInterlock
  27. private List<InterlockAction> _userDefineActions = new List<InterlockAction>();
  28. private List<InterlockAction> _userDefineFlagActions = new List<InterlockAction>();
  29. private Dictionary<string, bool> _userDefineFlagCurrentValues = new Dictionary<string, bool>();
  30. private Dictionary<string, Stopwatch> _userDefineKeepTimer = new Dictionary<string, Stopwatch>();
  31. private Dictionary<string, Stopwatch> _userDefineDelayTimer = new Dictionary<string, Stopwatch>();
  32. private Dictionary<string, RD_TRIG> _userDefineConditionTrig = new Dictionary<string, RD_TRIG>();
  33. private string _interlockUserDefineFile;
  34. private object _locker = new object();
  35. public event Func<string, object, bool> UserDefineInterlockHandler;
  36. public event Func<string, bool> UserDefineInterlocks;
  37. #endregion
  38. public string InterlockAlarmKey { get; set; }
  39. public string UserDefineInterlockAlarmKey { get; set; }
  40. public Dictionary<string, AlarmEventItem> InterlockAlarms { get; set; } = new Dictionary<string, AlarmEventItem>();
  41. public event Action<string, AlarmEventItem> OnDeviceAlarmStateChanged;
  42. private DeviceTimer _userDefineActionTimer = new DeviceTimer();
  43. public bool Initialize(string interlockFile, Dictionary<string, DOAccessor> doMap, Dictionary<string, DIAccessor> diMap, out string reason)
  44. {
  45. reason = string.Empty;
  46. try
  47. {
  48. _interlockFile = interlockFile;
  49. XmlDocument xmlConfig = new XmlDocument();
  50. xmlConfig.Load(_interlockFile);
  51. //<Action do="DO_RF_power_on_off" value="true" tip="" tip.zh-CN="" tip.en-US="">
  52. // <Limit di="DI_RF_hardware_interlock" value="true" tip="" tip.zh-CN="" tip.en-US="" />
  53. // <Limit di="DI_Chamber_door_sw" value="true" tip="" tip.zh-CN="" tip.en-US="" />
  54. //</Action>
  55. //InterlockAlarms = new Dictionary<string, AlarmEventItem>();
  56. XmlNode nodeInterlock = xmlConfig.SelectSingleNode("Interlock");
  57. foreach (XmlNode item in nodeInterlock.ChildNodes)
  58. {
  59. if (item.NodeType == XmlNodeType.Comment)
  60. continue;
  61. XmlElement actionNode = item as XmlElement;
  62. if (actionNode == null) continue;
  63. if (actionNode.Name != "Action")
  64. {
  65. if (actionNode.NodeType != XmlNodeType.Comment)
  66. {
  67. LOG.Write("interlock config file contains no comments content, " + actionNode.InnerXml);
  68. }
  69. continue;
  70. }
  71. if (!actionNode.HasAttribute("do") || !actionNode.HasAttribute("value"))
  72. {
  73. reason += "action node has no [do] or [value] attribute \r\n";
  74. continue;
  75. }
  76. string doName = actionNode.GetAttribute("do");
  77. bool value = Convert.ToBoolean(actionNode.GetAttribute("value"));
  78. string tip = string.Empty;
  79. Dictionary<string, string> cultureTip = new Dictionary<string, string>();
  80. List<InterlockLimit> limits = new List<InterlockLimit>();
  81. bool isAndCondition = true;
  82. bool isReverse = true;
  83. if (actionNode.HasAttribute("reverse"))
  84. isReverse = Convert.ToBoolean(actionNode.GetAttribute("reverse"));
  85. if (!doMap.ContainsKey(doName))
  86. {
  87. reason += "action node " + doName + " no such DO defined \r\n";
  88. continue;
  89. }
  90. DOAccessor doItem = doMap[doName] as DOAccessor;
  91. if (doItem == null)
  92. {
  93. reason += "action node " + doName + " no such DO defined \r\n";
  94. continue;
  95. }
  96. if (actionNode.HasAttribute("tip"))
  97. tip = actionNode.GetAttribute("tip");
  98. else
  99. tip = doName;
  100. if (actionNode.HasAttribute("tip.zh-CN"))
  101. cultureTip["zh-CN"] = actionNode.GetAttribute("tip.zh-CN");
  102. if (actionNode.HasAttribute("tip.en-US"))
  103. cultureTip["en-US"] = actionNode.GetAttribute("tip.en-US");
  104. if (actionNode.HasAttribute("condition"))
  105. isAndCondition = actionNode.GetAttribute("condition").ToLower() == "and";
  106. foreach (XmlElement limitNode in actionNode.ChildNodes)
  107. {
  108. if (limitNode.Name != "Limit")
  109. {
  110. if (limitNode.NodeType != XmlNodeType.Comment)
  111. {
  112. LOG.Write("interlock config file contains no comments content, " + limitNode.InnerXml);
  113. }
  114. continue;
  115. }
  116. if (!(limitNode.HasAttribute("di") || limitNode.HasAttribute("do") || limitNode.HasAttribute("poll")) || !limitNode.HasAttribute("value"))
  117. {
  118. reason += "limit node lack of di/do or value attribute \r\n";
  119. continue;
  120. }
  121. string stringValue = limitNode.GetAttribute("value");
  122. if (stringValue.Contains("*"))
  123. {
  124. continue;
  125. }
  126. string limitValueS = limitNode.GetAttribute("value");
  127. string limitTip = string.Empty;
  128. string condition = "AND";
  129. Dictionary<string, string> limitCultureTip = new Dictionary<string, string>();
  130. if (limitNode.HasAttribute("tip"))
  131. limitTip = limitNode.GetAttribute("tip");
  132. if (limitNode.HasAttribute("tip.zh-CN"))
  133. limitCultureTip["zh-CN"] = limitNode.GetAttribute("tip.zh-CN");
  134. if (limitNode.HasAttribute("tip.en-US"))
  135. limitCultureTip["en-US"] = limitNode.GetAttribute("tip.en-US");
  136. if (limitNode.HasAttribute("condition"))
  137. condition = limitNode.GetAttribute("condition");
  138. if (limitNode.HasAttribute("di"))
  139. {
  140. string diName = limitNode.GetAttribute("di");
  141. if (string.IsNullOrEmpty(limitTip))
  142. limitTip = diName;
  143. if (!diMap.ContainsKey(diName))
  144. {
  145. reason += "limit node " + diName + " no such DI defined \r\n";
  146. continue;
  147. }
  148. DIAccessor diItem = diMap[diName] as DIAccessor;
  149. if (diItem == null)
  150. {
  151. reason += "limit node " + diName + " no such DI defined \r\n";
  152. continue;
  153. }
  154. bool.TryParse(limitValueS, out bool limitValue);
  155. limits.Add(new DiLimit(diItem, limitValue, limitTip, limitCultureTip, condition));
  156. }
  157. else if (limitNode.HasAttribute("do"))
  158. {
  159. string ioName = limitNode.GetAttribute("do");
  160. if (string.IsNullOrEmpty(limitTip))
  161. limitTip = ioName;
  162. if (!doMap.ContainsKey(ioName))
  163. {
  164. reason += "limit node " + ioName + " no such DO defined \r\n";
  165. continue;
  166. }
  167. DOAccessor ioItem = doMap[ioName];
  168. if (ioItem == null)
  169. {
  170. reason += "limit node " + ioName + " no such DO defined \r\n";
  171. continue;
  172. }
  173. bool.TryParse(limitValueS, out bool limitValue);
  174. limits.Add(new DoLimit(ioItem, limitValue, limitTip, limitCultureTip, condition));
  175. }
  176. else if (limitNode.HasAttribute("poll"))
  177. {
  178. string name = limitNode.GetAttribute("poll");
  179. if (string.IsNullOrEmpty(limitTip))
  180. limitTip = name;
  181. if (DATA.Poll(name) == null)
  182. {
  183. reason += "limit node " + name + " no such poll defined \r\n";
  184. continue;
  185. }
  186. limits.Add(new DataPollLimit(name, limitValueS, limitNode.GetAttribute("condition")));
  187. }
  188. }
  189. InterlockAction action = new InterlockAction(doItem, value, tip, cultureTip, limits, isReverse);
  190. _actions.Add(action);
  191. if (isAndCondition)
  192. {
  193. foreach (var interlockLimit in limits)
  194. {
  195. bool isExist = false;
  196. foreach (var limit in _dicLimit.Keys)
  197. {
  198. if (interlockLimit.IsSame(limit))
  199. {
  200. _dicLimit[limit].Add(action);
  201. isExist = true;
  202. break;
  203. }
  204. }
  205. if (!isExist)
  206. {
  207. _dicLimit[interlockLimit] = new List<InterlockAction>();
  208. _dicLimit[interlockLimit].Add(action);
  209. }
  210. }
  211. }
  212. else
  213. {
  214. if (!_dicActionOrLimit.ContainsKey(action))
  215. {
  216. _dicActionOrLimit.Add(action, limits);
  217. }
  218. }
  219. }
  220. }
  221. catch (Exception ex)
  222. {
  223. reason += ex.Message;
  224. }
  225. if (!string.IsNullOrEmpty(reason))
  226. return false;
  227. return true;
  228. }
  229. public bool InitializeUserDefine(string interlockUserDefineFile, Dictionary<string, DOAccessor> doMap, Dictionary<string, DIAccessor> diMap,
  230. Dictionary<string, AIAccessor> aiMap, Dictionary<string, AOAccessor> aoMap, out string reason)
  231. {
  232. reason = string.Empty;
  233. try
  234. {
  235. _interlockUserDefineFile = interlockUserDefineFile;
  236. XmlDocument xmlConfig = new XmlDocument();
  237. xmlConfig.Load(_interlockUserDefineFile);
  238. //<Action do="DO_RF_power_on_off" value="true" tip="" tip.zh-CN="" tip.en-US="">
  239. // <Limit di="DI_RF_hardware_interlock" value="true" tip="" tip.zh-CN="" tip.en-US="" />
  240. // <Limit di="DI_Chamber_door_sw" value="true" tip="" tip.zh-CN="" tip.en-US="" />
  241. //</Action>
  242. //InterlockAlarms = new Dictionary<string, AlarmEventItem>();
  243. XmlNode nodeInterlock = xmlConfig.SelectSingleNode("Interlock");
  244. bool interlockParserEnd = false;
  245. //bool interlockParserMark = false;
  246. foreach (XmlNode item in nodeInterlock.ChildNodes)
  247. {
  248. if (interlockParserEnd)
  249. continue;
  250. if (item.NodeType == XmlNodeType.Comment)
  251. continue;
  252. XmlElement actionNode = item as XmlElement;
  253. if (actionNode == null) continue;
  254. if (actionNode.Name != "Action")
  255. {
  256. if (actionNode.NodeType != XmlNodeType.Comment)
  257. {
  258. LOG.Write($"interlock config file contains no comments content, {actionNode.InnerXml}");
  259. }
  260. continue;
  261. }
  262. if (!actionNode.HasAttribute("Name") || !actionNode.HasAttribute("Value"))
  263. {
  264. LOG.Write($"action node has no [Name] or [Value] attribute, {actionNode.InnerXml}");
  265. continue;
  266. }
  267. string actionName = actionNode.GetAttribute("Name");
  268. string value = actionNode.GetAttribute("Value");
  269. if (string.IsNullOrEmpty(value) ||
  270. (!value.ToUpper().Contains("ON")) && !value.ToUpper().Contains("OFF") &&
  271. !value.ToUpper().Contains("OPEN") && !value.ToUpper().Contains("CLOSE"))
  272. {
  273. LOG.Write($"action node has no [Name] or [Value] attribute, {actionNode.InnerXml}");
  274. continue;
  275. }
  276. string tip = string.Empty;
  277. List<InterlockLimit> limits = new List<InterlockLimit>();
  278. bool isAndCondition = true;
  279. if (UserDefineInterlocks != null && UserDefineInterlocks(actionName))
  280. {
  281. //do nothing
  282. }
  283. else if (!doMap.ContainsKey(actionName) && !actionName.ToUpper().StartsWith("FLAG"))
  284. {
  285. reason += "action node " + actionName + " no such DO defined \r\n";
  286. continue;
  287. }
  288. if (UserDefineInterlocks != null && !UserDefineInterlocks(actionName) && !actionName.ToUpper().StartsWith("FLAG"))
  289. {
  290. DOAccessor doItem;
  291. doItem = doMap[actionName] as DOAccessor;
  292. if (doItem == null)
  293. {
  294. reason += "action node " + actionName + " no such DO defined \r\n";
  295. continue;
  296. }
  297. }
  298. if (actionNode.HasAttribute("condition"))
  299. isAndCondition = actionNode.GetAttribute("condition").ToLower() == "and";
  300. bool isLimitInvalid = false;
  301. foreach (XmlElement limitNode in actionNode.ChildNodes)
  302. {
  303. if (limitNode.Name != "Limit")
  304. {
  305. if (limitNode.NodeType != XmlNodeType.Comment)
  306. {
  307. LOG.Write("interlock config file contains no comments content, " + limitNode.InnerXml);
  308. }
  309. isLimitInvalid = true;
  310. break;
  311. }
  312. if (!(limitNode.HasAttribute("Name") || limitNode.HasAttribute("Value")) || !limitNode.HasAttribute("Condition"))
  313. {
  314. LOG.Write("limit node lack of Name/Condition or Value attribute, " + limitNode.InnerXml);
  315. isLimitInvalid = true;
  316. break;
  317. }
  318. if (limitNode.GetAttribute("Condition").ToUpper() != "AND" &&
  319. limitNode.GetAttribute("Condition").ToUpper() != "OR" &&
  320. limitNode.GetAttribute("Condition").ToUpper() != "EXOR" &&
  321. limitNode.GetAttribute("Condition").ToUpper() != "M-START" &&
  322. limitNode.GetAttribute("Condition").ToUpper() != "M-END" &&
  323. limitNode.GetAttribute("Condition").ToUpper() != "END" &&
  324. limitNode.GetAttribute("Condition").ToUpper() != "BLANK")
  325. {
  326. LOG.Write("limit Condition attribute is invalid, " + limitNode.InnerXml);
  327. isLimitInvalid = true;
  328. break;
  329. }
  330. if (limitNode.GetAttribute("Condition").ToUpper() == "BLANK")
  331. continue;
  332. if (limitNode.GetAttribute("Condition").ToUpper() == "END")
  333. {
  334. interlockParserEnd = true;
  335. break;
  336. }
  337. //if (limitNode.GetAttribute("Condition").ToUpper() == "M-START")
  338. //{
  339. // interlockParserMark = true;
  340. // continue;
  341. //}
  342. //if (limitNode.GetAttribute("Condition").ToUpper() == "M-END")
  343. //{
  344. // interlockParserMark = false;
  345. //}
  346. //if (interlockParserMark)
  347. // continue;
  348. string stringValue = limitNode.GetAttribute("Value");
  349. if (stringValue.Contains("*"))
  350. {
  351. LOG.Write($"limit Value attribute is invalid, {limitNode.InnerXml}");
  352. isLimitInvalid = true;
  353. break;
  354. }
  355. string limitValue = limitNode.GetAttribute("Value");
  356. string limitTip = string.Empty;
  357. Dictionary<string, string> limitCultureTip = new Dictionary<string, string>();
  358. if (limitNode.HasAttribute("Name"))
  359. {
  360. string Name = limitNode.GetAttribute("Name");
  361. if (Name.ToUpper().StartsWith("FLAG"))
  362. {
  363. limits.Add(new UserDefineLimit(Name, limitValue.ToUpper().Contains("ON") ? true : false, limitNode.GetAttribute("Condition")));
  364. continue;
  365. }
  366. if (Name.Split('.')[1].ToLower().StartsWith("di"))
  367. {
  368. if (!diMap.ContainsKey(Name))
  369. {
  370. LOG.Write($"limit node {Name} no such DI defined, {limitNode.InnerXml}");
  371. isLimitInvalid = true;
  372. break;
  373. }
  374. DIAccessor diItem = diMap[Name] as DIAccessor;
  375. if (diItem == null)
  376. {
  377. LOG.Write($"limit node {Name} no such DI defined, {limitNode.InnerXml}");
  378. isLimitInvalid = true;
  379. break;
  380. }
  381. //limits.Add(new DiLimit(diItem, Convert.ToBoolean(limitValue), limitNode.GetAttribute("Condition")));
  382. limits.Add(new DiLimit(diItem, limitValue.ToUpper().Contains("ON") ? true : false, limitNode.GetAttribute("Condition")));
  383. }
  384. else if (Name.Split('.')[1].ToLower().StartsWith("do"))
  385. {
  386. if (!doMap.ContainsKey(Name))
  387. {
  388. LOG.Write($"limit node {Name} no such DO defined, {limitNode.InnerXml}");
  389. isLimitInvalid = true;
  390. break;
  391. }
  392. DOAccessor ioItem = doMap[Name];
  393. if (ioItem == null)
  394. {
  395. LOG.Write($"limit node {Name} no such DO defined, {limitNode.InnerXml}");
  396. isLimitInvalid = true;
  397. break;
  398. }
  399. //limits.Add(new DoLimit(ioItem, Convert.ToBoolean(limitValue), limitNode.GetAttribute("Condition")));
  400. limits.Add(new DoLimit(ioItem, limitValue.ToUpper().Contains("ON") ? true : false, limitNode.GetAttribute("Condition")));
  401. }
  402. else if (Name.Split('.')[1].ToLower().StartsWith("ao"))
  403. {
  404. if (!aoMap.ContainsKey(Name))
  405. {
  406. LOG.Write($"limit node {Name} no such AO defined, {limitNode.InnerXml}");
  407. isLimitInvalid = true;
  408. break;
  409. }
  410. AOAccessor ioItem = aoMap[Name];
  411. if (ioItem == null)
  412. {
  413. LOG.Write($"limit node {Name} no such AO defined, {limitNode.InnerXml}");
  414. isLimitInvalid = true;
  415. break;
  416. }
  417. limits.Add(new AoLimit(ioItem, limitValue, limitNode.GetAttribute("Condition")));
  418. }
  419. else if (Name.Split('.')[1].ToLower().StartsWith("ai"))
  420. {
  421. if (!aiMap.ContainsKey(Name))
  422. {
  423. LOG.Write($"limit node {Name} no such AI defined, {limitNode.InnerXml}");
  424. isLimitInvalid = true;
  425. break;
  426. }
  427. AIAccessor ioItem = aiMap[Name];
  428. if (ioItem == null)
  429. {
  430. LOG.Write($"limit node {Name} no such AI defined, {limitNode.InnerXml}");
  431. isLimitInvalid = true;
  432. break;
  433. }
  434. limits.Add(new AiLimit(ioItem, limitValue, limitNode.GetAttribute("Condition")));
  435. }
  436. else
  437. {
  438. if (DATA.Poll(Name) == null)
  439. {
  440. LOG.Write($"limit node {Name} no such DATA.Poll defined, {limitNode.InnerXml}");
  441. isLimitInvalid = true;
  442. break;
  443. }
  444. limits.Add(new DataPollLimit(Name, limitValue, limitNode.GetAttribute("Condition")));
  445. }
  446. }
  447. }
  448. if (isLimitInvalid)
  449. continue;
  450. if (limits.Count == 0)
  451. continue;
  452. var paras = value.Split(';');//KEEP30;ON;Auto
  453. string condition = "";
  454. float conditionTime = 0.0f;
  455. bool actionValue;
  456. bool actionAuto = true;
  457. if (paras.Length > 2)
  458. {
  459. if (paras[0].ToUpper().Contains("KEEP"))
  460. {
  461. condition = "KEEP";
  462. float.TryParse(paras[0].ToUpper().Replace("KEEP", ""), out conditionTime);
  463. }
  464. if (paras[0].ToUpper().Contains("DELAY"))
  465. {
  466. condition = "DELAY";
  467. float.TryParse(paras[0].ToUpper().Replace("DELAY", ""), out conditionTime);
  468. }
  469. actionValue = paras[1].ToUpper().Contains("ON") || paras[1].ToUpper() == "OPEN" ? true : false;
  470. actionAuto = paras[2].ToUpper().Contains("AUTO") ? true : false;
  471. }
  472. else if (paras.Length == 2)
  473. {
  474. if (value.ToUpper().Contains("KEEP") || value.ToUpper().Contains("DELAY"))
  475. {
  476. if (paras[0].ToUpper().Contains("KEEP"))
  477. {
  478. condition = "KEEP";
  479. float.TryParse(paras[0].ToUpper().Replace("KEEP", ""), out conditionTime);
  480. }
  481. if (paras[0].ToUpper().Contains("DELAY"))
  482. {
  483. condition = "DELAY";
  484. float.TryParse(paras[0].ToUpper().Replace("DELAY", ""), out conditionTime);
  485. }
  486. actionValue = paras[1].ToUpper().Contains("ON") || paras[1].ToUpper() == "OPEN" ? true : false;
  487. }
  488. else
  489. {
  490. actionValue = paras[0].ToUpper().Contains("ON") || paras[1].ToUpper() == "OPEN" ? true : false;
  491. actionAuto = paras[1].ToUpper().Contains("AUTO") ? true : false;
  492. }
  493. }
  494. else
  495. {
  496. actionValue = value.ToUpper().Contains("ON") || value.ToUpper() == "OPEN" ? true : false;
  497. }
  498. if (actionName.ToUpper().StartsWith("FLAG"))
  499. {
  500. InterlockAction action = new InterlockAction(actionName, actionValue, actionNode.OuterXml, condition, conditionTime, limits, actionAuto);
  501. _userDefineFlagActions.Add(action);
  502. if (!_userDefineFlagCurrentValues.ContainsKey(actionName.ToUpper()))
  503. _userDefineFlagCurrentValues.Add(actionName.ToUpper(), false);
  504. }
  505. else if (UserDefineInterlocks != null && UserDefineInterlocks(actionName))
  506. {
  507. InterlockAction action = new InterlockAction(actionName, actionValue, actionNode.OuterXml, condition, conditionTime, limits, actionAuto);
  508. _userDefineActions.Add(action);
  509. }
  510. else
  511. {
  512. DOAccessor doItem;
  513. doItem = doMap[actionName] as DOAccessor;
  514. InterlockAction action = new InterlockAction(doItem, actionValue, actionNode.OuterXml, condition, conditionTime, limits, actionAuto);
  515. _userDefineActions.Add(action);
  516. }
  517. }
  518. }
  519. catch (Exception ex)
  520. {
  521. reason += ex.Message;
  522. }
  523. if (!string.IsNullOrEmpty(reason))
  524. return false;
  525. _userDefineActionTimer.Start(3000);
  526. return true;
  527. }
  528. public void Monitor()
  529. {
  530. //AND condition
  531. foreach (var limit in _dicLimit)
  532. {
  533. if (SC.ContainsItem("System.BypassInterlock") && SC.GetValue<bool>("System.BypassInterlock"))
  534. continue;
  535. if (!limit.Key.IsTriggered())
  536. continue;
  537. string info = string.Empty;
  538. string module = "System";
  539. InterlockAction actionTemp = null;
  540. foreach (var action in limit.Value)
  541. {
  542. string reason = "";
  543. if (action.IsReverse && !action.Reverse(out reason))
  544. continue;
  545. if (!action.IsReverse && action.ActionDo.Value != action.ActionValue)
  546. continue;
  547. if (string.IsNullOrEmpty(info))
  548. {
  549. info = string.Format("Due to the {0}, {1}=[{2}]\n", limit.Key.Tip, limit.Key.Name,
  550. !limit.Key.LimitValue);
  551. }
  552. var nameArray = action.ActionName.Split('.');
  553. if (nameArray != null && nameArray.Length > 1)
  554. {
  555. switch (nameArray[0].ToUpper())
  556. {
  557. case "SPN1":
  558. module = "PM2_1";
  559. break;
  560. case "SPN2":
  561. module = "PM2_2";
  562. break;
  563. case "SPN3":
  564. module = "PM2_3";
  565. break;
  566. case "SPN4":
  567. module = "PM2_4";
  568. break;
  569. case "SPN5":
  570. module = "PM3_1";
  571. break;
  572. case "SPN6":
  573. module = "PM3_2";
  574. break;
  575. case "SPN7":
  576. module = "PM3_3";
  577. break;
  578. case "SPN8":
  579. module = "PM3_4";
  580. break;
  581. default:
  582. if (nameArray[0].ToUpper() != "MF" && ModuleHelper.IsPm(nameArray[0]))
  583. module = nameArray[0];
  584. break;
  585. }
  586. }
  587. info += reason + "\n";
  588. actionTemp = action;
  589. }
  590. if (!string.IsNullOrEmpty(info) && actionTemp != null)
  591. {
  592. if (!InterlockAlarms.ContainsKey(actionTemp.ActionName) && !InterlockAlarms.ContainsKey(InterlockAlarmKey))
  593. {
  594. LOG.Write(info.TrimEnd('\n'));
  595. }
  596. else
  597. {
  598. if (InterlockAlarms.ContainsKey(actionTemp.ActionName))
  599. {
  600. InterlockAlarms[actionTemp.ActionName].Set(info.TrimEnd('\n'));
  601. }
  602. else if (InterlockAlarms.ContainsKey(InterlockAlarmKey))
  603. {
  604. InterlockAlarms[InterlockAlarmKey].Set(info.TrimEnd('\n'));
  605. }
  606. }
  607. }
  608. }
  609. //OR condition
  610. foreach (var action in _dicActionOrLimit.Keys)
  611. {
  612. if (SC.ContainsItem("System.BypassInterlock") && SC.GetValue<bool>("System.BypassInterlock"))
  613. continue;
  614. var limits = _dicActionOrLimit[action];
  615. if (limits.Any(x => x.IsTriggered()))
  616. {
  617. string info = string.Empty;
  618. string reason = string.Empty;
  619. string module = "System";
  620. InterlockAction actionTemp = null;
  621. if (!limits.Any(x => x.CanDo(out info)))
  622. {
  623. if (!action.Reverse(out reason))
  624. continue;
  625. foreach (var interlockLimit in limits)
  626. {
  627. if (!interlockLimit.CanDo(out info))
  628. {
  629. if (reason.Length > 0)
  630. reason += "\n";
  631. info = string.Format("Due to the {0}, {1}=[{2}]", interlockLimit.Tip, interlockLimit.Name,
  632. !interlockLimit.LimitValue);
  633. reason += info;
  634. actionTemp = action;
  635. }
  636. }
  637. }
  638. if (!string.IsNullOrEmpty(info) && actionTemp != null)
  639. {
  640. if (!InterlockAlarms.ContainsKey(actionTemp.ActionName) && !InterlockAlarms.ContainsKey(InterlockAlarmKey))
  641. {
  642. LOG.Write(info.TrimEnd('\n'));
  643. }
  644. else
  645. {
  646. if (InterlockAlarms.ContainsKey(actionTemp.ActionName))
  647. {
  648. InterlockAlarms[actionTemp.ActionName].Set(info.TrimEnd('\n'));
  649. }
  650. else if (InterlockAlarms.ContainsKey(InterlockAlarmKey))
  651. {
  652. InterlockAlarms[InterlockAlarmKey].Set(info.TrimEnd('\n'));
  653. }
  654. }
  655. }
  656. }
  657. }
  658. if (_userDefineActionTimer.IsTimeout())
  659. MonitorUserDefineInterlock();
  660. }
  661. public bool CanSetDo(string doName, bool onOff, out string reason)
  662. {
  663. reason = string.Empty;
  664. try
  665. {
  666. if (SC.ContainsItem("System.BypassInterlock") && SC.GetValue<bool>("System.BypassInterlock"))
  667. return true;
  668. bool canSetDo = true;
  669. foreach (var interlockAction in _actions.ToArray())
  670. {
  671. if (interlockAction.IsSame(doName, onOff))
  672. {
  673. canSetDo = interlockAction.CanDo(out reason);
  674. break;
  675. }
  676. }
  677. if (!canSetDo)
  678. {
  679. if (InterlockAlarms.ContainsKey(InterlockAlarmKey))
  680. {
  681. InterlockAlarms[InterlockAlarmKey].Set(reason);
  682. }
  683. return canSetDo;
  684. }
  685. foreach (var userDefineAction in _userDefineActions.ToArray())
  686. {
  687. if (!userDefineAction.IsAuto && userDefineAction.IsSame(doName, onOff))
  688. {
  689. canSetDo = GetUserDefineInterlockTrigResult(userDefineAction.Limits);
  690. if (!canSetDo)
  691. {
  692. reason = $"Interlock triggered, {doName} can not be {(onOff ? "ON" : "OFF")}";
  693. if (InterlockAlarms.ContainsKey(UserDefineInterlockAlarmKey))
  694. {
  695. InterlockAlarms[UserDefineInterlockAlarmKey].Set(reason);
  696. }
  697. }
  698. break;
  699. }
  700. }
  701. return canSetDo;
  702. }
  703. catch (Exception ex)
  704. {
  705. reason = ex.Message;
  706. LOG.Write($"{ex.Message}");
  707. return false;
  708. }
  709. }
  710. public string GetInterlockConfigContent()
  711. {
  712. XmlDocument xmlConfig = new XmlDocument();
  713. xmlConfig.Load(_interlockFile);
  714. return xmlConfig.InnerXml;
  715. }
  716. public string GetInterlockUserDefineConfigContent()
  717. {
  718. XmlDocument xmlConfig = new XmlDocument();
  719. xmlConfig.Load(_interlockUserDefineFile);
  720. return xmlConfig.InnerXml;
  721. }
  722. public void SetInterlockConfigContent(string content)
  723. {
  724. if (File.Exists(_interlockUserDefineFile))
  725. {
  726. XmlDocument xmlData = new XmlDocument();
  727. xmlData.LoadXml(content);
  728. XmlTextWriter writer = new XmlTextWriter(_interlockUserDefineFile, Encoding.UTF8);
  729. writer.Formatting = Formatting.Indented;
  730. xmlData.Save(writer);
  731. writer.Close();
  732. }
  733. }
  734. public bool UpdateUserDefine(Dictionary<string, DOAccessor> doMap, Dictionary<string, DIAccessor> diMap,
  735. Dictionary<string, AIAccessor> aiMap, Dictionary<string, AOAccessor> aoMap, out string reason)
  736. {
  737. reason = string.Empty;
  738. try
  739. {
  740. XmlDocument xmlConfig = new XmlDocument();
  741. xmlConfig.Load(_interlockUserDefineFile);
  742. lock (_locker)
  743. {
  744. _userDefineActions.Clear();
  745. _userDefineFlagActions.Clear();
  746. _userDefineFlagCurrentValues.Clear();
  747. }
  748. //<Action do="DO_RF_power_on_off" value="true" tip="" tip.zh-CN="" tip.en-US="">
  749. // <Limit di="DI_RF_hardware_interlock" value="true" tip="" tip.zh-CN="" tip.en-US="" />
  750. // <Limit di="DI_Chamber_door_sw" value="true" tip="" tip.zh-CN="" tip.en-US="" />
  751. //</Action>
  752. //InterlockAlarms = new Dictionary<string, AlarmEventItem>();
  753. XmlNode nodeInterlock = xmlConfig.SelectSingleNode("Interlock");
  754. bool interlockParserEnd = false;
  755. //bool interlockParserMark = false;
  756. foreach (XmlNode item in nodeInterlock.ChildNodes)
  757. {
  758. if (interlockParserEnd)
  759. continue;
  760. if (item.NodeType == XmlNodeType.Comment)
  761. continue;
  762. XmlElement actionNode = item as XmlElement;
  763. if (actionNode == null) continue;
  764. if (actionNode.Name != "Action")
  765. {
  766. if (actionNode.NodeType != XmlNodeType.Comment)
  767. {
  768. LOG.Write($"interlock config file contains no comments content, {actionNode.InnerXml}");
  769. }
  770. continue;
  771. }
  772. if (!actionNode.HasAttribute("Name") || !actionNode.HasAttribute("Value"))
  773. {
  774. LOG.Write($"action node has no [Name] or [Value] attribute, {actionNode.InnerXml}");
  775. continue;
  776. }
  777. string actionName = actionNode.GetAttribute("Name");
  778. string value = actionNode.GetAttribute("Value");
  779. if (string.IsNullOrEmpty(value) ||
  780. (!value.ToUpper().Contains("ON")) && !value.ToUpper().Contains("OFF") &&
  781. !value.ToUpper().Contains("OPEN") && !value.ToUpper().Contains("CLOSE"))
  782. {
  783. LOG.Write($"action node has no [Name] or [Value] attribute, {actionNode.InnerXml}");
  784. continue;
  785. }
  786. string tip = string.Empty;
  787. List<InterlockLimit> limits = new List<InterlockLimit>();
  788. bool isAndCondition = true;
  789. if (UserDefineInterlocks != null && UserDefineInterlocks(actionName))
  790. {
  791. //do nothing
  792. }
  793. else if (!doMap.ContainsKey(actionName) && !actionName.ToUpper().StartsWith("FLAG"))
  794. {
  795. reason += "action node " + actionName + " no such DO defined \r\n";
  796. continue;
  797. }
  798. if (UserDefineInterlocks != null && !UserDefineInterlocks(actionName) && !actionName.ToUpper().StartsWith("FLAG"))
  799. {
  800. DOAccessor doItem;
  801. doItem = doMap[actionName] as DOAccessor;
  802. if (doItem == null)
  803. {
  804. reason += "action node " + actionName + " no such DO defined \r\n";
  805. continue;
  806. }
  807. }
  808. if (actionNode.HasAttribute("condition"))
  809. isAndCondition = actionNode.GetAttribute("condition").ToLower() == "and";
  810. bool isLimitInvalid = false;
  811. foreach (XmlElement limitNode in actionNode.ChildNodes)
  812. {
  813. if (limitNode.Name != "Limit")
  814. {
  815. if (limitNode.NodeType != XmlNodeType.Comment)
  816. {
  817. LOG.Write("interlock config file contains no comments content, " + limitNode.InnerXml);
  818. }
  819. isLimitInvalid = true;
  820. break;
  821. }
  822. if (!(limitNode.HasAttribute("Name") || limitNode.HasAttribute("Value")) || !limitNode.HasAttribute("Condition"))
  823. {
  824. LOG.Write("limit node lack of Name/Condition or Value attribute, " + limitNode.InnerXml);
  825. isLimitInvalid = true;
  826. break;
  827. }
  828. if (limitNode.GetAttribute("Condition").ToUpper() != "AND" &&
  829. limitNode.GetAttribute("Condition").ToUpper() != "OR" &&
  830. limitNode.GetAttribute("Condition").ToUpper() != "EXOR" &&
  831. limitNode.GetAttribute("Condition").ToUpper() != "M-START" &&
  832. limitNode.GetAttribute("Condition").ToUpper() != "M-END" &&
  833. limitNode.GetAttribute("Condition").ToUpper() != "END" &&
  834. limitNode.GetAttribute("Condition").ToUpper() != "BLANK")
  835. {
  836. LOG.Write("limit Condition attribute is invalid, " + limitNode.InnerXml);
  837. isLimitInvalid = true;
  838. break;
  839. }
  840. if (limitNode.GetAttribute("Condition").ToUpper() == "BLANK")
  841. continue;
  842. if (limitNode.GetAttribute("Condition").ToUpper() == "END")
  843. {
  844. interlockParserEnd = true;
  845. break;
  846. }
  847. //if (limitNode.GetAttribute("Condition").ToUpper() == "M-START")
  848. //{
  849. // interlockParserMark = true;
  850. // continue;
  851. //}
  852. //if (limitNode.GetAttribute("Condition").ToUpper() == "M-END")
  853. //{
  854. // interlockParserMark = false;
  855. //}
  856. //if (interlockParserMark)
  857. // continue;
  858. string stringValue = limitNode.GetAttribute("Value");
  859. if (stringValue.Contains("*"))
  860. {
  861. LOG.Write($"limit Value attribute is invalid, {limitNode.InnerXml}");
  862. isLimitInvalid = true;
  863. break;
  864. }
  865. string limitValue = limitNode.GetAttribute("Value");
  866. string limitTip = string.Empty;
  867. Dictionary<string, string> limitCultureTip = new Dictionary<string, string>();
  868. if (limitNode.HasAttribute("Name"))
  869. {
  870. string Name = limitNode.GetAttribute("Name");
  871. if (Name.ToUpper().StartsWith("FLAG"))
  872. {
  873. limits.Add(new UserDefineLimit(Name, limitValue.ToUpper().Contains("ON") ? true : false, limitNode.GetAttribute("Condition")));
  874. continue;
  875. }
  876. if (Name.Split('.')[1].ToLower().StartsWith("di"))
  877. {
  878. if (!diMap.ContainsKey(Name))
  879. {
  880. LOG.Write($"limit node {Name} no such DI defined, {limitNode.InnerXml}");
  881. isLimitInvalid = true;
  882. break;
  883. }
  884. DIAccessor diItem = diMap[Name] as DIAccessor;
  885. if (diItem == null)
  886. {
  887. LOG.Write($"limit node {Name} no such DI defined, {limitNode.InnerXml}");
  888. isLimitInvalid = true;
  889. break;
  890. }
  891. //limits.Add(new DiLimit(diItem, Convert.ToBoolean(limitValue), limitNode.GetAttribute("Condition")));
  892. limits.Add(new DiLimit(diItem, limitValue.ToUpper().Contains("ON") ? true : false, limitNode.GetAttribute("Condition")));
  893. }
  894. else if (Name.Split('.')[1].ToLower().StartsWith("do"))
  895. {
  896. if (!doMap.ContainsKey(Name))
  897. {
  898. LOG.Write($"limit node {Name} no such DO defined, {limitNode.InnerXml}");
  899. isLimitInvalid = true;
  900. break;
  901. }
  902. DOAccessor ioItem = doMap[Name];
  903. if (ioItem == null)
  904. {
  905. LOG.Write($"limit node {Name} no such DO defined, {limitNode.InnerXml}");
  906. isLimitInvalid = true;
  907. break;
  908. }
  909. //limits.Add(new DoLimit(ioItem, Convert.ToBoolean(limitValue), limitNode.GetAttribute("Condition")));
  910. limits.Add(new DoLimit(ioItem, limitValue.ToUpper().Contains("ON") ? true : false, limitNode.GetAttribute("Condition")));
  911. }
  912. else if (Name.Split('.')[1].ToLower().StartsWith("ao"))
  913. {
  914. if (!aoMap.ContainsKey(Name))
  915. {
  916. LOG.Write($"limit node {Name} no such AO defined, {limitNode.InnerXml}");
  917. isLimitInvalid = true;
  918. break;
  919. }
  920. AOAccessor ioItem = aoMap[Name];
  921. if (ioItem == null)
  922. {
  923. LOG.Write($"limit node {Name} no such AO defined, {limitNode.InnerXml}");
  924. isLimitInvalid = true;
  925. break;
  926. }
  927. limits.Add(new AoLimit(ioItem, limitValue, limitNode.GetAttribute("Condition")));
  928. }
  929. else if (Name.Split('.')[1].ToLower().StartsWith("ai"))
  930. {
  931. if (!aiMap.ContainsKey(Name))
  932. {
  933. LOG.Write($"limit node {Name} no such AI defined, {limitNode.InnerXml}");
  934. isLimitInvalid = true;
  935. break;
  936. }
  937. AIAccessor ioItem = aiMap[Name];
  938. if (ioItem == null)
  939. {
  940. LOG.Write($"limit node {Name} no such AI defined, {limitNode.InnerXml}");
  941. isLimitInvalid = true;
  942. break;
  943. }
  944. limits.Add(new AiLimit(ioItem, limitValue, limitNode.GetAttribute("Condition")));
  945. }
  946. else
  947. {
  948. if (DATA.Poll(Name) == null)
  949. {
  950. LOG.Write($"limit node {Name} no such DATA.Poll defined, {limitNode.InnerXml}");
  951. isLimitInvalid = true;
  952. break;
  953. }
  954. limits.Add(new DataPollLimit(Name, limitValue, limitNode.GetAttribute("Condition")));
  955. }
  956. }
  957. }
  958. if (isLimitInvalid)
  959. continue;
  960. if (limits.Count == 0)
  961. continue;
  962. var paras = value.Split(';');//KEEP30;ON
  963. string condition = "";
  964. float conditionTime = 0.0f;
  965. bool actionValue;
  966. bool actionAuto = true;
  967. if (paras.Length > 2)
  968. {
  969. if (paras[0].ToUpper().Contains("KEEP"))
  970. {
  971. condition = "KEEP";
  972. float.TryParse(paras[0].ToUpper().Replace("KEEP", ""), out conditionTime);
  973. }
  974. if (paras[0].ToUpper().Contains("DELAY"))
  975. {
  976. condition = "DELAY";
  977. float.TryParse(paras[0].ToUpper().Replace("DELAY", ""), out conditionTime);
  978. }
  979. actionValue = paras[1].ToUpper().Contains("ON") || paras[1].ToUpper() == "OPEN" ? true : false;
  980. actionAuto = paras[2].ToUpper().Contains("AUTO") ? true : false;
  981. }
  982. else if (paras.Length == 2)
  983. {
  984. if (value.ToUpper().Contains("KEEP") || value.ToUpper().Contains("DELAY"))
  985. {
  986. if (paras[0].ToUpper().Contains("KEEP"))
  987. {
  988. condition = "KEEP";
  989. float.TryParse(paras[0].ToUpper().Replace("KEEP", ""), out conditionTime);
  990. }
  991. if (paras[0].ToUpper().Contains("DELAY"))
  992. {
  993. condition = "DELAY";
  994. float.TryParse(paras[0].ToUpper().Replace("DELAY", ""), out conditionTime);
  995. }
  996. actionValue = paras[1].ToUpper().Contains("ON") || paras[1].ToUpper() == "OPEN" ? true : false;
  997. }
  998. else
  999. {
  1000. actionValue = paras[0].ToUpper().Contains("ON") || paras[1].ToUpper() == "OPEN" ? true : false;
  1001. actionAuto = paras[1].ToUpper().Contains("AUTO") ? true : false;
  1002. }
  1003. }
  1004. else
  1005. {
  1006. actionValue = value.ToUpper().Contains("ON") || value.ToUpper() == "OPEN" ? true : false;
  1007. }
  1008. if (actionName.ToUpper().StartsWith("FLAG"))
  1009. {
  1010. InterlockAction action = new InterlockAction(actionName, actionValue, actionNode.OuterXml, condition, conditionTime, limits, actionAuto);
  1011. lock (_locker)
  1012. {
  1013. _userDefineFlagActions.Add(action);
  1014. if (!_userDefineFlagCurrentValues.ContainsKey(actionName.ToUpper()))
  1015. _userDefineFlagCurrentValues.Add(actionName.ToUpper(), false);
  1016. }
  1017. }
  1018. else if (UserDefineInterlocks != null && UserDefineInterlocks(actionName))
  1019. {
  1020. InterlockAction action = new InterlockAction(actionName, actionValue, actionNode.OuterXml, condition, conditionTime, limits, actionAuto);
  1021. _userDefineActions.Add(action);
  1022. }
  1023. else
  1024. {
  1025. DOAccessor doItem;
  1026. doItem = doMap[actionName] as DOAccessor;
  1027. InterlockAction action = new InterlockAction(doItem, actionValue, actionNode.OuterXml, condition, conditionTime, limits);
  1028. lock (_locker)
  1029. {
  1030. _userDefineActions.Add(action);
  1031. }
  1032. }
  1033. }
  1034. }
  1035. catch (Exception ex)
  1036. {
  1037. reason += ex.Message;
  1038. }
  1039. if (!string.IsNullOrEmpty(reason))
  1040. return false;
  1041. return true;
  1042. }
  1043. private AlarmEventItem SubscribeAlarm(string name, string description, Func<bool> resetChecker, EventLevel level = EventLevel.Alarm)
  1044. {
  1045. AlarmEventItem item = new AlarmEventItem(name.Split('.')[0], name, description, resetChecker, this);
  1046. item.Level = level;
  1047. EV.Subscribe(item);
  1048. return item;
  1049. }
  1050. public void AlarmStateChanged(AlarmEventItem args)
  1051. {
  1052. if (OnDeviceAlarmStateChanged != null)
  1053. {
  1054. OnDeviceAlarmStateChanged($"{args.Id}{args.Description}", args);
  1055. }
  1056. }
  1057. private void MonitorUserDefineInterlock()
  1058. {
  1059. if (SC.ContainsItem("System.BypassInterlock") && SC.GetValue<bool>("System.BypassInterlock"))
  1060. return;
  1061. if (_userDefineFlagActions.Count != 0)
  1062. {
  1063. foreach (var action in _userDefineFlagActions)
  1064. {
  1065. if (action == null || action.Limits.Count == 0)
  1066. continue;
  1067. SetUserDefineActionValue(action, _userDefineFlagActions);
  1068. }
  1069. }
  1070. if (_userDefineActions.Count > 0)
  1071. {
  1072. foreach (var action in _userDefineActions)
  1073. {
  1074. if (!action.IsAuto)
  1075. continue;
  1076. if (action == null || action.Limits.Count == 0)
  1077. continue;
  1078. SetUserDefineActionValue(action, _userDefineActions);
  1079. }
  1080. }
  1081. }
  1082. private bool GetUserDefineInterlockTrigResult(List<InterlockLimit> limits)
  1083. {
  1084. bool isTrig = false;
  1085. if (limits == null || limits.Count == 0)
  1086. return false;
  1087. if (limits.Count > 1)
  1088. {
  1089. for (int i = 0; i < limits.Count; i++)
  1090. {
  1091. bool currentValue = false;
  1092. if (_userDefineFlagCurrentValues.ContainsKey(limits[i].Name.ToUpper()))
  1093. currentValue = _userDefineFlagCurrentValues[limits[i].Name.ToUpper()];
  1094. else
  1095. currentValue = limits[i].CurrentValue;
  1096. bool currentCondition;
  1097. if (limits[i].IsFloatType)
  1098. {
  1099. //AI,AO类型
  1100. currentCondition = currentValue;
  1101. }
  1102. else
  1103. {
  1104. //DI,DO类型
  1105. currentCondition = currentValue == limits[i].LimitValue;
  1106. }
  1107. if (i == 0)
  1108. {
  1109. isTrig = currentCondition;
  1110. continue;
  1111. }
  1112. switch (limits[i].Condition.ToUpper())
  1113. {
  1114. case "AND":
  1115. isTrig = isTrig && currentCondition;
  1116. break;
  1117. case "OR":
  1118. isTrig = isTrig || currentCondition;
  1119. break;
  1120. case "BLANK":
  1121. break;
  1122. }
  1123. }
  1124. }
  1125. else
  1126. {
  1127. bool currentValue = false;
  1128. if (_userDefineFlagCurrentValues.ContainsKey(limits[0].Name.ToUpper()))
  1129. currentValue = _userDefineFlagCurrentValues[limits[0].Name.ToUpper()];
  1130. else
  1131. currentValue = limits[0].CurrentValue;
  1132. if (limits[0].IsFloatType)
  1133. {
  1134. //AI,AO类型
  1135. isTrig = currentValue;
  1136. }
  1137. else
  1138. {
  1139. //DI,DO类型
  1140. isTrig = currentValue == limits[0].LimitValue;
  1141. }
  1142. }
  1143. return isTrig;
  1144. }
  1145. private void SetUserDefineActionValue(InterlockAction action, List<InterlockAction> actionLst)
  1146. {
  1147. var limits = action.Limits;
  1148. bool isTrig = GetUserDefineInterlockTrigResult(action.Limits);
  1149. var trigKey = $"{action.ActionName.ToUpper()}-{actionLst.IndexOf(action)}";//ActionName可能有多条
  1150. if (!_userDefineConditionTrig.ContainsKey(trigKey))
  1151. _userDefineConditionTrig.Add(trigKey, new RD_TRIG());
  1152. _userDefineConditionTrig[trigKey].CLK = isTrig;
  1153. if (_userDefineConditionTrig[trigKey].R)
  1154. {
  1155. if (action.Condition.ToUpper() == "KEEP" && action.ConditionTime > 0)
  1156. {
  1157. if (!_userDefineKeepTimer.ContainsKey($"{action.ActionName.ToUpper()}.{action.ActionValue}"))
  1158. _userDefineKeepTimer.Add($"{action.ActionName.ToUpper()}.{action.ActionValue}", new Stopwatch());
  1159. // 满足keep acition才计时keep,否则不keep
  1160. if (_userDefineFlagCurrentValues.ContainsKey(action.ActionName.ToUpper()))
  1161. {
  1162. //FLAG类型的值
  1163. if (_userDefineFlagCurrentValues[action.ActionName.ToUpper()] == action.ActionValue)
  1164. _userDefineKeepTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].Restart();
  1165. }
  1166. else
  1167. {
  1168. if (action.ActionValue == action.ActionDo.Value)
  1169. {
  1170. LOG.Write($"{action.ActionName} keep value to {action.ActionValue} for interlock trig : '{action.Tip}'");
  1171. //if (action.ActionDo.SetValue(action.ActionValue, out string reason))
  1172. // LOG.Write($"{action.ActionName} set value to {action.ActionValue} for interlock trig : '{action.Tip}'");
  1173. //else
  1174. // LOG.Write($"{action.ActionName} set interlock trig '{action.Tip}' value to {action.ActionValue} failed for {reason}");
  1175. _userDefineKeepTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].Restart();
  1176. }
  1177. }
  1178. }
  1179. else if (action.Condition.ToUpper() == "DELAY" && action.ConditionTime > 0)
  1180. {
  1181. if (!_userDefineDelayTimer.ContainsKey($"{action.ActionName.ToUpper()}.{action.ActionValue}"))
  1182. _userDefineDelayTimer.Add($"{action.ActionName.ToUpper()}.{action.ActionValue}", new Stopwatch());
  1183. _userDefineDelayTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].Restart();
  1184. }
  1185. else
  1186. {
  1187. if (_userDefineFlagCurrentValues.ContainsKey(action.ActionName.ToUpper()))
  1188. {
  1189. //FLAG类型的值
  1190. _userDefineFlagCurrentValues[action.ActionName.ToUpper()] = action.ActionValue;
  1191. }
  1192. else
  1193. {
  1194. if (UserDefineInterlockHandler != null && UserDefineInterlockHandler(action.ActionName, action.ActionValue))
  1195. LOG.Write($"{action.ActionName} set value to {action.ActionValue} for interlock trig : '{action.Tip}'");
  1196. else if (action.ActionDo.SetValue(action.ActionValue, out string reason))
  1197. LOG.Write($"{action.ActionName} set value to {action.ActionValue} for interlock trig : '{action.Tip}'");
  1198. else
  1199. LOG.Write($"{action.ActionName} set interlock trig '{action.Tip}' value to {action.ActionValue} failed for {reason}");
  1200. }
  1201. }
  1202. }
  1203. if (_userDefineConditionTrig[trigKey].T)
  1204. {
  1205. if (action.Condition.ToUpper() == "KEEP" && action.ConditionTime > 0)
  1206. {
  1207. if (!_userDefineKeepTimer.ContainsKey($"{action.ActionName.ToUpper()}.{action.ActionValue}"))
  1208. _userDefineKeepTimer.Add($"{action.ActionName.ToUpper()}.{action.ActionValue}", new Stopwatch());
  1209. //trig条件在keep时间内不能保持不变,则要把定时器stop
  1210. _userDefineKeepTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].Stop();
  1211. }
  1212. else if (action.Condition.ToUpper() == "DELAY" && action.ConditionTime > 0)
  1213. {
  1214. if (!_userDefineDelayTimer.ContainsKey($"{action.ActionName.ToUpper()}.{action.ActionValue}"))
  1215. _userDefineDelayTimer.Add($"{action.ActionName.ToUpper()}.{action.ActionValue}", new Stopwatch());
  1216. //trig条件在delay时间内不能保持不变,则要把定时器stop
  1217. _userDefineDelayTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].Stop();
  1218. }
  1219. }
  1220. if (_userDefineConditionTrig[trigKey].M)
  1221. {
  1222. if (action.Condition.ToUpper() == "KEEP" && action.ConditionTime > 0)
  1223. {
  1224. if (!_userDefineKeepTimer.ContainsKey($"{action.ActionName.ToUpper()}.{action.ActionValue}"))
  1225. _userDefineKeepTimer.Add($"{action.ActionName.ToUpper()}.{action.ActionValue}", new Stopwatch());
  1226. //在keep指定时间后,把定时器stop
  1227. if (_userDefineKeepTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].IsRunning &&
  1228. _userDefineKeepTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].ElapsedMilliseconds > action.ConditionTime * 1000)
  1229. {
  1230. _userDefineKeepTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].Stop();
  1231. }
  1232. else if (_userDefineKeepTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].IsRunning)
  1233. {
  1234. //在keep时间内,被keep的状态变了,抛出alarm
  1235. if (_userDefineFlagCurrentValues.ContainsKey(action.ActionName.ToUpper()))
  1236. {
  1237. if (_userDefineFlagCurrentValues[action.ActionName.ToUpper()] != action.ActionValue)
  1238. {
  1239. _userDefineKeepTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].Stop();
  1240. if (InterlockAlarms.ContainsKey(UserDefineInterlockAlarmKey))
  1241. {
  1242. InterlockAlarms[UserDefineInterlockAlarmKey].Set($"Due to the {action.ActionName} can not keep {action.ActionValue.ToString()} for {action.ConditionTime}s");
  1243. }
  1244. }
  1245. }
  1246. else
  1247. {
  1248. if (action.ActionValue != action.ActionDo.Value)
  1249. {
  1250. _userDefineKeepTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].Stop();
  1251. if (InterlockAlarms.ContainsKey(UserDefineInterlockAlarmKey))
  1252. {
  1253. InterlockAlarms[UserDefineInterlockAlarmKey].Set($"Due to the {action.ActionName} can not keep {action.ActionValue.ToString()} for {action.ConditionTime}s");
  1254. }
  1255. }
  1256. }
  1257. }
  1258. }
  1259. else if (action.Condition.ToUpper() == "DELAY" && action.ConditionTime > 0)
  1260. {
  1261. if (!_userDefineDelayTimer.ContainsKey($"{action.ActionName.ToUpper()}.{action.ActionValue}"))
  1262. _userDefineDelayTimer.Add($"{action.ActionName.ToUpper()}.{action.ActionValue}", new Stopwatch());
  1263. if (_userDefineKeepTimer.ContainsKey($"{action.ActionName.ToUpper()}.{action.ActionValue}") &&
  1264. _userDefineKeepTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].IsRunning)
  1265. {
  1266. //还处于keep时间内,啥也不干
  1267. }
  1268. else
  1269. {
  1270. //在delay指定时间后,把定时器stop,同时赋值
  1271. if (_userDefineDelayTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].IsRunning &&
  1272. _userDefineDelayTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].ElapsedMilliseconds > action.ConditionTime * 1000)
  1273. {
  1274. _userDefineDelayTimer[$"{action.ActionName.ToUpper()}.{action.ActionValue}"].Stop();
  1275. if (_userDefineFlagCurrentValues.ContainsKey(action.ActionName.ToUpper()))
  1276. {
  1277. //FLAG类型的值
  1278. _userDefineFlagCurrentValues[action.ActionName.ToUpper()] = action.ActionValue;
  1279. }
  1280. else
  1281. {
  1282. if (UserDefineInterlockHandler != null && UserDefineInterlockHandler(action.ActionName, action.ActionValue))
  1283. LOG.Write($"{action.ActionName} set value to {action.ActionValue} for interlock trig : '{action.Tip}'");
  1284. else if (action.ActionDo.SetValue(action.ActionValue, out string reason))
  1285. LOG.Write($"{action.ActionName} set value to {action.ActionValue} for interlock trig : '{action.Tip}'");
  1286. else
  1287. LOG.Write($"{action.ActionName} set interlock trig '{action.Tip}' value to {action.ActionValue} failed for {reason}");
  1288. }
  1289. }
  1290. }
  1291. }
  1292. else
  1293. {
  1294. if (!_userDefineFlagCurrentValues.ContainsKey(action.ActionName.ToUpper()))
  1295. {
  1296. if (UserDefineInterlockHandler != null)//alarm reset,实际还是满足条件,需要继续报
  1297. UserDefineInterlockHandler(action.ActionName, action.ActionValue);
  1298. }
  1299. }
  1300. }
  1301. }
  1302. }
  1303. }