SchedulerMetalTimeManager.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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 SchedulerMetalTimeManager: Singleton<SchedulerMetalTimeManager>
  19. {
  20. #region 内部变量
  21. private ConcurrentDictionary<string, List<SchedulerTime>> _metalScheduleTimeDic = 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<MetalEntity> modules)
  29. {
  30. List<SchedulerModuleUse> schedulerModuleUses = new List<SchedulerModuleUse>();
  31. foreach (IModuleEntity module in modules)
  32. {
  33. SchedulerModuleUse moduleUse = new SchedulerModuleUse();
  34. moduleUse.ModuleName = module.Module;
  35. moduleUse.Used = _metalScheduleTimeDic.ContainsKey(module.Module.ToString()) ? _metalScheduleTimeDic[module.Module.ToString()].Count : 0;
  36. schedulerModuleUses.Add(moduleUse);
  37. }
  38. List<ModuleName> results = schedulerModuleUses.OrderBy(O => O.Used).Select(O => O.ModuleName).ToList();
  39. return results;
  40. }
  41. /// <summary>
  42. /// 计算Metal已经使用次数
  43. /// </summary>
  44. /// <param name="metal"></param>
  45. /// <param name="metalPartTime"></param>
  46. /// <returns></returns>
  47. public int CalculateMetalUsed(string metal,SchedulerModulePartTime metalPartTime)
  48. {
  49. int usedCount = _metalScheduleTimeDic.ContainsKey(metal) ? _metalScheduleTimeDic[metal].Count : 0;
  50. return metalPartTime.GetModuleUsedCount(metal) + usedCount;
  51. }
  52. /// <summary>
  53. /// 按照计划时间排序
  54. /// </summary>
  55. /// <param name="modules"></param>
  56. /// <returns></returns>
  57. public List<ModuleName> ResetModuleOrderBySchedulerEndTime(List<IModuleEntity> modules)
  58. {
  59. List<SchedulerModuleEndTime> schedulerModuleUses = new List<SchedulerModuleEndTime>();
  60. foreach (IModuleEntity module in modules)
  61. {
  62. SchedulerModuleEndTime moduleEndTime = new SchedulerModuleEndTime();
  63. moduleEndTime.ModuleName = module.Module;
  64. if (_metalScheduleTimeDic.ContainsKey(module.Module.ToString()))
  65. {
  66. List<SchedulerTime> schedulerTimes = _metalScheduleTimeDic[module.Module.ToString()].OrderBy(O=>O.ScheduleStartTime).ToList();
  67. SchedulerTime lastSchedulerTime = schedulerTimes.Last();
  68. DateTime lastSchedulerEndTime = lastSchedulerTime.ScheduleStartTime.AddSeconds(lastSchedulerTime.ProcessTimeLength);
  69. moduleEndTime.SchedulerEndTime = lastSchedulerEndTime;
  70. }
  71. else
  72. {
  73. moduleEndTime.SchedulerEndTime = DateTime.MinValue;
  74. }
  75. schedulerModuleUses.Add(moduleEndTime);
  76. }
  77. List<ModuleName> results = schedulerModuleUses.OrderBy(O => O.SchedulerEndTime).Select(O => O.ModuleName).ToList();
  78. return results;
  79. }
  80. /// <summary>
  81. /// 获取最后的时间轴对象
  82. /// </summary>
  83. /// <param name="metal"></param>
  84. /// <returns></returns>
  85. public SchedulerTime GetLastSchedulerTime(string metal)
  86. {
  87. if (_metalScheduleTimeDic.ContainsKey(metal))
  88. {
  89. List<SchedulerTime> schedulerTimes = _metalScheduleTimeDic[metal].OrderBy(O=>O.ScheduleStartTime).ToList();
  90. if (schedulerTimes.Count != 0)
  91. {
  92. return schedulerTimes.Last();
  93. }
  94. else
  95. {
  96. return null;
  97. }
  98. }
  99. else
  100. {
  101. return null;
  102. }
  103. }
  104. /// <summary>
  105. /// 增加
  106. /// </summary>
  107. /// <param name="metal"></param>
  108. /// <param name="waferHolderId"></param>
  109. /// <param name="schedulerStartTime"></param>
  110. /// <param name="processTimeLength"></param>
  111. public void AddMetalScheduler(string metal,string waferHolderId,int schedulerIndex,DateTime schedulerStartTime,int processTimeLength,bool writeMetalLog=true)
  112. {
  113. if (!_metalScheduleTimeDic.ContainsKey(metal))
  114. {
  115. SchedulerTime metalTime = new SchedulerTime();
  116. metalTime.WaferHolderId = waferHolderId;
  117. metalTime.ScheduleStartTime = schedulerStartTime;
  118. metalTime.ProcessTimeLength = processTimeLength;
  119. metalTime.SchedulerIndex = schedulerIndex;
  120. List<SchedulerTime> schedulerMetalTimes = new List<SchedulerTime>();
  121. schedulerMetalTimes.Add(metalTime);
  122. _metalScheduleTimeDic.TryAdd(metal, schedulerMetalTimes);
  123. }
  124. else
  125. {
  126. List<SchedulerTime> schedulerMetalTimes = _metalScheduleTimeDic[metal];
  127. if(schedulerMetalTimes.Find(O=>O.WaferHolderId==waferHolderId&&O.SchedulerIndex==schedulerIndex) == null)
  128. {
  129. SchedulerTime metalTime = new SchedulerTime();
  130. metalTime.WaferHolderId = waferHolderId;
  131. metalTime.ScheduleStartTime = schedulerStartTime;
  132. metalTime.ProcessTimeLength = processTimeLength;
  133. metalTime.SchedulerIndex = schedulerIndex;
  134. schedulerMetalTimes.Add(metalTime);
  135. }
  136. }
  137. if (writeMetalLog)
  138. {
  139. WriteMetalSchedulerTimeLog();
  140. }
  141. LOG.WriteLog(eEvent.INFO_METAL, metal, $"add wafer shuttle {waferHolderId} scheduler {schedulerIndex} metal {metal} in scheduler time");
  142. }
  143. /// <summary>
  144. /// 写Metal调度时间轴日志
  145. /// </summary>
  146. public void WriteMetalSchedulerTimeLog()
  147. {
  148. List<string> keys = _metalScheduleTimeDic.Keys.ToList();
  149. foreach (string key in keys)
  150. {
  151. List<SchedulerTime> schedulerMetalTimes = _metalScheduleTimeDic[key].OrderBy(O=>O.ScheduleStartTime).ToList();
  152. foreach (SchedulerTime item in schedulerMetalTimes)
  153. {
  154. DateTime startTime = item.ScheduleStartTime;
  155. DateTime endTime = startTime.AddSeconds(item.ProcessTimeLength);
  156. LOG.WriteLog(eEvent.INFO_METAL, key, $"wafer shuttle {item.WaferHolderId} scheduler {item.SchedulerIndex} metal {key} start time {startTime} end time {endTime} processLength {item.ProcessTimeLength} s");
  157. }
  158. }
  159. }
  160. /// <summary>
  161. /// 更新Metal实际启动时间
  162. /// </summary>
  163. /// <param name="metal"></param>
  164. /// <param name="startTime"></param>
  165. public void UpdateMetalStartTime(string metal,string waferHolderId,int schedulerIndex,DateTime startTime)
  166. {
  167. if (_metalScheduleTimeDic.ContainsKey(metal))
  168. {
  169. List<SchedulerTime> schedulerMetalTimes= _metalScheduleTimeDic[metal];
  170. SchedulerTime schedulerMetalTime=schedulerMetalTimes.Find(O=>O.WaferHolderId==waferHolderId&&O.SchedulerIndex==schedulerIndex);
  171. if (schedulerMetalTime != null)
  172. {
  173. schedulerMetalTime.StartTime = startTime;
  174. if (schedulerMetalTime.StartTime > schedulerMetalTime.ScheduleStartTime)
  175. {
  176. LOG.WriteLog(eEvent.INFO_METAL, metal, $"wafer shuttle {waferHolderId} scheduler {schedulerIndex} metal {metal} start time {startTime} after scheduler start time {schedulerMetalTime.ScheduleStartTime}");
  177. double interSeconds = schedulerMetalTime.StartTime.Subtract(schedulerMetalTime.ScheduleStartTime).TotalSeconds;
  178. schedulerMetalTime.ScheduleStartTime = schedulerMetalTime.StartTime;
  179. DelayMetalSchedulerStartTime(waferHolderId,schedulerIndex, interSeconds);
  180. SchedulerQdrTimeManager.Instance.DelayQdrSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds);
  181. SchedulerDryerTimeManager.Instance.DelayDryerSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds);
  182. SchedulerTransporterTimeManager.Instance.DelayTransporterSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds);
  183. SchedulerWaferHolderTimeManager.Instance.DelayWaferHolderSchedulerStartTime(waferHolderId, schedulerIndex, interSeconds);
  184. }
  185. LOG.WriteLog(eEvent.INFO_METAL, metal, $"update wafer shuttle {waferHolderId} scheduler {schedulerIndex} metal {metal} start time {startTime}");
  186. }
  187. }
  188. }
  189. /// <summary>
  190. /// 延后metal后续时间
  191. /// </summary>
  192. /// <param name="waferHolderId"></param>
  193. /// <param name="schedulerIndex"></param>
  194. /// <param name="seconds"></param>
  195. public void DelayMetalSchedulerStartTime(string waferHolderId,int schedulerIndex,double seconds)
  196. {
  197. List<string> keys = _metalScheduleTimeDic.Keys.ToList();
  198. foreach(string key in keys)
  199. {
  200. List<SchedulerTime> schedulerTimes= _metalScheduleTimeDic[key];
  201. List<SchedulerTime> postSchedulerTimes= schedulerTimes.FindAll(O => O.WaferHolderId == waferHolderId && O.SchedulerIndex > schedulerIndex);
  202. foreach(SchedulerTime schedulerTime in postSchedulerTimes)
  203. {
  204. schedulerTime.ScheduleStartTime=schedulerTime.ScheduleStartTime.AddSeconds(seconds);
  205. }
  206. }
  207. }
  208. /// <summary>
  209. /// 是否为第一个Metal
  210. /// </summary>
  211. /// <param name="waferHolderId"></param>
  212. /// <param name="scheduleIndex"></param>
  213. /// <returns></returns>
  214. private bool IsFirstMetal(string waferHolderId,int scheduleIndex)
  215. {
  216. WaferHolderTask task = WaferHolderTaskManager.Instance.GetWaferHolderTaskByWaferHolderId(waferHolderId);
  217. if (task == null)
  218. {
  219. return false;
  220. }
  221. for(int i = 0; i < task.SchedulerSequences.Count; i++)
  222. {
  223. SchedulerSequence sequence=task.SchedulerSequences[i];
  224. if (sequence.ModuleType == ModuleType.Metal&&scheduleIndex==i)
  225. {
  226. return true;
  227. }
  228. }
  229. return false;
  230. }
  231. /// <summary>
  232. /// 移除
  233. /// </summary>
  234. /// <param name="metal"></param>
  235. public void RemoveMetalStartTime(string metal,string waferHolderId,int schedulerIndex)
  236. {
  237. if (_metalScheduleTimeDic.ContainsKey(metal))
  238. {
  239. List<SchedulerTime> schedulerMetalTimes = _metalScheduleTimeDic[metal];
  240. SchedulerTime schedulerMetalTime = schedulerMetalTimes.Find(O => O.WaferHolderId == waferHolderId && O.SchedulerIndex == schedulerIndex);
  241. if (schedulerMetalTime != null)
  242. {
  243. LOG.WriteLog(eEvent.INFO_RINSE, metal, $"remove wafer shuttle {waferHolderId} scheduler {schedulerIndex} metal {metal} in scheduler time");
  244. schedulerMetalTimes.Remove(schedulerMetalTime);
  245. }
  246. if (schedulerMetalTimes.Count == 0)
  247. {
  248. _metalScheduleTimeDic.TryRemove(metal, out schedulerMetalTimes);
  249. LOG.WriteLog(eEvent.INFO_METAL, metal, $"delete wafer shuttle {waferHolderId} scheduler {schedulerIndex} metal {metal} in scheduler time");
  250. }
  251. }
  252. }
  253. /// <summary>
  254. /// 检验Metal是否冲突
  255. /// </summary>
  256. /// <param name="waferHolderId"></param>
  257. /// <param name="schedulerStartTime"></param>
  258. /// <param name="processTimeLength"></param>
  259. /// <returns></returns>
  260. public (bool conflict,string waferHolderId,int schedluerIndex) CheckMetalConflict(string metal,string waferHolderId, DateTime schedulerStartTime, int processTimeLength)
  261. {
  262. if (!_metalScheduleTimeDic.ContainsKey(metal))
  263. {
  264. return (false, "", -1);
  265. }
  266. List<SchedulerTime> schedulerMetalTimes= _metalScheduleTimeDic[metal];
  267. foreach(SchedulerTime item in schedulerMetalTimes)
  268. {
  269. if (item.WaferHolderId == waferHolderId)
  270. {
  271. continue;
  272. }
  273. //if (WaferHolderManager.Instance.HasWaferHolder(metal))
  274. //{
  275. // WaferHolderInfo waferHolderInfo = WaferHolderManager.Instance.GetWaferHolder(metal);
  276. // if (waferHolderInfo==null)
  277. // {
  278. // return (true, "", -1);
  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. bool result=CheckMetalTimeConflict(item,schedulerStartTime, processTimeLength);
  288. if (result)
  289. {
  290. return (true,item.WaferHolderId,item.SchedulerIndex);
  291. }
  292. }
  293. return (false, "", -1);
  294. }
  295. /// <summary>
  296. /// 判定时间是否冲突
  297. /// </summary>
  298. /// <param name="schedulerMetalTime"></param>
  299. /// <param name="schedulerStartTime"></param>
  300. /// <param name="processTimeLength"></param>
  301. /// <returns></returns>
  302. private bool CheckMetalTimeConflict(SchedulerTime schedulerMetalTime, DateTime schedulerStartTime, int processTimeLength)
  303. {
  304. int transporterTransferSeconds = SC.GetValue<int>("Transporter.TransporterTransferSeconds");
  305. DateTime schedulerEndTime = schedulerStartTime.AddSeconds(processTimeLength);
  306. DateTime metalEndTime = schedulerMetalTime.ScheduleStartTime.AddSeconds(schedulerMetalTime.ProcessTimeLength);
  307. DateTime metalStartTime= schedulerMetalTime.ScheduleStartTime;
  308. if (schedulerStartTime > metalEndTime.AddSeconds(transporterTransferSeconds))
  309. {
  310. return false;
  311. }
  312. if (schedulerEndTime.AddSeconds(transporterTransferSeconds) < metalStartTime)
  313. {
  314. return false;
  315. }
  316. return true;
  317. }
  318. /// <summary>
  319. /// 清除所有
  320. /// </summary>
  321. public void RemoveAll()
  322. {
  323. List<string> keys = _metalScheduleTimeDic.Keys.ToList();
  324. foreach (string key in keys)
  325. {
  326. List<SchedulerTime> schedulerTimes = _metalScheduleTimeDic[key];
  327. schedulerTimes.Clear();
  328. }
  329. _metalScheduleTimeDic.Clear();
  330. LOG.Write(eEvent.INFO_RINSE,"System", "Remove all metal scheduler time");
  331. }
  332. /// <summary>
  333. /// 计算数量
  334. /// </summary>
  335. /// <param name="metal"></param>
  336. /// <returns></returns>
  337. public DateTime CalculateSchedulerEndTime(string metal)
  338. {
  339. if (_metalScheduleTimeDic.ContainsKey(metal))
  340. {
  341. DateTime dateTime = DateTime.MinValue;
  342. foreach(var item in _metalScheduleTimeDic[metal])
  343. {
  344. DateTime startTime = item.ScheduleStartTime;
  345. if (startTime.AddSeconds(item.ProcessTimeLength) > dateTime)
  346. {
  347. dateTime= startTime.AddSeconds(item.ProcessTimeLength);
  348. }
  349. }
  350. return dateTime;
  351. }
  352. else
  353. {
  354. return DateTime.MinValue;
  355. }
  356. }
  357. /// <summary>
  358. /// 是否包含
  359. /// </summary>
  360. /// <param name="metal"></param>
  361. /// <returns></returns>
  362. public bool ContainedMetal(string metal)
  363. {
  364. return _metalScheduleTimeDic.ContainsKey(metal);
  365. }
  366. }
  367. }