RGVSystems.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. using ServiceCenter.Extensions;
  2. using ServiceCenter.Logs;
  3. using ServiceCenter.SqlSugars;
  4. using System.ComponentModel;
  5. using WCS.Core;
  6. using WCS.Entity;
  7. using WCS.Entity.Protocol.Protocol.BCR;
  8. using WCS.Entity.Protocol.Protocol.RGV;
  9. using WCS.Entity.Protocol.Protocol.Robot;
  10. using WCS.Entity.Protocol.Protocol.Station;
  11. using WCS.Entity.Protocol.Protocol.Truss;
  12. using WCS.WorkEngineering.Extensions;
  13. using WCS.WorkEngineering.Worlds;
  14. using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
  15. using TaskStatus = WCS.Entity.TaskStatus;
  16. namespace WCS.WorkEngineering.Systems
  17. {
  18. /// <summary>
  19. /// Agv交互系统
  20. /// </summary>
  21. [BelongTo(typeof(RgvWorld))]
  22. [Description("RGV交互系统")]
  23. public class RGVSystems : DeviceSystem<Device<IRGV520, IRGV521, IBCR81>>
  24. {
  25. protected override bool ParallelDo => true;
  26. protected override bool SaveLogsToFile => true;
  27. /// <summary>
  28. /// 取货点设备集合
  29. /// </summary>
  30. private readonly Dictionary<string, List<Device<IStation520, IStation521, IStation523>>> _pickUpDevices = new();
  31. public RGVSystems()
  32. {
  33. //获取所有的巷道集合
  34. var rgvList = Device.All.Where(v => v.HasFlag(DeviceFlags.RGV));
  35. foreach (var rgv in rgvList)
  36. {
  37. _pickUpDevices.Add(rgv.Code, rgv.Sources.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => new Device<IStation520, IStation521, IStation523>(v, this.World)).ToList());
  38. }
  39. }
  40. public override void Do(Device<IRGV520, IRGV521, IBCR81> obj)
  41. {
  42. if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
  43. if (obj.Data2.WorkMode != RGVWorkMode.Automatic) return;
  44. if (obj.Data.RES1 == 1) return; //wcs任务完成确认信号未清除
  45. if (obj.Data2.Status.HasFlag(RGVStatus.Taskfinishi))
  46. {
  47. switch (obj.Data2.CmdType)
  48. {
  49. case RGVCmdType.PickGoods: //单独取货任务完成,默认只有空托盘才会下发单独取货任务
  50. //开始申请读码信息
  51. var bcrCode = obj.Data3.GetBCRCode();
  52. int taskNumber = 0;
  53. SqlSugarHelper.Do(_db =>
  54. {
  55. var db = _db.Default;
  56. var dev = Device.All.First(x => x.Code == obj.Data2.StartPosition.ToString());
  57. if (dev.HasFlag(DeviceFlags.拆盘机09))
  58. {
  59. //开始绑定任务,并下发新的任务信息到小车
  60. WCS_Palletizing palletizingInfo = db.Queryable<WCS_Palletizing>().Single(x => x.Id == obj.Data2.TaskNumber);
  61. if (palletizingInfo == null) return;
  62. palletizingInfo.PalleCode = bcrCode;
  63. db.Updateable(palletizingInfo).ExecuteCommand();
  64. taskNumber = palletizingInfo.Id;
  65. }
  66. else if (dev.HasFlag(DeviceFlags.拆盘机非09))
  67. {
  68. //开始处理对应的搬运任务信息
  69. var task = db.Queryable<WCS_TaskInfo>().First(x => x.Type == TaskType.Delivery && x.ID == obj.Data2.TaskNumber && x.AddrTo == obj.Data2.DestPosition.ToString());
  70. if (task == null) throw new KnownException($"未找到对应的任务{obj.Data2.TaskNumber}", LogLevelEnum.Mid);
  71. task.BarCode = bcrCode;
  72. db.Updateable(task).ExecuteCommand();
  73. task.AddWCS_TASK_DTL(db, obj.Entity.Code, obj.Data2.DestPosition.ToString(), $"环形库码垛位{obj.Data2.DestPosition}搬运任务绑定条码信息{bcrCode}");
  74. taskNumber = task.ID;
  75. }
  76. });
  77. if (taskNumber == 0) return;
  78. //清空起始点信息
  79. var staDev = new Device<IStation520>(Device.All.FirstOrDefault(x => x.Code == obj.Data2.DestPosition.ToString())!, World);
  80. staDev.Data.TaskNumber = 0;
  81. staDev.Data.GoodsStart = 0;
  82. staDev.Data.GoodsEnd = 0;
  83. obj.Data2.TaskNumber = taskNumber;
  84. obj.Data.RES1 = 1;
  85. break;
  86. case RGVCmdType.PutGoods:
  87. WCS_TaskInfo finishiTask = null;
  88. var startPosition = Device.All.Where(x => x.Code == obj.Data2.StartPosition.ToString()).Select(x => new Device<IStation520, IStation521, IStation523>(x, World)).FirstOrDefault();
  89. var destPosition = Device.All.FirstOrDefault(x => x.Code == obj.Data2.DestPosition.ToString());
  90. var isPalletizing = destPosition!.HasFlag(DeviceFlags.桁架码垛位, DeviceFlags.环形库码垛工位);
  91. short countQty = 0;
  92. short shortCode = 0;
  93. SqlSugarHelper.Do(_db =>
  94. {
  95. var db = _db.Default;
  96. if (isPalletizing)
  97. {
  98. if (destPosition.HasFlag(DeviceFlags.桁架码垛位))
  99. {
  100. var palletizingInfo = db.Queryable<WCS_Palletizing>().First(x => x.Id == obj.Data.TaskNumber);
  101. countQty = palletizingInfo.CountQty.ToShort();
  102. shortCode = palletizingInfo.ShortCode;
  103. }
  104. else if (destPosition.HasFlag(DeviceFlags.环形库码垛工位))
  105. {
  106. var deliveryTask = db.Queryable<WCS_TaskInfo>().First(x => x.ID == obj.Data.TaskNumber);
  107. countQty = deliveryTask.FullQty;
  108. shortCode = deliveryTask.PalletType;
  109. deliveryTask.Status = TaskStatus.RgvCompleted;
  110. deliveryTask.EditTime = DateTime.Now;
  111. deliveryTask.LastInteractionPoint = obj.Entity.Code;
  112. db.Updateable(deliveryTask).ExecuteCommand();
  113. deliveryTask.AddWCS_TASK_DTL(db, deliveryTask.AddrTo, $"RGV任务执行结束");
  114. }
  115. }
  116. });
  117. //初始化起始点信息
  118. startPosition.Data.TaskNumber = 0;
  119. startPosition.Data.GoodsEnd = 0;
  120. //目标地址是码垛工位
  121. if (isPalletizing)
  122. {
  123. if (destPosition.HasFlag(DeviceFlags.桁架码垛位))
  124. {
  125. var dest = new Device<ITruss530>(destPosition!, World);
  126. dest.Data.MaxQuantity = countQty;
  127. dest.Data.Type = shortCode;
  128. dest.Data.VoucherNo++;
  129. }
  130. else if (destPosition.HasFlag(DeviceFlags.环形库码垛工位))
  131. {
  132. var dest = new Device<IRobot530>(destPosition!, World);
  133. dest.Data.MaxQuantity = countQty;
  134. dest.Data.Type = shortCode;
  135. dest.Data.VoucherNo++;
  136. }
  137. }
  138. obj.Data.RES1 = 1;
  139. break;
  140. case RGVCmdType.Move:
  141. obj.Data.RES1 = 1;
  142. break;
  143. case RGVCmdType.ChangePutGoods:
  144. break;
  145. case RGVCmdType.ChangePickGoods:
  146. break;
  147. case RGVCmdType.PickPutGoods:
  148. staDev = new Device<IStation520, IStation521>(Device.All.FirstOrDefault(x => x.Code == obj.Data.DestPosition.ToString())!, World);
  149. staDev.Data.TaskNumber = 0;
  150. staDev.Data.GoodsStart = 0;
  151. staDev.Data.GoodsEnd = 0;
  152. obj.Data.RES1 = 1;
  153. break;
  154. default:
  155. throw new ArgumentOutOfRangeException();
  156. }
  157. return;
  158. }
  159. if (obj.Data2.SystemStatus != RGVSystemStatus.空闲) return;
  160. if (obj.Data2.Status.HasFlag(RGVStatus.RES1))
  161. {
  162. obj.Data.TaskNumber = obj.Data.TaskNumber;
  163. obj.Data.CmdType = RGVCmdType.Move;
  164. obj.Data.DestPosition = 1668;
  165. obj.Data.VoucherNo++;
  166. return;
  167. }
  168. if (obj.Data2.CmdType == RGVCmdType.PickGoods && !obj.Data2.Status.HasFlag(RGVStatus.Taskfinishi))
  169. {
  170. if (obj.Data2.Status.HasFlag(RGVStatus.PH_Status))
  171. {
  172. obj.Data.TaskNumber = obj.Data.TaskNumber;
  173. obj.Data.CmdType = RGVCmdType.PutGoods;
  174. obj.Data.StartPosition = obj.Data2.StartPosition;
  175. obj.Data.DestPosition = obj.Data2.DestPosition;
  176. obj.Data.VoucherNo++;
  177. return;
  178. }
  179. }
  180. var pickUpDevices = _pickUpDevices.FirstOrDefault(x => x.Key == obj.Entity.Code).Value;
  181. //有货且需要搬运货物的站台
  182. var devs = pickUpDevices.Where(v => v.Data3.Status.HasFlag(StationStatus.PH_Status) && v.Data.TaskNumber != 0)
  183. .Where(v => v.Entity.Code.ToShort() != v.Data.GoodsEnd && v.Data.GoodsEnd != 0)
  184. .ToList();
  185. //筛选出目标站台无货的站台
  186. var putDev = obj.Entity.Targets.Where(x => x.HasFlag(DeviceFlags.输送机))
  187. .Select(x => new Device<IStation520, IStation521, IStation523>(x, World))
  188. .Where(x => !x.Data3.Status.HasFlag(StationStatus.PH_Status))
  189. .Select(x => x.Entity.Code.ToShort());
  190. var dev = devs.OrderBy(x => x.Entity.Code).FirstOrDefault(x => putDev.Contains(x.Data.GoodsEnd));
  191. if (dev == null) return;
  192. //区分任务是拆盘机到码垛工位,还是码垛工位到拆盘机
  193. if (dev.Entity.HasFlag(DeviceFlags.拆盘机09, DeviceFlags.拆盘机非09))
  194. {
  195. obj.Data.TaskNumber = dev.Data.TaskNumber;
  196. obj.Data.CmdType = RGVCmdType.PickGoods;
  197. obj.Data.StartPosition = dev.Entity.Code.ToShort();
  198. obj.Data.DestPosition = dev.Data.GoodsEnd;
  199. obj.Data.VoucherNo++;
  200. }
  201. else //非拆盘机起始任务
  202. {
  203. //站台中的任务号
  204. WCS_TaskInfo task = null;
  205. SqlSugarHelper.Do(_db =>
  206. {
  207. var db = _db.Default;
  208. var taskInfo = db.Queryable<WCS_TaskInfo>().First(p => p.ID == dev.Data.TaskNumber && p.Status == TaskStatus.WaitingToExecute);
  209. if (taskInfo == null) return;
  210. taskInfo.Status = TaskStatus.RgvExecution;
  211. taskInfo.AddrNext = obj.Entity.Code;
  212. taskInfo.EditWho = "WCS";
  213. taskInfo.EditTime = DateTime.Now; ;
  214. db.Updateable(taskInfo).ExecuteCommand();
  215. taskInfo.AddWCS_TASK_DTL(db, dev.Entity.Code, obj.Entity.Code, $"任务分配至{obj.Entity.Code}");
  216. task = taskInfo;
  217. });
  218. if (task == null) return;
  219. obj.Data.TaskNumber = task.ID;
  220. obj.Data.CmdType = RGVCmdType.PickPutGoods;
  221. obj.Data.StartPosition = dev.Entity.Code.ToShort();
  222. obj.Data.DestPosition = dev.Data.GoodsEnd;
  223. obj.Data.VoucherNo++;
  224. }
  225. }
  226. public override bool Select(Device dev)
  227. {
  228. return dev.Code == "RGV1";
  229. //return dev.HasFlag(Extensions.DeviceFlags.RGV);
  230. }
  231. }
  232. }