Loadport.cs 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. using Aitex.Core.Common;
  2. using Aitex.Core.RT.DataCenter;
  3. using Aitex.Core.RT.Event;
  4. using Aitex.Core.RT.OperationCenter;
  5. using Aitex.Core.RT.SCCore;
  6. using Aitex.Core.Util;
  7. using Aitex.Sorter.Common;
  8. using MECF.Framework.Common.Equipment;
  9. using MECF.Framework.Common.SubstrateTrackings;
  10. using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts;
  11. using SecsGem.Core.Application.E87;
  12. using System;
  13. using System.Collections;
  14. using System.Collections.Generic;
  15. using System.Diagnostics;
  16. using Venus_Core;
  17. using Venus_RT.Devices.YASKAWA;
  18. using Venus_RT.Modules;
  19. namespace Venus_RT.Devices.EFEM
  20. {
  21. sealed class Loadport : ILoadport
  22. {
  23. private EfemEntity _controller => Singleton<RouteManager>.Instance.EFEM;
  24. //---------------------------------Properties------------------------------------
  25. //
  26. public OnlineFlag OnlineFlag { get; set; }
  27. public ModuleName Module { get; set; }
  28. public DeviceState Status { get; set; }
  29. public WaferSize WaferSize { get; set; }
  30. public WaferStatus[] WaferInfo { get; set; }
  31. public bool HasCassette { get; set; }
  32. public bool Protrusion { get; set; }
  33. public bool IsMapped { get; set; }
  34. public bool JobDone { get; set; }
  35. public Stopwatch TimerNotifyJobDone { get; set; }
  36. public IE87CallBack LPCallBack
  37. {
  38. get { return _lpCallBack; }
  39. set { _lpCallBack = value; }
  40. }
  41. private IE87CallBack _lpCallBack;
  42. public bool IsThicknessValid
  43. {
  44. get
  45. {
  46. return !_enableThickness || !string.IsNullOrEmpty(_waferThicknessType);
  47. }
  48. }
  49. public string ThicknessType
  50. {
  51. get
  52. {
  53. return _waferThicknessType;
  54. }
  55. }
  56. public string PortId
  57. {
  58. get; private set;
  59. }
  60. public bool IsClamped { get; set; }
  61. public bool IsLoaded { get; set; }
  62. public bool IsDocked { get; set; }
  63. public string CarrierId { get; set; }
  64. public string SmartTag { get; set; }
  65. public string LotId { get; set; }
  66. public bool IsBusy { get; set; }
  67. public bool IsError { get; set; }
  68. private string[] _slotMap = new string[25];
  69. public string SlotMap
  70. {
  71. get
  72. {
  73. if (_slotMap == null)
  74. {
  75. _slotMap = new string[SC.GetValue<int>("EFEM.LoadPort.SlotNumber")];
  76. }
  77. for (int i = 0; i < _slotMap.Length; i++)
  78. {
  79. _slotMap[i] = ((int)WaferManager.Instance.GetWafer(Module, i).Status).ToString();
  80. }
  81. return string.Join("", _slotMap);
  82. }
  83. }
  84. private string _waferThicknessType;
  85. private bool _enableThickness;
  86. private string AlarmWaferProtrude = "WaferProtrude";
  87. private LoadPortFACallback _faCallback = new LoadPortFACallback();
  88. // Constructor
  89. //
  90. public Loadport(ModuleName mod, EfemBase efem)
  91. {
  92. Module = mod;
  93. PortId = ((int)mod - (int)ModuleName.LP1 + 1).ToString();
  94. TimerNotifyJobDone = new Stopwatch();
  95. _enableThickness = false;// SC.GetValue<bool>("System.WaferThickness.EnableThickness");
  96. EV.Subscribe(new EventItem("Event", AlarmWaferProtrude, "Wafer protrude", EventLevel.Alarm, EventType.HostNotification));
  97. DATA.Subscribe($"{mod}.WaferSize", () => WaferSize.ToString());
  98. DATA.Subscribe($"{mod}.CassetteState", () => HasCassette ? LoadportCassetteState.Normal : LoadportCassetteState.Absent);
  99. DATA.Subscribe($"{mod}.CassettePresent", () => HasCassette ? 1 : 0);
  100. DATA.Subscribe($"{mod}.CassettePlaced", () => HasCassette);
  101. DATA.Subscribe($"{mod}.SlotMap", () => SlotMap);
  102. DATA.Subscribe($"{mod}.IsWaferProtrude", () => Protrusion ? 1 : 0);
  103. DATA.Subscribe($"{mod}.IsMapped", () => IsMapped);
  104. DATA.Subscribe($"{mod}.IsLoaded", () => IsLoaded);
  105. DATA.Subscribe($"{mod}.IsClamped", () => IsClamped);
  106. DATA.Subscribe($"{mod}.IsDocked", () => IsDocked);
  107. DATA.Subscribe($"{mod}.CarrierId", () => CarrierId);
  108. DATA.Subscribe($"{mod}.SmartTag", () => SmartTag);
  109. DATA.Subscribe($"{Module}.WaferThicknessType", () => _waferThicknessType);
  110. OP.Subscribe($"{Module}.SetThick", (cmd, args) => { SetThick(); return true; });
  111. OP.Subscribe($"{Module}.SetThin", (cmd, args) => { SetThin(); return true; });
  112. _lpCallBack = E87LoadPortManager.Instance.GetLoadPort((int)mod - (int)ModuleName.LP1 + 1);
  113. }
  114. // Methods
  115. //
  116. public void OnError()
  117. {
  118. IsError = true;
  119. IsBusy = false;
  120. }
  121. public void SetThick()
  122. {
  123. _waferThicknessType = "Thick";
  124. SC.SetItemValue($"System.WaferThickness.{Module}WaferThicknessType", _waferThicknessType);
  125. _controller.SendEfemBackroundCommand(EfemEntity.MSG.SetThickness, Module, _waferThicknessType);
  126. }
  127. public void SetThin()
  128. {
  129. _waferThicknessType = "Thin";
  130. SC.SetItemValue($"System.WaferThickness.{Module}WaferThicknessType", _waferThicknessType);
  131. _controller.SendEfemBackroundCommand(EfemEntity.MSG.SetThickness, Module, _waferThicknessType);
  132. }
  133. #region Home
  134. public void Home()
  135. {
  136. if (IsBusy)
  137. {
  138. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not home");
  139. return;
  140. }
  141. IsBusy = true;
  142. _controller.SendEfemBackroundCommand(EfemEntity.MSG.HomeLP, Module);
  143. }
  144. public void NoteJobStart()
  145. {
  146. JobDone = false;
  147. }
  148. public void NoteJobComplete()
  149. {
  150. TimerNotifyJobDone.Restart();
  151. JobDone = true;
  152. }
  153. public void OnHomeFailed(string data)
  154. {
  155. IsError = true;
  156. IsBusy = false;
  157. }
  158. public void OnHomed()
  159. {
  160. IsError = false;
  161. IsBusy = false;
  162. IsClamped = false;
  163. IsLoaded = false;
  164. IsMapped = false;
  165. IsDocked = false;
  166. }
  167. #endregion
  168. #region Load
  169. public void Load()
  170. {
  171. if (IsLoaded)
  172. {
  173. EV.PostWarningLog(Module.ToString(), $"{Module} is loaded, can not load");
  174. return;
  175. }
  176. if (IsBusy)
  177. {
  178. EV.PostInfoLog(Module.ToString(), $"{Module} is busy, can not load");
  179. return;
  180. }
  181. if (IsError)
  182. {
  183. EV.PostInfoLog(Module.ToString(), $"{Module} is error, can not load");
  184. return;
  185. }
  186. IsBusy = true;
  187. _controller.SendEfemBackroundCommand(EfemEntity.MSG.Load, Module);
  188. }
  189. public void LoadStart()
  190. {
  191. if(_lpCallBack!=null)
  192. {
  193. _lpCallBack.LoadStart();
  194. }
  195. }
  196. public void OnLoadFailed(string data)
  197. {
  198. IsError = true;
  199. IsBusy = false;
  200. _faCallback.LoadFailed(this);
  201. }
  202. public void OnLoaded()
  203. {
  204. IsError = false;
  205. IsBusy = false;
  206. IsLoaded = true;
  207. IsMapped = true;
  208. _faCallback.LoadComplete(this);
  209. if(_lpCallBack!=null)
  210. {
  211. _lpCallBack.LoadComplete();
  212. }
  213. }
  214. #endregion
  215. #region unload
  216. public void Unload()
  217. {
  218. if (!IsLoaded)
  219. {
  220. EV.PostWarningLog(Module.ToString(), $"{Module} is not loaded, can not unload");
  221. return;
  222. }
  223. if (IsBusy)
  224. {
  225. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not unload");
  226. return;
  227. }
  228. if (IsError)
  229. {
  230. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not unload");
  231. return;
  232. }
  233. IsBusy = true;
  234. _controller.SendEfemBackroundCommand(EfemEntity.MSG.Unload, Module);
  235. }
  236. public void UnloadStart()
  237. {
  238. if(_lpCallBack!=null)
  239. {
  240. _lpCallBack.UnLoadStart();
  241. }
  242. }
  243. public void OnUnloadFailed(string data)
  244. {
  245. IsError = true;
  246. IsBusy = false;
  247. _faCallback.UnloadFailed(this);
  248. }
  249. public void OnUnloaded()
  250. {
  251. IsBusy = false;
  252. IsError = false;
  253. IsLoaded = false;
  254. IsMapped = false;
  255. if (SC.GetValue<bool>("EFEM.AutoUnlockAfterUnload"))
  256. {
  257. _faCallback.UnloadComplete(this);
  258. }
  259. else
  260. {
  261. _faCallback.UnloadComplete(this);
  262. }
  263. }
  264. #endregion
  265. #region Dock
  266. public void Dock()
  267. {
  268. if (IsBusy)
  269. {
  270. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not dock");
  271. return;
  272. }
  273. if (IsError)
  274. {
  275. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not dock");
  276. return;
  277. }
  278. IsBusy = true;
  279. _controller.SendEfemBackroundCommand(EfemEntity.MSG.Dock, Module);
  280. }
  281. public void OnDocked()
  282. {
  283. IsBusy = false;
  284. IsError = false;
  285. IsDocked = true;
  286. }
  287. public void OnDockFailed(string data)
  288. {
  289. IsError = true;
  290. IsBusy = false;
  291. }
  292. #endregion
  293. #region Undock
  294. public void Undock()
  295. {
  296. if (IsBusy)
  297. {
  298. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not undock");
  299. return;
  300. }
  301. if (IsError)
  302. {
  303. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not undock");
  304. return;
  305. }
  306. IsBusy = true;
  307. _controller.SendEfemBackroundCommand(EfemEntity.MSG.Undock, Module);
  308. }
  309. public void OnUndocked()
  310. {
  311. IsBusy = false;
  312. IsError = false;
  313. IsDocked = false;
  314. }
  315. public void OnUndockFailed(string data)
  316. {
  317. IsError = true;
  318. IsBusy = false;
  319. }
  320. #endregion
  321. #region Clamp
  322. public void Clamp(bool isUnloadClamp)
  323. {
  324. if (IsBusy)
  325. {
  326. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not clamp");
  327. return;
  328. }
  329. if (IsError)
  330. {
  331. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not clamp");
  332. return;
  333. }
  334. IsBusy = true;
  335. _controller.SendEfemBackroundCommand(EfemEntity.MSG.Clamp, Module, isUnloadClamp);
  336. }
  337. public void OnClamped(bool isUnloadClamp)
  338. {
  339. IsBusy = false;
  340. IsError = false;
  341. IsClamped = true;
  342. if (isUnloadClamp)
  343. {
  344. _faCallback.UnloadComplete(this);
  345. }
  346. else
  347. {
  348. _faCallback.Clamped(this);
  349. }
  350. }
  351. public void OnClampFailed(string data)
  352. {
  353. IsError = true;
  354. IsBusy = false;
  355. }
  356. #endregion
  357. #region Unclamp
  358. public void Unclamp()
  359. {
  360. if (IsBusy)
  361. {
  362. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not unclamp");
  363. return;
  364. }
  365. if (IsError)
  366. {
  367. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not unclamp");
  368. return;
  369. }
  370. IsBusy = true;
  371. _controller.SendEfemBackroundCommand(EfemEntity.MSG.Unclamp, Module);
  372. }
  373. public void OnUnclamped()
  374. {
  375. IsBusy = false;
  376. IsError = false;
  377. IsClamped = false;
  378. _faCallback.Unclamped(this);
  379. }
  380. public void OnUnclampFailed(string data)
  381. {
  382. }
  383. #endregion
  384. #region map
  385. public void Map()
  386. {
  387. _controller.SendEfemBackroundCommand(EfemEntity.MSG.Map, Module);
  388. }
  389. #endregion
  390. #region carrierID
  391. public void ReadCarrierID()
  392. {
  393. if (IsBusy)
  394. {
  395. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not read carrier ID");
  396. return;
  397. }
  398. if (IsError)
  399. {
  400. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not read carrier ID");
  401. return;
  402. }
  403. IsBusy = true;
  404. _controller.SendEfemBackroundCommand(EfemEntity.MSG.ReadCarrierId, Module);
  405. }
  406. public void OnCarrierIDRead(string data)
  407. {
  408. IsBusy = false;
  409. IsError = false;
  410. //Regex rg = new Regex("(?<=(" + "LOT :" + "))[.\\s\\S]*?(?=(" + "QTY :" + "))", RegexOptions.Multiline | RegexOptions.Singleline);
  411. //string carrierID = rg.Match(data).Value.Replace(":", "").Trim();
  412. //data =
  413. // "CST:C082259 TYPE:CST25_AU LOT:AF2403 QTY:24 FLOW:033000 STATUS:HOLD PRI:3-1 PD:0418A CSRLOT: CLEAN:2021/11/14 19:57:50 EQPGRP:DUMMY STAGE:CP-TEST1 RECIPE:DUMMY EMP:N ";
  414. var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
  415. CarrierId = "";
  416. foreach (var item in items)
  417. {
  418. if (item.StartsWith("CST:") && item.Length > 4)
  419. CarrierId = item.Substring(4).Trim();
  420. if (item.StartsWith("LOT:") && item.Length > 4)
  421. LotId = item.Substring(4).Trim();
  422. }
  423. if (string.IsNullOrEmpty(CarrierId))
  424. {
  425. CarrierId = data;
  426. }
  427. SmartTag = data;
  428. _faCallback.IDRead(this);
  429. }
  430. public void OnCarrierIDReadFailed(string data)
  431. {
  432. IsError = true;
  433. IsBusy = false;
  434. _faCallback.ReadIDFailed(this);
  435. }
  436. public void WriteCarrierID(string id)
  437. {
  438. if (IsBusy)
  439. {
  440. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not write carrier ID");
  441. return;
  442. }
  443. if (IsError)
  444. {
  445. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not write carrier ID");
  446. return;
  447. }
  448. IsBusy = true;
  449. _controller.SendEfemBackroundCommand(EfemEntity.MSG.WriteCarrierID, Module, id);
  450. }
  451. public void OnCarrierIDWrite(string data)
  452. {
  453. IsBusy = false;
  454. IsError = false;
  455. var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
  456. CarrierId = "";
  457. foreach (var item in items)
  458. {
  459. if (item.StartsWith("CST:") && item.Length > 4)
  460. CarrierId = item.Substring(4);
  461. }
  462. if (string.IsNullOrEmpty(CarrierId))
  463. {
  464. CarrierId = data;
  465. }
  466. SmartTag = data;
  467. _faCallback.IDWrite(this);
  468. }
  469. public void OnCarrierIDWriteFailed(string data)
  470. {
  471. IsError = true;
  472. IsBusy = false;
  473. _faCallback.WriteIDFailed(this);
  474. }
  475. #endregion
  476. #region event
  477. public void HandleEvent(EfemEventArgs eArg)
  478. {
  479. switch (eArg.CommandType)
  480. {
  481. case EfemOperation.GetWaferInfo:
  482. string sWaferInfo = eArg.DataList[0];
  483. bool resultNormal = true;
  484. for (byte index = 0; index < sWaferInfo.Length; index++)
  485. {
  486. int waferState = int.Parse(sWaferInfo.Substring(index, 1));
  487. //合理的映射到内部支持的叠片/交叉片
  488. if (waferState >= 7) waferState = 7;
  489. else if (waferState >= 2) waferState = 3;
  490. WaferStatus st = (WaferStatus)waferState;
  491. WaferManager.Instance.UpdateWaferSize(this.Module, index, WaferSize);
  492. if (st != WaferStatus.Empty)
  493. {
  494. WaferManager.Instance.CreateWafer(this.Module, index, st);
  495. if (st == WaferStatus.Normal)
  496. {
  497. //EV.PostInfoLog(this.Module.ToString(), $"Found Wafer on Slot {index + 1} {WaferSize}");
  498. }
  499. else
  500. {
  501. resultNormal = false;
  502. }
  503. }
  504. }
  505. if (resultNormal)
  506. {
  507. _faCallback.CarrierSlotMapComplete(this);
  508. }
  509. else
  510. {
  511. _faCallback.CarrierSlotMapFailed(this);
  512. }
  513. this.IsMapped = true;
  514. break;
  515. case EfemOperation.SigStatus:
  516. // EVT: SIGSTAT/P2/00000381/00000000;
  517. string sParam = eArg.DataList[0];
  518. ModuleName mod = sParam.ToModule();
  519. if (!ModuleHelper.IsLoadPort(mod))
  520. return;
  521. // DATA1 & DATA2
  522. int nData1 = Convert.ToInt32(eArg.DataList[1], 16);
  523. int nData2 = Convert.ToInt32(eArg.DataList[2], 16);
  524. BitArray baData1 = new BitArray(new int[] { nData1 });
  525. BitArray baData2 = new BitArray(new int[] { nData2 });
  526. // wafer size
  527. this.WaferSize = !baData1[6] ? WaferSize.WS3 :
  528. !baData1[7] ? WaferSize.WS4 :
  529. !baData1[8] ? WaferSize.WS6 : WaferSize.WS0;
  530. // placement & present
  531. bool bPlacement = baData1[0]; // bit 0
  532. bool bPresence = !baData1[1]; // bit 1
  533. bool bArrived = bPlacement && bPresence;
  534. if (HasCassette)
  535. {
  536. if (!bArrived)
  537. {
  538. this.HasCassette = false;
  539. this.IsMapped = false;
  540. //EV.PostInfoLog(mod.ToString(), "Cassette removed");
  541. OP.DoOperation("System.CassetteLeave"); //For unload light control off afer job done
  542. CarrierManager.Instance.DeleteCarrier(Module.ToString());
  543. WaferManager.Instance.DeleteWafer(this.Module, 0, 25);
  544. _faCallback.CarrierRemoved(this);
  545. JobDone = false;
  546. _waferThicknessType = "";
  547. }
  548. }
  549. else
  550. {
  551. if (bArrived)
  552. {
  553. this.HasCassette = true;
  554. CarrierManager.Instance.CreateCarrier(Module.ToString());
  555. _faCallback.CarrierArrived(this);
  556. JobDone = false;
  557. _waferThicknessType = "";
  558. }
  559. }
  560. this.Protrusion = !baData1[9];
  561. if (Protrusion)
  562. {
  563. //EV.PostAlarmLog(Module.ToString(), "发现 wafer 突出");
  564. //EV.Notify(AlarmWaferProtrude);
  565. //Singleton<RouteManager>.Instance.EFEM.PostMsg(EfemEntity.MSG.Error);
  566. }
  567. // DATA2, loadport上面的LED 灯, 暂时不需要用到
  568. break;
  569. default:
  570. break;
  571. }
  572. }
  573. #endregion
  574. #region TagData
  575. public void ReadTagData()
  576. {
  577. if (IsBusy)
  578. {
  579. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not read tag data");
  580. return;
  581. }
  582. if (IsError)
  583. {
  584. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not read tag data");
  585. return;
  586. }
  587. IsBusy = true;
  588. _controller.SendEfemBackroundCommand(EfemEntity.MSG.ReadTagData, Module);
  589. }
  590. public void OnTagDataRead(string data)
  591. {
  592. IsBusy = false;
  593. IsError = false;
  594. //Regex rg = new Regex("(?<=(" + "LOT :" + "))[.\\s\\S]*?(?=(" + "QTY :" + "))", RegexOptions.Multiline | RegexOptions.Singleline);
  595. //string carrierID = rg.Match(data).Value.Replace(":", "").Trim();
  596. //data =
  597. // "CST:C082259 TYPE:CST25_AU LOT:AF2403 QTY:24 FLOW:033000 STATUS:HOLD PRI:3-1 PD:0418A CSRLOT: CLEAN:2021/11/14 19:57:50 EQPGRP:DUMMY STAGE:CP-TEST1 RECIPE:DUMMY EMP:N ";
  598. var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
  599. CarrierId = "";
  600. foreach (var item in items)
  601. {
  602. if (item.StartsWith("CST:") && item.Length > 4)
  603. CarrierId = item.Substring(4);
  604. if (item.StartsWith("LOT:") && item.Length > 4)
  605. LotId = item.Substring(4).Trim();
  606. }
  607. if (string.IsNullOrEmpty(CarrierId))
  608. {
  609. CarrierId = data;
  610. }
  611. SmartTag = data;
  612. _faCallback.TagDataRead(this);
  613. }
  614. public void OnTagDataReadFailed(string data)
  615. {
  616. IsError = true;
  617. IsBusy = false;
  618. _faCallback.ReadTagDataFailed(this);
  619. }
  620. public void WriteTagData(string tagData)
  621. {
  622. if (IsBusy)
  623. {
  624. EV.PostInfoLog(Module.ToString(), $"{Module} is busy can not write tag data");
  625. return;
  626. }
  627. if (IsError)
  628. {
  629. EV.PostInfoLog(Module.ToString(), $"{Module} is error can not write tag data");
  630. return;
  631. }
  632. IsBusy = true;
  633. _controller.SendEfemBackroundCommand(EfemEntity.MSG.WriteTagData, Module, tagData);
  634. }
  635. public void OnTagDataWrite(string data)
  636. {
  637. IsBusy = false;
  638. IsError = false;
  639. var items = data.Split(new string[] { " ", "\t", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
  640. CarrierId = "";
  641. foreach (var item in items)
  642. {
  643. if (item.StartsWith("CST:") && item.Length > 4)
  644. CarrierId = item.Substring(4);
  645. }
  646. if (string.IsNullOrEmpty(CarrierId))
  647. {
  648. CarrierId = data;
  649. }
  650. SmartTag = data;
  651. _faCallback.TagDataWrite(this);
  652. }
  653. public void OnTagDataWriteFailed(string data)
  654. {
  655. IsError = true;
  656. IsBusy = false;
  657. _faCallback.WriteTagDataFailed( this);
  658. }
  659. #endregion
  660. public void SetOnline(bool online)
  661. {
  662. OnlineFlag = online ? OnlineFlag.Online : OnlineFlag.Offline;
  663. }
  664. sealed class LoadPortFACallback
  665. {
  666. private string CARRIER_ARRIVED = "CARRIER_ARRIVED";
  667. private string CARRIER_REMOVED = "CARRIER_REMOVED";
  668. private string SLOT_MAP_AVAILABLE = "SLOT_MAP_AVAILABLE";
  669. private string SLOT_MAP_FAILED = "SLOT_MAP_FAILED";
  670. private const string CARRIER_LOADED = "CARRIER_LOADED";
  671. private const string PortLoadFailed = "PortLoadFailed";
  672. private const string CARRIER_UNLOADED = "CARRIER_UNLOADED";
  673. private const string PortUnloadFailed = "PortUnloadFailed";
  674. private const string PortClamped = "PortClamped";
  675. private const string PortUnclamped = "PortUnclamped";
  676. private const string CARRIER_ID_READ = "CARRIER_ID_READ";
  677. private const string PortReadIDFailed = "PortReadIDFailed";
  678. private const string PortIDWrite = "PortIDWrite";
  679. private const string PortWriteIDFailed = "PortWriteIDFailed";
  680. private const string PortTagDataRead = "PortTagDataRead";
  681. private const string PortReadTagDataFailed = "PortReadTagDataFailed";
  682. private const string PortTagDataWrite = "PortTagDataWrite";
  683. private const string PortWriteTagDataFailed = "PortWriteTagDataFailed";
  684. public LoadPortFACallback()
  685. {
  686. EV.Subscribe(new EventItem("Event", CARRIER_ARRIVED, "Carrier Arrived"));
  687. EV.Subscribe(new EventItem("Event", CARRIER_REMOVED, "Carrier Removed"));
  688. EV.Subscribe(new EventItem("Event", SLOT_MAP_AVAILABLE, "Slot map available"));
  689. EV.Subscribe(new EventItem("Event", SLOT_MAP_FAILED, "Slot map failed"));
  690. EV.Subscribe(new EventItem("Event", CARRIER_LOADED, "Carrier Loaded"));
  691. EV.Subscribe(new EventItem("Event", PortLoadFailed, PortLoadFailed));
  692. EV.Subscribe(new EventItem("Event", CARRIER_UNLOADED, "Carrier Unloaded"));
  693. EV.Subscribe(new EventItem("Event", PortUnloadFailed, PortUnloadFailed));
  694. EV.Subscribe(new EventItem("Event", PortClamped, "Port Clamped"));
  695. EV.Subscribe(new EventItem("Event", PortUnclamped, PortUnclamped));
  696. EV.Subscribe(new EventItem("Event", CARRIER_ID_READ, "Carrier Id Read"));
  697. EV.Subscribe(new EventItem("Event", PortReadIDFailed, PortReadIDFailed));
  698. EV.Subscribe(new EventItem("Event", PortIDWrite, PortIDWrite));
  699. EV.Subscribe(new EventItem("Event", PortWriteIDFailed, PortWriteIDFailed));
  700. EV.Subscribe(new EventItem("Event", PortTagDataRead, PortTagDataRead));
  701. EV.Subscribe(new EventItem("Event", PortReadTagDataFailed, PortReadTagDataFailed));
  702. EV.Subscribe(new EventItem("Event", PortTagDataWrite, PortTagDataWrite));
  703. EV.Subscribe(new EventItem("Event", PortWriteTagDataFailed, PortWriteTagDataFailed));
  704. }
  705. public void CarrierArrived(Loadport lp)
  706. {
  707. SerializableDictionary<string, string> dvid = new SerializableDictionary<string, string>();
  708. dvid["PortID"] = lp.PortId;
  709. EV.Notify(CARRIER_ARRIVED, dvid);
  710. }
  711. public void CarrierRemoved(Loadport lp)
  712. {
  713. SerializableDictionary<string, string> dvid = new SerializableDictionary<string, string>();
  714. dvid["PortID"] = lp.PortId;
  715. dvid["CarrierID"] = lp.CarrierId ?? "";
  716. EV.Notify(CARRIER_REMOVED, dvid);
  717. }
  718. public void CarrierSlotMapComplete(Loadport lp)
  719. {
  720. SerializableDictionary<string, string> dvid = new SerializableDictionary<string, string>();
  721. dvid["SlotMap"] = lp.SlotMap;
  722. dvid["PortID"] = lp.PortId;
  723. dvid["CarrierID"] = lp.CarrierId ?? "";
  724. EV.Notify(SLOT_MAP_AVAILABLE, dvid);
  725. }
  726. public void CarrierSlotMapFailed(Loadport lp)
  727. {
  728. }
  729. public void LoadComplete(Loadport lp)
  730. {
  731. ModuleName moduleName = lp.Module;
  732. var dvid = new SerializableDictionary<string, string>
  733. {
  734. ["CarrierID"] = lp.CarrierId ?? "",
  735. ["PortID"] = lp.PortId.ToString()
  736. };
  737. EV.Notify(CARRIER_LOADED, dvid);
  738. }
  739. public void LoadFailed(Loadport lp)
  740. {
  741. }
  742. public void UnloadComplete(Loadport lp)
  743. {
  744. ModuleName moduleName = lp.Module;
  745. var dvid = new SerializableDictionary<string, string>
  746. {
  747. ["CarrierID"] = lp.CarrierId ?? "",
  748. ["PortID"] = lp.PortId.ToString()
  749. };
  750. EV.Notify(CARRIER_UNLOADED, dvid);
  751. }
  752. public void UnloadFailed(Loadport lp)
  753. {
  754. }
  755. public void Clamped(Loadport lp)
  756. {
  757. ModuleName moduleName = lp.Module;
  758. var dvid = new SerializableDictionary<string, string>
  759. {
  760. ["CarrierID"] = lp.CarrierId ?? "",
  761. ["PortID"] = lp.PortId.ToString()
  762. };
  763. EV.Notify(PortClamped, dvid);
  764. }
  765. public void Unclamped(Loadport lp)
  766. {
  767. ModuleName moduleName = lp.Module;
  768. var dvid = new SerializableDictionary<string, string>
  769. {
  770. ["CarrierID"] = lp.CarrierId ?? "",
  771. ["PortID"] = lp.PortId.ToString()
  772. };
  773. EV.Notify(PortUnclamped, dvid);
  774. }
  775. public void IDRead(Loadport lp)
  776. {
  777. }
  778. public void ReadIDFailed(Loadport lp)
  779. {
  780. }
  781. public void IDWrite(Loadport lp)
  782. {
  783. }
  784. public void WriteIDFailed(Loadport lp)
  785. {
  786. }
  787. public void TagDataRead(Loadport lp)
  788. {
  789. }
  790. public void ReadTagDataFailed(Loadport lp)
  791. {
  792. }
  793. public void TagDataWrite(Loadport lp)
  794. {
  795. }
  796. public void WriteTagDataFailed(Loadport lp)
  797. {
  798. }
  799. }
  800. }
  801. }