SchedulerQdrTimeManager.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. using Aitex.Core.RT.Fsm;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.SCCore;
  4. using Aitex.Core.Util;
  5. using CyberX8_RT.Dispatch;
  6. using CyberX8_RT.Modules.Metal;
  7. using CyberX8_RT.Modules.Rinse;
  8. using MECF.Framework.Common.Equipment;
  9. using MECF.Framework.Common.WaferHolder;
  10. using System;
  11. using System.Collections.Concurrent;
  12. using System.Collections.Generic;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. namespace CyberX8_RT.Schedulers
  17. {
  18. public class SchedulerQdrTimeManager: Singleton<SchedulerQdrTimeManager>
  19. {
  20. #region 内部变量
  21. private ConcurrentDictionary<string, List<SchedulerTime>> _qdrScheduleTimeDic = new ConcurrentDictionary<string, List<SchedulerTime>>();
  22. #endregion
  23. /// <summary>
  24. /// 重置
  25. /// </summary>
  26. /// <param name="modules"></param>
  27. /// <returns></returns>
  28. public List<ModuleName> ResetModuleOrder(List<string> modules,SchedulerModulePartTime qdrPartTime)
  29. {
  30. List<SchedulerModuleUse> schedulerModuleUses = new List<SchedulerModuleUse>();
  31. foreach (string module in modules)
  32. {
  33. SchedulerModuleUse moduleUse = new SchedulerModuleUse();
  34. moduleUse.ModuleName = (ModuleName)Enum.Parse(typeof(ModuleName),module);
  35. int partUsedCount = qdrPartTime.GetModuleUsedCount(module);
  36. moduleUse.Used = _qdrScheduleTimeDic.ContainsKey(module.ToString()) ? _qdrScheduleTimeDic[module].Count+partUsedCount : 0+ partUsedCount;
  37. schedulerModuleUses.Add(moduleUse);
  38. }
  39. List<ModuleName> results = schedulerModuleUses.OrderBy(O => O.Used).Select(O => O.ModuleName).ToList();
  40. return results;
  41. }
  42. /// <summary>
  43. /// 按照计划时间排序
  44. /// </summary>
  45. /// <param name="modules"></param>
  46. /// <returns></returns>
  47. public List<ModuleName> ResetModuleOrderBySchedulerEndTime(List<string> modules,SchedulerModulePartTime partTime)
  48. {
  49. List<SchedulerModuleEndTime> schedulerModuleUses = new List<SchedulerModuleEndTime>();
  50. foreach (string module in modules)
  51. {
  52. SchedulerModuleEndTime moduleEndTime = new SchedulerModuleEndTime();
  53. moduleEndTime.ModuleName = (ModuleName)Enum.Parse(typeof(ModuleName), module);
  54. if (_qdrScheduleTimeDic.ContainsKey(module))
  55. {
  56. List<SchedulerTime> schedulerTimes = _qdrScheduleTimeDic[module].OrderBy(O => O.ScheduleStartTime).ToList();
  57. SchedulerTime lastSchedulerTime = schedulerTimes.Last();
  58. DateTime lastSchedulerEndTime = lastSchedulerTime.ScheduleStartTime.AddSeconds(lastSchedulerTime.ProcessTimeLength);
  59. DateTime partEndTime = partTime.GetLastSchedulerTime(module);
  60. if (partEndTime > lastSchedulerEndTime)
  61. {
  62. moduleEndTime.SchedulerEndTime = partEndTime;
  63. }
  64. else
  65. {
  66. moduleEndTime.SchedulerEndTime = lastSchedulerEndTime;
  67. }
  68. }
  69. else
  70. {
  71. moduleEndTime.SchedulerEndTime = DateTime.MinValue;
  72. }
  73. schedulerModuleUses.Add(moduleEndTime);
  74. }
  75. List<ModuleName> results = schedulerModuleUses.OrderBy(O => O.SchedulerEndTime).Select(O => O.ModuleName).ToList();
  76. return results;
  77. }
  78. /// <summary>
  79. /// 按照计划时间排序
  80. /// </summary>
  81. /// <param name="modules"></param>
  82. /// <returns></returns>
  83. public List<ModuleName> ResetModuleOrderBySchedulerEndTime(List<IModuleEntity> modules)
  84. {
  85. List<SchedulerModuleEndTime> schedulerModuleUses = new List<SchedulerModuleEndTime>();
  86. foreach (IModuleEntity module in modules)
  87. {
  88. SchedulerModuleEndTime moduleEndTime = new SchedulerModuleEndTime();
  89. moduleEndTime.ModuleName = module.Module;
  90. if (_qdrScheduleTimeDic.ContainsKey(module.Module.ToString()))
  91. {
  92. List<SchedulerTime> schedulerTimes = _qdrScheduleTimeDic[module.Module.ToString()].OrderBy(O => O.ScheduleStartTime).ToList();
  93. SchedulerTime lastSchedulerTime = schedulerTimes.Last();
  94. DateTime lastSchedulerEndTime = lastSchedulerTime.ScheduleStartTime.AddSeconds(lastSchedulerTime.ProcessTimeLength);
  95. moduleEndTime.SchedulerEndTime = lastSchedulerEndTime;
  96. }
  97. else
  98. {
  99. moduleEndTime.SchedulerEndTime = DateTime.MinValue;
  100. }
  101. schedulerModuleUses.Add(moduleEndTime);
  102. }
  103. List<ModuleName> results = schedulerModuleUses.OrderBy(O => O.SchedulerEndTime).Select(O => O.ModuleName).ToList();
  104. return results;
  105. }
  106. /// <summary>
  107. /// 获取最后的时间轴对象
  108. /// </summary>
  109. /// <param name="metal"></param>
  110. /// <returns></returns>
  111. public SchedulerTime GetLastSchedulerTime(string metal)
  112. {
  113. if (_qdrScheduleTimeDic.ContainsKey(metal))
  114. {
  115. List<SchedulerTime> schedulerTimes = _qdrScheduleTimeDic[metal].OrderBy(O=>O.ScheduleStartTime).ToList();
  116. if (schedulerTimes.Count != 0)
  117. {
  118. return schedulerTimes.Last();
  119. }
  120. else
  121. {
  122. return null;
  123. }
  124. }
  125. else
  126. {
  127. return null;
  128. }
  129. }
  130. /// <summary>
  131. /// 增加
  132. /// </summary>
  133. /// <param name="qdr"></param>
  134. /// <param name="waferHolderId"></param>
  135. /// <param name="schedulerStartTime"></param>
  136. /// <param name="processTimeLength"></param>
  137. public void AddQdrScheduler(string qdr,string waferHolderId,int schedulerIndex,DateTime schedulerStartTime,int processTimeLength,bool writeQdrLog=true)
  138. {
  139. if (!_qdrScheduleTimeDic.ContainsKey(qdr))
  140. {
  141. SchedulerTime qdrTime = new SchedulerTime();
  142. qdrTime.WaferHolderId = waferHolderId;
  143. qdrTime.ScheduleStartTime = schedulerStartTime;
  144. qdrTime.ProcessTimeLength = processTimeLength;
  145. qdrTime.SchedulerIndex = schedulerIndex;
  146. List<SchedulerTime> schedulerQdrTimes = new List<SchedulerTime>();
  147. schedulerQdrTimes.Add(qdrTime);
  148. _qdrScheduleTimeDic.TryAdd(qdr, schedulerQdrTimes);
  149. }
  150. else
  151. {
  152. List<SchedulerTime> schedulerQdrTimes = _qdrScheduleTimeDic[qdr];
  153. if(schedulerQdrTimes.Find(O=>O.WaferHolderId==waferHolderId&&O.SchedulerIndex==schedulerIndex) == null)
  154. {
  155. SchedulerTime qdrTime = new SchedulerTime();
  156. qdrTime.WaferHolderId = waferHolderId;
  157. qdrTime.ScheduleStartTime = schedulerStartTime;
  158. qdrTime.ProcessTimeLength = processTimeLength;
  159. qdrTime.SchedulerIndex = schedulerIndex;
  160. schedulerQdrTimes.Add(qdrTime);
  161. }
  162. }
  163. if (writeQdrLog)
  164. {
  165. WriteQdrSchedulerTimeLog();
  166. }
  167. LOG.WriteLog(eEvent.INFO_RINSE, qdr, $"add wafer shuttle {waferHolderId} scheduler {schedulerIndex} qdr {qdr} in scheduler time");
  168. }
  169. /// <summary>
  170. /// 写Qdr调度时间轴日志
  171. /// </summary>
  172. /// <param name="key"></param>
  173. /// <param name="schedulerQdrTime"></param>
  174. public void WriteQdrSchedulerTimeLog()
  175. {
  176. List<string> keys = _qdrScheduleTimeDic.Keys.ToList();
  177. foreach (string key in keys)
  178. {
  179. List<SchedulerTime> schedulerQdrTimes = _qdrScheduleTimeDic[key].OrderBy(O=>O.ScheduleStartTime).ToList();
  180. foreach (SchedulerTime item in schedulerQdrTimes)
  181. {
  182. DateTime startTime = item.ScheduleStartTime;
  183. DateTime endTime = startTime.AddSeconds(item.ProcessTimeLength);
  184. LOG.WriteLog(eEvent.INFO_RINSE, key, $"wafer shuttle {item.WaferHolderId} scheduler {item.SchedulerIndex} qdr {key} start time {startTime} end time {endTime} processLength {item.ProcessTimeLength} s");
  185. }
  186. }
  187. }
  188. /// <summary>
  189. /// 更新QDR实际启动时间
  190. /// </summary>
  191. /// <param name="qdr"></param>
  192. /// <param name="startTime"></param>
  193. public void UpdateQdrStartTime(string qdr,string waferHolderId,int schedulerIndex,DateTime startTime)
  194. {
  195. if (_qdrScheduleTimeDic.ContainsKey(qdr))
  196. {
  197. List<SchedulerTime> schedulerQdrTimes= _qdrScheduleTimeDic[qdr];
  198. SchedulerTime schedulerQdrTime=schedulerQdrTimes.Find(O=>O.WaferHolderId==waferHolderId&&O.SchedulerIndex==schedulerIndex);
  199. if (schedulerQdrTime != null)
  200. {
  201. schedulerQdrTime.StartTime = startTime;
  202. if (schedulerQdrTime.StartTime > schedulerQdrTime.ScheduleStartTime)
  203. {
  204. LOG.WriteLog(eEvent.INFO_RINSE, qdr, $"wafer shuttle {waferHolderId} scheduler {schedulerIndex} qdr {qdr} start time {startTime} after scheduler start time {schedulerQdrTime.ScheduleStartTime}");
  205. double interSeconds = schedulerQdrTime.StartTime.Subtract(schedulerQdrTime.ScheduleStartTime).TotalSeconds;
  206. schedulerQdrTime.ScheduleStartTime = schedulerQdrTime.StartTime;
  207. SchedulerMetalTimeManager.Instance.DelayMetalSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds);
  208. DelayQdrSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds);
  209. SchedulerDryerTimeManager.Instance.DelayDryerSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds);
  210. SchedulerTransporterTimeManager.Instance.DelayTransporterSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds);
  211. SchedulerWaferHolderTimeManager.Instance.DelayWaferHolderSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds);
  212. }
  213. LOG.WriteLog(eEvent.INFO_RINSE, qdr, $"update wafer shuttle {waferHolderId} scheduler {schedulerIndex} qdr {qdr} start time {startTime}");
  214. }
  215. }
  216. }
  217. /// <summary>
  218. /// 延后qdr后续时间
  219. /// </summary>
  220. /// <param name="waferHolderId"></param>
  221. /// <param name="schedulerIndex"></param>
  222. /// <param name="seconds"></param>
  223. public void DelayQdrSchedulerStartTime(string waferHolderId, int schedulerIndex, double seconds)
  224. {
  225. List<string> keys = _qdrScheduleTimeDic.Keys.ToList();
  226. foreach (string key in keys)
  227. {
  228. List<SchedulerTime> schedulerTimes = _qdrScheduleTimeDic[key];
  229. List<SchedulerTime> postSchedulerTimes = schedulerTimes.FindAll(O => O.WaferHolderId == waferHolderId && O.SchedulerIndex > schedulerIndex);
  230. foreach (SchedulerTime schedulerTime in postSchedulerTimes)
  231. {
  232. schedulerTime.ScheduleStartTime = schedulerTime.ScheduleStartTime.AddSeconds(seconds);
  233. }
  234. }
  235. }
  236. /// <summary>
  237. /// 移除
  238. /// </summary>
  239. /// <param name="qdr"></param>
  240. public void RemoveQdrStartTime(string qdr,string waferHolderId,int schedulerIndex)
  241. {
  242. if (_qdrScheduleTimeDic.ContainsKey(qdr))
  243. {
  244. List<SchedulerTime> schedulerQdrTimes = _qdrScheduleTimeDic[qdr];
  245. SchedulerTime schedulerQdrTime = schedulerQdrTimes.Find(O => O.WaferHolderId == waferHolderId && O.SchedulerIndex == schedulerIndex);
  246. if (schedulerQdrTime != null)
  247. {
  248. LOG.WriteLog(eEvent.INFO_RINSE, qdr, $"remove wafer shuttle {waferHolderId} scheduler {schedulerIndex} qdr {qdr} in scheduler time");
  249. schedulerQdrTimes.Remove(schedulerQdrTime);
  250. }
  251. if (schedulerQdrTimes.Count == 0)
  252. {
  253. _qdrScheduleTimeDic.TryRemove(qdr, out schedulerQdrTimes);
  254. LOG.WriteLog(eEvent.INFO_RINSE, qdr, $"delete wafer shuttle {waferHolderId} scheduler {schedulerIndex} qdr {qdr} in scheduler time");
  255. }
  256. }
  257. }
  258. /// <summary>
  259. /// 检验QDR是否冲突
  260. /// </summary>
  261. /// <param name="waferHolderId"></param>
  262. /// <param name="schedulerStartTime"></param>
  263. /// <param name="processTimeLength"></param>
  264. /// <returns></returns>
  265. public (bool conflict,string waferHolderId,int schedluerIndex) CheckQdrConflict(string qdr,string waferHolderId, DateTime schedulerStartTime, int processTimeLength)
  266. {
  267. if (!_qdrScheduleTimeDic.ContainsKey(qdr))
  268. {
  269. return (false, "", -1);
  270. }
  271. List<SchedulerTime> schedulerQdrTimes= _qdrScheduleTimeDic[qdr];
  272. foreach(SchedulerTime item in schedulerQdrTimes)
  273. {
  274. if (item.WaferHolderId == waferHolderId)
  275. {
  276. continue;
  277. }
  278. //if (WaferHolderManager.Instance.HasWaferHolder(qdr))
  279. //{
  280. // WaferHolderInfo waferHolderInfo = WaferHolderManager.Instance.GetWaferHolder(qdr);
  281. // if (waferHolderInfo!=null)
  282. // {
  283. // WaferHolderTask waferHolderTask= WaferHolderTaskManager.Instance.GetWaferHolderTaskByWaferHolderId(waferHolderInfo.Id);
  284. // if (waferHolderTask != null)
  285. // {
  286. // return (true, waferHolderInfo.Id, waferHolderTask.GetCurrentSchedulerIndex());
  287. // }
  288. // return (true, "", -1);
  289. // }
  290. // return (true, "", -1);
  291. //}
  292. bool result=CheckQdrTimeConflict(item,schedulerStartTime, processTimeLength);
  293. if (result)
  294. {
  295. return (true,item.WaferHolderId,item.SchedulerIndex);
  296. }
  297. }
  298. return (false, "", -1);
  299. }
  300. /// <summary>
  301. /// 判定时间是否冲突
  302. /// </summary>
  303. /// <param name="schedulerQdrTime"></param>
  304. /// <param name="schedulerStartTime"></param>
  305. /// <param name="processTimeLength"></param>
  306. /// <returns></returns>
  307. private bool CheckQdrTimeConflict(SchedulerTime schedulerQdrTime, DateTime schedulerStartTime, int processTimeLength)
  308. {
  309. int transporterTransferSeconds = SC.GetValue<int>("Transporter.TransporterTransferSeconds");
  310. DateTime schedulerEndTime = schedulerStartTime.AddSeconds(processTimeLength);
  311. DateTime qdrEndTime = schedulerQdrTime.ScheduleStartTime.AddSeconds(schedulerQdrTime.ProcessTimeLength);
  312. DateTime qdrStartTime= schedulerQdrTime.ScheduleStartTime;
  313. if (schedulerStartTime > qdrEndTime.AddSeconds(transporterTransferSeconds))
  314. {
  315. return false;
  316. }
  317. if (schedulerEndTime.AddSeconds(transporterTransferSeconds) < qdrStartTime)
  318. {
  319. return false;
  320. }
  321. return true;
  322. }
  323. /// <summary>
  324. /// 计算QDR调度预计开始时间
  325. /// </summary>
  326. /// <param name="depRecipeTimeLength"></param>
  327. /// <returns></returns>
  328. public DateTime CalculateQdrSchedulerStartTime(DateTime dateTime,int depRecipeTimeLength)
  329. {
  330. int transporterTransferSeconds = SC.GetValue<int>("Transporter.TransporterTransferSeconds");
  331. //DEP的Recipe时长+transporter传输时间
  332. return dateTime.AddSeconds(depRecipeTimeLength).AddSeconds(transporterTransferSeconds);
  333. }
  334. /// <summary>
  335. /// 清除所有
  336. /// </summary>
  337. public void RemoveAll()
  338. {
  339. List<string> keys = _qdrScheduleTimeDic.Keys.ToList();
  340. foreach (string key in keys)
  341. {
  342. List<SchedulerTime> schedulerTimes = _qdrScheduleTimeDic[key];
  343. schedulerTimes.Clear();
  344. }
  345. _qdrScheduleTimeDic.Clear();
  346. LOG.Write(eEvent.INFO_RINSE,"System", "Remove all qdr scheduler time");
  347. }
  348. }
  349. }