RouteManager.cs 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Aitex.Core.RT.Fsm;
  8. using Aitex.Core.Common;
  9. using Aitex.Core.RT.DataCenter;
  10. using Aitex.Core.RT.Event;
  11. using Aitex.Core.RT.OperationCenter;
  12. using Aitex.Core.RT.SCCore;
  13. using Aitex.Core.Util;
  14. using MECF.Framework.Common.Jobs;
  15. using MECF.Framework.Common.Equipment;
  16. using MECF.Framework.Common.SubstrateTrackings;
  17. using CyberX8_Core;
  18. using Aitex.Core.RT.Log;
  19. using SecsGem.Core.Application;
  20. using CyberX8_RT.Modules.SRD;
  21. using CyberX8_RT.Modules.PUF;
  22. using CyberX8_RT.Modules.Dummy;
  23. using CyberX8_RT.Modules.Loader;
  24. using Aitex.Core.RT.Device;
  25. using CyberX8_RT.Modules.Prewet;
  26. using CyberX8_RT.Modules.Dryer;
  27. using MECF.Framework.Common.ToolLayout;
  28. using CyberX8_RT.Modules.Metal;
  29. using CyberX8_RT.Modules.Rinse;
  30. using MECF.Framework.Common.Routine;
  31. using CyberX8_RT.Dispatch;
  32. using CyberX8_RT.Modules.Reservoir;
  33. using System.IO;
  34. using CyberX8_RT.Modules.Buffer;
  35. using CyberX8_RT.Modules.Transporter;
  36. using CyberX8_RT.Devices.Loader;
  37. using CyberX8_RT.Devices.PUF;
  38. using CyberX8_RT.Devices.SRD;
  39. using MECF.Framework.Common.Alarm;
  40. using System.Diagnostics;
  41. using MECF.Framework.Common.WaferHolder;
  42. using CyberX8_RT.Schedulers;
  43. using MECF.Framework.Common.ProcessCell;
  44. using System.Reflection;
  45. namespace CyberX8_RT.Modules
  46. {
  47. class RouteManager : Entity, IEntity
  48. {
  49. public enum MSG
  50. {
  51. MoveWafer,
  52. ReturnWafer,
  53. HomeUnit,
  54. PauseAuto,
  55. ResumeAuto,
  56. Stop,
  57. StartCycle,
  58. StopCycle,
  59. HOME,
  60. RESET,
  61. ABORT,
  62. ERROR,
  63. SetAutoMode,
  64. SetManualMode,
  65. ResetIdleCleanTime,
  66. ResetIdlePurgeTime,
  67. CreateJob,
  68. PauseJob,
  69. PauseAllJobs,
  70. ResumeJob,
  71. ResumeAllJobs,
  72. StartJob,
  73. StopJob,
  74. AbortJob,
  75. JobDone,
  76. CassetteLeave, //For unload light control off afer job done
  77. Map,
  78. ReturnAllWafer,
  79. TMCycle,
  80. Retry,
  81. ConfirmComplete,
  82. ResetWafers,
  83. FaStartJob,
  84. FaStopJob,
  85. }
  86. #region 属性
  87. public string Name { get; set; }
  88. public bool IsAutoMode
  89. {
  90. get
  91. {
  92. return fsm.State == (int)RtState.AutoRunning || fsm.State == (int)RtState.AutoIdle||fsm.State==(int)RtState.AutoAborting;
  93. }
  94. }
  95. public bool IsFaAutoMode
  96. {
  97. get
  98. {
  99. return fsm.State == (int)RtState.AutoRunning || fsm.State == (int)RtState.AutoIdle;
  100. }
  101. }
  102. public bool IsInit
  103. {
  104. get { return fsm.State == (int)RtState.Init; }
  105. }
  106. public bool IsIdle
  107. {
  108. get { return fsm.State == (int)RtState.Idle || fsm.State == (int)RtState.AutoIdle; }
  109. }
  110. public bool IsAlarm
  111. {
  112. get { return fsm.State == (int)RtState.Error; }
  113. }
  114. public bool IsPaused
  115. {
  116. get { return _jobCycle.CycleState == RState.Paused; }
  117. }
  118. public bool IsRunning
  119. {
  120. get
  121. {
  122. return !IsInit && !IsAlarm && !IsIdle;
  123. }
  124. }
  125. /// <summary>
  126. /// 是否AutoRunning
  127. /// </summary>
  128. public bool IsAutoRunning
  129. {
  130. get { return fsm.State == (int)RtState.AutoRunning||fsm.State==(int)RtState.AutoAborting; }
  131. }
  132. /// <summary>
  133. /// 是否
  134. /// </summary>
  135. public bool IsAutoIdle
  136. {
  137. get { return fsm.State == (int)RtState.AutoIdle; }
  138. }
  139. /// <summary>
  140. /// EFEM实体
  141. /// </summary>
  142. public EfemEntity EFEM { get; }
  143. public WaferSize WaferSize { get; private set; }
  144. #endregion
  145. #region 内部变量
  146. private string _systemControlIp;
  147. private ICycle _jobCycle;
  148. private ModuleHomeAllRoutine _homeAllRoutine;
  149. private List<ReservoirMetalHomeRoutine> _reservoirMetalRoutines=new List<ReservoirMetalHomeRoutine>();
  150. /// <summary>
  151. /// 模块实体字典
  152. /// </summary>
  153. private Dictionary<string, IModuleEntity> _moduleEntitiesDic = new Dictionary<string, IModuleEntity>();
  154. /// <summary>
  155. /// 模块类型实体字典
  156. /// </summary>
  157. private Dictionary<ModuleType, List<IModuleEntity>> _modultTypeEntitiesDic = new Dictionary<ModuleType, List<IModuleEntity>>();
  158. /// <summary>
  159. /// Home stopwatch
  160. /// </summary>
  161. private Stopwatch _homeStopWatch = new Stopwatch();
  162. #endregion
  163. /// <summary>
  164. /// 构造函数
  165. /// </summary>
  166. public RouteManager()
  167. {
  168. Name = "System";
  169. WaferSize = (WaferSize)SC.GetValue<int>("System.WaferSize");
  170. if (ModuleHelper.IsInstalled(ModuleName.EFEM))
  171. {
  172. EFEM = new EfemEntity();
  173. EFEM.Initialize();
  174. _moduleEntitiesDic[ModuleName.EFEM.ToString()] = EFEM;
  175. }
  176. InitialModuleList(PufItemManager.Instance.InstalledModules, typeof(PUFEntity),ModuleType.PUF);
  177. InitialModuleList(DummyCasseteItemManager.Instance.InstalledModules, typeof(DummyEntity),ModuleType.Dummy);
  178. InitialModuleList(LoaderItemManager.Instance.InstalledModules, typeof(LoaderEntity),ModuleType.Loader);
  179. InitialModuleList(TransporterItemManager.Instance.InstalledModules, typeof(TransporterEntity),ModuleType.Transporter);
  180. InitialModuleList(BufferItemManager.Instance.InstalledModules, typeof(BufferEntity), ModuleType.Buffer);
  181. InitialModuleList(PrewetItemManager.Instance.InstalledModules, typeof(PrewetEntity),ModuleType.Prewet);
  182. InitialModuleList(DryerItemManager.Instance.InstalledModules, typeof(DryerEntity),ModuleType.Dryer);
  183. InitialModuleList(MetalItemManager.Instance.InstalledModules, typeof(MetalEntity),ModuleType.Metal);
  184. InitialModuleList(RinseItemManager.Instance.InstalledModules, typeof(RinseEntity),ModuleType.Rinse);
  185. InitialModuleList(ReservoirItemManager.Instance.InstalledModules,typeof(ReservoirEntity),ModuleType.Reservoir);
  186. InitialModuleList(SrdItemManager.Instance.InstalledModules, typeof(SRDEntity), ModuleType.SRD);
  187. fsm = new StateMachine<RouteManager>(Name, (int)RtState.Init, 200);
  188. SubscribeOperation();
  189. SubscribeDataVariable();
  190. }
  191. /// <summary>
  192. /// 初始化模块集合
  193. /// </summary>
  194. /// <param name="lst"></param>
  195. /// <param name="entityType"></param>
  196. private void InitialModuleList(List<string> lst,Type entityType,ModuleType moduleType)
  197. {
  198. foreach(string item in lst)
  199. {
  200. InitialModule(item, entityType,moduleType);
  201. }
  202. }
  203. /// <summary>
  204. /// 初始化模块对象
  205. /// </summary>
  206. /// <param name="item"></param>
  207. /// <param name="moduleType"></param>
  208. private void InitialModule(string item,Type entityType,ModuleType moduleType)
  209. {
  210. ModuleName moduleName = (ModuleName)Enum.Parse(typeof(ModuleName), item);
  211. IModuleEntity moduleEntity= (IModuleEntity)System.Activator.CreateInstance(entityType,moduleName);
  212. moduleEntity.Initialize();
  213. _moduleEntitiesDic[item] = moduleEntity;
  214. List<IModuleEntity> lst = new List<IModuleEntity>();
  215. if(_modultTypeEntitiesDic.ContainsKey(moduleType))
  216. {
  217. lst= _modultTypeEntitiesDic[moduleType];
  218. }
  219. else
  220. {
  221. _modultTypeEntitiesDic[moduleType] = lst;
  222. }
  223. lst.Add(moduleEntity);
  224. }
  225. public bool Check(int msg, out string reason, params object[] args)
  226. {
  227. if (!fsm.FindTransition(fsm.State, msg))
  228. {
  229. reason = String.Format("{0} is in {1} state,can not do {2}", Name, 0, (MSG)msg);
  230. return false;
  231. }
  232. if (msg == (int)MSG.StartCycle)
  233. {
  234. if (!IsAutoMode)
  235. {
  236. reason = String.Format("can not do {0}, isn't auto mode.", msg.ToString());
  237. return false;
  238. }
  239. }
  240. reason = "";
  241. return true;
  242. }
  243. /// <summary>
  244. /// 订阅数据
  245. /// </summary>
  246. void SubscribeDataVariable()
  247. {
  248. DATA.Subscribe("System.SystemControlIp", ()=>_systemControlIp, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  249. DATA.Subscribe("Rt.Status", () => ((RtState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  250. DATA.Subscribe("System.State", () => ((RtState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  251. DATA.Subscribe("System.IsAutoMode", () => IsAutoMode, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  252. DATA.Subscribe("System.IsAutoRunning", () => IsAutoRunning, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  253. DATA.Subscribe("System.IsIdle", () => IsIdle || IsInit, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  254. DATA.Subscribe("System.IsAlarm", () => IsAlarm, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  255. DATA.Subscribe("System.IsBusy", () => IsRunning, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  256. DATA.Subscribe("System.IsConnectedWithHost", () => CheckSecsGemOnline(Singleton<SecGemApplication>.Instance.ControlState),SubscriptionAttribute.FLAG.IgnoreSaveDB);
  257. DATA.Subscribe("System.IsDisconnectWithHost", () => CheckSecsGemOnline(Singleton<SecGemApplication>.Instance.ControlState),SubscriptionAttribute.FLAG.IgnoreSaveDB);
  258. DATA.Subscribe("System.EquipmentMode", () => IsAutoMode ? "Auto":"Manual", SubscriptionAttribute.FLAG.IgnoreSaveDB);
  259. DATA.Subscribe("EquipmentStatus", () =>
  260. {
  261. if (IsInit) return 0;
  262. if (IsIdle) return 1;
  263. if (IsAlarm) return 3;
  264. if (IsPaused) return 4;
  265. return 2;
  266. }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
  267. }
  268. /// <summary>
  269. /// 订阅操作
  270. /// </summary>
  271. void SubscribeOperation()
  272. {
  273. OP.Subscribe("ApplySystemControl", ApplySystemControl);
  274. OP.Subscribe("ReleaseSystemControl", ReleaseSystemControl);
  275. OP.Subscribe("CreateWafer", InvokeCreateWafer);
  276. OP.Subscribe("DeleteWafer", InvokeDeleteWafer);
  277. OP.Subscribe("System.Home", (cmd, args) => CheckToPostMessage((int)MSG.HOME, args));
  278. DATA.Subscribe("SYSTEM.FsmState", () => (((RtState)fsm.State).ToString()), SubscriptionAttribute.FLAG.IgnoreSaveDB);
  279. OP.Subscribe("System.ReturnAllWafer", (string cmd, object[] args) =>
  280. {
  281. return CheckToPostMessage((int)MSG.ReturnAllWafer, args[0], args[1], args[2], args[3]);
  282. });
  283. OP.Subscribe("System.MoveWafer", (string cmd, object[] args) =>
  284. {
  285. if (!Enum.TryParse((string)args[0], out ModuleName source))
  286. {
  287. EV.PostWarningLog(Name, $"Parameter source {(string)args[0]} not valid");
  288. return false;
  289. }
  290. if (!Enum.TryParse((string)args[2], out ModuleName destination))
  291. {
  292. EV.PostWarningLog(Name, $"Parameter destination {(string)args[1]} not valid");
  293. return false;
  294. }
  295. return CheckToPostMessage((int)MSG.MoveWafer,
  296. source, (int)args[1],
  297. destination, (int)args[3],
  298. args[4], args[5],
  299. args[6], args[7], (string)args[8]);
  300. });
  301. OP.Subscribe("System.HomeAll", (string cmd, object[] args) =>
  302. {
  303. return CheckToPostMessage((int)MSG.HOME);
  304. });
  305. OP.Subscribe("System.Abort", (string cmd, object[] args) =>
  306. {
  307. return CheckToPostMessage((int)MSG.ABORT);
  308. });
  309. OP.Subscribe("System.Reset", (string cmd, object[] args) =>
  310. {
  311. return CheckToPostMessage((int)MSG.RESET);
  312. });
  313. OP.Subscribe("System.SetAutoMode", (string cmd, object[] args) =>
  314. {
  315. return CheckToPostMessage((int)MSG.SetAutoMode);
  316. });
  317. OP.Subscribe("System.SetManualMode", (string cmd, object[] args) =>
  318. {
  319. return CheckToPostMessage((int)MSG.SetManualMode);
  320. });
  321. OP.Subscribe("System.CreateJob", (string cmd, object[] args) =>
  322. {
  323. return CheckToPostMessage((int)MSG.CreateJob, args[0]);
  324. });
  325. OP.Subscribe("System.StartJob", (string cmd, object[] args) =>
  326. {
  327. return CheckToPostMessage((int)MSG.StartJob, args[0]);
  328. });
  329. OP.Subscribe("System.PauseJob", (string cmd, object[] args) =>
  330. {
  331. return CheckToPostMessage((int)MSG.PauseJob, args[0]);
  332. });
  333. OP.Subscribe("System.ResumeJob", (string cmd, object[] args) =>
  334. {
  335. return CheckToPostMessage((int)MSG.ResumeJob, args[0]);
  336. });
  337. OP.Subscribe("System.PauseAllJob", (cmd, args) => { return CheckToPostMessage((int)MSG.PauseAllJobs); }) ;
  338. OP.Subscribe("System.ResumeAllJob", (cmd, args) => { return CheckToPostMessage((int)MSG.ResumeAllJobs); });
  339. OP.Subscribe("System.StopJob", (string cmd, object[] args) =>
  340. {
  341. return CheckToPostMessage((int)MSG.StopJob, args[0]);
  342. });
  343. OP.Subscribe("System.AbortJob", (string cmd, object[] args) =>
  344. {
  345. return CheckToPostMessage((int)MSG.AbortJob, args[0]);
  346. });
  347. OP.Subscribe(RtOperation.SetConfig.ToString(), (name, args) =>
  348. {
  349. string sc_key = args[0] as string;
  350. if (!string.IsNullOrWhiteSpace(sc_key) && args.Length > 1)
  351. {
  352. SC.SetItemValue(sc_key, args[1]);
  353. }
  354. return true;
  355. });
  356. OP.Subscribe("System.ResetIdleCleanTime", (string cmd, object[] args) =>
  357. {
  358. return CheckToPostMessage((int)MSG.ResetIdleCleanTime, args[0]);
  359. });
  360. OP.Subscribe("System.ResetIdlePurgeTime", (string cmd, object[] args) =>
  361. {
  362. return CheckToPostMessage((int)MSG.ResetIdlePurgeTime, args[0]);
  363. });
  364. OP.Subscribe("System.SetWaferSize", (string cmd, object[] args) =>
  365. {
  366. string module = (string)args[0];
  367. string size = (string)args[1];
  368. switch (size)
  369. {
  370. case "3":
  371. WaferManager.Instance.UpdateWaferSize(ModuleHelper.Converter(module), 0, WaferSize.WS3);
  372. break;
  373. case "4":
  374. WaferManager.Instance.UpdateWaferSize(ModuleHelper.Converter(module), 0, WaferSize.WS4);
  375. break;
  376. case "6":
  377. WaferManager.Instance.UpdateWaferSize(ModuleHelper.Converter(module), 0, WaferSize.WS6);
  378. break;
  379. default:
  380. EV.PostWarningLog("System", $"wafer size {size} not valid");
  381. break;
  382. }
  383. return true;
  384. });
  385. //OP.Subscribe("System.CassetteLeave", (string cmd, object[] args) =>
  386. //{
  387. // return CheckToPostMessage((int)MSG.CassetteLeave);
  388. //});
  389. OP.Subscribe("System.Retry", (string cmd, object[] args) =>
  390. {
  391. return CheckToPostMessage((int)MSG.Retry, args[0]);
  392. });
  393. OP.Subscribe("System.ConfirmComplete", (string cmd, object[] args) =>
  394. {
  395. return CheckToPostMessage((int)MSG.ConfirmComplete, args[0]);
  396. });
  397. OP.Subscribe("WaferHolder.ResetLayoutWafers", (string cmd, object[] args) =>
  398. {
  399. return CheckToPostMessage((int)MSG.ResetWafers, args);
  400. });
  401. }
  402. /// <summary>
  403. /// 申请系统控制权
  404. /// </summary>
  405. /// <param name="cmd"></param>
  406. /// <param name="args"></param>
  407. /// <returns></returns>
  408. private bool ApplySystemControl(string cmd, object[] args)
  409. {
  410. if (args[0].ToString() == "")
  411. {
  412. LOG.WriteLog(eEvent.WARN_ROUTER, "System", $"Current IP does not allow the application of UI control permissions");
  413. return false;
  414. }
  415. string applyIp = args[0].ToString();
  416. if (string.IsNullOrEmpty(_systemControlIp))
  417. {
  418. _systemControlIp = applyIp;
  419. LOG.WriteLog(eEvent.EV_ROUTER, "System", $"{_systemControlIp} apply system control success");
  420. return true;
  421. }
  422. else if(_systemControlIp!=applyIp)
  423. {
  424. LOG.WriteLog(eEvent.WARN_ROUTER, "System", $"{_systemControlIp} already has system control permission");
  425. return false;
  426. }
  427. return false;
  428. }
  429. /// <summary>
  430. /// 释放系统控制权
  431. /// </summary>
  432. /// <param name="cmd"></param>
  433. /// <param name="args"></param>
  434. /// <returns></returns>
  435. private bool ReleaseSystemControl(string cmd, object[] args)
  436. {
  437. string releaseIp = args[0].ToString();
  438. if (_systemControlIp == releaseIp)
  439. {
  440. LOG.WriteLog(eEvent.EV_ROUTER, "System", $"{releaseIp} release system control success");
  441. _systemControlIp = "";
  442. }
  443. else
  444. {
  445. LOG.WriteLog(eEvent.ERR_ROUTER, "System", $"{releaseIp} is not SystemControlIp");
  446. }
  447. return false;
  448. }
  449. /// <summary>
  450. /// 检验Secsgem在线情况
  451. /// </summary>
  452. /// <param name="controlState"></param>
  453. /// <returns></returns>
  454. private bool CheckSecsGemOnline(SecsGem.Core.EnumData.ControlState controlState)
  455. {
  456. if (controlState == SecsGem.Core.EnumData.ControlState.OnlineLocal || controlState == SecsGem.Core.EnumData.ControlState.OnlineRemote)
  457. {
  458. return true;
  459. }
  460. return false;
  461. }
  462. public bool CheckToPostMessage(int msg, params object[] args)
  463. {
  464. if (!fsm.FindTransition(fsm.State, msg))
  465. {
  466. LOG.Write(eEvent.WARN_ROUTER, ModuleName.System, $"System is in {(RtState)fsm.State} state,can not do {(MSG)msg}");
  467. return false;
  468. }
  469. Running = true;
  470. fsm.PostMsg(msg, args);
  471. return true;
  472. }
  473. private bool InvokeCreateWafer(string arg1, object[] args)
  474. {
  475. ModuleName chamber = ModuleHelper.Converter(args[0].ToString());
  476. int slot = (int)args[1];
  477. WaferStatus state = WaferStatus.Normal;
  478. if (WaferManager.Instance.IsWaferSlotLocationValid(chamber, slot))
  479. {
  480. if (WaferManager.Instance.CheckHasWafer(chamber, slot))
  481. {
  482. LOG.Write(eEvent.EV_ROUTER, "System", string.Format("{0} slot {1} already has wafer.create wafer is not valid", chamber, slot));
  483. }
  484. else if (WaferManager.Instance.CreateWafer(chamber, slot, state) != null)
  485. {
  486. LOG.Write(eEvent.EV_WAFER_CREATE, ModuleName.System, chamber.ToString(), (slot + 1).ToString(), state.ToString());
  487. }
  488. }
  489. else
  490. {
  491. LOG.Write(eEvent.WARN_ROUTER, "System", string.Format("Invalid position,{0},{1}", chamber.ToString(), slot.ToString()));
  492. return false;
  493. }
  494. return true;
  495. }
  496. private bool InvokeDeleteWafer(string arg1, object[] args)
  497. {
  498. ModuleName chamber = ModuleHelper.Converter(args[0].ToString());
  499. int slot = (int)args[1];
  500. if (WaferManager.Instance.IsWaferSlotLocationValid(chamber, slot))
  501. {
  502. if (WaferManager.Instance.CheckHasWafer(chamber, slot))
  503. {
  504. WaferManager.Instance.DeleteWafer(chamber, slot);
  505. EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferDelete, chamber.ToString(), slot + 1);
  506. }
  507. else
  508. {
  509. LOG.Write(eEvent.EV_ROUTER, "System", string.Format("No wafer at {0} {1}, delete not valid", chamber.ToString(), slot + 1));
  510. }
  511. }
  512. else
  513. {
  514. LOG.Write(eEvent.WARN_ROUTER, "System", string.Format("Invalid position,{0},{1}", chamber.ToString(), slot.ToString()));
  515. return false;
  516. }
  517. return true;
  518. }
  519. private bool InvokeReturnWafer(string arg1, object[] args)
  520. {
  521. ModuleName target = ModuleHelper.Converter(args[0].ToString());
  522. int slot = (int)args[1];
  523. if (ModuleHelper.IsLoadPort(target))
  524. {
  525. LOG.Write(eEvent.WARN_ROUTER, "System", string.Format("Wafer already at LoadPort {0} {1}, return operation is not valid", target.ToString(), slot + 1));
  526. return false;
  527. }
  528. if (!WaferManager.Instance.IsWaferSlotLocationValid(target, slot))
  529. {
  530. LOG.Write(eEvent.WARN_ROUTER, "System", string.Format("Invalid position,{0},{1}", target.ToString(), slot.ToString()));
  531. return false;
  532. }
  533. WaferInfo wafer = WaferManager.Instance.GetWafer(target, slot);
  534. if (wafer.IsEmpty)
  535. {
  536. LOG.Write(eEvent.WARN_ROUTER, "System", string.Format("No wafer at {0} {1}, return operation is not valid", target.ToString(), slot + 1));
  537. return false;
  538. }
  539. return CheckToPostMessage((int)MSG.MoveWafer,
  540. target, slot,
  541. (ModuleName)wafer.OriginStation, wafer.OriginSlot,
  542. false, 0, false, 0, "Blade1");
  543. }
  544. protected override bool Init()
  545. {
  546. _jobCycle = new JobDispatcher();
  547. Singleton<FaRemoteManager>.Instance.JobCycle = _jobCycle;
  548. _homeAllRoutine = new ModuleHomeAllRoutine("System");
  549. BuildTransitionTable();
  550. return true;
  551. }
  552. private void BuildTransitionTable()
  553. {
  554. //Init sequence
  555. Transition(RtState.Init, MSG.HOME, FsmStartHome, RtState.Initializing);
  556. Transition(RtState.Idle, MSG.HOME, FsmStartHome, RtState.Initializing);
  557. Transition(RtState.Error, MSG.HOME, FsmStartHome, RtState.Initializing);
  558. EnterExitTransition<RtState, FSM_MSG>(RtState.AutoRunning, FsmEnterAutoRunning, FSM_MSG.NONE, FsmExitAutoTransfer);
  559. EnterExitTransition<RtState, FSM_MSG>(RtState.Transfer, null, FSM_MSG.NONE, FsmExitTransfer);
  560. EnterExitTransition<RtState, FSM_MSG>(RtState.ReturnWafer, null, FSM_MSG.NONE, FsmExitReturnWafer);
  561. AnyStateTransition(MSG.ERROR, FsmError, RtState.Error);
  562. Transition(RtState.Idle, FSM_MSG.TIMER, FsmMonitor, RtState.Idle);
  563. Transition(RtState.Init, FSM_MSG.TIMER, FsmMonitor, RtState.Init);
  564. Transition(RtState.Init, MSG.ABORT, FsmAbort, RtState.Init);
  565. Transition(RtState.Error, MSG.ABORT, FsmAbort, RtState.Init);
  566. Transition(RtState.Idle, MSG.ABORT, FsmAbort, RtState.Idle);
  567. Transition(RtState.Initializing, MSG.ABORT, FsmAbort, RtState.Init);
  568. Transition(RtState.Initializing, FSM_MSG.TIMER, FsmMonitorHome, RtState.Idle);
  569. Transition(RtState.Initializing, MSG.ERROR, FsmError, RtState.Error);
  570. //Auto/manual
  571. Transition(RtState.Idle, MSG.SetAutoMode, FsmStartAutoTransfer, RtState.AutoIdle);
  572. Transition(RtState.AutoAborting, FSM_MSG.TIMER, FsmAutoTransfer, RtState.AutoIdle);
  573. Transition(RtState.AutoRunning, FSM_MSG.TIMER, FsmAutoTransfer, RtState.AutoIdle);
  574. Transition(RtState.AutoRunning, MSG.ABORT, FsmAbort, RtState.AutoAborting);
  575. Transition(RtState.AutoAborting, MSG.SetManualMode, FsmStartAbortingSetManualMode, RtState.Idle);
  576. //Transition(RtState.AutoRunning, MSG.SetManualMode, FsmStartSetManualMode, RtState.Idle);
  577. Transition(RtState.AutoRunning, MSG.JobDone, FsmJobDone, RtState.AutoIdle);
  578. //Transition(RtState.AutoRunning, MSG.CassetteLeave, fCassetteLeave, RtState.AutoRunning); //For unload light control off afer job done
  579. Transition(RtState.AutoRunning, MSG.CreateJob, FsmCreateJob, RtState.AutoRunning);
  580. Transition(RtState.AutoRunning, MSG.StartJob, FsmStartJob, RtState.AutoRunning);
  581. Transition(RtState.AutoRunning, MSG.PauseJob, FsmPauseJob, RtState.AutoRunning);
  582. Transition(RtState.AutoRunning, MSG.PauseAllJobs, FsmPauseAllJobs, RtState.AutoRunning);
  583. Transition(RtState.AutoRunning, MSG.ResumeJob, FsmResumeJob, RtState.AutoRunning);
  584. Transition(RtState.AutoRunning, MSG.ResumeAllJobs, FsmResumeAllJobs, RtState.AutoRunning);
  585. Transition(RtState.AutoRunning, MSG.StopJob, FsmStopJob, RtState.AutoRunning);
  586. Transition(RtState.AutoRunning, MSG.Retry, FsmRetry, RtState.AutoRunning);
  587. Transition(RtState.AutoRunning, MSG.ConfirmComplete, FsmConfirmComplete, RtState.AutoRunning);
  588. Transition(RtState.AutoIdle, FSM_MSG.TIMER, FsmMonitorAutoIdle, RtState.AutoIdle);
  589. Transition(RtState.AutoIdle, MSG.SetManualMode, FsmStartSetManualMode, RtState.Idle);
  590. Transition(RtState.AutoIdle, MSG.CreateJob, FsmCreateJob, RtState.AutoIdle);
  591. Transition(RtState.AutoIdle, MSG.StartJob, FsmStartJob, RtState.AutoRunning);
  592. Transition(RtState.AutoIdle, MSG.PauseJob, FsmPauseJob, RtState.AutoIdle);
  593. Transition(RtState.AutoIdle, MSG.PauseAllJobs, FsmPauseAllJobs, RtState.AutoIdle);
  594. Transition(RtState.AutoIdle, MSG.ResumeJob, FsmResumeJob, RtState.AutoIdle);
  595. Transition(RtState.AutoIdle, MSG.ResumeAllJobs, FsmResumeAllJobs, RtState.AutoIdle);
  596. Transition(RtState.AutoIdle, MSG.StopJob, FsmStopJob, RtState.AutoIdle);
  597. Transition(RtState.AutoIdle, MSG.FaStartJob, FsmEnterAutoRunning, RtState.AutoRunning);
  598. Transition(RtState.AutoRunning, MSG.FaStartJob, FsmEnterAutoRunning, RtState.AutoRunning);
  599. Transition(RtState.AutoIdle, MSG.ResetWafers, ResetWafers, RtState.AutoIdle);
  600. Transition(RtState.Idle, MSG.ResetWafers, ResetWafers, RtState.Idle);
  601. Transition(RtState.Init, MSG.ResetWafers, ResetWafers, RtState.Init);
  602. }
  603. private bool FsmMonitor(object[] objs)
  604. {
  605. return true;
  606. }
  607. /// <summary>
  608. /// 检验前置条件
  609. /// </summary>
  610. /// <returns></returns>
  611. private bool CheckPreCondition()
  612. {
  613. if (ModuleHelper.IsInstalled(ModuleName.PUF1))
  614. {
  615. PufVacuum pufVacuum = DEVICE.GetDevice<PufVacuum>($"{ModuleName.PUF1}.Vacuum");
  616. if (!pufVacuum.IsChuckAReleased || !pufVacuum.ISChuckBReleased)
  617. {
  618. LOG.WriteLog(eEvent.ERR_AXIS, ModuleName.PUF1.ToString(), "Vacuum is on");
  619. return false;
  620. }
  621. }
  622. if (ModuleHelper.IsInstalled(ModuleName.Loader1))
  623. {
  624. LoaderSideDevice loaderSideADevice = DEVICE.GetDevice<LoaderSideDevice>($"{ModuleName.Loader1}.SideA");
  625. LoaderSideDevice loaderSideBDevice = DEVICE.GetDevice<LoaderSideDevice>($"{ModuleName.Loader1}.SideB");
  626. if (loaderSideADevice.SideData.CRSVacuum || loaderSideBDevice.SideData.CRSVacuum)
  627. {
  628. LOG.WriteLog(eEvent.ERR_AXIS, ModuleName.Loader1.ToString(), "Vacuum is on");
  629. return false;
  630. }
  631. }
  632. if (ModuleHelper.IsInstalled(ModuleName.SRD1))
  633. {
  634. SrdCommonDevice srdCommonDevice = DEVICE.GetDevice<SrdCommonDevice>($"{ModuleName.SRD1}.Common");
  635. if (!srdCommonDevice.CommonData.ChuckVacuum)
  636. {
  637. LOG.WriteLog(eEvent.ERR_AXIS, ModuleName.SRD1.ToString(), "Vacuum is on");
  638. return false;
  639. }
  640. }
  641. if (ModuleHelper.IsInstalled(ModuleName.SRD2))
  642. {
  643. SrdCommonDevice srdCommonDevice = DEVICE.GetDevice<SrdCommonDevice>($"{ModuleName.SRD2}.Common");
  644. if (!srdCommonDevice.CommonData.ChuckVacuum)
  645. {
  646. LOG.WriteLog(eEvent.ERR_AXIS, ModuleName.SRD2.ToString(), "Vacuum is on");
  647. return false;
  648. }
  649. }
  650. return true;
  651. }
  652. private bool FsmStartHome(object[] objs)
  653. {
  654. if (!CheckPreCondition())
  655. {
  656. return false;
  657. }
  658. List<string> keys = _moduleEntitiesDic.Keys.ToList();
  659. foreach (string item in keys)
  660. {
  661. if (!NeedSequenceHome(item))
  662. {
  663. IModuleEntity entity = _moduleEntitiesDic[item];
  664. if (!entity.IsDisable)
  665. {
  666. entity.Invoke("HomeAll");
  667. }
  668. }
  669. }
  670. _homeAllRoutine.Start();
  671. _reservoirMetalRoutines.Clear();
  672. foreach (string item in keys)
  673. {
  674. if (Enum.TryParse(item, out ModuleName moduleName))
  675. {
  676. if (ModuleHelper.IsReservoir(moduleName))
  677. {
  678. IModuleEntity moduleEntity = _moduleEntitiesDic[item];
  679. if (!moduleEntity.IsDisable)
  680. {
  681. ReservoirMetalHomeRoutine reservoirMetalHomeRoutine = new ReservoirMetalHomeRoutine(item);
  682. _reservoirMetalRoutines.Add(reservoirMetalHomeRoutine);
  683. }
  684. }
  685. }
  686. }
  687. foreach (ReservoirMetalHomeRoutine item in _reservoirMetalRoutines)
  688. {
  689. item.Start();
  690. }
  691. _homeStopWatch.Restart();
  692. _jobCycle.RemoveAllJob();
  693. return true;
  694. }
  695. /// <summary>
  696. /// 需要按照顺序Home
  697. /// </summary>
  698. /// <returns></returns>
  699. private bool NeedSequenceHome(string item)
  700. {
  701. bool result = item == ModuleName.PUF1.ToString() || item == ModuleName.Loader1.ToString() ||
  702. item == ModuleName.Transporter2.ToString() || item == ModuleName.Transporter1.ToString();
  703. if (result)
  704. {
  705. return true;
  706. }
  707. else
  708. {
  709. if(Enum.TryParse(item,out ModuleName moduleName))
  710. {
  711. if (!ModuleHelper.IsMetal(moduleName)&&!ModuleHelper.IsReservoir(moduleName))
  712. {
  713. return false;
  714. }
  715. }
  716. return true;
  717. }
  718. }
  719. private bool FsmMonitorHome(object[] objs)
  720. {
  721. RState rstate = _homeAllRoutine.Monitor();
  722. if (_homeStopWatch.ElapsedMilliseconds <= 500)
  723. {
  724. return false;
  725. }
  726. if (rstate == RState.Failed || rstate == RState.Timeout)
  727. {
  728. PostMsg(MSG.ERROR);
  729. return false;
  730. }
  731. List<string> keys = LoadInitializeCheckModuleList();
  732. int idleCount = 0;
  733. foreach (string item in keys)
  734. {
  735. IModuleEntity ModuleEntity = _moduleEntitiesDic[item];
  736. if (ModuleEntity.IsError && !NeedSequenceHome(item))
  737. {
  738. LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"{ModuleEntity.Module} home error");
  739. PostMsg(MSG.ERROR);
  740. return true;
  741. }
  742. else if (ModuleEntity.IsIdle)
  743. {
  744. idleCount++;
  745. }
  746. }
  747. int homeCount = 0;
  748. foreach (ReservoirMetalHomeRoutine item in _reservoirMetalRoutines)
  749. {
  750. RState ret = item.Monitor();
  751. if (ret != RState.Running)
  752. {
  753. homeCount++;
  754. }
  755. }
  756. if (homeCount != _reservoirMetalRoutines.Count)
  757. {
  758. return false;
  759. }
  760. if (idleCount == keys.Count)
  761. {
  762. return true;
  763. }
  764. else
  765. {
  766. return false;
  767. }
  768. }
  769. /// <summary>
  770. /// 加载初始化检验模块集合
  771. /// </summary>
  772. /// <returns></returns>
  773. private List<string> LoadInitializeCheckModuleList()
  774. {
  775. string checkModuleList = SC.GetStringValue("System.InitializeCheckModuleList");
  776. List<string> moduleList= checkModuleList.Split(',').ToList();
  777. List<string> modules = new List<string>();
  778. foreach (var item in moduleList)
  779. {
  780. if(Enum.TryParse(item, out ModuleName moduleName))
  781. {
  782. if (ModuleHelper.IsInstalled(moduleName))
  783. {
  784. modules.Add(item);
  785. }
  786. }
  787. }
  788. return modules;
  789. }
  790. private bool FsmEnterAutoRunning(object[] objs)
  791. {
  792. return true;
  793. }
  794. private bool FsmExitAutoTransfer(object[] objs)
  795. {
  796. _jobCycle.Clear();
  797. return true;
  798. }
  799. private bool FsmExitTransfer(object[] objs)
  800. {
  801. return true;
  802. }
  803. private bool FsmExitReturnWafer(object[] objs)
  804. {
  805. return true;
  806. }
  807. private bool FsmError(object[] objs)
  808. {
  809. return true;
  810. }
  811. private bool FsmAbort(object[] objs)
  812. {
  813. //_manualTransfer.Clear();
  814. //_returnWafer.Clear();
  815. //_jobCycle.Clear();
  816. AlarmListManager.Instance.ClearAllAlarm();
  817. return _jobCycle.SystemAbort();
  818. }
  819. private bool FsmStartAutoTransfer(object[] objs)
  820. {
  821. return _jobCycle.Start(objs) == RState.Running;
  822. }
  823. private bool FsmAutoTransfer(object[] objs)
  824. {
  825. if (_jobCycle.CheckJobJustDone(out string jobInfo))
  826. {
  827. //EV.PostPopDialogMessage(EventLevel.InformationNoDelay, "Job complete", jobInfo);
  828. LOG.Write(eEvent.EV_ROUTER, ModuleName.System, $"Job complete,{jobInfo}");
  829. }
  830. if (_jobCycle.CheckAllJobDone())
  831. {
  832. if (!CheckToPostMessage((int)MSG.JobDone))
  833. return false;
  834. }
  835. RState ret = _jobCycle.Monitor();
  836. if (ret == RState.Failed)
  837. {
  838. if (!CheckToPostMessage((int)MSG.ERROR))
  839. return false;
  840. }
  841. return ret == RState.End;
  842. }
  843. private bool FsmAbortAutoTransfer(object[] objs)
  844. {
  845. _jobCycle.Clear();
  846. return true;
  847. }
  848. private bool FsmJobDone(object[] objs)
  849. {
  850. return true;
  851. }
  852. private bool FsmCreateJob(object[] objs)
  853. {
  854. return _jobCycle.CreateJob((Dictionary<string, object>)objs[0],out string reason);
  855. }
  856. private bool FsmStartJob(object[] objs)
  857. {
  858. bool result = CheckPMCounter();
  859. if (!result)
  860. {
  861. return false;
  862. }
  863. return _jobCycle.StartJob((string)objs[0],out string reason);
  864. }
  865. /// <summary>
  866. /// 检查PM counter
  867. /// </summary>
  868. /// <returns></returns>
  869. private bool CheckPMCounter()
  870. {
  871. bool result = false;
  872. foreach (string item in ReservoirItemManager.Instance.InstalledModules)
  873. {
  874. result = ReservoirUsageMonitor(item);
  875. if (!result)
  876. {
  877. return false;
  878. }
  879. }
  880. foreach (string item in MetalItemManager.Instance.InstalledModules)
  881. {
  882. result = MetalUsageMointor(item);
  883. if (!result)
  884. {
  885. return false;
  886. }
  887. }
  888. return true;
  889. }
  890. private bool FsmPauseJob(object[] objs)
  891. {
  892. return _jobCycle.PauseJob((string)objs[0],out string reason);
  893. }
  894. private bool FsmResumeJob(object[] objs)
  895. {
  896. return _jobCycle.ResumeJob((string)objs[0],out string reason);
  897. }
  898. private bool FsmPauseAllJobs(object[] objs)
  899. {
  900. return _jobCycle.PauseAllJobs();
  901. }
  902. private bool FsmResumeAllJobs(object[] objs)
  903. {
  904. return _jobCycle.ResumeAllJobs();
  905. }
  906. private bool FsmStopJob(object[] objs)
  907. {
  908. return _jobCycle.StopJob((string)objs[0], out string reason);
  909. }
  910. /// <summary>
  911. /// 重试
  912. /// </summary>
  913. /// <param name="objs"></param>
  914. /// <returns></returns>
  915. private bool FsmRetry(object[] objs)
  916. {
  917. string moduleName = objs[0].ToString();
  918. IModuleEntity moduleEntity = GetModule<IModuleEntity>(moduleName);
  919. moduleEntity.Invoke("Retry");
  920. return true;
  921. }
  922. /// <summary>
  923. /// 重试
  924. /// </summary>
  925. /// <param name="objs"></param>
  926. /// <returns></returns>
  927. private bool FsmConfirmComplete(object[] objs)
  928. {
  929. string moduleName = objs[0].ToString();
  930. IModuleEntity moduleEntity = GetModule<IModuleEntity>(moduleName);
  931. moduleEntity.Invoke("ConfirmComplete");
  932. return true;
  933. }
  934. private bool FsmMonitorAutoIdle(object[] objs)
  935. {
  936. RState ret = _jobCycle.Monitor();
  937. return ret == RState.End;
  938. }
  939. private bool FsmStartAbortingSetManualMode(object[] objs)
  940. {
  941. return _jobCycle.RemoveAllJob();
  942. }
  943. private bool FsmStartSetManualMode(object[] objs)
  944. {
  945. if (_jobCycle.HasJobRunning)
  946. {
  947. LOG.Write(eEvent.WARN_ROUTER, "System", "Can not change to manual mode, abort running job first");
  948. return false;
  949. }
  950. return true;
  951. }
  952. /// <summary>
  953. /// 重置Wafers
  954. /// </summary>
  955. /// <param name="objs"></param>
  956. /// <returns></returns>
  957. private bool ResetWafers(object[] objs)
  958. {
  959. return WaferHolderManager.Instance.ResetLayoutWafers();
  960. }
  961. /// <summary>
  962. /// 获取模块对象
  963. /// </summary>
  964. /// <typeparam name="T"></typeparam>
  965. /// <param name="name"></param>
  966. /// <returns></returns>
  967. public T GetModule<T>(string name) where T : class, IModuleEntity
  968. {
  969. return _moduleEntitiesDic.ContainsKey(name)?_moduleEntitiesDic[name] as T:default(T);
  970. }
  971. /// <summary>
  972. /// 根据模块类型获取模块集合
  973. /// </summary>
  974. /// <param name="type"></param>
  975. /// <returns></returns>
  976. public List<IModuleEntity> GetModulesByModuleType(ModuleType type)
  977. {
  978. return _modultTypeEntitiesDic.ContainsKey(type) ? _modultTypeEntitiesDic[type] : new List<IModuleEntity>();
  979. }
  980. /// <summary>
  981. /// 监控PM Counter Reservoir Usage
  982. /// </summary>
  983. public bool ReservoirUsageMonitor(string Module)
  984. {
  985. ReservoirUsage reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(Module);
  986. ReservoirEntity reservoirEntity = Singleton<RouteManager>.Instance.GetModule<ReservoirEntity>(Module);
  987. if (reservoirUsage == null || reservoirEntity == null) return true;
  988. //reservoirTotalAmpHours Check
  989. double reservoirTotalAmpHoursWarningLimit = 0;
  990. if (SC.ContainsItem($"Reservoir.{Module}.ReservoirTotalAmpHoursWarningLimit"))
  991. {
  992. reservoirTotalAmpHoursWarningLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.ReservoirTotalAmpHoursWarningLimit");
  993. }
  994. double reservoirTotalAmpHoursFaultLimit = 0;
  995. if (SC.ContainsItem($"Reservoir.{Module}.ReservoirTotalAmpHoursFaultLimit"))
  996. {
  997. reservoirTotalAmpHoursFaultLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.ReservoirTotalAmpHoursFaultLimit");
  998. }
  999. if (reservoirUsage.TotalUsage > reservoirTotalAmpHoursFaultLimit && reservoirTotalAmpHoursFaultLimit != 0)
  1000. {
  1001. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Total Usage(AHr):{reservoirUsage.TotalUsage} is over config item ReservoirTotalAmpHoursFaultLimit:{reservoirTotalAmpHoursFaultLimit}");
  1002. return false;
  1003. }
  1004. else if (reservoirUsage.TotalUsage > reservoirTotalAmpHoursWarningLimit && reservoirTotalAmpHoursWarningLimit != 0)
  1005. {
  1006. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Total Usage(AHr):{reservoirUsage.TotalUsage} is over config item ReservoirTotalAmpHoursWarningLimit:{reservoirTotalAmpHoursWarningLimit}");
  1007. }
  1008. //MembraneTotalAmpHoursCheck
  1009. double membraneTotalAmpHoursWarningLimit = 0;
  1010. if (SC.ContainsItem($"Reservoir.{Module}.MembraneTotalAmpHoursWarningLimit"))
  1011. {
  1012. membraneTotalAmpHoursWarningLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.MembraneTotalAmpHoursWarningLimit");
  1013. }
  1014. double membraneTotalAmpHoursFaultLimit = 0;
  1015. if (SC.ContainsItem($"Reservoir.{Module}.MembraneTotalAmpHoursFaultLimit"))
  1016. {
  1017. membraneTotalAmpHoursFaultLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.MembraneTotalAmpHoursFaultLimit");
  1018. }
  1019. if (reservoirUsage.MembranceUsage > membraneTotalAmpHoursFaultLimit && membraneTotalAmpHoursFaultLimit != 0)
  1020. {
  1021. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Membrane Usage(AHr):{reservoirUsage.MembranceUsage} is over config item MembraneTotalAmpHoursFaultLimit:{membraneTotalAmpHoursFaultLimit}");
  1022. return false;
  1023. }
  1024. else if (reservoirUsage.MembranceUsage > membraneTotalAmpHoursWarningLimit && membraneTotalAmpHoursWarningLimit != 0)
  1025. {
  1026. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Membrane Usage(AHr):{reservoirUsage.MembranceUsage} is over config item MembraneTotalAmpHoursWarningLimit:{membraneTotalAmpHoursWarningLimit}");
  1027. }
  1028. double bathTotalAmpHoursWarningLimit = 0;
  1029. if (SC.ContainsItem($"Reservoir.{Module}.BathTotalAmpHoursWarningLimit"))
  1030. {
  1031. bathTotalAmpHoursWarningLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.BathTotalAmpHoursWarningLimit");
  1032. }
  1033. double bathTotalAmpHoursFaultLimit = 0;
  1034. if (SC.ContainsItem($"Reservoir.{Module}.BathTotalAmpHoursFaultLimit"))
  1035. {
  1036. bathTotalAmpHoursFaultLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.BathTotalAmpHoursFaultLimit");
  1037. }
  1038. if (reservoirUsage.BathUsage > bathTotalAmpHoursFaultLimit && bathTotalAmpHoursFaultLimit != 0)
  1039. {
  1040. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Bath Usage(AHr):{reservoirUsage.BathUsage} is over config item BathTotalAmpHoursFaultLimit:{bathTotalAmpHoursFaultLimit}");
  1041. return false;
  1042. }
  1043. else if (reservoirUsage.BathUsage > bathTotalAmpHoursWarningLimit && bathTotalAmpHoursWarningLimit != 0)
  1044. {
  1045. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Bath Usage(AHr):{reservoirUsage.BathUsage} is over config item BathTotalAmpHoursWarningLimit:{bathTotalAmpHoursWarningLimit}");
  1046. }
  1047. //BathTotalDaysCheck
  1048. int bathTotalDaysWarningLimit = 0;
  1049. if (SC.ContainsItem($"Reservoir.{Module}.BathTotalDaysWarningLimit"))
  1050. {
  1051. bathTotalDaysWarningLimit = SC.GetValue<int>($"Reservoir.{Module}.BathTotalDaysWarningLimit");
  1052. }
  1053. int bathTotalDaysFaultLimit = 0;
  1054. if (SC.ContainsItem($"Reservoir.{Module}.BathTotalDaysFaultLimit"))
  1055. {
  1056. bathTotalDaysFaultLimit = SC.GetValue<int>($"Reservoir.{Module}.BathTotalDaysFaultLimit");
  1057. }
  1058. if (reservoirUsage.BathUsageDays > bathTotalDaysFaultLimit && bathTotalDaysFaultLimit != 0)
  1059. {
  1060. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Bath Usage(Days):{reservoirUsage.BathUsageDays} is over config item BathTotalDaysFaultLimit:{bathTotalDaysFaultLimit}");
  1061. return false;
  1062. }
  1063. else if (reservoirUsage.BathUsageDays > bathTotalDaysWarningLimit && bathTotalDaysWarningLimit != 0)
  1064. {
  1065. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Bath Usage(Days):{reservoirUsage.BathUsageDays} is over config item BathTotalDaysWarningLimit:{bathTotalDaysWarningLimit}");
  1066. }
  1067. //ReservoirTotalWafersCheck
  1068. int reservoirTotalWafersWarningLimit = 0;
  1069. if (SC.ContainsItem($"Reservoir.{Module}.ReservoirTotalWafersWarningLimit"))
  1070. {
  1071. reservoirTotalWafersWarningLimit = SC.GetValue<int>($"Reservoir.{Module}.ReservoirTotalWafersWarningLimit");
  1072. }
  1073. int reservoirTotalWafersFaultLimit = 0;
  1074. if (SC.ContainsItem($"Reservoir.{Module}.ReservoirTotalWafersFaultLimit"))
  1075. {
  1076. reservoirTotalWafersFaultLimit = SC.GetValue<int>($"Reservoir.{Module}.ReservoirTotalWafersFaultLimit");
  1077. }
  1078. if (reservoirUsage.TotalWafers > reservoirTotalWafersFaultLimit && reservoirTotalWafersFaultLimit != 0)
  1079. {
  1080. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} Total Wafers:{reservoirUsage.TotalWafers} is over config item ReservoirTotalWafersFaultLimit:{reservoirTotalWafersFaultLimit}");
  1081. return false;
  1082. }
  1083. else if (reservoirUsage.TotalWafers > reservoirTotalWafersWarningLimit && reservoirTotalWafersWarningLimit != 0)
  1084. {
  1085. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} Total Wafers:{reservoirUsage.TotalWafers} is over config item ReservoirTotalWafersWarningLimit:{reservoirTotalWafersWarningLimit}");
  1086. }
  1087. //CMMAnodeTotalAmpHoursCheck
  1088. double cmmAnodeTotalAmpHoursWarningLimit = 0;
  1089. if (SC.ContainsItem($"Reservoir.{Module}.CMMAnodeTotalAmpHoursWarningLimit"))
  1090. {
  1091. cmmAnodeTotalAmpHoursWarningLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.CMMAnodeTotalAmpHoursWarningLimit");
  1092. }
  1093. double cmmAnodeTotalAmpHoursFaultLimit = 0;
  1094. if (SC.ContainsItem($"Reservoir.{Module}.CMMAnodeTotalAmpHoursFaultLimit"))
  1095. {
  1096. cmmAnodeTotalAmpHoursFaultLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.CMMAnodeTotalAmpHoursFaultLimit");
  1097. }
  1098. if (reservoirUsage.CMMAnodeUsage > cmmAnodeTotalAmpHoursFaultLimit && cmmAnodeTotalAmpHoursFaultLimit != 0)
  1099. {
  1100. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} CMM Anode Usage(AHr):{reservoirUsage.CMMAnodeUsage} is over config item CMMAnodeTotalAmpHoursFaultLimit:{cmmAnodeTotalAmpHoursFaultLimit}");
  1101. return false;
  1102. }
  1103. else if (reservoirUsage.CMMAnodeUsage > cmmAnodeTotalAmpHoursWarningLimit && cmmAnodeTotalAmpHoursWarningLimit != 0)
  1104. {
  1105. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} CMM Anode Usage(AHr):{reservoirUsage.CMMAnodeUsage} is over config item CMMAnodeTotalAmpHoursWarningLimit:{cmmAnodeTotalAmpHoursWarningLimit}");
  1106. }
  1107. //CMMCathodeTotalAmpHoursCheck
  1108. double cmmCathodeTotalAmpHoursWarningLimit = 0;
  1109. if (SC.ContainsItem($"Reservoir.{Module}.CMMCathodeTotalAmpHoursWarningLimit"))
  1110. {
  1111. cmmCathodeTotalAmpHoursWarningLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.CMMCathodeTotalAmpHoursWarningLimit");
  1112. }
  1113. double cmmCathodeTotalAmpHoursFaultLimit = 0;
  1114. if (SC.ContainsItem($"Reservoir.{Module}.CMMCathodeTotalAmpHoursFaultLimit"))
  1115. {
  1116. cmmCathodeTotalAmpHoursFaultLimit = (double)SC.GetValue<double>($"Reservoir.{Module}.CMMCathodeTotalAmpHoursFaultLimit");
  1117. }
  1118. if (reservoirUsage.CMMMembranceUsage > cmmCathodeTotalAmpHoursFaultLimit && cmmCathodeTotalAmpHoursFaultLimit != 0)
  1119. {
  1120. LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"{Module} CMM Cathode Usage(AHr):{reservoirUsage.CMMMembranceUsage} is over config item CMMCathodeTotalAmpHoursFaultLimit:{cmmCathodeTotalAmpHoursFaultLimit}");
  1121. return false;
  1122. }
  1123. else if (reservoirUsage.CMMMembranceUsage > cmmCathodeTotalAmpHoursWarningLimit && cmmCathodeTotalAmpHoursWarningLimit != 0)
  1124. {
  1125. LOG.WriteLog(eEvent.WARN_RESERVOIR, Module, $"{Module} CMM Cathode Usage(AHr):{reservoirUsage.CMMMembranceUsage} is over config item CMMCathodeTotalAmpHoursWarningLimit:{cmmCathodeTotalAmpHoursWarningLimit}");
  1126. }
  1127. return true;
  1128. }
  1129. /// <summary>
  1130. /// 监控 PM Counter Metal用量
  1131. /// </summary>
  1132. private bool MetalUsageMointor(string Module)
  1133. {
  1134. MetalUsage metalUsage = MetalUsageManager.Instance.GetMetalUsage(Module);
  1135. if (metalUsage != null)
  1136. {
  1137. //TotalAUsage
  1138. if (metalUsage.TotalUsage > SC.GetValue<double>($"Metal.{Module}.MetalTotalAmpHoursWarningLimit") && SC.GetValue<double>($"Metal.{Module}.MetalTotalAmpHoursWarningLimit") != 0 && SC.GetValue<double>($"Metal.{Module}.MetalTotalAmpHoursFaultLimit") != 0)
  1139. {
  1140. if (metalUsage.TotalUsage > SC.GetValue<double>($"Metal.{Module}.MetalTotalAmpHoursFaultLimit"))
  1141. {
  1142. LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), $"{Module} usage:{metalUsage.TotalUsage} is exceed MetalTotalAmpHoursFaultLimit:{SC.GetValue<double>($"Metal.{Module}.MetalTotalAmpHoursFaultLimit")}");
  1143. return false;
  1144. }
  1145. else
  1146. {
  1147. LOG.WriteLog(eEvent.WARN_METAL, Module.ToString(), $"{Module} usage:{metalUsage.TotalUsage} is exceed MetalTotalAmpHoursWarningLimit:{SC.GetValue<double>($"Metal.{Module}.MetalTotalAmpHoursWarningLimit")}");
  1148. }
  1149. }
  1150. //AnodeAUsage
  1151. if (metalUsage.AnodeAUsage > SC.GetValue<double>($"Metal.{Module}.AnodeATotalAmpHoursWarningLimit") && SC.GetValue<double>($"Metal.{Module}.AnodeATotalAmpHoursWarningLimit") != 0 && SC.GetValue<double>($"Metal.{Module}.AnodeATotalAmpHoursFaultLimit") != 0)
  1152. {
  1153. if (metalUsage.AnodeAUsage > SC.GetValue<double>($"Metal.{Module}.AnodeATotalAmpHoursFaultLimit"))
  1154. {
  1155. LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), $"{Module} usage:{metalUsage.AnodeAUsage} is exceed AnodeATotalAmpHoursFaultLimit:{SC.GetValue<double>($"Metal.{Module}.AnodeATotalAmpHoursFaultLimit")}");
  1156. return false;
  1157. }
  1158. else
  1159. {
  1160. LOG.WriteLog(eEvent.WARN_METAL, Module, $"{Module} usage:{metalUsage.AnodeAUsage} is exceed AnodeATotalAmpHoursWarningLimit:{SC.GetValue<double>($"Metal.{Module}.AnodeATotalAmpHoursWarningLimit")}");
  1161. }
  1162. }
  1163. //AnodeBUsage
  1164. if (metalUsage.AnodeBUsage > SC.GetValue<double>($"Metal.{Module}.AnodeBTotalAmpHoursWarningLimit") && SC.GetValue<double>($"Metal.{Module}.AnodeBTotalAmpHoursWarningLimit") != 0 && SC.GetValue<double>($"Metal.{Module}.AnodeBTotalAmpHoursFaultLimit") != 0)
  1165. {
  1166. if (metalUsage.AnodeBUsage > SC.GetValue<double>($"Metal.{Module}.AnodeBTotalAmpHoursFaultLimit"))
  1167. {
  1168. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} usage:{metalUsage.AnodeBUsage} is exceed AnodeBTotalAmpHoursFaultLimit:{SC.GetValue<double>($"Metal.{Module}.AnodeBTotalAmpHoursFaultLimit")}");
  1169. return false ;
  1170. }
  1171. else
  1172. {
  1173. LOG.WriteLog(eEvent.WARN_METAL, Module, $"{Module} usage:{metalUsage.AnodeBUsage} is exceed AnodeBTotalAmpHoursWarningLimit:{SC.GetValue<double>($"Metal.{Module}.AnodeBTotalAmpHoursWarningLimit")}");
  1174. }
  1175. }
  1176. //MembraneAUsage
  1177. if (metalUsage.MembranceAUsage > SC.GetValue<double>($"Metal.{Module}.MembraneATotalAmpHoursWarningLimit") && SC.GetValue<double>($"Metal.{Module}.MembraneATotalAmpHoursWarningLimit") != 0 && SC.GetValue<double>($"Metal.{Module}.MembraneATotalAmpHoursFaultLimit") != 0)
  1178. {
  1179. if (metalUsage.MembranceAUsage > SC.GetValue<double>($"Metal.{Module}.MembraneATotalAmpHoursFaultLimit"))
  1180. {
  1181. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} usage:{metalUsage.MembranceAUsage} is exceed MembraneATotalAmpHoursFaultLimit:{SC.GetValue<double>($"Metal.{Module}.MembraneATotalAmpHoursFaultLimit")}");
  1182. return false;
  1183. }
  1184. else
  1185. {
  1186. LOG.WriteLog(eEvent.WARN_METAL, Module, $"{Module} usage:{metalUsage.MembranceAUsage} is exceed MembraneATotalAmpHoursWarningLimit:{SC.GetValue<double>($"Metal.{Module}.MembraneATotalAmpHoursWarningLimit")}");
  1187. }
  1188. }
  1189. //MembraneBUsage
  1190. if (metalUsage.MembranceBUsage > SC.GetValue<double>($"Metal.{Module}.MembraneBTotalAmpHoursWarningLimit") && SC.GetValue<double>($"Metal.{Module}.MembraneBTotalAmpHoursWarningLimit") != 0 && SC.GetValue<double>($"Metal.{Module}.MembraneBTotalAmpHoursFaultLimit") != 0)
  1191. {
  1192. if (metalUsage.MembranceBUsage > SC.GetValue<double>($"Metal.{Module}.MembraneBTotalAmpHoursFaultLimit"))
  1193. {
  1194. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} usage:{metalUsage.MembranceBUsage} is exceed MembraneBTotalAmpHoursFaultLimit:{SC.GetValue<double>($"Metal.{Module}.MembraneBTotalAmpHoursFaultLimit")}");
  1195. }
  1196. else
  1197. {
  1198. LOG.WriteLog(eEvent.WARN_METAL, Module, $"{Module} usage:{metalUsage.MembranceBUsage} is exceed MembraneBTotalAmpHoursWarningLimit:{SC.GetValue<double>($"Metal.{Module}.MembraneBTotalAmpHoursWarningLimit")}");
  1199. }
  1200. }
  1201. //TotalWafer
  1202. if (metalUsage.TotalWafers > SC.GetValue<int>($"Metal.{Module}.MetalTotalWafersWarningLimit") && SC.GetValue<int>($"Metal.{Module}.MetalTotalWafersWarningLimit") != 0 && SC.GetValue<int>($"Metal.{Module}.MetalTotalWafersFaultLimit") != 0)
  1203. {
  1204. if (metalUsage.TotalWafers > SC.GetValue<int>($"Metal.{Module}.MetalTotalWafersFaultLimit"))
  1205. {
  1206. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} usage:{metalUsage.TotalWafers} is exceed MetalTotalWafersFaultLimit:{SC.GetValue<int>($"Metal.{Module}.MetalTotalWafersFaultLimit")}");
  1207. return false;
  1208. }
  1209. else
  1210. {
  1211. LOG.WriteLog(eEvent.WARN_METAL, Module, $"{Module} usage:{metalUsage.TotalWafers} is exceed MetalTotalWafersWarningLimit:{SC.GetValue<int>($"Metal.{Module}.MetalTotalWafersWarningLimit")}");
  1212. }
  1213. }
  1214. //AnodeAWafer
  1215. if (metalUsage.AnodeAWafers > SC.GetValue<int>($"Metal.{Module}.AnodeATotalWafersWarningLimit") && SC.GetValue<int>($"Metal.{Module}.AnodeATotalWafersWarningLimit") != 0 && SC.GetValue<int>($"Metal.{Module}.AnodeATotalWafersFaultLimit") != 0)
  1216. {
  1217. if (metalUsage.AnodeAWafers > SC.GetValue<int>($"Metal.{Module}.AnodeATotalWafersFaultLimit"))
  1218. {
  1219. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} usage:{metalUsage.AnodeAWafers} is exceed AnodeATotalWafersFaultLimit:{SC.GetValue<int>($"Metal.{Module}.AnodeATotalWafersFaultLimit")}");
  1220. return false;
  1221. }
  1222. else
  1223. {
  1224. LOG.WriteLog(eEvent.WARN_METAL, Module, $"{Module} usage:{metalUsage.AnodeAWafers} is exceed AnodeATotalWafersWarningLimit:{SC.GetValue<int>($"Metal.{Module}.AnodeATotalWafersWarningLimit")}");
  1225. }
  1226. }
  1227. //AnodeBWafer
  1228. if (metalUsage.AnodeBWafers > SC.GetValue<int>($"Metal.{Module}.AnodeBTotalWafersWarningLimit") && SC.GetValue<int>($"Metal.{Module}.AnodeBTotalWafersWarningLimit") != 0 && SC.GetValue<int>($"Metal.{Module}.AnodeBTotalWafersFaultLimit") != 0)
  1229. {
  1230. if (metalUsage.AnodeBWafers > SC.GetValue<int>($"Metal.{Module}.AnodeBTotalWafersFaultLimit"))
  1231. {
  1232. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} usage:{metalUsage.AnodeBWafers} is exceed AnodeBTotalWafersFaultLimit:{SC.GetValue<int>($"Metal.{Module}.AnodeBTotalWafersFaultLimit")}");
  1233. return false;
  1234. }
  1235. else
  1236. {
  1237. LOG.WriteLog(eEvent.WARN_METAL, Module, $"{Module} usage:{metalUsage.AnodeBWafers} is exceed AnodeBTotalWafersWarningLimit:{SC.GetValue<int>($"Metal.{Module}.AnodeBTotalWafersWarningLimit")}");
  1238. }
  1239. }
  1240. //AnodeAbathUsage
  1241. if (metalUsage.AnodeABathUsage > SC.GetValue<int>($"Metal.{Module}.AnodeABathTotalUsageDaysWarningLimit") && SC.GetValue<int>($"Metal.{Module}.AnodeABathTotalUsageDaysWarningLimit") != 0 && SC.GetValue<int>($"Metal.{Module}.AnodeABathTotalUsageDaysFaultLimit") != 0)
  1242. {
  1243. if (metalUsage.AnodeABathUsage > SC.GetValue<int>($"Metal.{Module}.AnodeABathTotalUsageDaysFaultLimit"))
  1244. {
  1245. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} usage:{metalUsage.AnodeABathUsage} is exceed AnodeABathTotalUsageDaysFaultLimit:{SC.GetValue<int>($"Metal.{Module}.AnodeABathTotalUsageDaysFaultLimit")}");
  1246. return false;
  1247. }
  1248. else
  1249. {
  1250. LOG.WriteLog(eEvent.WARN_METAL, Module, $"{Module} usage:{metalUsage.AnodeABathUsage} is exceed AnodeABathTotalUsageDaysWarningLimit:{SC.GetValue<int>($"Metal.{Module}.AnodeABathTotalUsageDaysWarningLimit")}");
  1251. }
  1252. }
  1253. //AnodeBbathUsage
  1254. if (metalUsage.AnodeBBathUsage > SC.GetValue<int>($"Metal.{Module}.AnodeBBathTotalUsageDaysWarningLimit") && SC.GetValue<int>($"Metal.{Module}.AnodeBBathTotalUsageDaysWarningLimit") != 0 && SC.GetValue<int>($"Metal.{Module}.AnodeBBathTotalUsageDaysFaultLimit") != 0)
  1255. {
  1256. if (metalUsage.AnodeBBathUsage > SC.GetValue<int>($"Metal.{Module}.AnodeBBathTotalUsageDaysFaultLimit"))
  1257. {
  1258. LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} usage:{metalUsage.AnodeBBathUsage} is exceed AnodeBBathTotalUsageDaysFaultLimit:{SC.GetValue<int>($"Metal.{Module}.AnodeBBathTotalUsageDaysFaultLimit")}");
  1259. return false;
  1260. }
  1261. else
  1262. {
  1263. LOG.WriteLog(eEvent.WARN_METAL, Module, $"{Module} usage:{metalUsage.AnodeBBathUsage} is exceed AnodeBBathTotalUsageDaysWarningLimit:{SC.GetValue<int>($"Metal.{Module}.AnodeBBathTotalUsageDaysWarningLimit")}");
  1264. }
  1265. }
  1266. }
  1267. return true;
  1268. }
  1269. }
  1270. }