OverViewModel.cs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413
  1. using Aitex.Core.Common.DeviceData;
  2. using Aitex.Core.Util;
  3. using Aitex.Sorter.Common;
  4. using Bolt.Toolkit.Wpf.Data.Enum;
  5. using Caliburn.Micro;
  6. using MECF.Framework.Common.DataCenter;
  7. using MECF.Framework.Common.OperationCenter;
  8. using MECF.Framework.Common.RecipeCenter;
  9. using OpenSEMI.ClientBase;
  10. using System.Collections.Generic;
  11. using System.Collections.ObjectModel;
  12. using System.Windows;
  13. using System.Windows.Input;
  14. using Aitex.Core.UI.MVVM;
  15. using VirgoCommon;
  16. using VirgoUI.Client.Dialog;
  17. using VirgoUI.Client.Models.Operate.WaferAssociation;
  18. using VirgoUI.Client.Models.Platform.LoadPort;
  19. using VirgoUI.Client.Models.Recipe;
  20. using VirgoUI.Client.Models.Sys;
  21. namespace VirgoUI.Client.Models.Operate
  22. {
  23. public enum EfemType
  24. {
  25. FutureEfem = 1,
  26. JetEfem = 2,
  27. }
  28. public class OverViewModel : UiViewModelBase
  29. {
  30. #region Property
  31. //private int MenuPermission;
  32. #region PM
  33. public string PMABackground
  34. {
  35. get
  36. {
  37. if (!PMAIsOnline)
  38. return "Red";
  39. if (PMAServiceStatus == PMState.Error.ToString())
  40. return "Red";
  41. if (PMAServiceStatus == PMState.Idle.ToString()
  42. || PMAServiceStatus == PMState.Init.ToString())
  43. {
  44. return "Transparent";
  45. }
  46. return "Green";
  47. }
  48. }
  49. public string PMBBackground
  50. {
  51. get
  52. {
  53. if (!PMBIsOnline)
  54. return "Red";
  55. if (PMBServiceStatus == PMState.Error.ToString())
  56. return "Red";
  57. if (PMBServiceStatus == PMState.Idle.ToString()
  58. || PMBServiceStatus == PMState.Init.ToString())
  59. {
  60. return "Transparent";
  61. }
  62. return "Green";
  63. }
  64. }
  65. #endregion
  66. #region EFEM
  67. private WaferAssociationInfo _lp1WaferAssociation;
  68. public WaferAssociationInfo LP1WaferAssociation
  69. {
  70. get { return _lp1WaferAssociation; }
  71. set { _lp1WaferAssociation = value; }
  72. }
  73. private WaferAssociationInfo _lp2WaferAssociation;
  74. public WaferAssociationInfo LP2WaferAssociation
  75. {
  76. get { return _lp2WaferAssociation; }
  77. set { _lp2WaferAssociation = value; }
  78. }
  79. public string LP1ProcStatus
  80. {
  81. get
  82. {
  83. if (LP1WaferAssociation.JobStatus == "")
  84. {
  85. return "Idle";
  86. }
  87. return LP1WaferAssociation.JobStatus;
  88. }
  89. }
  90. public string LP2ProcStatus
  91. {
  92. get
  93. {
  94. if (LP2WaferAssociation.JobStatus == "")
  95. {
  96. return "Idle";
  97. }
  98. return LP2WaferAssociation.JobStatus;
  99. }
  100. }
  101. private string[] _LP1StatusColor = new string[2];
  102. public string[] LP1StatusColor
  103. {
  104. get
  105. {
  106. switch (LP1ProcStatus)
  107. {
  108. case "Idle":
  109. _LP1StatusColor[0] = "Gold";
  110. _LP1StatusColor[1] = "Black";
  111. break;
  112. case "WaitingForStart":
  113. _LP1StatusColor[0] = "Blue";
  114. _LP1StatusColor[1] = "White";
  115. break;
  116. case "Executing":
  117. _LP1StatusColor[0] = "Cyan";
  118. _LP1StatusColor[1] = "Black";
  119. break;
  120. case "Paused":
  121. _LP1StatusColor[0] = "Blue";
  122. _LP1StatusColor[1] = "White";
  123. break;
  124. default:
  125. _LP1StatusColor[0] = "Gold";
  126. _LP1StatusColor[1] = "Black";
  127. break;
  128. }
  129. return _LP1StatusColor;
  130. }
  131. }
  132. private string[] _LP2StatusColor = new string[2];
  133. public string[] LP2StatusColor
  134. {
  135. get
  136. {
  137. switch (LP2ProcStatus)
  138. {
  139. case "Idle":
  140. _LP2StatusColor[0] = "Gold";
  141. _LP2StatusColor[1] = "Black";
  142. break;
  143. case "WaitingForStart":
  144. _LP2StatusColor[0] = "Blue";
  145. _LP2StatusColor[1] = "White";
  146. break;
  147. case "Executing":
  148. _LP2StatusColor[0] = "Cyan";
  149. _LP2StatusColor[1] = "Black";
  150. break;
  151. case "Paused":
  152. _LP2StatusColor[0] = "Blue";
  153. _LP2StatusColor[1] = "White";
  154. break;
  155. default:
  156. _LP2StatusColor[0] = "Gold";
  157. _LP2StatusColor[1] = "Black";
  158. break;
  159. }
  160. return _LP2StatusColor;
  161. }
  162. }
  163. [Subscription("LP1.CassetteState")]
  164. public LoadportCassetteState LP1CassetteState { get; set; }
  165. [Subscription("LP1.FoupDoorState")]
  166. public FoupDoorState LP1DoorState { get; set; }
  167. [Subscription("LP2.CassetteState")]
  168. public LoadportCassetteState LP2CassetteState { get; set; }
  169. [Subscription("LP2.FoupDoorState")]
  170. public FoupDoorState LP2DoorState { get; set; }
  171. [Subscription("LP1.CassettePlaced")]
  172. public bool PlacedLP1 { get; set; }
  173. public Visibility Foup1Visibility
  174. {
  175. get
  176. {
  177. if (IsLP1Installed)
  178. {
  179. return Visibility.Visible;
  180. }
  181. else
  182. return Visibility.Hidden;
  183. }
  184. }
  185. [Subscription("LP1.IsLoaded")]
  186. public bool IsLoadedLP1 { get; set; }
  187. [Subscription("LP2.CassettePlaced")]
  188. public bool PlacedLP2 { get; set; }
  189. public Visibility Foup2Visibility
  190. {
  191. get
  192. {
  193. if (IsLP2Installed)
  194. {
  195. return Visibility.Visible;
  196. }
  197. else
  198. return Visibility.Hidden;
  199. }
  200. }
  201. [Subscription("LP2.IsLoaded")]
  202. public bool IsLoadedLP2 { get; set; }
  203. private R_TRIG _lp1JobFinished = new R_TRIG();
  204. private R_TRIG _lp2JobFinished = new R_TRIG();
  205. private R_TRIG _lp1Removed = new R_TRIG();
  206. private R_TRIG _lp2Removed = new R_TRIG();
  207. [Subscription("EfemRobot.RobotMoveAction")]
  208. public MECF.Framework.Common.CommonData.RobotMoveInfo EfemRobotMoveAction
  209. {
  210. get;
  211. set;
  212. }
  213. public bool Foup1Present
  214. {
  215. get { return LP1CassetteState == LoadportCassetteState.Normal; }
  216. }
  217. public bool Foup1Idle
  218. {
  219. get { return LP1CassetteState == LoadportCassetteState.Normal && !Foup1Busy && !Foup1Complete; }
  220. }
  221. public bool Foup1Complete
  222. {
  223. get { return LP1JobDone && Foup1Present; }
  224. }
  225. public bool Foup1Busy
  226. {
  227. get { return LP1JobStatus == "WaitingForStart" || LP1JobStatus == "Executing" || LP1JobStatus == "Paused"; }
  228. }
  229. public bool Foup1Error
  230. {
  231. get { return LP1WaferProtrude == 1; }
  232. }
  233. public bool Foup2Present
  234. {
  235. get { return LP2CassetteState == LoadportCassetteState.Normal; }
  236. }
  237. public bool Foup2Idle
  238. {
  239. get { return LP2CassetteState == LoadportCassetteState.Normal && !Foup2Busy && !Foup2Complete; }
  240. }
  241. public bool Foup2Complete
  242. {
  243. get { return LP2JobDone && Foup2Present; }
  244. }
  245. public bool Foup2Busy
  246. {
  247. get { return LP2JobStatus == "WaitingForStart" || LP2JobStatus == "Executing" || LP2JobStatus == "Paused"; }
  248. }
  249. public bool Foup2Error
  250. {
  251. get { return LP2WaferProtrude == 1; }
  252. }
  253. //public RobotMoveInfo EfemRobotMoveInfo
  254. //{
  255. // get
  256. // {
  257. // RobotMoveInfo _moveInfo = new RobotMoveInfo() { BladeTarget = "System" };
  258. // if (!string.IsNullOrEmpty(EfemRobotMoveAction))
  259. // {
  260. // var action = EfemRobotMoveAction.Split('.');
  261. // _moveInfo.BladeTarget = action[0];
  262. // _moveInfo.Action = (RobotAction)Enum.Parse(typeof(RobotAction), action[1]);
  263. // }
  264. // return _moveInfo;
  265. // }
  266. //}
  267. [Subscription("LP1.JobDone")]
  268. public bool LP1JobDone { get; set; }
  269. [Subscription("LP1.IsWaferProtrude")]
  270. public int LP1WaferProtrude { get; set; }
  271. [Subscription("LP2.JobDone")]
  272. public bool LP2JobDone { get; set; }
  273. [Subscription("LP2.IsWaferProtrude")]
  274. public int LP2WaferProtrude { get; set; }
  275. [Subscription("LP1.WaferSize")]
  276. public string LP1WaferSize { get; set; }
  277. public string WaferSizeLP1
  278. {
  279. get { return LP1CassetteState == LoadportCassetteState.Normal ? GetWaferSize(LP1WaferSize) : "--"; }
  280. }
  281. [Subscription("LP2.WaferSize")]
  282. public string LP2WaferSize { get; set; }
  283. public string WaferSizeLP2
  284. {
  285. get { return LP2CassetteState == LoadportCassetteState.Normal ? GetWaferSize(LP2WaferSize) : "--"; }
  286. }
  287. [Subscription("Aligner1.WaferSize")]
  288. public string Aligner1WaferSize { get; set; }
  289. public string WaferSizeAligner1
  290. {
  291. get { return GetWaferSize(Aligner1WaferSize); }
  292. }
  293. [Subscription("Aligner2.WaferSize")]
  294. public string Aligner2WaferSize { get; set; }
  295. public string WaferSizeAligner2
  296. {
  297. get { return GetWaferSize(Aligner2WaferSize); }
  298. }
  299. [Subscription("Cooling1.WaferSize")]
  300. public string Cooling1WaferSize { get; set; }
  301. public string WaferSizeCooling1
  302. {
  303. get { return GetWaferSize(Cooling1WaferSize); }
  304. }
  305. [Subscription("Cooling2.WaferSize")]
  306. public string Cooling2WaferSize { get; set; }
  307. public string WaferSizeCooling2
  308. {
  309. get { return GetWaferSize(Cooling2WaferSize); }
  310. }
  311. [Subscription("EfemRobot.WaferSize")]
  312. public string EfemRobotWaferSize { get; set; }
  313. public string WaferSizeEfemRobot
  314. {
  315. get { return GetWaferSize(EfemRobotWaferSize); }
  316. }
  317. [Subscription("PMA.WaferSize")]
  318. public string PMAWaferSize { get; set; }
  319. public string WaferSizePMA
  320. {
  321. get { return GetWaferSize(PMAWaferSize); }
  322. }
  323. [Subscription("PMB.WaferSize")]
  324. public string PMBWaferSize { get; set; }
  325. public string WaferSizePMB
  326. {
  327. get { return GetWaferSize(PMBWaferSize); }
  328. }
  329. [Subscription("PMA.IsAutoMode")]
  330. public bool PMAIsAutoMode { get; set; }
  331. [Subscription("PMB.IsAutoMode")]
  332. public bool PMBIsAutoMode { get; set; }
  333. [Subscription("PMA.IsOnline")]
  334. public bool PMAIsOnline { get; set; }
  335. [Subscription("PMB.IsOnline")]
  336. public bool PMBIsOnline { get; set; }
  337. public string PMAState
  338. {
  339. get
  340. {
  341. return "PMA/" + (PMAIsAutoMode ? "Auto/" : "Manual/") + (PMAIsOnline ? "Online" : "Offline");
  342. }
  343. }
  344. public string PMBState
  345. {
  346. get
  347. {
  348. return "PMB/" + (PMBIsAutoMode ? "Auto/" : "Manual/") + (PMBIsOnline ? "Online" : "Offline");
  349. }
  350. }
  351. [Subscription("EFEM.SmallWafer")]
  352. public int SmallWafer { get; set; }
  353. [Subscription("EFEM.MidWafer")]
  354. public int MidWafer { get; set; }
  355. [Subscription("EFEM.BigWafer")]
  356. public int BigWafer { get; set; }
  357. //[Subscription("EFEM.CassetteDoor")]
  358. //public AITSensorData CassetteDoorStatus
  359. //{
  360. // get;
  361. // set;
  362. //}
  363. [Subscription("EFEM.CassetteDoor")]
  364. public LidState CassetteDoorStatus
  365. {
  366. get;
  367. set;
  368. }
  369. public Visibility CassetteDoorIsOpened
  370. {
  371. get
  372. {
  373. return CassetteDoorStatus == LidState.Open ? Visibility.Visible : Visibility.Hidden;
  374. }
  375. }
  376. //public Visibility CassetteDoorVisibility
  377. //{
  378. // get
  379. // {
  380. // return _efemType == EfemType.FutureEfem ? Visibility.Visible : Visibility.Collapsed;
  381. // }
  382. //}
  383. public Dictionary<string, string> _waferSizeMap = new Dictionary<string, string>()
  384. {
  385. {"WS3", "3'"},{"WS4", "4'"},{"WS6", "6'"}
  386. };
  387. private string GetWaferSize(string size)
  388. {
  389. //if (_efemType == EfemType.JetEfem)
  390. // return "";
  391. if (size != null && _waferSizeMap.ContainsKey(size))
  392. switch (size)
  393. {
  394. case "WS3": return SmallWafer.ToString();
  395. case "WS4": return MidWafer.ToString();
  396. case "WS6": return BigWafer.ToString();
  397. default: return "";
  398. }
  399. //return _waferSizeMap[size];
  400. return "";
  401. }
  402. public DoorState Chamber1DoorState
  403. {
  404. get { return DoorState.Unknown; }
  405. }
  406. public DoorState Chamber2DoorState
  407. {
  408. get { return DoorState.Unknown; }
  409. }
  410. public bool EnableAuto
  411. {
  412. get { return !IsAutoMode; }
  413. }
  414. public bool EnableManual
  415. {
  416. get { return IsAutoMode; }
  417. }
  418. public bool IsRtInitialized
  419. {
  420. get { return false; }
  421. }
  422. public bool EnableMapLP1
  423. {
  424. get
  425. {
  426. return Foup1Present && CassetteDoorStatus == LidState.Close;
  427. }
  428. }
  429. public bool EnableMapLP2
  430. {
  431. get
  432. {
  433. return Foup2Present && CassetteDoorStatus == LidState.Close;
  434. }
  435. }
  436. public bool EnableJobLP1
  437. {
  438. get { return IsAutoMode; }
  439. }
  440. public bool EnableJobLP2
  441. {
  442. get { return IsAutoMode; }
  443. }
  444. #region Mainframe
  445. public bool ButtonControl { get; set; }
  446. [Subscription("Aligner.Status")]
  447. public string AlignerStatus { get; set; }
  448. [Subscription("EFEM.Status")]
  449. public string EFEMStatus { get; set; }
  450. [Subscription("LP1.Status")]
  451. public string LP1Status { get; set; }
  452. [Subscription("LP2.Status")]
  453. public string LP2Status { get; set; }
  454. #endregion Mainframe
  455. #region PM
  456. public string PMALabel
  457. {
  458. get;
  459. set;
  460. }
  461. public string PMBLabel
  462. {
  463. get;
  464. set;
  465. }
  466. [Subscription("PMA.FsmState")]
  467. public string PMAServiceStatus { get; set; }
  468. [Subscription("PMA.RecipeName")]
  469. public string PMARecipeName { get; set; }
  470. [Subscription("PMA.RecipeProcessTime")]
  471. public string PMARemainTime { get; set; }
  472. [Subscription("PMA.StepNo")]
  473. public int PMAStepNo { get; set; }
  474. [Subscription("PMA.RecipeStepName")]
  475. public string PMAStepName { get; set; }
  476. [Subscription("PMA.ChamberPressure")]
  477. public double PMAChamberPressure { get; set; }
  478. [Subscription("PMA.HeaterChamber.Temperature")]
  479. public double PMATemperature { get; set; }
  480. [Subscription("PMA.Chiller.CoolantOutletTempFeedback")]
  481. public double PMAChillerTemperature { get; set; }
  482. public bool PMASlitValveIsOpen
  483. {
  484. get { return SlitDoorDataA != null && SlitDoorDataA.OpenFeedback && !SlitDoorDataA.CloseFeedback; }
  485. }
  486. [Subscription("PMA.SlitDoor.DeviceData")]
  487. public AITCylinderData SlitDoorDataA
  488. {
  489. get;
  490. set;
  491. }
  492. [Subscription("PMB.FsmState")]
  493. public string PMBServiceStatus { get; set; }
  494. [Subscription("PMB.RecipeName")]
  495. public string PMBRecipeName { get; set; }
  496. [Subscription("PMB.RecipeProcessTime")]
  497. public string PMBRemainTime { get; set; }
  498. [Subscription("PMB.StepNo")]
  499. public string PMBStepNo { get; set; }
  500. [Subscription("PMB.RecipeStepName")]
  501. public string PMBStepName { get; set; }
  502. [Subscription("PMB.ChamberPressure")]
  503. public double PMBChamberPressure { get; set; }
  504. [Subscription("PMB.HeaterChamber.Temperature")]
  505. public double PMBTemperature { get; set; }
  506. [Subscription("PMB.Chiller.CoolantOutletTempFeedback")]
  507. public double PMBChillerTemperature { get; set; }
  508. public bool PMBSlitValveIsOpen
  509. {
  510. get { return SlitDoorDataB != null && SlitDoorDataB.OpenFeedback && !SlitDoorDataB.CloseFeedback; }
  511. }
  512. [Subscription("PMB.SlitDoor.DeviceData")]
  513. public AITCylinderData SlitDoorDataB
  514. {
  515. get;
  516. set;
  517. }
  518. public bool IsPMAChillerVisibility
  519. {
  520. get
  521. {
  522. return (bool)QueryDataClient.Instance.Service.GetConfig($"PMA.Chiller.EnableChiller");
  523. }
  524. }
  525. public bool IsPMBChillerVisibility
  526. {
  527. get
  528. {
  529. return (bool)QueryDataClient.Instance.Service.GetConfig($"PMB.Chiller.EnableChiller");
  530. }
  531. }
  532. public bool IsPMAHeaterVisibility
  533. {
  534. get
  535. {
  536. return !IsPMAChillerVisibility;
  537. }
  538. }
  539. public bool IsPMBHeaterVisibility
  540. {
  541. get
  542. {
  543. return !IsPMBChillerVisibility;
  544. }
  545. }
  546. #endregion PM
  547. #region Scheduler
  548. [Subscription("System.IsAutoMode")]
  549. public bool IsAutoMode { get; set; }
  550. public bool _isCycleMode;
  551. public bool _isATMMode;
  552. public Visibility IsCycleInfoVisibility
  553. {
  554. get { return _isCycleMode ? Visibility.Visible : Visibility.Hidden; }
  555. }
  556. public Visibility IsATMInfoVisibility
  557. {
  558. get { return _isATMMode ? Visibility.Visible : Visibility.Hidden; }
  559. }
  560. [Subscription("Scheduler.CycledCount")]
  561. public int CycledCount { get; set; }
  562. [Subscription("Scheduler.CycledWafer")]
  563. public int CycledWafer { get; set; }
  564. [Subscription("Scheduler.CycleSetPoint")]
  565. public int CycleSetPoint { get; set; }
  566. public string CycleCountDisplay
  567. {
  568. get { return (CycleSetPoint > 0 && (CycledCount > CycleSetPoint)) ? $"{CycledCount + 1}/{CycleSetPoint}" : $"{CycledCount}/{CycleSetPoint}"; }
  569. }
  570. [Subscription("LP1.CurrentRecipeList")]
  571. public List<string> LP1CurrentRecipeList { get; set; }
  572. [Subscription("LP1.LocalJobName")]
  573. public string LP1JobName { get; set; }
  574. [Subscription("LP1.LocalJobStatus")]
  575. public string LP1JobStatus { get; set; }
  576. [Subscription("LP1.JobLotName")]
  577. public string LP1JobLotName { get; set; }
  578. [Subscription("LP2.CurrentRecipeList")]
  579. public List<string> LP2CurrentRecipeList { get; set; }
  580. [Subscription("LP2.LocalJobName")]
  581. public string LP2JobName { get; set; }
  582. [Subscription("LP2.LocalJobStatus")]
  583. public string LP2JobStatus { get; set; }
  584. [Subscription("LP2.JobLotName")]
  585. public string LP2JobLotName { get; set; }
  586. [Subscription("Scheduler.BufferSlot1Time")]
  587. public int BufferSlot1Time { get; set; }
  588. [Subscription("Scheduler.BufferSlot2Time")]
  589. public int BufferSlot2Time { get; set; }
  590. public bool IsPauseAllEnable => LP1JobStatus == "Executing" || LP2JobStatus == "Executing";
  591. #endregion Scheduler
  592. public Visibility LowerArmVisibility
  593. {
  594. get
  595. {
  596. try
  597. {
  598. var armTypeConfig = QueryDataClient.Instance.Service.GetConfig("EFEM.EfemRobotArmType");
  599. if (armTypeConfig == null || !int.TryParse(armTypeConfig.ToString(), out int armType) || armType != 2)
  600. return Visibility.Visible;
  601. var lowerBladeConfig = QueryDataClient.Instance.Service.GetConfig("EFEM.EfemRobot.LowerBladeEnable");
  602. if (lowerBladeConfig != null && bool.TryParse(lowerBladeConfig.ToString(), out bool lowerEnabled))
  603. {
  604. return lowerEnabled ? Visibility.Visible : Visibility.Collapsed;
  605. }
  606. return Visibility.Collapsed;
  607. }
  608. catch
  609. {
  610. return Visibility.Visible;
  611. }
  612. }
  613. }
  614. public Visibility UpperArmVisibility
  615. {
  616. get
  617. {
  618. try
  619. {
  620. var armTypeConfig = QueryDataClient.Instance.Service.GetConfig("EFEM.EfemRobotArmType");
  621. if (armTypeConfig == null || !int.TryParse(armTypeConfig.ToString(), out int armType) || armType != 2)
  622. return Visibility.Visible;
  623. var upperBladeConfig = QueryDataClient.Instance.Service.GetConfig("EFEM.EfemRobot.UpperBladeEnable");
  624. if (upperBladeConfig != null && bool.TryParse(upperBladeConfig.ToString(), out bool upperEnabled))
  625. {
  626. return upperEnabled ? Visibility.Visible : Visibility.Collapsed;
  627. }
  628. return Visibility.Collapsed;
  629. }
  630. catch
  631. {
  632. return Visibility.Visible;
  633. }
  634. }
  635. }
  636. #endregion EFEM
  637. public Visibility MapVisibility => (bool)QueryDataClient.Instance.Service.GetConfig("EFEM.LoadPort.HasMapFunction") ? Visibility.Visible : Visibility.Collapsed;
  638. public Visibility LoadVisibility => (bool)QueryDataClient.Instance.Service.GetConfig("EFEM.LoadPort.HasLoadFunction") ? Visibility.Visible : Visibility.Collapsed;
  639. #region LP
  640. public bool EnableLoadLP1
  641. {
  642. get
  643. {
  644. return Foup1Present && string.IsNullOrEmpty(LP1JobStatus) && !IsLoadedLP1 && LP1Status != "Loading";
  645. }
  646. }
  647. public bool EnableLoadLP2
  648. {
  649. get
  650. {
  651. return Foup2Present && string.IsNullOrEmpty(LP2JobStatus) && !IsLoadedLP2 && LP2Status != "Loading";
  652. }
  653. }
  654. public bool EnableUnloadLP1
  655. {
  656. get
  657. {
  658. return Foup1Present && (string.IsNullOrEmpty(LP1JobStatus) || LP1JobStatus == "Completed") && IsLoadedLP1 && LP1Status != "Unloading";
  659. }
  660. }
  661. public bool EnableUnloadLP2
  662. {
  663. get
  664. {
  665. return Foup2Present && (string.IsNullOrEmpty(LP2JobStatus) || LP2JobStatus == "Completed") && IsLoadedLP2 && LP2Status != "Unloading";
  666. }
  667. }
  668. public ICommand LP1CarrierIDChangedCommand
  669. {
  670. get;
  671. set;
  672. }
  673. public ICommand LP2CarrierIDChangedCommand
  674. {
  675. get;
  676. set;
  677. }
  678. public string LP1CarrierIDText
  679. {
  680. get;
  681. set;
  682. }
  683. public string LP2CarrierIDText
  684. {
  685. get;
  686. set;
  687. }
  688. public Visibility ScannerVisibility
  689. {
  690. get;
  691. set;
  692. }
  693. #endregion
  694. public Visibility IsLP1Visibility
  695. {
  696. get { return IsLP1Installed ? Visibility.Visible : Visibility.Collapsed; }
  697. }
  698. public Visibility IsLP2Visibility
  699. {
  700. get { return IsLP2Installed ? Visibility.Visible : Visibility.Collapsed; }
  701. }
  702. #endregion Property
  703. public OverViewModel()
  704. {
  705. this.DisplayName = "OverView";
  706. }
  707. protected override void OnInitialize()
  708. {
  709. base.OnInitialize();
  710. base.InitModules();
  711. LP1WaferAssociation = new WaferAssociationInfo();
  712. if(ModuleManager.ModuleInfos.ContainsKey("LP1"))
  713. {
  714. LP1WaferAssociation.ModuleData = ModuleManager.ModuleInfos["LP1"];
  715. }
  716. LP2WaferAssociation = new WaferAssociationInfo();
  717. if (ModuleManager.ModuleInfos.ContainsKey("LP2"))
  718. {
  719. LP2WaferAssociation.ModuleData = ModuleManager.ModuleInfos["LP2"];
  720. }
  721. LP1CarrierIDChangedCommand = new DelegateCommand<object>(LP1CarrierIDInputChanged);
  722. LP2CarrierIDChangedCommand = new DelegateCommand<object>(LP2CarrierIDInputChanged);
  723. }
  724. protected override void OnActivate()
  725. {
  726. base.OnActivate();
  727. ScannerVisibility = (bool)QueryDataClient.Instance.Service.GetConfig("EFEM.LoadPort.EnableScanner") ? Visibility.Visible:Visibility.Hidden;
  728. _isCycleMode = (bool)QueryDataClient.Instance.Service.GetConfig("System.IsCycleMode");
  729. _isATMMode = (bool)QueryDataClient.Instance.Service.GetConfig("System.IsATMMode");
  730. PMALabel = (string)QueryDataClient.Instance.Service.GetConfig("PMA.ChamberLabel");
  731. PMBLabel = (string)QueryDataClient.Instance.Service.GetConfig("PMB.ChamberLabel");
  732. }
  733. public void Start()
  734. {
  735. //if (MenuPermission != 3) return;
  736. InvokeClient.Instance.Service.DoOperation("System.StartAutoRun");
  737. }
  738. public void Stop()
  739. {
  740. //InvokeClient.Instance.Service.DoOperation("System.StartAutoRun");
  741. }
  742. protected override void InvokeAfterUpdateProperty(Dictionary<string, object> data)
  743. {
  744. ContextMenuManager.Instance.IsAutoMode = this.IsAutoMode;
  745. ModuleTemperature["PMA"] = (float)PMATemperature;
  746. ModuleTemperature["PMB"] = (float)PMBTemperature;
  747. LP1WaferAssociation.JobID = LP1JobName;
  748. LP1WaferAssociation.JobStatus = LP1JobStatus;
  749. LP2WaferAssociation.JobID = LP2JobName;
  750. LP2WaferAssociation.JobStatus = LP2JobStatus;
  751. LP1WaferAssociation.JobID = LP1JobName;
  752. LP1WaferAssociation.JobStatus = LP1JobStatus;
  753. if (!string.IsNullOrEmpty(LP1JobName))
  754. LP1WaferAssociation.LotId = LP1JobLotName;
  755. LP2WaferAssociation.JobID = LP2JobName;
  756. LP2WaferAssociation.JobStatus = LP2JobStatus;
  757. if (!string.IsNullOrEmpty(LP2JobName))
  758. LP2WaferAssociation.LotId = LP2JobLotName;
  759. _lp1JobFinished.CLK = string.IsNullOrEmpty(LP1JobName);
  760. if (_lp1JobFinished.Q)
  761. {
  762. var wafers = LP1WaferAssociation.ModuleData.WaferManager.Wafers;
  763. for (int i = 0; i < wafers.Count; i++)
  764. {
  765. wafers[i].SequenceName = "";
  766. }
  767. LP1WaferAssociation.LotId = "";
  768. LP1WaferAssociation.SequenceName = "";
  769. }
  770. _lp2JobFinished.CLK = string.IsNullOrEmpty(LP2JobName);
  771. if (_lp2JobFinished.Q)
  772. {
  773. var wafers = LP2WaferAssociation.ModuleData.WaferManager.Wafers;
  774. for (int i = 0; i < wafers.Count; i++)
  775. {
  776. wafers[i].SequenceName = "";
  777. }
  778. LP2WaferAssociation.LotId = "";
  779. LP2WaferAssociation.SequenceName = "";
  780. }
  781. if (!string.IsNullOrEmpty(LP1JobStatus) && LP1JobStatus == "Executing")
  782. {
  783. var wafers = LP1WaferAssociation.ModuleData.WaferManager.Wafers;
  784. for (int i = 0; i < wafers.Count; i++)
  785. {
  786. wafers[i].SequenceName = LP1CurrentRecipeList[wafers[i].SlotID];
  787. }
  788. }
  789. if (!string.IsNullOrEmpty(LP2JobStatus) && LP2JobStatus == "Executing")
  790. {
  791. var wafers = LP2WaferAssociation.ModuleData.WaferManager.Wafers;
  792. for (int i = 0; i < wafers.Count; i++)
  793. {
  794. wafers[i].SequenceName = LP2CurrentRecipeList[wafers[i].SlotID];
  795. }
  796. }
  797. _lp1Removed.CLK = (LP1CassetteState != LoadportCassetteState.Normal);
  798. if (_lp1Removed.Q)
  799. {
  800. LP1CarrierIDText = "";
  801. }
  802. _lp2Removed.CLK = (LP2CassetteState != LoadportCassetteState.Normal);
  803. if (_lp2Removed.Q)
  804. {
  805. LP2CarrierIDText = "";
  806. }
  807. if (LP1CassetteState != LoadportCassetteState.Normal)
  808. {
  809. foreach (var wafer in LP1WaferAssociation.ModuleData.WaferManager.Wafers)
  810. {
  811. wafer.SequenceName = "";
  812. }
  813. }
  814. if (LP2CassetteState != LoadportCassetteState.Normal)
  815. {
  816. foreach (var wafer in LP2WaferAssociation.ModuleData.WaferManager.Wafers)
  817. {
  818. wafer.SequenceName = "";
  819. }
  820. }
  821. FOUPA.IsJobDone = LP1JobDone;
  822. FOUPB.IsJobDone = LP2JobDone;
  823. }
  824. #region LP Operation
  825. public void SetThick(string moduleID)
  826. {
  827. //if (MenuPermission != 3) return;
  828. //LoadPortProvider.Instance.SetThick(moduleID);
  829. }
  830. public void SetThin(string moduleID)
  831. {
  832. //if (MenuPermission != 3) return;
  833. //LoadPortProvider.Instance.SetThin(moduleID);
  834. }
  835. public void MapLP(string moduleID)
  836. {
  837. //if (MenuPermission != 3) return;
  838. LoadPortProvider.Instance.MapLP(moduleID);
  839. }
  840. public void LoadLP(string moduleID)
  841. {
  842. InvokeClient.Instance.Service.DoOperation($"{moduleID}.Load");
  843. }
  844. public void UnloadLP(string moduleID)
  845. {
  846. InvokeClient.Instance.Service.DoOperation($"{moduleID}.Unload");
  847. }
  848. public void HomeAll()
  849. {
  850. //if (MenuPermission != 3) return;
  851. InvokeClient.Instance.Service.DoOperation("System.HomeAll");
  852. }
  853. public void ReturnAllWafer()
  854. {
  855. //if (MenuPermission != 3) return;
  856. WindowManager wm = new WindowManager();
  857. bool needCooling = false;
  858. int coolingTime = 0;
  859. bool needAligning = false;
  860. int alignAngle = 0;
  861. if (ModuleManager.ModuleInfos.ContainsKey("Cooling1") || ModuleManager.ModuleInfos.ContainsKey("Cooling2") || ModuleManager.ModuleInfos.ContainsKey("Buffer"))
  862. {
  863. WaferTransferDialogViewModel _transferVM = new WaferTransferDialogViewModel("Would the wafer need cooling?", false, true, "");
  864. bool? bret = wm.ShowDialogWithNoStyle(_transferVM);
  865. if ((bool)bret)
  866. {
  867. //get and use transfer conditions
  868. WaferTransferCondition conditions = _transferVM.DialogResult;
  869. needCooling = conditions.IsPassCooling;
  870. coolingTime = conditions.CoolingTime;
  871. InvokeClient.Instance.Service.DoOperation("System.ReturnAllWafer", needCooling, coolingTime, needAligning, alignAngle);
  872. }
  873. }
  874. else if(ModuleManager.ModuleInfos.ContainsKey("Aligner1") || ModuleManager.ModuleInfos.ContainsKey("Aligner2"))
  875. {
  876. WaferTransferDialogViewModel _transferVM = new WaferTransferDialogViewModel("Would the wafer need aligning?", true, false, "");
  877. bool? bret = wm.ShowDialogWithNoStyle(_transferVM);
  878. if ((bool)bret)
  879. {
  880. //get and use transfer conditions
  881. WaferTransferCondition conditions = _transferVM.DialogResult;
  882. needAligning = conditions.IsPassAligner;
  883. alignAngle = conditions.AlignerAngle;
  884. InvokeClient.Instance.Service.DoOperation("System.ReturnAllWafer", needCooling, coolingTime, needAligning, alignAngle);
  885. }
  886. }
  887. }
  888. public void PauseAllJob()
  889. {
  890. if (!string.IsNullOrEmpty(LP1WaferAssociation.JobID))
  891. WaferAssociationProvider.Instance.Pause(LP1WaferAssociation.JobID);
  892. if (!string.IsNullOrEmpty(LP2WaferAssociation.JobID))
  893. WaferAssociationProvider.Instance.Pause(LP2WaferAssociation.JobID);
  894. }
  895. public void Abort()
  896. {
  897. //if (MenuPermission != 3) return;
  898. InvokeClient.Instance.Service.DoOperation("System.Abort");
  899. }
  900. public void Auto()
  901. {
  902. //if (MenuPermission != 3) return;
  903. InvokeClient.Instance.Service.DoOperation("System.SetAutoMode");
  904. }
  905. public void Manual()
  906. {
  907. //if (MenuPermission != 3) return;
  908. InvokeClient.Instance.Service.DoOperation("System.SetManualMode");
  909. }
  910. #endregion LP Operation
  911. #region Sequence operation
  912. public void SelectSequence(WaferAssociationInfo info)
  913. {
  914. //if (MenuPermission != 3) return;
  915. SequenceDialogViewModel dialog = new SequenceDialogViewModel();
  916. dialog.DisplayName = "Select Sequence";
  917. dialog.Files = new ObservableCollection<FileNode>(RecipeSequenceTreeBuilder.GetFiles(
  918. RecipeClient.Instance.Service.GetSequenceNameList()
  919. ));
  920. WindowManager wm = new WindowManager();
  921. bool? bret = wm.ShowDialog(dialog);
  922. if ((bool)bret)
  923. {
  924. info.SequenceName = dialog.DialogResult;
  925. }
  926. }
  927. public void SetSlot(WaferAssociationInfo info)
  928. {
  929. if (InputSlotCheck(info.SlotFrom, info.SlotTo))
  930. AssociateSequence(info, true);
  931. }
  932. public void SkipSlot(WaferAssociationInfo info)
  933. {
  934. if (InputSlotCheck(info.SlotFrom, info.SlotTo))
  935. AssociateSequence(info, false);
  936. }
  937. public void SetAll(WaferAssociationInfo info)
  938. {
  939. //if (MenuPermission != 3) return;
  940. info.SlotFrom = 1;
  941. info.SlotTo = (int)QueryDataClient.Instance.Service.GetConfig($"EFEM.LoadPort.SlotNumber");
  942. AssociateSequence(info, true);
  943. }
  944. public void DeselectAll(WaferAssociationInfo info)
  945. {
  946. //if (MenuPermission != 3) return;
  947. info.SlotFrom = 1;
  948. info.SlotTo = (int)QueryDataClient.Instance.Service.GetConfig($"EFEM.LoadPort.SlotNumber");
  949. AssociateSequence(info, false);
  950. }
  951. public void SetSequence(WaferAssociationInfo info, int slotIndex, string seqName)
  952. {
  953. bool flag = string.IsNullOrEmpty(seqName);
  954. AssociateSequence(info, flag, slotIndex - 1);
  955. }
  956. private bool InputSlotCheck(int from, int to)
  957. {
  958. if (from > to)
  959. {
  960. DialogBox.ShowInfo("This index of from slot should be large than the index of to slot.");
  961. return false;
  962. }
  963. if (from < 1 || to > (int)QueryDataClient.Instance.Service.GetConfig($"EFEM.LoadPort.SlotNumber"))
  964. {
  965. DialogBox.ShowInfo($"This input value for from should be between 1 and {(int)QueryDataClient.Instance.Service.GetConfig($"EFEM.LoadPort.SlotNumber")}.");
  966. return false;
  967. }
  968. return true;
  969. }
  970. private void AssociateSequence(WaferAssociationInfo info, bool flag, int slot = -1)
  971. {
  972. List<WaferInfo> wafers = info.ModuleData.WaferManager.Wafers;
  973. var fromBottom = QueryDataClient.Instance.Service.GetConfig($"EFEM.LoadPort.SlotFromBottom");
  974. int parityFlag = (int)QueryDataClient.Instance.Service.GetConfig("EFEM.LoadPort.WaferPlacementParityFlag");
  975. if (slot >= 0) //by wafer
  976. {
  977. // Wafer Placement Parity Checking
  978. if(parityFlag != 0 && slot % 2 == parityFlag % 2)
  979. {
  980. string slotParity = parityFlag == 2 ? "Odd" : "Even";
  981. DialogBox.ShowWarning($"Cannot process {slotParity} slot wafer.");
  982. return;
  983. }
  984. int index = wafers.Count - slot - 1;
  985. if (fromBottom != null && !((bool)fromBottom))
  986. {
  987. index = slot;
  988. }
  989. if (index < wafers.Count)
  990. {
  991. if (flag && HasWaferOnSlot(wafers, index))
  992. wafers[index].SequenceName = info.SequenceName;
  993. else
  994. wafers[index].SequenceName = string.Empty;
  995. }
  996. }
  997. else //by from-to
  998. {
  999. for (int i = info.SlotFrom - 1; i < info.SlotTo; i++)
  1000. {
  1001. int index = wafers.Count - i - 1;
  1002. if (fromBottom != null && !((bool)fromBottom))
  1003. {
  1004. index = i;
  1005. }
  1006. if (index < wafers.Count)
  1007. {
  1008. if (flag && HasWaferOnSlot(wafers, index) && (parityFlag == 0 || wafers[index].SlotID % 2 != parityFlag % 2))
  1009. wafers[index].SequenceName = info.SequenceName;
  1010. else
  1011. wafers[index].SequenceName = string.Empty;
  1012. }
  1013. }
  1014. }
  1015. }
  1016. private bool HasWaferOnSlot(List<WaferInfo> wafers, int index)
  1017. {
  1018. if (wafers[index].WaferStatus == 0)
  1019. return false;
  1020. return true;
  1021. }
  1022. public int LP1WaferCount
  1023. {
  1024. get
  1025. {
  1026. int iWaferCount = 0;
  1027. foreach (var Wafers in ModuleManager.ModuleInfos["LP1"].WaferManager.Wafers)
  1028. {
  1029. if (Wafers.WaferStatus != 0)
  1030. {
  1031. iWaferCount++;
  1032. }
  1033. }
  1034. return iWaferCount;
  1035. }
  1036. }
  1037. public string LP1WaferCountInfo
  1038. {
  1039. get
  1040. {
  1041. return $"Mask Count:{LP1WaferCount}";
  1042. }
  1043. }
  1044. public int LP2WaferCount
  1045. {
  1046. get
  1047. {
  1048. int iWaferCount = 0;
  1049. foreach (var Wafers in ModuleManager.ModuleInfos["LP2"].WaferManager.Wafers)
  1050. {
  1051. if (Wafers.WaferStatus != 0)
  1052. {
  1053. iWaferCount++;
  1054. }
  1055. }
  1056. return iWaferCount;
  1057. }
  1058. }
  1059. public string LP2WaferCountInfo
  1060. {
  1061. get
  1062. {
  1063. return $"Mask Count:{LP2WaferCount}";
  1064. }
  1065. }
  1066. #region barcode
  1067. private void LP1CarrierIDInputChanged(object param)
  1068. {
  1069. string barcode = param as string;
  1070. if (string.IsNullOrEmpty(barcode.Trim()))
  1071. {
  1072. return;
  1073. }
  1074. InvokeClient.Instance.Service.DoOperation($"LP1.CarrierIDScanned", barcode.Trim());
  1075. }
  1076. private void LP2CarrierIDInputChanged(object param)
  1077. {
  1078. string barcode = param as string;
  1079. if (string.IsNullOrEmpty(barcode.Trim()))
  1080. {
  1081. return;
  1082. }
  1083. InvokeClient.Instance.Service.DoOperation($"LP2.CarrierIDScanned", barcode.Trim());
  1084. }
  1085. #endregion barcode
  1086. #endregion Sequence operation
  1087. #region Job operation
  1088. private bool JobCheck(string jobID)
  1089. {
  1090. if (jobID.Length == 0)
  1091. {
  1092. DialogBox.ShowWarning("Please create job first.");
  1093. return false;
  1094. }
  1095. else
  1096. return true;
  1097. }
  1098. public void CreateJob(WaferAssociationInfo info)
  1099. {
  1100. // Parity Check
  1101. int parityFlag = (int)QueryDataClient.Instance.Service.GetConfig("EFEM.LoadPort.WaferPlacementParityFlag");
  1102. if(parityFlag != 0)
  1103. {
  1104. foreach (var wafer in info.ModuleData.WaferManager.Wafers)
  1105. {
  1106. if (wafer.WaferStatus != 0 && wafer.SlotID % 2 == parityFlag % 2)
  1107. {
  1108. string slotParity = parityFlag == 2 ? "Odd" : "Even";
  1109. DialogBox.ShowWarning($"Cannot create job as {slotParity} slots have wafers.");
  1110. return;
  1111. }
  1112. }
  1113. }
  1114. //if (MenuPermission != 3) return;
  1115. List<string> slotSequence = new List<string>();
  1116. var fromBottom = QueryDataClient.Instance.Service.GetConfig($"EFEM.LoadPort.SlotFromBottom");
  1117. if (fromBottom != null && !((bool)fromBottom))
  1118. {
  1119. info.ModuleData.WaferManager.Wafers.ForEach(key => { slotSequence.Add(key.SequenceName); });
  1120. }
  1121. else
  1122. {
  1123. info.ModuleData.WaferManager.Wafers.ForEach(key => { slotSequence.Insert(0, key.SequenceName); });
  1124. }
  1125. string jobId = info.LotId.Trim();
  1126. if (string.IsNullOrEmpty(jobId))
  1127. jobId = "CJ_Local_" + info.ModuleData.ModuleID;
  1128. info.LotId = jobId;
  1129. info.LotIdSaved = true;
  1130. WaferAssociationProvider.Instance.CreateJob(jobId, info.ModuleData.ModuleID, slotSequence, true);
  1131. }
  1132. public void AbortJob(string jobID)
  1133. {
  1134. //if (MenuPermission != 3) return;
  1135. if (JobCheck(jobID))
  1136. WaferAssociationProvider.Instance.AbortJob(jobID);
  1137. }
  1138. public void Start(string jobID)
  1139. {
  1140. //if (MenuPermission != 3) return;
  1141. if (JobCheck(jobID))
  1142. WaferAssociationProvider.Instance.Start(jobID);
  1143. }
  1144. public void Pause(string jobID)
  1145. {
  1146. //if (MenuPermission != 3) return;
  1147. if (JobCheck(jobID))
  1148. WaferAssociationProvider.Instance.Pause(jobID);
  1149. }
  1150. public void Resume(string jobID)
  1151. {
  1152. //if (MenuPermission != 3) return;
  1153. if (JobCheck(jobID))
  1154. WaferAssociationProvider.Instance.Resume(jobID);
  1155. }
  1156. public void Stop(string jobID)
  1157. {
  1158. //if (MenuPermission != 3) return;
  1159. if (JobCheck(jobID))
  1160. WaferAssociationProvider.Instance.Stop(jobID);
  1161. }
  1162. #endregion Job operation
  1163. }
  1164. }