分线计算09.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. using ServiceCenter.Extensions;
  2. using ServiceCenter.SqlSugars;
  3. using System.ComponentModel;
  4. using WCS.Core;
  5. using WCS.Entity;
  6. using WCS.WorkEngineering.Extensions;
  7. using WCS.WorkEngineering.Protocol.Station;
  8. using WCS.WorkEngineering.Worlds;
  9. using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
  10. using TaskStatus = WCS.Entity.TaskStatus;
  11. namespace WCS.WorkEngineering.Systems
  12. {
  13. /// <summary>
  14. /// 分线计算09
  15. /// </summary>
  16. [BelongTo(typeof(NoInteractionWorld))]
  17. [Description("分线计算09")]
  18. public class 分线计算09 : DeviceSystem<Device<IStation520>>
  19. {
  20. protected override bool ParallelDo => true;
  21. protected override bool SaveLogsToFile => true;
  22. public override void Do(Device<IStation520> obj)
  23. {
  24. SqlSugarHelper.Do(_db =>
  25. {
  26. //获取所有待执行的任务
  27. var db = _db.Default;
  28. var taskList = db.Queryable<WCS_TaskInfo>().Where(x => x.Status == TaskStatus.WaitingToExecute && x.Type == TaskType.SetPlate && x.AddrFrom == "Robot").Take(1).ToList();
  29. //开始对任务进行处理
  30. foreach (var taskInfo in taskList)
  31. {
  32. //TODO:暂时不来考虑动态计算可前往的目标
  33. var nextAdd = taskInfo.WarehouseCode switch
  34. {
  35. "1N" => "455",
  36. "1S" => "455",
  37. "2N" => "455",
  38. "2S" => "455",
  39. "3N" => "455",
  40. "3S" => "455",
  41. _ => "0"
  42. };
  43. //获取这个地址的下一个地址集合
  44. var cacheLineDevList = Device.All.First(x => x.Code == nextAdd).Targets.Where(x => x.HasFlag(DeviceFlags.桁架缓存放行点));
  45. var cacheLineCodes = cacheLineDevList.Select(x => x.Code.ToShort());
  46. var cacheLineList = db.Queryable<WCS_CacheLine>().Includes(x => x.Locations).ToList();
  47. #region 跟据缓存信息寻找可以到达的缓存点
  48. //找到当前任务可用的缓存线信息
  49. var cacheLine = cacheLineList.Where(x => x.Locations.Any(l => l is { InStock: false, IsEmpty: false })).FirstOrDefault(x => cacheLineCodes.Contains(x.LocationNo) && x.MatCodeList.Contains(taskInfo.MatCode) && !x.InStock);
  50. if (cacheLine != null)//这个任务可以直接去一条线体,不需要新建缓存信息
  51. {
  52. //找到这条线体中序号最小的一条位信息 非空置且无货
  53. var cacheLoc = cacheLine.Locations.Where(x => x is { InStock: false, IsEmpty: false }).MinBy(x => x.XYNo);
  54. if (cacheLoc != null)
  55. {
  56. cacheLoc = db.Queryable<WCS_CacheLineLoc>().Single(x => x.Id == cacheLoc.Id);
  57. cacheLoc.InStock = true;
  58. cacheLoc.TaskId = taskInfo.ID;
  59. cacheLoc.EditTime = DateTime.Now;
  60. db.Updateable(cacheLoc).ExecuteCommand();
  61. //WCS任务相关信息
  62. taskInfo.Status = TaskStatus.FinishOfShunt;
  63. taskInfo.AddrNext = cacheLine.LocationNo.ToString();
  64. taskInfo.EditWho = "WCS";
  65. taskInfo.EditTime = DateTime.Now;
  66. taskInfo.AddWCS_TASK_DTL(_db, obj.Entity.Code, taskInfo.AddrNext, $"完成分库计算,目标地址:{cacheLine.LocationNo}");
  67. db.Updateable(taskInfo).ExecuteCommand();
  68. taskInfo.UpdateRedisHash();
  69. return;
  70. }
  71. }
  72. #endregion 跟据缓存信息寻找可以到达的缓存点
  73. #region 初始化一个信息的缓存信息
  74. //找到所有当前轮子可以去的垛形
  75. var palletizingList = db.Queryable<WCS_Palletizing>()
  76. .Includes(x => x.Layers, r => r.Rows, l => l.Locs)
  77. .Where(x => x.MatCodeList.Contains(taskInfo.MatCode) && !x.Finish).ToList().Where(x => x.Layers.SelectMany(x => x.Rows).Any(r => r.LineCode == null)).OrderBy(x => x.AddTime).ToList();
  78. //如果没有对应的垛形信息就初始化一个垛形信息
  79. if (palletizingList.Count <= 0)
  80. {
  81. taskInfo.InitStackStructure();
  82. return;
  83. }
  84. foreach (var palletizing in palletizingList)
  85. {
  86. //TODO:当前不考虑不按顺序码垛的情况
  87. //按码垛顺序找到一个最近的没有码垛成功的行,
  88. //先找层:未空置、未结束 TODO:暂不考虑所有层全部结束,但是垛形信息未清除的情况
  89. var palletizingLayer = palletizing.Layers
  90. .Where(x => !x.IsEmpty)
  91. .Where(x => !x.Finish)
  92. .Where(x => x.MatCodeList.Contains(taskInfo.MatCode))
  93. .Where(x => x.Rows.Any(r => r.CacheLineId == 0))
  94. .MinBy(x => x.LayerNo);
  95. //如果没有哪一层需要这个物料号,就初始化一个新的垛形信息
  96. if (palletizingLayer == null)
  97. {
  98. taskInfo.InitStackStructure();
  99. return;
  100. }
  101. //再找行:未空置、未结束
  102. var palletizingRow = palletizingLayer.Rows.Where(x => x is { IsEmpty: false, Finish: false } && x.MatCodeList.Contains(taskInfo.MatCode) && x.CacheLineId == 0)
  103. .MinBy(x => x.RowNo);
  104. //如果没有哪一行需要这个物料号,就初始化一个新的垛形信息
  105. if (palletizingRow == null)
  106. {
  107. taskInfo.InitStackStructure();
  108. return;
  109. }
  110. //走到这一步就表示没有哪一段线体缓存了当前物料,需要选一段新的线体进行缓存
  111. //TODO:暂时不处理就近分线的逻辑
  112. //获取一个当前可以使用的分配锁
  113. var devCode = cacheLineDevList.Select(x => x.Code.ToShort()).FirstOrDefault(x => !cacheLineList.Select(s => s.LocationNo).Contains(x));
  114. if (devCode == 0)
  115. {
  116. World.Log($"无可用线体:{taskInfo.ID}");
  117. return;
  118. }
  119. //开始初始化缓存位信息
  120. cacheLine = new WCS_CacheLine()
  121. {
  122. LocationNo = devCode,
  123. AddTime = DateTime.Now,
  124. PalletizingRowId = palletizingRow.Id,
  125. InStock = false,
  126. Put = false,
  127. MatCodeList = palletizingRow.MatCodeList
  128. };
  129. var res = db.Insertable(cacheLine).ExecuteReturnEntity();
  130. palletizingRow = db.Queryable<WCS_PalletizingRow>().Includes(x => x.Locs).Single(x => x.Id == palletizingRow.Id);
  131. palletizingRow.Locs = palletizingRow.Locs.OrderBy(x => x.XYNo).ToList();
  132. palletizingRow.CacheLineId = res.Id;
  133. palletizingRow.EditTime = DateTime.Now;
  134. db.Updateable(palletizingRow).ExecuteCommand();
  135. for (var i = 0; i < palletizingRow.Locs.Count; i++)
  136. {
  137. var loc = new WCS_CacheLineLoc()
  138. {
  139. XYNo = palletizingRow.Locs[i].XYNo,
  140. InStock = i == 0,
  141. IsEmpty = palletizingRow.Locs[i].IsEmpty,
  142. MatCode = palletizingRow.Locs[i].MatCode,
  143. TaskId = i == 0 ? taskInfo.ID : 0,
  144. CacheLineId = res.Id
  145. };
  146. db.Insertable(loc).ExecuteCommand();
  147. }
  148. taskInfo.Status = TaskStatus.FinishOfShunt;
  149. taskInfo.AddrNext = devCode.ToString();
  150. taskInfo.EditWho = "WCS";
  151. taskInfo.EditTime = DateTime.Now;
  152. taskInfo.AddWCS_TASK_DTL(_db, obj.Entity.Code, taskInfo.AddrNext, $"完成分库计算,目标地址:{cacheLine.LocationNo}");
  153. db.Updateable(taskInfo).ExecuteCommand();
  154. taskInfo.UpdateRedisHash();
  155. return;
  156. }
  157. #endregion 初始化一个信息的缓存信息
  158. }
  159. });
  160. }
  161. public override bool Select(Device dev)
  162. {
  163. return dev.Code == nameof(分线计算09);
  164. }
  165. }
  166. public class LineCache
  167. {
  168. /// <summary>
  169. /// 位置
  170. /// </summary>
  171. public string Location { get; set; }
  172. /// <summary>
  173. /// 是否放行
  174. /// </summary>
  175. public bool IsPut { get; set; }
  176. /// <summary>
  177. /// 具体缓存信息
  178. /// </summary>
  179. public List<LineCacheInfo> LineInfos { get; set; }
  180. }
  181. /// <summary>
  182. /// 线体缓存组员
  183. /// </summary>
  184. public class LineCacheInfo
  185. {
  186. /// <summary>
  187. /// 序号
  188. /// </summary>
  189. public string Index { get; set; }
  190. /// <summary>
  191. /// 物料号
  192. /// </summary>
  193. public string MatCode { get; set; }
  194. /// <summary>
  195. /// 任务号
  196. /// </summary>
  197. public int TaskNumber { get; set; }
  198. /// <summary>
  199. /// 是否有货
  200. /// </summary>
  201. public bool InStock { get; set; }
  202. /// <summary>
  203. /// 是否空置
  204. /// </summary>
  205. public bool IsEmpty { get; set; }
  206. }
  207. }