林豪 左 1 year ago
parent
commit
c0ff2a2236
1 changed files with 342 additions and 238 deletions
  1. 342 238
      业务工程/分拣库/WCS.WorkEngineering/Systems/环形库/机械臂cs.cs

+ 342 - 238
业务工程/分拣库/WCS.WorkEngineering/Systems/环形库/机械臂cs.cs

@@ -1,81 +1,71 @@
-using Newtonsoft.Json;
+using System.ComponentModel;
+using Newtonsoft.Json;
 using ServiceCenter.Extensions;
 using ServiceCenter.Logs;
 using ServiceCenter.SqlSugars;
-using System.ComponentModel;
 using WCS.Core;
 using WCS.Entity;
 using WCS.Entity.Protocol.Protocol.Robot;
 using WCS.Entity.Protocol.Robot;
 using WCS.Entity.Protocol.Station;
 using WCS.WorkEngineering.Extensions;
-using WCS.WorkEngineering.WebApi.Controllers;
-using WCS.WorkEngineering.WebApi.Models.WMS.Response;
 using WCS.WorkEngineering.Worlds.环形库.环形库;
 using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
 using TaskStatus = WCS.Entity.TaskStatus;
 
-namespace WCS.WorkEngineering.Systems
+namespace WCS.WorkEngineering.Systems.环形库
 {
     /// <summary>
-    ///   机械臂
+    ///  机械臂扩展
     /// </summary>
-    [BelongTo(typeof(RingWorld1))]
-    [Description("机械臂")]
-    public class 机械臂 : DeviceSystem<Device<IRobot520, IRobot521, IRobot522>>
+    public class Roobot : Device<IRobot520, IRobot521, IRobot522>
     {
-        protected override bool ParallelDo => true;
-
         /// <summary>
         /// 取货点设备集合
         /// </summary>
-        private Dictionary<string, List<Device>> PickUpDevices = new();
+        private List<Device> PickUpDevices = new();
 
         /// <summary>
         /// 放货设备
         /// </summary>
-        private Dictionary<string, List<Device<IStation520, IStation521, IStation523, IRobot530>>> PutDevices = new();
+        private List<Device<IStation520, IStation521, IStation523, IRobot530>> PutDevices = new();
 
-        public 机械臂()
+        public Roobot(Device device, World world) : base(device, world)
         {
             //获取所有的机械臂 集合
-            var devices = Device.All.Where(v => v.HasFlag(DeviceFlags.Robot));
+            var robot = Device.All.First(x => x.Code == Entity.Code);
 
-            //开始分配
-            foreach (var robot in devices)
-            {
-                //取货设备
-                PickUpDevices.Add(robot.Code, robot.Sources.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => v).ToList());
-                PutDevices.Add(robot.Code, robot.Targets.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => new Device<IStation520, IStation521, IStation523, IRobot530>(v, World)).ToList());
-            }
+            //取货设备
+            PickUpDevices.AddRange(robot.Sources.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => v));
+            PutDevices.AddRange(robot.Targets.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => new Device<IStation520, IStation521, IStation523, IRobot530>(v, World)));
         }
 
-        public override void Do(Device<IRobot520, IRobot521, IRobot522> obj)
+        public void Do()
         {
             #region 处理完成任务
 
             //判断DB520 完成任务确认清除信号 是否为1
-            if (obj.Data.OkAck == 1 && obj.Data2 is { TaskFinishId1: 0, TaskFinishId2: 0 }) obj.Data.OkAck = 0;
+            if (Data.OkAck == 1 && Data2 is { TaskFinishId1: 0, TaskFinishId2: 0 }) Data.OkAck = 0;
 
-            if (obj.Data2.TaskFinishId1 > 0 || obj.Data2.TaskFinishId2 > 0)
+            if (Data2.TaskFinishId1 > 0 || Data2.TaskFinishId2 > 0)
             {
                 //处理完成的任务信息
                 var tasks = new List<WCS_TaskInfo>();
                 //开始处理
                 SqlSugarHelper.Do(db =>
                 {
-                    World.Log($"机械臂任务处理:开始--完成任务{obj.Data2.TaskFinishId1}--{obj.Data2.TaskFinishId2}", LogLevelEnum.Low);
+                    World.Log($"机械臂任务处理:开始--完成任务{Data2.TaskFinishId1}--{Data2.TaskFinishId2}", LogLevelEnum.Low);
 
                     //根据DB521任务号获取对应任务
-                    var taskInfoList = db.Default.Queryable<WCS_TaskInfo>().Where(v => v.ID == obj.Data2.TaskFinishId1 || v.ID == obj.Data2.TaskFinishId2).ToList();
-                    foreach (var task in taskInfoList.Where(task => task.Status == Entity.TaskStatus.StackerExecution))
+                    var taskInfoList = db.Default.Queryable<WCS_TaskInfo>().Where(v => v.ID == Data2.TaskFinishId1 || v.ID == Data2.TaskFinishId2).ToList();
+                    foreach (var task in taskInfoList.Where(task => task.Status == TaskStatus.StackerExecution))
                     {
                         //根据任务类型做不同的处理
                         switch (task.Type)
                         {
                             case TaskType.SetPlate: //工字轮入库
                                 //完成任务
-                                task.Status = Entity.TaskStatus.Finish;
+                                task.Status = TaskStatus.Finish;
                                 task.EndTime = DateTime.Now;
                                 db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.EndTime }).ExecuteCommand();
                                 task.AddWCS_TASK_DTL(db.Default, task.AddrTo, "入库任务结束");
@@ -84,7 +74,7 @@ namespace WCS.WorkEngineering.Systems
                             case TaskType.OutDepot:
                                 //var pall = db.Default.Queryable<WCS_TaskInfo>().Where(x => x.AddrTo == task.AddrTo && x.Type == TaskType.Delivery && x.Status < TaskStatus.Finish).First() ?? throw new Exception($"未找到对应的托盘搬运任务,无法进行绑盘");
 
-                                task.Status = Entity.TaskStatus.StackerCompleted;
+                                task.Status = TaskStatus.StackerCompleted;
                                 task.EditTime = DateTime.Now;
                                 db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.EditTime }).ExecuteCommand();
                                 task.AddWCS_TASK_DTL(db.Default, task.AddrTo, "出库任务结束");
@@ -92,7 +82,7 @@ namespace WCS.WorkEngineering.Systems
                                 break;
 
                             case TaskType.TransferDepot:
-                                task.Status = Entity.TaskStatus.Finish;
+                                task.Status = TaskStatus.Finish;
                                 task.EndTime = DateTime.Now;
                                 db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.EndTime }).ExecuteCommand();
                                 task.AddWCS_TASK_DTL(db.Default, task.AddrTo, "移库任务结束");
@@ -104,29 +94,29 @@ namespace WCS.WorkEngineering.Systems
                 if (!tasks.Any()) throw new KnownException("数据库提交事务错误", LogLevelEnum.High);
 
                 // 写入信号
-                obj.Data.OkAck = 1;
+                Data.OkAck = 1;
 
-                World.Log($"机械臂任务处理:结束--完成任务{obj.Data2.TaskFinishId1}--{obj.Data2.TaskFinishId2}", LogLevelEnum.Mid);
+                World.Log($"机械臂任务处理:结束--完成任务{Data2.TaskFinishId1}--{Data2.TaskFinishId2}", LogLevelEnum.Mid);
             }
 
             #endregion 处理完成任务
 
             //robot是否可以下发任务
-            if (obj.Data2.VoucherNo != obj.Data.VoucherNo)
+            if (Data2.VoucherNo != Data.VoucherNo)
             {
-                World.Log($"凭证号不一致,DB520:{obj.Data.VoucherNo},DB521:{obj.Data2.VoucherNo}", LogLevelEnum.Mid);
+                World.Log($"凭证号不一致,DB520:{Data.VoucherNo},DB521:{Data2.VoucherNo}", LogLevelEnum.Mid);
                 return;
             }
 
-            if (obj.Data2.RobotMode != RobotMode.Automatic)
+            if (Data2.RobotMode != RobotMode.Automatic)
             {
-                World.Log($"robot处于{obj.Data2.RobotMode.GetDescription()}模式", LogLevelEnum.Mid);
+                World.Log($"robot处于{Data2.RobotMode.GetDescription()}模式", LogLevelEnum.Mid);
                 return;
             }
 
-            if (obj.Data2.RunStatus != RobotRunStatus.Idle)
+            if (Data2.RunStatus != RobotRunStatus.Idle)
             {
-                World.Log($"robot处于{obj.Data2.RunStatus.GetDescription()}状态", LogLevelEnum.Mid);
+                World.Log($"robot处于{Data2.RunStatus.GetDescription()}状态", LogLevelEnum.Mid);
                 return;
             }
 
@@ -135,31 +125,31 @@ namespace WCS.WorkEngineering.Systems
             SqlSugarHelper.Do(db =>
             {
                 //获取当前堆垛机的所有未完成任务 ,就算查到了未提交的事务也无所谓,无非下一个周期再执行一次
-                var tasks = db.Default.Queryable<WCS_TaskInfo>().NoLock().Where(v => v.Status < Entity.TaskStatus.Finish && v.Device == obj.Entity.Code);
+                var tasks = db.Default.Queryable<WCS_TaskInfo>().NoLock().Where(v => v.Status < TaskStatus.Finish && v.Device == Entity.Code);
                 //任务集合是否有处于堆垛机执行状态的任务
-                if (tasks.Any(v => v.Status == Entity.TaskStatus.StackerExecution)) throw new KnownException($"有任务处于堆垛机执行状态", LogLevelEnum.High);
+                if (tasks.Any(v => v.Status == TaskStatus.StackerExecution)) throw new KnownException($"有任务处于堆垛机执行状态", LogLevelEnum.High);
             });
             //获取入库次数
-            var inQuantity = obj.Entity.GetFlag<int>("InQuantity");
+            var inQuantity = Entity.GetFlag<int>("InQuantity");
             var inMaxQuantity = 2; //出入库的周期检查比为1:3
             //入库任务优先 或 上一个周期是出库任务并且出库任务无优先
             if (inQuantity <= inMaxQuantity) //入库任务
             {
                 //判断本次优先执行楼层,并设置下次执行时优先楼层
-                var floor = obj.Entity.GetFlag<int>("FloorIn");
+                var floor = Entity.GetFlag<int>("FloorIn");
                 floor = floor % 2 + 1;
-                obj.Entity.SetFlag("FloorIn", floor);
-                obj.Entity.SetFlag("InQuantity", inQuantity + 1);
+                Entity.SetFlag("FloorIn", floor);
+                Entity.SetFlag("InQuantity", inQuantity + 1);
 
                 //获取当前机械臂所有的取货站台
-                var pickUpDevices = obj.Entity.Sources.Where(x => x.HasFlag(DeviceFlags.输送机)).Where(x => x.DeviceGroup.Any()).Select(
+                var pickUpDevices = Entity.Sources.Where(x => x.HasFlag(DeviceFlags.输送机)).Where(x => x.DeviceGroup.Any()).Select(
                     x =>
                     {
                         var group = x.DeviceGroup.Select(s => new Device<IStation523, IStation524>(s, World)).ToList();
                         return new Tuple<Device<IStation523, IStation524>, List<Device<IStation523, IStation524>>>(new Device<IStation523, IStation524>(x, World), group);
                     }).ToList();
 
-                if (!pickUpDevices.Any()) throw new KnownException($"机械臂{obj.Entity.Code}无取货路径点", LogLevelEnum.High);
+                if (!pickUpDevices.Any()) throw new KnownException($"机械臂{Entity.Code}无取货路径点", LogLevelEnum.High);
 
                 //获取取货设备的设备组中都是停止运行的
                 var arrIn = pickUpDevices.Where(x => x.Item2.All(a => !a.Data.Status.HasFlag(StationStatus.Run)))
@@ -173,8 +163,8 @@ namespace WCS.WorkEngineering.Systems
 
                 if (!arrIn.Any())
                 {
-                    World.Log($"[{obj.Entity.Code}]等待入库任务输送到位");
-                    obj.Entity.SetFlag("InQuantity", 4); //在无货物的情况下,只检查一次,下次直接查询是否有出库任务,避免无效检查周期的产生
+                    World.Log($"[{Entity.Code}]等待入库任务输送到位");
+                    Entity.SetFlag("InQuantity", 4); //在无货物的情况下,只检查一次,下次直接查询是否有出库任务,避免无效检查周期的产生
                     return;
                 }
 
@@ -195,22 +185,22 @@ namespace WCS.WorkEngineering.Systems
                     //.Take(2);
                     if (!devGroup.Any())
                     {
-                        obj.Entity.SetFlag("InQuantity", 4); //在无有效取货位的情况下,只检查一次,下次直接查询是否有出库任务,避免无效检查周期的产生
+                        Entity.SetFlag("InQuantity", 4); //在无有效取货位的情况下,只检查一次,下次直接查询是否有出库任务,避免无效检查周期的产生
                         throw new KnownException($"无有效入库取货位", LogLevelEnum.High);
                     }
 
                     foreach (var dev in devGroup)
                     {
-                        var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.Type == TaskType.SetPlate && v.Status == Entity.TaskStatus.FinishOfShunt && dev.Data2.TaskNumber == v.ID);
+                        var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.Type == TaskType.SetPlate && v.Status == TaskStatus.FinishOfShunt && dev.Data2.TaskNumber == v.ID);
                         if (task == null) continue;
                         //var res = WmsApi.RingApplyStockInLoc(task.ID, task.Device, dev.Entity.Code, task.GoodsType);
                         //if (res.ResCode != ResponseStatusCodeEnum.Sucess)
                         //{
                         //    World.Log(res.ResMsg);
-                        //    obj.Entity.SetFlag("InQuantity", 4); //在获取货物异常的情况下,只检查一次,下次直接查询是否有出库任务,避免无效检查周期的产生
+                        //    Entity.SetFlag("InQuantity", 4); //在获取货物异常的情况下,只检查一次,下次直接查询是否有出库任务,避免无效检查周期的产生
                         //    return;
                         //}
-                        task.Status = Entity.TaskStatus.StackerExecution;
+                        task.Status = TaskStatus.StackerExecution;
                         //task.AddrTo = res.ResData.CellNo;
                         //task.Line = res.ResData.Row;
                         //task.Col = res.ResData.Colomn;
@@ -218,7 +208,7 @@ namespace WCS.WorkEngineering.Systems
                         //task.Depth = res.ResData.Row;
                         task.LastInteractionPoint = dev.Entity.Code;
                         task.SrmStation = dev.Entity.Code;
-                        task.Device = obj.Entity.Code;
+                        task.Device = Entity.Code;
                         task.EditWho = "WCS";
                         db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.AddrTo, x.Line, x.Col, x.Layer, x.Depth, x.LastInteractionPoint, x.SrmStation, x.Device, x.EditWho }).ExecuteCommand();
                         task.AddWCS_TASK_DTL(db.Default, dev.Entity.Code, task.AddrTo, "任务下发机械臂执行");
@@ -234,34 +224,34 @@ namespace WCS.WorkEngineering.Systems
                         var task = taskList.FirstOrDefault().Item1;
                         var dev = taskList.FirstOrDefault().Item2;
                         //下发任务
-                        obj.Data.TaskNumber1 = task.ID;
-                        obj.Data.SLine1 = dev.Entity.Code.ToShort();
-                        obj.Data.SCol1 = 0;
-                        obj.Data.SLayer1 = 0;
-                        obj.Data.SDepth1 = 0;
-                        obj.Data.ELine1 = task.Line.ToShort();
-                        obj.Data.ECol1 = task.Col.ToShort();
-                        obj.Data.ELayer1 = task.Layer.ToShort();
-                        obj.Data.EDepth1 = task.Depth.ToShort();
-                        obj.Data.TaskNumber2 = 0;
-                        obj.Data.SLine2 = 0;
-                        obj.Data.SCol2 = 0;
-                        obj.Data.SLayer2 = 0;
-                        obj.Data.SDepth2 = 0;
-                        obj.Data.ELine2 = 0;
-                        obj.Data.ECol2 = 0;
-                        obj.Data.ELayer2 = 0;
-                        obj.Data.EDepth2 = 0;
-                        obj.Data.TaskSum = taskList.Count.ToShort();
-                        obj.Data.GoodsType = task.GoodsType switch
+                        Data.TaskNumber1 = task.ID;
+                        Data.SLine1 = dev.Entity.Code.ToShort();
+                        Data.SCol1 = 0;
+                        Data.SLayer1 = 0;
+                        Data.SDepth1 = 0;
+                        Data.ELine1 = task.Line.ToShort();
+                        Data.ECol1 = task.Col.ToShort();
+                        Data.ELayer1 = task.Layer.ToShort();
+                        Data.EDepth1 = task.Depth.ToShort();
+                        Data.TaskNumber2 = 0;
+                        Data.SLine2 = 0;
+                        Data.SCol2 = 0;
+                        Data.SLayer2 = 0;
+                        Data.SDepth2 = 0;
+                        Data.ELine2 = 0;
+                        Data.ECol2 = 0;
+                        Data.ELayer2 = 0;
+                        Data.EDepth2 = 0;
+                        Data.TaskSum = taskList.Count.ToShort();
+                        Data.GoodsType = task.GoodsType switch
                         {
                             18 => 1,
                             34 => 2,
                             50 => 3,
                             _ => 0
                         };
-                        obj.Data.TaskType = 3;
-                        obj.Data.VoucherNo++;
+                        Data.TaskType = 3;
+                        Data.VoucherNo++;
                         break;
 
                     case 2:
@@ -270,62 +260,61 @@ namespace WCS.WorkEngineering.Systems
                         var taskInfo = taskList[1];
                         task = taskInfo.Item1;
                         dev = taskInfo.Item2;
-                        obj.Data.TaskNumber1 = task.ID;
-                        obj.Data.SLine1 = dev.Entity.Code.ToShort();
-                        obj.Data.SCol1 = 0;
-                        obj.Data.SLayer1 = 0;
-                        obj.Data.SDepth1 = 0;
-                        obj.Data.ELine1 = task.Line.ToShort();
-                        obj.Data.ECol1 = task.Col.ToShort();
-                        obj.Data.ELayer1 = task.Layer.ToShort();
-                        obj.Data.EDepth1 = task.Depth.ToShort();
+                        Data.TaskNumber1 = task.ID;
+                        Data.SLine1 = dev.Entity.Code.ToShort();
+                        Data.SCol1 = 0;
+                        Data.SLayer1 = 0;
+                        Data.SDepth1 = 0;
+                        Data.ELine1 = task.Line.ToShort();
+                        Data.ECol1 = task.Col.ToShort();
+                        Data.ELayer1 = task.Layer.ToShort();
+                        Data.EDepth1 = task.Depth.ToShort();
                         //二工位取深度较少的值
                         taskInfo = taskList[0];
                         task = taskInfo.Item1;
                         dev = taskInfo.Item2;
-                        obj.Data.TaskNumber2 = task.ID;
-                        obj.Data.SLine2 = dev.Entity.Code.ToShort();
-                        obj.Data.SCol2 = 0;
-                        obj.Data.SLayer2 = 0;
-                        obj.Data.SDepth2 = 0;
-                        obj.Data.ELine2 = task.Line.ToShort();
-                        obj.Data.ECol2 = task.Col.ToShort();
-                        obj.Data.ELayer2 = task.Layer.ToShort();
-                        obj.Data.EDepth2 = task.Depth.ToShort();
-                        obj.Data.TaskSum = taskList.Count.ToShort();
-                        obj.Data.GoodsType = task.GoodsType switch
+                        Data.TaskNumber2 = task.ID;
+                        Data.SLine2 = dev.Entity.Code.ToShort();
+                        Data.SCol2 = 0;
+                        Data.SLayer2 = 0;
+                        Data.SDepth2 = 0;
+                        Data.ELine2 = task.Line.ToShort();
+                        Data.ECol2 = task.Col.ToShort();
+                        Data.ELayer2 = task.Layer.ToShort();
+                        Data.EDepth2 = task.Depth.ToShort();
+                        Data.TaskSum = taskList.Count.ToShort();
+                        Data.GoodsType = task.GoodsType switch
                         {
                             18 => 1,
                             34 => 2,
                             50 => 3,
                             _ => 0
                         };
-                        obj.Data.TaskType = 3;
-                        obj.Data.VoucherNo++;
+                        Data.TaskType = 3;
+                        Data.VoucherNo++;
                         break;
 
                     default:
                         throw new KnownException($"无法执行多个任务", LogLevelEnum.Mid);
                 }
-                World.Log($"机械臂任务处理:下发入库任务{obj.Data.TaskNumber1}--{obj.Data.TaskNumber2}--{obj.Data.VoucherNo}", LogLevelEnum.Mid);
+                World.Log($"机械臂任务处理:下发入库任务{Data.TaskNumber1}--{Data.TaskNumber2}--{Data.VoucherNo}", LogLevelEnum.Mid);
             }
             else //出库任务
             {
                 //判断本次优先执行楼层,并设置下次执行时优先楼层
-                var floor = obj.Entity.GetFlag<int>("FloorOut");
+                var floor = Entity.GetFlag<int>("FloorOut");
                 floor = floor % 2 + 1;
-                obj.Entity.SetFlag("FloorOut", floor);
-                obj.Entity.SetFlag("InQuantity", 0);
+                Entity.SetFlag("FloorOut", floor);
+                Entity.SetFlag("InQuantity", 0);
 
                 //获取当前堆垛机所有的取货站台
-                var arrOut = PutDevices.First(v => v.Key == obj.Entity.Code).Value;
-                if (!arrOut.Any()) throw new KnownException($"机械臂{obj.Entity.Code}无放货路径点", LogLevelEnum.High);
+                if (!PutDevices.Any()) throw new KnownException($"机械臂{Entity.Code}无放货路径点", LogLevelEnum.High);
 
                 //获取可以放货的设备集合
-                arrOut = arrOut.Where(v => v.Data3.Status.HasFlag(StationStatus.PH_Status) && v.Data.TaskNumber == 0 && v.Data.GoodsEnd == 0).ToList();//有光电
-                if (!arrOut.Any())
+                PutDevices = PutDevices.Where(v => v.Data3.Status.HasFlag(StationStatus.PH_Status) && v.Data.TaskNumber == 0 && v.Data.GoodsEnd == 0).ToList();//有光电
+                if (!PutDevices.Any())
                 {
-                    World.Log($"[{obj.Entity.Code}]等待出库任务输送到位");
+                    World.Log($"[{Entity.Code}]等待出库任务输送到位");
                     return;
                 }
 
@@ -333,99 +322,99 @@ namespace WCS.WorkEngineering.Systems
                 var nextAdd = "";
 
                 SqlSugarHelper.Do(db =>
-                        {
-                            //所有出库点设备号,即
-                            var allOutCode = arrOut.Select(v => new
-                            {
-                                v.Entity.Code,
-                                v.Data4.Type
-                            }).ToList();
-                            //两个工位同时码垛,并不会一个执行一次,只有一个托盘任务全部执行完毕,才会继续执行下一个,先生成任务的码垛工位会优先执行
-                            var taskInfos = db.Default.Queryable<WCS_TaskInfo>().Where(v => (v.Status == Entity.TaskStatus.WaitingToExecute || v.Status == TaskStatus.ConveyorExecution) && v.Type == TaskType.OutDepot)
-                                .ToList().Where(v => allOutCode.Any(x => v.SrmStation == x.Code && v.PalletType == x.Type)).ToList();
-
-                            var deliveryTask = db.Default.Queryable<WCS_TaskInfo>().Where(x => x.Status > 0 && x.Type == TaskType.Delivery).ToList().Select(x => x.AddrTo);
-                            taskInfos = taskInfos.Where(x => deliveryTask.Contains(x.SrmStation)).ToList();
-                            if (!taskInfos.Any())
-                            {
-                                World.Log("等待空托盘到位");
-                                return;
-                            }
+                {
+                    //所有出库点设备号,即
+                    var allOutCode = PutDevices.Select(v => new
+                    {
+                        v.Entity.Code,
+                        v.Data4.Type
+                    }).ToList();
+                    //两个工位同时码垛,并不会一个执行一次,只有一个托盘任务全部执行完毕,才会继续执行下一个,先生成任务的码垛工位会优先执行
+                    var taskInfos = db.Default.Queryable<WCS_TaskInfo>().Where(v => (v.Status == TaskStatus.WaitingToExecute || v.Status == TaskStatus.ConveyorExecution) && v.Type == TaskType.OutDepot)
+                        .ToList().Where(v => allOutCode.Any(x => v.SrmStation == x.Code && v.PalletType == x.Type)).ToList();
 
-                            if (!taskInfos.Any()) throw new KnownException($"未找到站台{JsonConvert.SerializeObject(allOutCode)}可用的出库任务", LogLevelEnum.Mid);
-                            var srmStation = taskInfos.GroupBy(x => x.SrmStation).Where(x => x.Any(s => s.Status == TaskStatus.WaitingToExecute)).Select(x => new
-                            {
-                                x.Key,
-                                x.OrderByDescending(t => t.AddTime).First().AddTime
-                            }).OrderBy(x => x.AddTime).First().Key;
-                            taskInfos = taskInfos.Where(x => x.SrmStation == srmStation).ToList(); //找到一个可以放货的待执行站台
+                    var deliveryTask = db.Default.Queryable<WCS_TaskInfo>().Where(x => x.Status > 0 && x.Type == TaskType.Delivery).ToList().Select(x => x.AddrTo);
+                    taskInfos = taskInfos.Where(x => deliveryTask.Contains(x.SrmStation)).ToList();
+                    if (!taskInfos.Any())
+                    {
+                        World.Log("等待空托盘到位");
+                        return;
+                    }
 
-                            //如果全部是待执行状态,需要验证待执行的任务的数量是否与任务总数相等
-                            if (taskInfos.All(x => x.Status == TaskStatus.WaitingToExecute))
-                            {
-                                var task = taskInfos.First();
-                                if (task.FullQty != taskInfos.Count) throw new KnownException($"等待站台{srmStation}所有码垛出库任务完成初始化", LogLevelEnum.Mid);
-                            }
-                            taskInfos = taskInfos.Where(x => x.Status == TaskStatus.WaitingToExecute).OrderBy(x => x.ProdLine).ToList();
+                    if (!taskInfos.Any()) throw new KnownException($"未找到站台{JsonConvert.SerializeObject(allOutCode)}可用的出库任务", LogLevelEnum.Mid);
+                    var srmStation = taskInfos.GroupBy(x => x.SrmStation).Where(x => x.Any(s => s.Status == TaskStatus.WaitingToExecute)).Select(x => new
+                    {
+                        x.Key,
+                        x.OrderByDescending(t => t.AddTime).First().AddTime
+                    }).OrderBy(x => x.AddTime).First().Key;
+                    taskInfos = taskInfos.Where(x => x.SrmStation == srmStation).ToList(); //找到一个可以放货的待执行站台
 
-                            if (taskInfos.FirstOrDefault().WarehouseCode.Contains("S")) //如果是南侧,翻转排序
-                            {
-                                taskInfos = taskInfos.OrderByDescending(x => x.ProdLine).ToList();
-                            }
+                    //如果全部是待执行状态,需要验证待执行的任务的数量是否与任务总数相等
+                    if (taskInfos.All(x => x.Status == TaskStatus.WaitingToExecute))
+                    {
+                        var task = taskInfos.First();
+                        if (task.FullQty != taskInfos.Count) throw new KnownException($"等待站台{srmStation}所有码垛出库任务完成初始化", LogLevelEnum.Mid);
+                    }
+                    taskInfos = taskInfos.Where(x => x.Status == TaskStatus.WaitingToExecute).OrderBy(x => x.ProdLine).ToList();
 
-                            taskInfos = taskInfos.Take(2).ToList();
-                            var warehouseCode = taskInfos.FirstOrDefault().WarehouseCode;
-                            if (taskInfos.Count == 2) //有两个任务
+                    if (taskInfos.FirstOrDefault().WarehouseCode.Contains("S")) //如果是南侧,翻转排序
+                    {
+                        taskInfos = taskInfos.OrderByDescending(x => x.ProdLine).ToList();
+                    }
+
+                    taskInfos = taskInfos.Take(2).ToList();
+                    var warehouseCode = taskInfos.FirstOrDefault().WarehouseCode;
+                    if (taskInfos.Count == 2) //有两个任务
+                    {
+                        var minDepth = taskInfos!.MinBy(x => x.Depth);
+                        var maxDepth = taskInfos.MaxBy(x => x.Depth);
+                        //产品类型不同时,只能取一个
+                        if (minDepth.GoodsType != maxDepth.GoodsType)
+                        {
+                            //南边取位号较大的,北边取位号较小的
+                            taskInfos = warehouseCode.Contains("S") ? taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList() : taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
+                        }
+                        //深度之和等于6(机械臂当前无法同时执行两个三深度的取货任务)
+                        else if (taskInfos.Sum(x => x.Depth) == 6)
+                        {
+                            taskInfos = warehouseCode.Contains("S") ? taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList() : taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
+                        }
+                        else if (taskInfos[0].SrmStation != taskInfos[1].SrmStation)
+                        {
+                            taskInfos = warehouseCode.Contains("S") ? taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList() : taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
+                        }
+                        else if (warehouseCode.Contains("S"))
+                        {
+                            //从大到小 一抓偶数
+                            var max = taskInfos.MaxBy(x => x.ProdLine).ProdLine;
+                            if ((max & 1) == 1) //抓一不是偶数
                             {
-                                var minDepth = taskInfos!.MinBy(x => x.Depth);
-                                var maxDepth = taskInfos.MaxBy(x => x.Depth);
-                                //产品类型不同时,只能取一个
-                                if (minDepth.GoodsType != maxDepth.GoodsType)
-                                {
-                                    //南边取位号较大的,北边取位号较小的
-                                    taskInfos = warehouseCode.Contains("S") ? taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList() : taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
-                                }
-                                //深度之和等于6(机械臂当前无法同时执行两个三深度的取货任务)
-                                else if (taskInfos.Sum(x => x.Depth) == 6)
-                                {
-                                    taskInfos = warehouseCode.Contains("S") ? taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList() : taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
-                                }
-                                else if (taskInfos[0].SrmStation != taskInfos[1].SrmStation)
-                                {
-                                    taskInfos = warehouseCode.Contains("S") ? taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList() : taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
-                                }
-                                else if (warehouseCode.Contains("S"))
-                                {
-                                    //从大到小 一抓偶数
-                                    var max = taskInfos.MaxBy(x => x.ProdLine).ProdLine;
-                                    if ((max & 1) == 1) //抓一不是偶数
-                                    {
-                                        taskInfos = taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList();
-                                    }
-                                }
-                                else if (warehouseCode.Contains("N"))
-                                {
-                                    //从小到达 一抓奇数
-                                    var mix = taskInfos.MinBy(x => x.ProdLine).ProdLine;
-                                    if ((mix & 1) == 0) //抓一不是奇数
-                                    {
-                                        taskInfos = taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
-                                    }
-                                }
+                                taskInfos = taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList();
                             }
-
-                            foreach (var task in taskInfos)
+                        }
+                        else if (warehouseCode.Contains("N"))
+                        {
+                            //从小到达 一抓奇数
+                            var mix = taskInfos.MinBy(x => x.ProdLine).ProdLine;
+                            if ((mix & 1) == 0) //抓一不是奇数
                             {
-                                task.Status = Entity.TaskStatus.StackerExecution;
-                                task.LastInteractionPoint = task.Device;
-                                task.StartTime = DateTime.Now;
-                                task.EditWho = "WCS";
-                                nextAdd = task.SrmStation;
-                                db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.LastInteractionPoint, x.StartTime, x.EditWho }).ExecuteCommand();
-                                task.AddWCS_TASK_DTL(db.Default, task.Device, task.SrmStation, "任务下发机械臂执行");
-                                taskInfoList.Add(task);
+                                taskInfos = taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
                             }
-                        });
+                        }
+                    }
+
+                    foreach (var task in taskInfos)
+                    {
+                        task.Status = TaskStatus.StackerExecution;
+                        task.LastInteractionPoint = task.Device;
+                        task.StartTime = DateTime.Now;
+                        task.EditWho = "WCS";
+                        nextAdd = task.SrmStation;
+                        db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.LastInteractionPoint, x.StartTime, x.EditWho }).ExecuteCommand();
+                        task.AddWCS_TASK_DTL(db.Default, task.Device, task.SrmStation, "任务下发机械臂执行");
+                        taskInfoList.Add(task);
+                    }
+                });
 
                 if (!taskInfoList.Any()) return;
 
@@ -435,34 +424,34 @@ namespace WCS.WorkEngineering.Systems
                         var task = taskInfoList.FirstOrDefault();
 
                         //下发任务
-                        obj.Data.TaskNumber1 = task.ID;
-                        obj.Data.SLine1 = task.Line.ToShort();
-                        obj.Data.SCol1 = task.Col.ToShort();
-                        obj.Data.SLayer1 = task.Layer.ToShort();
-                        obj.Data.SDepth1 = task.Depth.ToShort();
-                        obj.Data.ELine1 = nextAdd.ToShort();
-                        obj.Data.ECol1 = task.ProdLine;
-                        obj.Data.ELayer1 = 0;
-                        obj.Data.EDepth1 = 0;
-                        obj.Data.TaskNumber2 = 0;
-                        obj.Data.SLine2 = 0;
-                        obj.Data.SCol2 = 0;
-                        obj.Data.SLayer2 = 0;
-                        obj.Data.SDepth2 = 0;
-                        obj.Data.ELine2 = 0;
-                        obj.Data.ECol2 = 0;
-                        obj.Data.ELayer2 = 0;
-                        obj.Data.EDepth2 = 0;
-                        obj.Data.TaskSum = taskInfoList.Count.ToShort();
-                        obj.Data.GoodsType = task.GoodsType switch
+                        Data.TaskNumber1 = task.ID;
+                        Data.SLine1 = task.Line.ToShort();
+                        Data.SCol1 = task.Col.ToShort();
+                        Data.SLayer1 = task.Layer.ToShort();
+                        Data.SDepth1 = task.Depth.ToShort();
+                        Data.ELine1 = nextAdd.ToShort();
+                        Data.ECol1 = task.ProdLine;
+                        Data.ELayer1 = 0;
+                        Data.EDepth1 = 0;
+                        Data.TaskNumber2 = 0;
+                        Data.SLine2 = 0;
+                        Data.SCol2 = 0;
+                        Data.SLayer2 = 0;
+                        Data.SDepth2 = 0;
+                        Data.ELine2 = 0;
+                        Data.ECol2 = 0;
+                        Data.ELayer2 = 0;
+                        Data.EDepth2 = 0;
+                        Data.TaskSum = taskInfoList.Count.ToShort();
+                        Data.GoodsType = task.GoodsType switch
                         {
                             18 => 1,
                             34 => 2,
                             50 => 3,
                             _ => 0
                         };
-                        obj.Data.TaskType = 4;
-                        obj.Data.VoucherNo++;
+                        Data.TaskType = 4;
+                        Data.VoucherNo++;
                         break;
 
                     case 2:
@@ -471,49 +460,164 @@ namespace WCS.WorkEngineering.Systems
 
                         //一工位取深度较大的任务
                         var taskInfo = taskInfoList[1];
-                        obj.Data.TaskNumber1 = taskInfo.ID;
-                        obj.Data.SLine1 = taskInfo.Line.ToShort();
-                        obj.Data.SCol1 = taskInfo.Col.ToShort();
-                        obj.Data.SLayer1 = taskInfo.Layer.ToShort();
-                        obj.Data.SDepth1 = taskInfo.Depth.ToShort();
-                        obj.Data.ELine1 = nextAdd.ToShort();
-                        obj.Data.ECol1 = taskInfo.WarehouseCode.Contains("S") ? taskInfoList.Max(x => x.ProdLine) : taskInfoList.Min(x => x.ProdLine);
-                        obj.Data.ELayer1 = 0;
-                        obj.Data.EDepth1 = 0;
+                        Data.TaskNumber1 = taskInfo.ID;
+                        Data.SLine1 = taskInfo.Line.ToShort();
+                        Data.SCol1 = taskInfo.Col.ToShort();
+                        Data.SLayer1 = taskInfo.Layer.ToShort();
+                        Data.SDepth1 = taskInfo.Depth.ToShort();
+                        Data.ELine1 = nextAdd.ToShort();
+                        Data.ECol1 = taskInfo.WarehouseCode.Contains("S") ? taskInfoList.Max(x => x.ProdLine) : taskInfoList.Min(x => x.ProdLine);
+                        Data.ELayer1 = 0;
+                        Data.EDepth1 = 0;
                         //二工位取深度较少的值
                         taskInfo = taskInfoList[0];
-                        obj.Data.TaskNumber2 = taskInfo.ID;
-                        obj.Data.SLine2 = taskInfo.Line.ToShort();
-                        obj.Data.SCol2 = taskInfo.Col.ToShort();
-                        obj.Data.SLayer2 = taskInfo.Layer.ToShort();
-                        obj.Data.SDepth2 = taskInfo.Depth.ToShort();
-                        obj.Data.ELine2 = nextAdd.ToShort();
-                        obj.Data.ECol2 = taskInfo.WarehouseCode.Contains("S") ? taskInfoList.Min(x => x.ProdLine) : taskInfoList.Max(x => x.ProdLine);
-                        obj.Data.ELayer2 = 0;
-                        obj.Data.EDepth2 = 0;
-                        obj.Data.TaskSum = taskInfoList.Count.ToShort();
-                        obj.Data.GoodsType = taskInfo.GoodsType switch
+                        Data.TaskNumber2 = taskInfo.ID;
+                        Data.SLine2 = taskInfo.Line.ToShort();
+                        Data.SCol2 = taskInfo.Col.ToShort();
+                        Data.SLayer2 = taskInfo.Layer.ToShort();
+                        Data.SDepth2 = taskInfo.Depth.ToShort();
+                        Data.ELine2 = nextAdd.ToShort();
+                        Data.ECol2 = taskInfo.WarehouseCode.Contains("S") ? taskInfoList.Min(x => x.ProdLine) : taskInfoList.Max(x => x.ProdLine);
+                        Data.ELayer2 = 0;
+                        Data.EDepth2 = 0;
+                        Data.TaskSum = taskInfoList.Count.ToShort();
+                        Data.GoodsType = taskInfo.GoodsType switch
                         {
                             18 => 1,
                             34 => 2,
                             50 => 3,
                             _ => 0
                         };
-                        obj.Data.TaskType = 4;
-                        obj.Data.VoucherNo++;
+                        Data.TaskType = 4;
+                        Data.VoucherNo++;
                         break;
 
                     default:
 
                         throw new KnownException($"无法执行多个任务", LogLevelEnum.Mid);
                 }
-                World.Log($"机械臂任务处理:下发出库任务{obj.Data.TaskNumber1}--{obj.Data.TaskNumber2}--{obj.Data.VoucherNo}", LogLevelEnum.Mid);
+                World.Log($"机械臂任务处理:下发出库任务{Data.TaskNumber1}--{Data.TaskNumber2}--{Data.VoucherNo}", LogLevelEnum.Mid);
             }
         }
+    }
+
+    /// <summary>
+    ///   Robot1
+    /// </summary>
+    [BelongTo(typeof(RingWorld1))]
+    [Description("Robot1")]
+    public class Robot1 : DeviceSystem<Roobot>
+    {
+        protected override bool ParallelDo => true;
+
+        public override void Do(Roobot obj)
+        {
+            obj.Do();
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.Code == "Robot1";
+        }
+    }
+
+    /// <summary>
+    ///   Robot2
+    /// </summary>
+    [BelongTo(typeof(RingWorld2))]
+    [Description("Robot2")]
+    public class Robot2 : DeviceSystem<Roobot>
+    {
+        protected override bool ParallelDo => true;
+
+        public override void Do(Roobot obj)
+        {
+            obj.Do();
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.Code == "Robot2";
+        }
+    }
+
+    /// <summary>
+    ///   Robot3
+    /// </summary>
+    [BelongTo(typeof(RingWorld3))]
+    [Description("Robot3")]
+    public class Robot3 : DeviceSystem<Roobot>
+    {
+        protected override bool ParallelDo => true;
+
+        public override void Do(Roobot obj)
+        {
+            obj.Do();
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.Code == "Robot3";
+        }
+    }
+
+    /// <summary>
+    ///   Robot4
+    /// </summary>
+    [BelongTo(typeof(RingWorld4))]
+    [Description("Robot4")]
+    public class Robot4 : DeviceSystem<Roobot>
+    {
+        protected override bool ParallelDo => true;
+
+        public override void Do(Roobot obj)
+        {
+            obj.Do();
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.Code == "Robot4";
+        }
+    }
+
+    /// <summary>
+    ///   Robot5
+    /// </summary>
+    [BelongTo(typeof(RingWorld5))]
+    [Description("Robot5")]
+    public class Robot5 : DeviceSystem<Roobot>
+    {
+        protected override bool ParallelDo => true;
+
+        public override void Do(Roobot obj)
+        {
+            obj.Do();
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.Code == "Robot5";
+        }
+    }
+
+    /// <summary>
+    ///   Robot6
+    /// </summary>
+    [BelongTo(typeof(RingWorld6))]
+    [Description("Robot6")]
+    public class Robot6 : DeviceSystem<Roobot>
+    {
+        protected override bool ParallelDo => true;
+
+        public override void Do(Roobot obj)
+        {
+            obj.Do();
+        }
 
         public override bool Select(Device dev)
         {
-            return dev.Code is "Robot1" or "Robot2" or "Robot3" or "Robot4" or "Robot5" or "Robot6";
+            return dev.Code == "Robot6";
         }
     }
 }