库尾入库.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. using Newtonsoft.Json;
  2. using ServiceCenter.Extensions;
  3. using ServiceCenter.Logs;
  4. using ServiceCenter.Redis;
  5. using ServiceCenter.SqlSugars;
  6. using SqlSugar;
  7. using System.ComponentModel;
  8. using System.Linq;
  9. using System.Threading.Tasks;
  10. using WCS.Core;
  11. using WCS.Entity;
  12. using WCS.WorkEngineering.Extensions;
  13. using WCS.WorkEngineering.Protocol.BCR;
  14. using WCS.WorkEngineering.Protocol.SRM;
  15. using WCS.WorkEngineering.Protocol.Station;
  16. using WCS.WorkEngineering.WebApi.Controllers;
  17. using WCS.WorkEngineering.Worlds;
  18. using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
  19. namespace WCS.WorkEngineering.Systems
  20. {
  21. /// <summary>
  22. /// 库尾入库
  23. /// </summary>
  24. [BelongTo(typeof(MainWorld))]
  25. [Description("库尾入库")]
  26. public class 库尾入库 : DeviceSystem<Device<IStation520, IStation521, IStation523, IStation91, IBCR81>>
  27. {
  28. protected override bool ParallelDo => false;
  29. protected override bool SaveLogsToFile => true;
  30. private List<Station> devs = new List<Station>();
  31. private List<SRM> srms = new List<SRM>();
  32. public 库尾入库()
  33. {
  34. devs = Device.All.Where(v => v.HasFlag(DeviceFlags.入库)).Select(v => new Station(v, this.World)).ToList();
  35. srms = Device.All.Where(v => v.HasProtocol(typeof(ISRM520))).Select(v => new SRM(v, this.World)).ToList();
  36. }
  37. public override void Do(Device<IStation520, IStation521, IStation523, IStation91, IBCR81> obj)
  38. {
  39. var key = $"WCS:Lock:出入库管制SRM";
  40. try
  41. {
  42. if (RedisHub.Default.Get(key) != null)
  43. {
  44. throw new KnownException($"[{obj.Entity.Code}]--触发并发管控", LogLevelEnum.High);
  45. }
  46. RedisHub.Default.Set(key, obj.Entity.Code);
  47. obj.入库站点是否被禁止();
  48. obj.入库站点是否满足执行条件();
  49. if (obj.Data2.Request != 1.ToShort()) throw new KnownException("无请求", LogLevelEnum.Mid);
  50. if (!obj.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("无光电", LogLevelEnum.Mid);
  51. //开始读取条码
  52. var bcr = obj.Data5.GetBCRCode();
  53. World.Log($"扫码记录:条码:{bcr}");
  54. WCS_TaskInfo task = null;
  55. List<SRM> inlist = new List<SRM>();
  56. SqlSugarHelper.Do(_db =>
  57. {
  58. var db = _db.Default;
  59. //找到对应任务
  60. var taskInfo = db.Queryable<WCS_TaskInfo>().First(x => x.BarCode == bcr && x.Type == TaskType.EnterDepot && x.AddrFrom == "8277");
  61. //未找到对应任务
  62. if (taskInfo == null)
  63. {
  64. //向WMS申请入库任务
  65. var res = WmsApi.I_WCS_GetInTask(bcr, obj.Entity.Code);
  66. if (res.ResCode != WebApi.Models.WMS.Response.ResponseStatusCodeEnum.Sucess)
  67. {
  68. if (res == null) throw new Exception($"向WMS申请入库任务失败" + res.ResMsg);
  69. }
  70. return;
  71. }
  72. //任务生成
  73. if (taskInfo.Status == Entity.TaskStatus.WaitingToExecute)
  74. {
  75. // 开始获取堆垛机与可用站台信息
  76. var res = WmsApi.GetTunnelPriorityList(taskInfo.ID);
  77. if (res == null) throw new Exception("未返回巷道");
  78. var tunnelNo = res.ResData.Split(",")
  79. .Select(v => "SRM" + v)
  80. .ToList();
  81. //if (taskInfo.Floor == 10 && tunnelNo.Contains("SRM5"))
  82. //{
  83. // // 优化:直接在查询中完成条件判断,避免实例化不必要的对象
  84. // var srm5 = Device.All.FirstOrDefault(x => x.Code == "SRM5" &&
  85. // new Device<ISRM521>(x, World).Data.AutoStatus == SrmAutoStatus.Automatic);
  86. // if (srm5 != null)
  87. // {
  88. // // 如果任务在10楼且SRM5处于自动模式,则只保留SRM5
  89. // tunnelNo = new List<string> { "SRM5" };
  90. // }
  91. //}
  92. SRM srm = null;
  93. List<Station> stations = new List<Station>();
  94. //成品库背面堆垛机取货点
  95. stations = devs.Where(v => v.Entity.Code is "8271" or "8272" or "8273" or "8274" or "8275").ToList();
  96. //筛选出可用站台c
  97. stations = stations.Where(v => v.Data3.Status.HasFlag(StationStatus.Auto))// v.Data.VoucherNo == v.Data2.VoucherNo &&
  98. .Where(v => !v.Data3.Status.HasFlag(StationStatus.PH_Status) && !v.Data3.Status.HasFlag(StationStatus.OT_Status))
  99. .Where(v => !v.Data3.Status.HasFlag(StationStatus.Run)).ToList(); // 筛选出可用站台
  100. if (stations == null)
  101. {
  102. throw new KnownException($"{obj.Entity.Code}无可用放货站台", LogLevelEnum.High);
  103. }
  104. //World.Log($"可用站台信息[{count}]" + JsonConvert.SerializeObject(stations));
  105. var srms = stations.Select(v => v.Entity.Targets).SelectMany(v => v).Where(v => v.IsTunnel()) //下一个地址是巷道的
  106. .Select(v => v.Sources).SelectMany(v => v).Where(v => v.HasProtocol(typeof(ISRM520))) //筛选出堆垛机
  107. .Select(v => new SRM(v, this.World)).ToList();
  108. foreach (var device in srms)
  109. {
  110. try
  111. {
  112. var canusem = device.Data2.AutoStatus;
  113. inlist.Add(device);
  114. }
  115. catch (Exception)
  116. {
  117. continue;
  118. }
  119. }
  120. var tun = res.ResData.Split(",");
  121. var tasktunnelNo = db.Queryable<WCS_TaskInfo>().Where(p => tun.Contains(p.Tunnel) && p.AddrFrom == "8277").ToList().Select(p => p.Tunnel).Distinct().ToList();
  122. if (tasktunnelNo.Any())
  123. {
  124. var tunnelNo1 = res.ResData.Split(",").Except(tasktunnelNo).ToList();
  125. World.Log($"Tunnel:taskid{obj.Data.TaskNumber}-" +
  126. $"tasktunnelNo{JsonConvert.SerializeObject(tasktunnelNo)}-" +
  127. $"tunnelNo1{JsonConvert.SerializeObject(tunnelNo1)}");
  128. tunnelNo = tunnelNo1.Select(v => "SRM" + v).ToList();
  129. }
  130. else
  131. {
  132. World.Log($"Tunnel:taskid{obj.Data.TaskNumber}-notunel-" + JsonConvert.SerializeObject(tunnelNo));
  133. }
  134. //可用堆垛机
  135. srm = inlist.Where(v => v != null && !v.Data2.Status.HasFlag(SrmStatus.Alarm) && v.Data2.AutoStatus == SrmAutoStatus.Automatic) //筛选出可用堆垛机
  136. .Where(v => tunnelNo.Contains(v.Entity.Code)) //筛选出巷道优先级最高的堆垛机
  137. .MinBy(v => tunnelNo.IndexOf(v.Entity.Code)); //按照巷道优先级排序
  138. if (srm == null)
  139. {
  140. throw new Exception($"任务{taskInfo.ID}无可用堆垛机");
  141. }
  142. inlist = null;
  143. //筛选出堆垛机的取货站台
  144. var nextPos = stations.FirstOrDefault(v => v.Entity.Sources.Where(t => t.IsTunnel()).Select(t => t.Sources).SelectMany(v => v) //获取所有巷道
  145. .Where(t => t.HasProtocol(typeof(ISRM520)))//筛选出堆垛机
  146. .SelectMany(v => v.Sources).Any(t => t.Code == srm.Entity.Parent.Code));
  147. if (nextPos == null)
  148. {
  149. throw new KnownException($"{obj.Entity.Code}没有可用的放货站台", LogLevelEnum.High);
  150. }
  151. var dev = devs.Find(v => v.Entity.Code == nextPos.Entity.Code);
  152. var nextCode = nextPos.Entity.Code;
  153. var taskout = db.Queryable<WCS_TaskInfo>().First(v => v.AddrTo == "8278" && v.Status > Entity.TaskStatus.WaitingToExecute && v.Status < Entity.TaskStatus.Finish && nextPos.Entity.Code == v.SrmStation && v.AddrNext == null);
  154. if (taskout != null) throw new KnownException($"{obj.Entity.Code}存在正在出库任务{taskout.ID},禁止入库!", LogLevelEnum.High);
  155. if (dev == null) throw new Exception($"找不到放货点");
  156. //放货点有光电或任务号不下发任务
  157. //if (obj.Data3.Status.HasFlag(StationStatus.OT_Status) || obj.Data2.TaskNumber > 0 || obj.Data3.Status.HasFlag(StationStatus.PH_Status))
  158. //{
  159. // throw new KnownException($"{obj.Entity.Code}有任务或光电", LogLevelEnum.High);
  160. //}
  161. //堆垛机的可用取货站台
  162. var tasklist = db.Queryable<WCS_TaskInfo>().Where(x => x.Type == TaskType.OutDepot && x.AddrTo == "8278" && x.Device == srm.Entity.Code
  163. && x.Status >= Entity.TaskStatus.StackerExecution && x.Status< Entity.TaskStatus.Finish && x.AddrNext == null).ToList();
  164. if (tasklist.Any())
  165. {
  166. throw new KnownException($"[{srm.Entity.Code.GetLastDigit().ToString()}]巷道存在库尾执行的出库任务", LogLevelEnum.High);
  167. }
  168. taskInfo.SrmStation = nextPos.Entity.Code;
  169. taskInfo.AddrNext = nextPos.Entity.Sources.First().Code;
  170. taskInfo.Device = srm.Entity.Code;
  171. taskInfo.Tunnel = taskInfo.Device.GetLastDigit().ToString();
  172. taskInfo.Status = Entity.TaskStatus.ConveyorExecution;
  173. taskInfo.EditWho = "WCS";
  174. taskInfo.EditTime = DateTime.Now;
  175. db.Updateable(taskInfo).ExecuteCommand();
  176. taskInfo.AddWCS_TASK_DTL(_db, obj.Entity.Code, taskInfo.AddrNext, $"完成巷道分配,分配至{taskInfo.Device}");
  177. //taskInfo.updateRedisHash();
  178. task = taskInfo;
  179. if (task == null) throw new KnownException($"[{obj.Entity.Code}]等待入库任务为空", LogLevelEnum.Mid);
  180. }
  181. });
  182. if (task == null) return;
  183. obj.Data.TaskNumber = task.ID;
  184. obj.Data.GoodsStart = obj.Entity.Code.ToShort();
  185. obj.Data.GoodsEnd = task.SrmStation.ToShort();
  186. obj.Data.VoucherNo++;
  187. World.Log($"执行记录:taskid{obj.Data.TaskNumber}-" +
  188. $"GoodsStart{obj.Data.GoodsStart}-" +
  189. $"GoodsEnd{obj.Data.GoodsEnd}-" +
  190. $"VoucherNo{obj.Data.VoucherNo}");
  191. }
  192. finally
  193. {
  194. RedisHub.Default.Del(key);
  195. }
  196. }
  197. public override bool Select(Device dev)
  198. {
  199. return dev.Code == "8277";
  200. }
  201. }
  202. }