TaskExtension.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. using DBHelper;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using WCS.Core;
  6. using WCS.Entity;
  7. using WCS.Entity.Protocol;
  8. using WCS.Service.Helpers;
  9. using WCS.Service.Log;
  10. namespace WCS.Service.Extensions
  11. {
  12. /// <summary>
  13. /// 任务扩展
  14. /// </summary>
  15. public static class TaskExtension
  16. {
  17. public static T Create<T>(this WCS_TASK source)
  18. {
  19. return (T)Activator.CreateInstance(typeof(T), source);
  20. }
  21. /// <summary>
  22. /// 获取可用的出库任务
  23. /// </summary>
  24. /// <param name="tasks"></param>
  25. /// <returns></returns>
  26. public static Task[] GetOutTask(this List<WCS_TASK> tasks)
  27. {
  28. var tasklist = tasks.Select(v => v.Create<Task>());
  29. var task = tasklist.FirstOrDefault() ?? throw new WarnException("无可用出库任务--GetOutTask");
  30. //AGV任务ID不为零表示为车间叫料任务
  31. if (task.AgvTask != 0)
  32. {
  33. //按照AGV任务ID分一次组
  34. tasklist = tasklist.OrderByDescending(v => v.Priority)
  35. .ThenBy(v => v.CREATETIME)
  36. .GroupBy(v => v.AgvTask)
  37. .FirstOrDefault() ?? throw new WarnException("无可用叫料任务--GetOutTask");
  38. //无论这个AGV任务绑定的货物相隔多远都必须要一起出出去
  39. return tasklist.OrderBy(v => v.Col).ToArray();
  40. }
  41. return tasklist.OrderByDescending(v => v.Priority)
  42. .GroupBy(v => v.MaterialCode)
  43. .OrderBy(v => v.Key).FirstOrDefault()
  44. .OrderByDescending(v => v.Priority)
  45. .ThenBy(v => v.Line)
  46. .ThenBy(v => v.Layer)
  47. .ThenBy(v => v.Col)
  48. .Take(2)
  49. .DistinctBy(v => v.Col)
  50. .OrderBy(v => v.Col)
  51. .ToArray();
  52. }
  53. /// <summary>
  54. /// 获取出库任务的站台号及下一个地址
  55. /// </summary>
  56. /// <param name="task">任务</param>
  57. /// <param name="srmFork">货叉</param>
  58. public static void GetSrmStationAndaddNext(this WCS_TASK task, SrmFork srmFork)
  59. {
  60. List<Device<IStation520, IStation521, IStation523>> stations = new List<Device<IStation520, IStation521, IStation523>>();
  61. //取任务巷道到达目标地址的下一个地址,即任务堆垛机的站台对应的设备组
  62. if (task.TYPE == TaskType.倒库)
  63. {
  64. stations = Device.Where(v => v.DEVICEGROUP.Any(p => p.MEMBER == Device.Find(task.TUNNEL).GetPath(task.DEVICEDL)))
  65. .Select(v => v.Create<StationDeviceGroup>())
  66. .FirstOrDefault()?.Items
  67. .OrderByDescending(v => v.Entity.CODE)
  68. .ToList();
  69. }
  70. else
  71. {
  72. stations = Device.Where(v => v.DEVICEGROUP.Any(p => p.MEMBER == Device.Find(task.TUNNEL).GetPath(task.ADDRTO.Replace("G", ""))))
  73. .Select(v => v.Create<StationDeviceGroup>())
  74. .FirstOrDefault()?.Items
  75. .OrderByDescending(v => v.Entity.CODE)
  76. .ToList();
  77. }
  78. var ts = stations.ToArray();
  79. var addNext = task.TYPE == TaskType.倒库 ? task.DEVICEDL : task.ADDRTO;
  80. //一工位放较大的站台号
  81. switch (srmFork)
  82. {
  83. case SrmFork.货叉1:
  84. task.SRMSTATION = ts?[0].Entity.CODE;
  85. task.ADDRNEXT = ts?[0].Entity.GetPath(addNext).CODE;
  86. break;
  87. case SrmFork.货叉2:
  88. task.SRMSTATION = ts?[1].Entity.CODE;
  89. task.ADDRNEXT = ts?[1].Entity.GetPath(addNext).CODE;
  90. break;
  91. }
  92. }
  93. /// <summary>
  94. /// 有效任务数是否符合任务组任务数
  95. /// </summary>
  96. /// <param name="tasks"></param>
  97. /// <param name="executable"></param>
  98. /// <param name="db"></param>
  99. public static void ValidTaskCheck(this List<WCS_TASK> tasks, int executable, DB db)
  100. {
  101. var task = tasks.FirstOrDefault();
  102. var taskCount = db.Default.Set<WCS_TASK>().Count(v => v.TaskGroupKey == task.TaskGroupKey && (v.TYPE == TaskType.入库 || v.TYPE == TaskType.倒库));
  103. //开始检查任务数是否匹配
  104. if (executable != taskCount) throw new WarnException($"可执行数{executable},任务组任务数{taskCount},数量不匹配,{task.ID}-{task.TaskGroupKey}");
  105. }
  106. /// <summary>
  107. /// 有效任务数是否符合任务组任务数 临时
  108. /// </summary>
  109. /// <param name="tasks"></param>
  110. /// <param name="executable"></param>
  111. /// <param name="db"></param>
  112. public static List<WCS_TASK> ValidTaskCheck(this List<FinishTaskList<string>> devs, DB db)
  113. {
  114. var taskIds = devs.Select(v => v.Station.Data2.Tasknum).ToList();
  115. var taskList = db.Default.Set<WCS_TASK>().Where(v => taskIds.Contains(v.ID)).ToList();
  116. var task = taskList.FirstOrDefault() ?? throw new WarnException($"ValidTaskCheck 无任务"); ;
  117. var taskCount = db.Default.Set<WCS_TASK>().Count(v => v.TaskGroupKey == task.TaskGroupKey && v.TYPE == TaskType.入库);
  118. //开始检查任务数是否匹配
  119. if (devs.Count != taskCount) throw new WarnException($"可执行数{devs.Count},任务组任务数{taskCount},数量不匹配,{task.ID}-{task.TaskGroupKey}");
  120. return taskList;
  121. }
  122. /// <summary>
  123. /// 用于任务创建时获取放货站台
  124. /// </summary>
  125. /// <param name="task"></param>
  126. public static void TaskGetSrmStation(this WCS_TASK task)
  127. {
  128. task.GetSrmStationAndaddNext(SrmFork.货叉1);
  129. task.SRMSTATION = Device.Where(v => v.IsDevGroup()).FirstOrDefault(v => v.DEVICEGROUP.Any(b => b.MEMBER.CODE == task.SRMSTATION))?.CODE;
  130. task.ADDRNEXT = string.Empty;
  131. }
  132. public static void AGVStatusChange(this WCS_AGVTask task, AGVTaskStatus status, string type = "同步")
  133. {
  134. var time = task.AGVUpdateTime - task.UpdateTime;
  135. InfoLog.INFO_AGV($"WCS更新Status:{task.Status},AGVStatus:{status},{type};耗时:{time.Value.TotalMilliseconds}");
  136. }
  137. }
  138. public enum SrmIndex
  139. {
  140. 工位一 = 0,
  141. 工位二 = 1,
  142. }
  143. public class Task : WCS_TASK
  144. {
  145. /// <summary>
  146. /// 行
  147. /// </summary>
  148. public short Line { get; set; }
  149. /// <summary>
  150. /// 列
  151. /// </summary>
  152. public short Col { get; set; }
  153. /// <summary>
  154. /// 层
  155. /// </summary>
  156. public short Layer { get; set; }
  157. /// <summary>
  158. /// 行
  159. /// </summary>
  160. public short EndLine { get; set; }
  161. /// <summary>
  162. /// 列
  163. /// </summary>
  164. public short EndCol { get; set; }
  165. /// <summary>
  166. /// 层
  167. /// </summary>
  168. public short EndLayer { get; set; }
  169. public Task(WCS_TASK task)
  170. {
  171. var addrFrom = task.ADDRFROM.Split("-");
  172. ADDRTO = task.ADDRTO;
  173. TUNNEL = task.TUNNEL;
  174. DEVICE = task.DEVICE;
  175. Priority = task.Priority;
  176. AgvTask = task.AgvTask;
  177. CREATETIME = task.CREATETIME;
  178. MaterialCode = task.MaterialCode;
  179. SRMSTATION = task.SRMSTATION;
  180. ID = task.ID;
  181. Line = addrFrom[0].ToShort();
  182. Col = addrFrom[1].ToShort();
  183. Layer = addrFrom[2].ToShort();
  184. TYPE = task.TYPE;
  185. if (task.TYPE == TaskType.移库)
  186. {
  187. var addrto = task.ADDRTO.Split("-");
  188. EndLine = addrto[0].ToShort();
  189. EndCol = addrto[1].ToShort();
  190. EndLayer = addrto[2].ToShort();
  191. }
  192. }
  193. }
  194. }