SchedulerDryerTimeManager.cs 15 KB

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