RGVSystems.cs 9.4 KB

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