SrmSystems.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using ServiceCenter.Extensions;
  2. using ServiceCenter.SqlSugars;
  3. using System.ComponentModel;
  4. using WCS.Core;
  5. using WCS.Entity;
  6. using WCS.Entity.Protocol.SRM;
  7. using WCS.Entity.Protocol.Station;
  8. using WCS.WorkEngineering.Extensions;
  9. using WCS.WorkEngineering.Worlds;
  10. using WCS.WorkEngineering.Worlds.Logs;
  11. using KnownException = WCS.WorkEngineering.Worlds.Logs.KnownException;
  12. namespace WCS.WorkEngineering.Systems
  13. {
  14. /// <summary>
  15. /// 堆垛机系统
  16. /// </summary>
  17. [BelongTo(typeof(MainWorld))]
  18. [Description("堆垛机系统")]
  19. public class SrmSystems : DeviceSystem<Device<ISRM520, ISRM521, ISRM523>>
  20. {
  21. /// <summary>
  22. /// 取货点设备集合
  23. /// </summary>
  24. private List<Device<IStation520, IStation521, IStation522>> PickUpDevices;
  25. /// <summary>
  26. /// 放货设备
  27. /// </summary>
  28. private List<Device<IStation520, IStation521, IStation522>> PutDevices;
  29. public SrmSystems()
  30. {
  31. //分拣库1
  32. PickUpDevices = World.Devices.Where(v => v.Code is "" or "")
  33. .Select(v => new Device<IStation520, IStation521, IStation522>(v)).ToList();
  34. PutDevices = World.Devices.Where(v => v.Code is "" or "")
  35. .Select(v => new Device<IStation520, IStation521, IStation522>(v)).ToList();
  36. //分拣库2
  37. PickUpDevices = World.Devices.Where(v => v.Code is "" or "")
  38. .Select(v => new Device<IStation520, IStation521, IStation522>(v)).ToList();
  39. PutDevices = World.Devices.Where(v => v.Code is "" or "")
  40. .Select(v => new Device<IStation520, IStation521, IStation522>(v)).ToList();
  41. //分拣库3
  42. PickUpDevices = World.Devices.Where(v => v.Code is "" or "")
  43. .Select(v => new Device<IStation520, IStation521, IStation522>(v)).ToList();
  44. PutDevices = World.Devices.Where(v => v.Code is "" or "")
  45. .Select(v => new Device<IStation520, IStation521, IStation522>(v)).ToList();
  46. }
  47. protected override bool ParallelDo => true;
  48. protected override bool SaveLogsToFile => true;
  49. public override void Do(Device<ISRM520, ISRM521, ISRM523> obj)
  50. {
  51. //判断堆垛机是否报警
  52. if (obj.Data2.Status.HasFlag(SrmStatus.Alarm)) throw new KnownException(obj.Data3.Alarm.ToString(), LogLevelEnum.High);
  53. //判断DB520 完成任务确认清除信号 是否为1
  54. if (obj.Data.OkAck == 1) throw new KnownException("任务完成确认信号未清除", LogLevelEnum.Mid);
  55. //判断完成任务号是否大于0
  56. if (obj.Data2.TaskFinishiId > 0)
  57. {
  58. SqlSugarHelper.Do(db =>
  59. {
  60. //根据DB521任务号获取对应任务
  61. var task = db.Default.Queryable<WCS_TASK>().First(v => v.ID == obj.Data2.TaskFinishiId) ?? throw new KnownException($"未找到任务{obj.Data2.TaskFinishiId}", LogLevelEnum.High);
  62. if (task.STATUS != Entity.TaskStatus.StackerExecution)
  63. throw new KnownException($"任务{task.ID}状态是{task.STATUS.Description()}.堆垛机完成任务需要对应任务状态处于堆垛机执行中", LogLevelEnum.High);
  64. //根据任务类型做不同的处理
  65. switch (task.TYPE)
  66. {
  67. case TaskType.EnterDepot:
  68. //完成任务
  69. task.STATUS = Entity.TaskStatus.Finish;
  70. task.UPDATETIME = DateTime.Now;
  71. task.ENDTIME = DateTime.Now;
  72. task.AddWCS_TASK_DTL(db, task.ADDRTO, "入库任务结束");
  73. break;
  74. case TaskType.OutDepot:
  75. task.STATUS = Entity.TaskStatus.ConveyorInProgress;
  76. task.UPDATETIME = DateTime.Now;
  77. task.AddWCS_TASK_DTL(db, task.SRMSTATION, "出库任务到达放货站台");
  78. break;
  79. case TaskType.TransferDepot:
  80. task.STATUS = Entity.TaskStatus.Finish;
  81. task.UPDATETIME = DateTime.Now;
  82. task.ENDTIME = DateTime.Now;
  83. task.AddWCS_TASK_DTL(db, task.ADDRTO, "移库任务结束");
  84. break;
  85. }
  86. db.Default.Updateable(task).AddQueue();
  87. db.Default.SaveQueues();
  88. obj.Data.OkAck = 1;
  89. });
  90. }
  91. //堆垛机是否可以下发任务
  92. if (obj.Data2.VoucherNo != obj.Data.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo},DB521:{obj.Data2.VoucherNo}", LogLevelEnum.Mid);
  93. if (obj.Data2.AutoStatus != SrmAutoStatus.Automatic) throw new KnownException($"堆垛机处于{obj.Data2.AutoStatus}模式", LogLevelEnum.Low);
  94. if (obj.Data2.RunStatus != SrmRunStatus.Idle) throw new KnownException($"堆垛机处于{obj.Data2.RunStatus}状态", LogLevelEnum.High);
  95. //默认没有移库任务
  96. bool isTransfer = false;
  97. //出入库优先级任务 1:无优先 2:入库 3:出库
  98. int enterOrOut = 1;
  99. //再检查是否有等待执行的货物
  100. SqlSugarHelper.Do(db =>
  101. {
  102. //获取当前堆垛机的所有未完成任务
  103. var tasks = db.Default.Queryable<WCS_TASK>().Where(v => v.STATUS < Entity.TaskStatus.Finish && (v.DEVICE == obj.Entity.Code));
  104. //任务集合是否有处于堆垛机执行状态的任务
  105. if (tasks.Any(v => v.STATUS == Entity.TaskStatus.StackerExecution)) throw new KnownException($"有任务处于堆垛机执行状态", LogLevelEnum.High);
  106. //判断是否存在调整优先级任务
  107. if (!tasks.Any(v => v.TYPE != TaskType.TransferDepot && v.STATUS < Entity.TaskStatus.StackerExecution && v.Priority > 0))
  108. {
  109. //不存在调整优先级任务,判断是否存在移库任务
  110. isTransfer = tasks.Any(v => v.TYPE == TaskType.TransferDepot && v.STATUS == Entity.TaskStatus.NewBuild);
  111. }
  112. else //存在调整优先级任务
  113. {
  114. //获取出库任务中新建状态最大优先级
  115. var outPriorityNewBuild = tasks.Where(v => v.TYPE == TaskType.OutDepot && v.STATUS == Entity.TaskStatus.NewBuild).Max(v => v.Priority);
  116. //获取入库任务中最后一个交互点是取货点任务的最大优先级
  117. var enterPriority = tasks.Where(v => v.TYPE == TaskType.EnterDepot && v.STATUS < Entity.TaskStatus.StackerExecution && PickUpDevices.Any(p => p.Entity.Code == v.LastInteractionPoint))
  118. .Max(v => v.Priority);
  119. //出入库最大优先级相加大于零
  120. if (outPriorityNewBuild + enterPriority > 0)
  121. {
  122. //出入库优先级任务 1:无优先 2:入库 3:出库
  123. enterOrOut = enterPriority > outPriorityNewBuild ? 2 : 3;
  124. }
  125. }
  126. });
  127. #region 移库
  128. if (isTransfer)
  129. {
  130. SqlSugarHelper.Do(db =>
  131. {
  132. //获取一条当前堆垛机优先级最高的新建移库任务
  133. var task = db.Default.Queryable<WCS_TASK>().Where(v => v.DEVICE == obj.Entity.Code && v.TYPE == TaskType.TransferDepot && v.STATUS == Entity.TaskStatus.NewBuild)
  134. .OrderByDescending(v => v.Priority)
  135. .First() ?? throw new KnownException("未找到移库任务", LogLevelEnum.High);
  136. //任务状态改为堆垛机执行中
  137. task.STATUS = Entity.TaskStatus.StackerExecution;
  138. task.STARTTIME = DateTime.Now;
  139. task.UPDATETIME = DateTime.Now;
  140. task.AddWCS_TASK_DTL(db, task.ADDRFROM, task.DEVICE, $"堆垛机{obj.Entity.Code}开始执行任务");
  141. db.Default.Updateable(task).AddQueue();
  142. db.Default.SaveQueues();
  143. var addrFrom = task.ADDRFROM.Split("-");
  144. var addrTo = task.ADDRTO.Split("-");
  145. //下发任务
  146. obj.Data.TaskNumber = task.ID;
  147. obj.Data.RowPos1 = addrFrom[0].ToShort();
  148. obj.Data.TravelPos1 = addrFrom[1].ToShort();
  149. obj.Data.LiftPos1 = addrFrom[2].ToShort();
  150. obj.Data.RowPos2 = addrTo[0].ToShort();
  151. obj.Data.TravelPos2 = addrTo[1].ToShort();
  152. obj.Data.LiftPos2 = addrTo[2].ToShort();
  153. obj.Data.VoucherNo++;
  154. });
  155. }
  156. #endregion 移库
  157. #region 出入库
  158. //上一个周期是不是出库任务 第一次获取返回结果会是false
  159. var lastIsOut = obj.Entity.Get<bool>("LastIsOut");
  160. obj.Entity.Set("LastIsOut", !lastIsOut);
  161. //入库任务优先 或 上一个周期是出库任务并且出库任务无优先
  162. if (enterOrOut == 2 || (lastIsOut && enterOrOut == 1)) //入库任务
  163. {
  164. //判断本次优先执行楼层,并设置下次执行时优先楼层
  165. var floor = obj.Entity.Get<int>("Floor");
  166. floor = floor % 2 + 1;
  167. obj.Entity.Set("Floor", floor);
  168. }
  169. else if (enterOrOut == 3 || !lastIsOut) //出库任务
  170. {
  171. }
  172. #endregion 出入库
  173. }
  174. public override bool Select(Device dev)
  175. {
  176. return dev.Code.Contains("SRM");
  177. }
  178. }
  179. }