SchedulerPrewet.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. using Aitex.Common.Util;
  2. using Aitex.Core.RT.ConfigCenter;
  3. using Aitex.Core.RT.Log;
  4. using Aitex.Core.Util;
  5. using MECF.Framework.Common.Equipment;
  6. using MECF.Framework.Common.RecipeCenter;
  7. using CyberX8_Core;
  8. using CyberX8_RT.Modules;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using CyberX8_RT.Modules.Prewet;
  15. using MECF.Framework.Common.CommonData;
  16. using Aitex.Core.RT.Fsm;
  17. using Aitex.Core.RT.SCCore;
  18. using CyberX8_RT.Modules.Rinse;
  19. using CyberX8_RT.Dispatch;
  20. using CyberX8_RT.Schedulers.Transporter;
  21. namespace CyberX8_RT.Schedulers.Prewet
  22. {
  23. public class SchedulerPrewet : SchedulerModule
  24. {
  25. private enum PrewetOperation
  26. {
  27. None,
  28. RunRecipe,
  29. WaitForPick,
  30. Keepwet
  31. }
  32. #region 内部变量
  33. /// <summary>
  34. /// Prewet实体
  35. /// </summary>
  36. private PrewetEntity _prewetEntity;
  37. /// <summary>
  38. /// keep wet次数
  39. /// </summary>
  40. private int _keepwetCount = 0;
  41. /// <summary>
  42. /// keep wet限制次数
  43. /// </summary>
  44. private int _keepwetLimit = 0;
  45. /// <summary>
  46. /// 当前操作
  47. /// </summary>
  48. private PrewetOperation _currentOperation=PrewetOperation.None;
  49. #endregion
  50. #region 属性
  51. /// <summary>
  52. /// 是否空闲
  53. /// </summary>
  54. public override bool IsIdle
  55. {
  56. get { return _state == RState.End; }
  57. }
  58. /// <summary>
  59. /// 是否错误
  60. /// </summary>
  61. public override bool IsError
  62. {
  63. get { return _state == RState.Failed || _state == RState.Timeout; }
  64. }
  65. #endregion
  66. /// <summary>
  67. /// 构造函数
  68. /// </summary>
  69. /// <param name="module"></param>
  70. public SchedulerPrewet(ModuleName moduleName) : base(moduleName.ToString())
  71. {
  72. _prewetEntity = Singleton<RouteManager>.Instance.GetModule<PrewetEntity>(moduleName.ToString());
  73. }
  74. /// <summary>
  75. /// 执行
  76. /// </summary>
  77. /// <param name="parameter"></param>
  78. /// <returns></returns>
  79. public override bool RunProcess(object recipe, object parameter, List<SchedulerSyncModuleMessage> syncModuleMessages)
  80. {
  81. if (!(recipe is PwtRecipe))
  82. {
  83. _state = RState.Failed;
  84. LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), "recipe is invalid");
  85. return false;
  86. }
  87. _keepwetCount = 0;
  88. _keepwetLimit = SC.GetValue<int>("Prewet.KeepWetMaxLimit");
  89. PwtRecipe pwtRecipe = (PwtRecipe)recipe;
  90. bool result = _prewetEntity.CheckToPostMessage<PrewetState, PrewetMsg>(eEvent.ERR_PREWET, Module.ToString(), (int)PrewetMsg.RunRecipe, pwtRecipe,1);
  91. if (result)
  92. {
  93. _state = RState.Running;
  94. _currentOperation = PrewetOperation.RunRecipe;
  95. }
  96. return result;
  97. }
  98. /// <summary>
  99. /// 监控执行
  100. /// </summary>
  101. /// <returns></returns>
  102. public override bool MonitorProcess(SchedulerSequence schedulerSequence, bool hasMatchWafer)
  103. {
  104. bool exsitEnableCell = false;
  105. if (_prewetEntity.IsError)
  106. {
  107. _state=RState.Failed;
  108. return true;
  109. }
  110. if (_prewetEntity.State == (int)PrewetState.WaitForPick || (_prewetEntity.IsIdle && _prewetEntity.WaferHolderInfo == null))
  111. {
  112. _state = RState.End;
  113. _currentOperation = PrewetOperation.None;
  114. return true;
  115. }
  116. string waferHolderId = _prewetEntity.WaferHolderInfo?.Id;
  117. if (_prewetEntity.State==(int)PrewetState.RunRecipeComplete&&_currentOperation==PrewetOperation.RunRecipe)
  118. {
  119. CheckNextModuleCondition(schedulerSequence,waferHolderId,ref exsitEnableCell);
  120. }
  121. else if((_prewetEntity.State==(int)PrewetState.DelayKeepwetComplete)&&_currentOperation==PrewetOperation.Keepwet)
  122. {
  123. if(_keepwetCount>_keepwetLimit)
  124. {
  125. LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"keepwet count {_keepwetCount} over limit {_keepwetLimit}");
  126. _state = RState.Failed;
  127. }
  128. else
  129. {
  130. CheckNextModuleTimeToReady(schedulerSequence,waferHolderId,ref exsitEnableCell);
  131. }
  132. }
  133. else if (_prewetEntity.State == (int)PrewetState.DelayKeepweting && _currentOperation == PrewetOperation.Keepwet)
  134. {
  135. CheckNextModuleTimeToReady(schedulerSequence,waferHolderId, ref exsitEnableCell);
  136. }
  137. return true;
  138. }
  139. /// <summary>
  140. /// 检验下一个
  141. /// </summary>
  142. /// <param name="sequence"></param>
  143. /// <returns></returns>
  144. private void CheckNextModuleCondition(SchedulerSequence sequence, string waferHolderId, ref bool existEnableCell)
  145. {
  146. PwtRecipe pwtRecipe = (PwtRecipe)sequence.Recipe;
  147. if(!pwtRecipe.KeepWet)
  148. {
  149. NotifyPrewetReadyForPick("prewet no keepwet");
  150. return;
  151. }
  152. CheckNextModuleTimeToReady(sequence,waferHolderId,ref existEnableCell);
  153. }
  154. /// <summary>
  155. /// 检验下一模块剩余时间
  156. /// </summary>
  157. /// <param name="sequence"></param>
  158. private void CheckNextModuleTimeToReady(SchedulerSequence sequence,string waferHolderId, ref bool existEnableCell)
  159. {
  160. int idleKeepwetPauseBetweenScanSeconds = SC.GetValue<int>("Prewet.IdleKeepwetPauseBetweenScanSeconds");
  161. int transporterTransferSeconds = SC.GetValue<int>("Transporter.TransporterTransferSeconds");
  162. ModuleType nextModuleType = sequence.NextModuleType;
  163. if (nextModuleType == ModuleType.Metal)
  164. {
  165. if (!(sequence.NextRecipe is DepRecipe))
  166. {
  167. NotifyPrewetReadyForPick("sequence nextRecipe is not deprecipe");
  168. }
  169. else
  170. {
  171. bool isQdrCheckConflict = SchedulerManager.Instance.IsQdrCheckConflict;
  172. DepRecipe depRecipe = sequence.NextRecipe as DepRecipe;
  173. ModuleName metalModule = ModuleName.Unknown;
  174. SchedulerSequence metalSequence = WaferHolderTaskManager.Instance.GetNextMetalSequence(sequence.SequenceIndex, waferHolderId);
  175. if (!isQdrCheckConflict || metalSequence == null || metalSequence.NextRecipe == null || metalSequence.NextModuleType != ModuleType.Rinse)
  176. {
  177. metalModule = SchedulerSequenceManager.Instance.CalculateAvaibleMetalCellByChemistry(depRecipe.Chemistry, "", sequence.SequenceType,sequence.WaferSize, ref existEnableCell);
  178. }
  179. else
  180. {
  181. QdrRecipe qdrRecipe = (QdrRecipe)metalSequence.NextRecipe;
  182. int depRecipeTimeLength = depRecipe.CalculateRecipeTotalTime();
  183. int qdrRecipeTimeLength = qdrRecipe.CalculateRunRecipeTime();
  184. WaferHolderTask waferHolderTask = WaferHolderTaskManager.Instance.GetWaferHolderTaskByWaferHolderId(waferHolderId);
  185. if (waferHolderTask == null)
  186. {
  187. return;
  188. }
  189. SchedulerSequence transporterSequence = WaferHolderTaskManager.Instance.GetNextTransporterlSequence(sequence.SequenceIndex, waferHolderId);
  190. if (transporterSequence == null)
  191. {
  192. return;
  193. }
  194. bool result = true;
  195. if(!(transporterSequence.Parameters is TransporterAction))
  196. {
  197. return;
  198. }
  199. TransporterAction transporterAction=transporterSequence.Parameters as TransporterAction;
  200. WaferHolderMoveItem waferHolderMoveItem = transporterAction.Parameter as WaferHolderMoveItem;
  201. if (waferHolderMoveItem.DestModule == ModuleName.Unknown)
  202. {
  203. result = SchedulerModuleTimeManager.Instance.ConfirmAllMetalQdrAndDryer(waferHolderTask.SchedulerSequences, waferHolderId, waferHolderTask.GetCurrentSchedulerIndex(), true, DateTime.Now);
  204. }
  205. if (result)
  206. {
  207. CheckNextModuleAvaible(waferHolderMoveItem.DestModule.ToString(), transporterTransferSeconds);
  208. }
  209. else
  210. {
  211. NotifyPrewetKeepWet();
  212. }
  213. return;
  214. }
  215. if (metalModule != ModuleName.Unknown)
  216. {
  217. CheckNextModuleAvaible(metalModule.ToString(), transporterTransferSeconds);
  218. }
  219. else
  220. {
  221. if (existEnableCell)
  222. {
  223. NotifyPrewetKeepWet();
  224. }
  225. else
  226. {
  227. NotifyPrewetReadyForPick($"no enable metal");
  228. }
  229. }
  230. }
  231. }
  232. else
  233. {
  234. ModuleName moduleName = SchedulerSequenceManager.Instance.GetAvaibleEmptyModuleCell(nextModuleType, sequence.SequenceType);
  235. if (moduleName != ModuleName.Unknown)
  236. {
  237. CheckNextModuleAvaible(moduleName.ToString(), idleKeepwetPauseBetweenScanSeconds);
  238. }
  239. else
  240. {
  241. NotifyPrewetKeepWet();
  242. }
  243. }
  244. }
  245. /// <summary>
  246. /// 检验下一个模块是否可用
  247. /// </summary>
  248. /// <param name="moduleName"></param>
  249. /// <param name="resSecond"></param>
  250. private void CheckNextModuleAvaible(string moduleName, int resSecond)
  251. {
  252. IModuleEntity moduleEntity = Singleton<RouteManager>.Instance.GetModule<IModuleEntity>(moduleName);
  253. if (moduleEntity.IsIdle)
  254. {
  255. NotifyPrewetReadyForPick($"{moduleEntity.Module} is idle");
  256. }
  257. else
  258. {
  259. if (moduleEntity.TimeToReady <= resSecond)
  260. {
  261. NotifyPrewetReadyForPick($"{moduleEntity.Module} remain seconds {moduleEntity.TimeToReady}");
  262. }
  263. else
  264. {
  265. NotifyPrewetKeepWet();
  266. }
  267. }
  268. }
  269. /// <summary>
  270. /// 通知Prewet准备Process for pick
  271. /// </summary>
  272. private void NotifyPrewetReadyForPick(string reason)
  273. {
  274. bool result= _prewetEntity.CheckToPostMessage<PrewetState, PrewetMsg>(eEvent.ERR_PREWET, Module.ToString(),
  275. (int)PrewetMsg.PrepareToPick);
  276. if (result)
  277. {
  278. _currentOperation = PrewetOperation.WaitForPick;
  279. LOG.WriteLog(eEvent.INFO_PREWET, Module.ToString(), reason);
  280. }
  281. }
  282. /// <summary>
  283. /// 通知Prewet准备Keep Wet
  284. /// </summary>
  285. private void NotifyPrewetKeepWet()
  286. {
  287. if (_prewetEntity.State == (int)PrewetState.DelayKeepweting)
  288. {
  289. return;
  290. }
  291. bool result= _prewetEntity.CheckToPostMessage<PrewetState, PrewetMsg>(eEvent.ERR_PREWET, ModuleName.Prewet1.ToString(),
  292. (int)PrewetMsg.DelayKeepwet);
  293. if(result)
  294. {
  295. if (_currentOperation != PrewetOperation.Keepwet)
  296. {
  297. _currentOperation = PrewetOperation.Keepwet;
  298. }
  299. _keepwetCount++;
  300. }
  301. }
  302. /// <summary>
  303. /// 检验前置条件
  304. /// </summary>
  305. /// <param name="sequenceIndex"></param>
  306. /// <param name="parameter"></param>
  307. /// <returns></returns>
  308. public override bool CheckPrecondition(List<SchedulerSequence> schedulerSequences, int sequenceIndex, object parameter,string materialId,ref string reason)
  309. {
  310. if (_state == RState.Running)
  311. {
  312. reason = "scheduler module is already running";
  313. return false;
  314. }
  315. if (_prewetEntity.State!=(int)PrewetState.WaitForPlace)
  316. {
  317. reason = "prewet state is not WaitForPlace";
  318. return false;
  319. }
  320. if(_prewetEntity.WaferHolderInfo==null)
  321. {
  322. reason = "prewet has no wafer shuttle";
  323. return false;
  324. }
  325. if (_prewetEntity.WaferHolderInfo.Id != materialId)
  326. {
  327. reason = $"{_prewetEntity.Module} wafer shuttle {_prewetEntity.WaferHolderInfo.Id} is not matched with {materialId}";
  328. return false;
  329. }
  330. _currentOperation = PrewetOperation.None;
  331. return true;
  332. }
  333. }
  334. }