SchedulerQdrTimeManager.cs 17 KB

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