林豪 左 2 سال پیش
والد
کامیت
f3ef844585

+ 11 - 0
ServiceCenter/Extensions/TypeExtension.cs

@@ -7,6 +7,7 @@ using System.Numerics;
 using System.Reflection;
 using System.Security.Cryptography;
 using System.Text;
+using System.Text.RegularExpressions;
 
 namespace ServiceCenter.Extensions
 {
@@ -55,6 +56,16 @@ namespace ServiceCenter.Extensions
             return Convert.ToInt32(value);
         }
 
+        /// <summary>
+        ///  获取最后一位数字
+        /// </summary>
+        /// <param name="value">字符串</param>
+        /// <returns></returns>
+        public static int GetLastDigit(this string value)
+        {
+            return Convert.ToInt32(Regex.Match(value, @"\d+$").Value);
+        }
+
         /// <summary>
         /// 判断值为奇数/偶数
         /// </summary>

+ 6 - 0
WCS.Core/World.cs

@@ -21,6 +21,11 @@ namespace WCS.Core
 
         #region Static
 
+        /// <summary>
+        ///  世界是否启用成功
+        /// </summary>
+        public static bool IsStart = false;
+
         private static List<World> _Worlds;
 
         internal static List<World> Worlds
@@ -78,6 +83,7 @@ namespace WCS.Core
                 Console.WriteLine(str);
                 Console.ResetColor();
             }
+            IsStart = true;
         }
 
         public static void StopAll()

+ 7 - 1
WCS.Entity/WCS_AgvTaskInfo.cs

@@ -160,6 +160,12 @@ namespace WCS.Entity
         [Description("取放完成2")]
         Complete2 = 31,
 
+        /// <summary>
+        ///  小车离开取货位
+        /// </summary>
+        [Description("小车离开取货位")]
+        Complete3 = 32,
+
         /// <summary>
         /// 任务完成
         /// </summary>
@@ -191,7 +197,7 @@ namespace WCS.Entity
         EnterDepot = 1,
 
         /// <summary>
-        /// 叫料
+        /// 背负式补空
         /// </summary>
         [Description("叫料")]
         CallForMaterial = 2,

+ 6 - 0
WCS.Entity/WCS_TaskInfo.cs

@@ -287,6 +287,12 @@ namespace WCS.Entity
         /// </summary>
         [Description("搬运")]
         Delivery = 5,
+
+        /// <summary>
+        ///  空轮初始化
+        /// </summary>
+        [Description("空轮初始化")]
+        EmptyInit = 6,
     }
 
     /// <summary>

+ 6 - 0
WCS.Entity/WCS_TaskOld.cs

@@ -136,6 +136,12 @@ namespace WCS.Entity
         [SugarColumn(ColumnDescription = "满盘数量", IsNullable = true)]
         public short FullQty { get; set; }
 
+        /// <summary>
+        ///  重量
+        /// </summary>
+        [SugarColumn(ColumnDescription = "重量", IsNullable = true)]
+        public float Weight { get; set; }
+
         /// <summary>
         /// 高度
         /// </summary>

+ 3 - 0
WCS.WorkEngineering/Extensions/DeviceExtension.cs

@@ -94,6 +94,9 @@ namespace WCS.WorkEngineering.Extensions
         巷道 = 1 << 14,
         堆垛机 = 1 << 15,
         输送机 = 1 << 16,
+        一楼出库口 = 1 << 17,
+        一楼入库口 = 1 << 18,
+        二楼入库口 = 1 << 19,
     }
 
     /// <summary>

+ 6 - 16
WCS.WorkEngineering/Extensions/TaskExtension.cs

@@ -1,7 +1,5 @@
 using ServiceCenter.SqlSugars;
-using WCS.Core;
 using WCS.Entity;
-using WCS.WorkEngineering.WebApi.Controllers;
 using WCS.WorkEngineering.Worlds.Logs;
 
 namespace WCS.WorkEngineering.Extensions
@@ -47,19 +45,13 @@ namespace WCS.WorkEngineering.Extensions
         /// <param name="taskInfo"></param>
         /// <param name="db"></param>
         /// <param name="world"></param>
-        public static void CompleteOrCancelTasks(this WCS_TaskInfo taskInfo, SqlSugarHelper db, World world)
+        public static void CompleteOrCancelTasks(this WCS_TaskInfo taskInfo, SqlSugarHelper db)
         {
-            if (taskInfo.Status is not Entity.TaskStatus.Finish and not Entity.TaskStatus.Cancel)
-            {
-                world.Log("任务未完成或取消,无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid, ErrorTypeEnum.Kown, LogUpLoadEnum.NotUpLoad);
-            }
+            if (taskInfo.Status is not Entity.TaskStatus.Finish and not Entity.TaskStatus.Cancel) throw new KnownException("任务未完成或取消,无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid);
             else // 任务完成或取消,进行相关同步动作
             {
-                WCS_TaskOld taskOld = db.Default.Queryable<WCS_TaskOld>().SplitTable(tabs => tabs.Take(1)).Where(v => v.ID == taskInfo.ID).OrderByDescending(v => v.AddTime).First();
-                if (taskOld is null)
-                {
-                    world.Log($"WCS_TaskOld表中不存在任务:{taskInfo.ID},无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid, ErrorTypeEnum.Kown, LogUpLoadEnum.UpLoadWMS);
-                }
+                WCS_TaskOld taskOld = db.Default.Queryable<WCS_TaskOld>().SplitTable(tabs => tabs.Take(2)).Where(v => v.ID == taskInfo.ID).OrderByDescending(v => v.AddTime).First();
+                if (taskOld is null) throw new KnownException($"WCS_TaskOld表中不存在任务:{taskInfo.ID},无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid);
                 else
                 {
                     //状态
@@ -96,15 +88,13 @@ namespace WCS.WorkEngineering.Extensions
                     //外形信息
                     taskOld.Height = taskInfo.Height;
                     taskOld.Length = taskInfo.Length;
+                    taskOld.Weight = taskInfo.Weight;
                     //手动处理备注
                     taskOld.ManualRemarks = taskInfo.ManualRemarks;
 
                     //更新任务历史表,删除任务当前表
-                    db.Default.Updateable(taskOld).ExecuteCommand();
+                    db.Default.Updateable(taskOld).SplitTable().ExecuteCommand();
                     db.Default.Deleteable(taskInfo).ExecuteCommand();
-
-                    //通知WMS任务完成
-                    WmsApi.CompleteTask(taskOld.ID);
                 }
             }
         }

+ 25 - 8
WCS.WorkEngineering/Systems/AgvSystems.cs

@@ -39,7 +39,7 @@ namespace WCS.WorkEngineering.Systems
                 SqlSugarHelper.Do(db =>
                 {
                     //获取所有未结束的AGV任务
-                    var agvTaks = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.Status <= AGVTaskStatus.MissionCompleted && v.Position == obj.Entity.Code).SplitTable(tabs => tabs.Take(3)).ToList();
+                    var agvTaks = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.Status <= AGVTaskStatus.MissionCompleted && v.Status > AGVTaskStatus.NewBuild && v.Station == obj.Entity.Code).SplitTable(tabs => tabs.Take(2)).ToList();
 
                     foreach (var agv in agvTaks)
                     {
@@ -47,13 +47,13 @@ namespace WCS.WorkEngineering.Systems
                         {
                             case AGVTaskStatus.RequestOrPermission2:
                                 //调继续执行任务接口
-                                var res = AgvApi.ContinueTask(agv.AgvID, "");
+                                var res = AgvApi.ContinueTask(agv.AgvID, agv.Station);
                                 agv.Status = AGVTaskStatus.Complete2;
 
                                 break;
                         }
 
-                        db.Default.Updateable(agv).AddQueue();
+                        db.Default.Updateable(agv).SplitTable().ExecuteCommand();
                     }
 
                     db.Default.SaveQueues();
@@ -64,7 +64,7 @@ namespace WCS.WorkEngineering.Systems
                 SqlSugarHelper.Do(db =>
                 {
                     //获取所有未结束的AGV任务
-                    var agvTaks = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot).SplitTable(tabs => tabs.Take(1)).ToList();
+                    var agvTaks = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot).SplitTable(tabs => tabs.Take(2)).ToList();
 
                     foreach (var agv in agvTaks)
                     {
@@ -86,11 +86,22 @@ namespace WCS.WorkEngineering.Systems
                                                                 && !v.Data3.Status.HasFlag(StatusEunm.PH_Status)
                                                                 && !v.Data3.Status.HasFlag(StatusEunm.OT_Status)
                                                                 && !v.Data3.Status.HasFlag(StatusEunm.Run)).ToList();
+
+                                    //var a = stations.Select(v => v.Entity.Sources)
+                                    //                     .SelectMany(v => v)
+                                    //                     .Where(v => v.IsTunnel())
+                                    //                     .Select(v => v.Sources)
+                                    //                     .SelectMany(v => v)
+                                    //                     .Where(v => v.HasProtocol(typeof(ISRM520)))
+                                    //                     .Select(v => new SRM(v, this.World));
+                                    //srm = a.Where(v => !v.Data2.Status.HasFlag(SrmStatus.Alarm) && v.Data2.RunStatus == SrmRunStatus.Idle && v.Data2.AutoStatus == SrmAutoStatus.Automatic)
+                                    //                    .MinBy(v => tunnelNo.IndexOf(v.Entity.Code));
+
                                     //可用堆垛机
-                                    srm = stations.Select(v => v.Entity.Targets)
+                                    srm = stations.Select(v => v.Entity.Sources)
                                                          .SelectMany(v => v)
                                                          .Where(v => v.IsTunnel())
-                                                         .Select(v => v.Targets)
+                                                         .Select(v => v.Sources)
                                                          .SelectMany(v => v)
                                                          .Where(v => v.HasProtocol(typeof(ISRM520)))
                                                          .Select(v => new SRM(v, this.World))
@@ -105,7 +116,12 @@ namespace WCS.WorkEngineering.Systems
                                 task.Device = srm.Entity.Code;
                                 agv.Status = AGVTaskStatus.Complete1;
 
-                                var nextPos = stations.FirstOrDefault(v => v.Entity.Targets.Any(t => t.Code == srm.Entity.Parent.Code));
+                                var nextPos = stations.FirstOrDefault(v => v.Entity.Sources.Where(t => t.IsTunnel()) //上一个地址是巷道的
+                                                                                           .Select(t => t.Sources) //筛选出巷道
+                                                                                           .SelectMany(v => v) //合并
+                                                                                           .Where(t => t.HasProtocol(typeof(ISRM520)))
+                                                                                           .SelectMany(v => v.Sources)
+                                                                                           .Any(t => t.Code == srm.Entity.Parent.Code));
                                 agv.Position = nextPos.Entity.Code;
                                 task.AddWCS_TASK_DTL(db, "AGV巷道分配点", nextPos.Entity.Code, $"任务分配至堆垛机:{srm.Entity.Code}");
                                 db.Default.Updateable(task).ExecuteCommand();
@@ -137,7 +153,8 @@ namespace WCS.WorkEngineering.Systems
 
         public override bool Select(Device dev)
         {
-            return dev.Code == "1011";
+            return dev.HasFlag(DeviceFlags.巷道口);
+            //return dev.Code == "1011";
         }
     }
 }

+ 54 - 14
WCS.WorkEngineering/Systems/NoInteractionSystems.cs

@@ -1,4 +1,5 @@
-using ServiceCenter.SqlSugars;
+using PlcSiemens.Core.Extension;
+using ServiceCenter.SqlSugars;
 using System.ComponentModel;
 using WCS.Core;
 using WCS.Entity;
@@ -10,10 +11,10 @@ using WCS.WorkEngineering.Worlds;
 namespace WCS.WorkEngineering.Systems
 {
     /// <summary>
-    ///  数据采集系统
+    ///  无交互系统
     /// </summary>
     [BelongTo(typeof(NoInteractionWorld))]
-    [Description("数据采集系统")]
+    [Description("无交互系统")]
     public class NoInteractionSystems : DeviceSystem<Station>
     {
         public NoInteractionSystems()
@@ -26,12 +27,12 @@ namespace WCS.WorkEngineering.Systems
 
         public override void Do(Station obj)
         {
+            #region 处理所有的新增入库任务
+
             SqlSugarHelper.Do(db =>
             {
                 List<WCS_TaskInfo> tasks = new List<WCS_TaskInfo>();
 
-                #region 处理所有的新增入库任务
-
                 tasks = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.Status == Entity.TaskStatus.NewBuild && t.Type == TaskType.EnterDepot).ToList();
 
                 if (tasks.Count > 0)
@@ -53,9 +54,38 @@ namespace WCS.WorkEngineering.Systems
                     });
                 }
 
-                #endregion 处理所有的新增入库任务
+                db.Default.SaveQueues();
+            });
+
+            #endregion 处理所有的新增入库任务
+
+            #region 处理所有的新增初始化入库任务
+
+            SqlSugarHelper.Do(db =>
+            {
+                List<WCS_TaskInfo> tasks = new List<WCS_TaskInfo>();
 
-                #region 处理所有新建出库任务
+                tasks = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.Status == Entity.TaskStatus.NewBuild && t.Type == TaskType.EmptyInit).ToList();
+
+                if (tasks.Count > 0)
+                {
+                    tasks.ForEach(task =>
+                    {
+                        //开始处理
+                        task.Status = Entity.TaskStatus.WaitingToExecute;
+                        task.AddWCS_TASK_DTL(db, task.Device, $"初始化任务信息");
+                        db.Default.Updateable(task).ExecuteCommand();
+                    });
+                }
+            });
+
+            #endregion 处理所有的新增初始化入库任务
+
+            #region 处理所有新建出库任务
+
+            SqlSugarHelper.Do(db =>
+            {
+                List<WCS_TaskInfo> tasks = new List<WCS_TaskInfo>();
 
                 //获取所有新建状态的出库任务
                 tasks = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.Status == Entity.TaskStatus.NewBuild && t.Type == TaskType.OutDepot).ToList();
@@ -66,7 +96,10 @@ namespace WCS.WorkEngineering.Systems
                         //获取堆垛机到目标地址的路径信息
                         var ty = DevicePath.GetPath(task.Device, task.AddrTo);
                         //开始处理
-                        task.SrmStation = ty.Points[1].Code;
+                        if (task.SrmStation.IsNullOrEmpty())
+                        {
+                            task.SrmStation = ty.Points[1].Code;
+                        }
                         //task.AddrNext = path[2];
                         task.Status = Entity.TaskStatus.WaitingToExecute;
                         task.AddWCS_TASK_DTL(db, task.Device, $"初始化出库任务信息,放货站台:{task.SrmStation}");
@@ -74,9 +107,16 @@ namespace WCS.WorkEngineering.Systems
                     });
                 }
 
-                #endregion 处理所有新建出库任务
+                db.Default.SaveQueues();
+            });
+
+            #endregion 处理所有新建出库任务
 
-                #region 处理所有的搬运任务
+            #region 处理所有的搬运任务
+
+            SqlSugarHelper.Do(db =>
+            {
+                List<WCS_TaskInfo> tasks = new List<WCS_TaskInfo>();
 
                 tasks = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.Status == Entity.TaskStatus.NewBuild && t.Type == TaskType.Delivery).ToList();
 
@@ -99,16 +139,16 @@ namespace WCS.WorkEngineering.Systems
                     });
                 }
 
-                #endregion 处理所有的搬运任务
-
                 db.Default.SaveQueues();
             });
 
+            #endregion 处理所有的搬运任务
+
             #region 下发入库AGV任务
 
             SqlSugarHelper.Do(db =>
             {
-                var agvTasks = db.Default.Queryable<WCS_AgvTaskInfo>().Where(t => t.Status == AGVTaskStatus.NewBuild && t.TaskType == AGVTaskType.EnterDepot).SplitTable(v => v.Take(1)).ToList();
+                var agvTasks = db.Default.Queryable<WCS_AgvTaskInfo>().Where(t => t.Status == AGVTaskStatus.NewBuild && t.TaskType == AGVTaskType.EnterDepot).SplitTable(v => v.Take(2)).ToList();
 
                 if (agvTasks.Count > 0)
                 {
@@ -146,7 +186,7 @@ namespace WCS.WorkEngineering.Systems
 
             SqlSugarHelper.Do(db =>
             {
-                var agvTasks = db.Default.Queryable<WCS_AgvTaskInfo>().Where(t => t.Status == AGVTaskStatus.NewBuild && t.TaskType == AGVTaskType.ForkliftFilling).SplitTable(v => v.Take(1)).ToList();
+                var agvTasks = db.Default.Queryable<WCS_AgvTaskInfo>().Where(t => t.Status == AGVTaskStatus.NewBuild && t.TaskType == AGVTaskType.ForkliftFilling).SplitTable(v => v.Take(2)).ToList();
 
                 if (agvTasks.Count > 0)
                 {

+ 15 - 5
WCS.WorkEngineering/Systems/OutboundSiteInteractionSystems.cs

@@ -1,5 +1,9 @@
-using WCS.Core;
+using ServiceCenter.SqlSugars;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity;
 using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.WebApi.Controllers;
 using WCS.WorkEngineering.Worlds;
 using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
 
@@ -9,6 +13,7 @@ namespace WCS.WorkEngineering.Systems
     /// 出库站台交互
     /// </summary>
     [BelongTo(typeof(MainWorld))]
+    [Description("出站站点交互系统")]
     public class OutboundSiteInteractionSystems : DeviceSystem<Station>
     {
         protected override bool ParallelDo => true;
@@ -35,17 +40,22 @@ namespace WCS.WorkEngineering.Systems
             }
             else
             {
-                //TODO判断当前站台是否是一楼
-                if (true) //一楼无任务站台开始呼叫空轮出库任务
+                if (obj.Entity.HasFlag(DeviceFlags.一楼出库口))
                 {
-                    //ApplyStockOutTaskRequest
+                    var any = false;
+                    SqlSugarHelper.Do(db =>
+                    {
+                        any = db.Default.Queryable<WCS_TaskInfo>().Any(v => v.AddrTo == obj.Entity.Code);
+                    });
+                    if (!any) WmsApi.ApplyStockOutTask(obj.Entity.Code);
                 }
             }
         }
 
         public override bool Select(Device dev)
         {
-            return dev.HasFlag(DeviceFlags.巷道口) && dev.HasFlag(DeviceFlags.出库);
+            return dev.Code == "1016";
+            //return dev.HasFlag(DeviceFlags.巷道口) && dev.HasFlag(DeviceFlags.出库);
         }
     }
 }

+ 56 - 27
WCS.WorkEngineering/Systems/SrmSystems.cs

@@ -66,6 +66,7 @@ namespace WCS.WorkEngineering.Systems
             //判断完成任务号是否大于0
             if (obj.Data2.TaskFinishiId > 0)
             {
+                WCS_TaskInfo taskInfo = null;
                 var result = SqlSugarHelper.Do(db =>
                   {
                       //根据DB521任务号获取对应任务
@@ -84,6 +85,8 @@ namespace WCS.WorkEngineering.Systems
 
                           case TaskType.OutDepot:
                               task.Status = Entity.TaskStatus.ConveyorExecution;
+                              var dev = new Station(Device.All.FirstOrDefault(v => v.Code == task.SrmStation), this.World);
+                              dev.Data.TaskNumber = task.ID;
                               task.AddWCS_TASK_DTL(db, task.SrmStation, "出库任务到达放货站台");
                               break;
 
@@ -92,12 +95,23 @@ namespace WCS.WorkEngineering.Systems
                               task.EedTime = DateTime.Now;
                               task.AddWCS_TASK_DTL(db, task.AddrTo, "移库任务结束");
                               break;
+
+                          case TaskType.EmptyInit:
+                              task.Status = Entity.TaskStatus.Finish;
+                              task.EedTime = DateTime.Now;
+                              task.AddWCS_TASK_DTL(db, task.AddrTo, "移库任务结束");
+                              break;
                       }
 
                       db.Default.Updateable(task).ExecuteCommand();
-                      task.CompleteOrCancelTasks(db, World);
+                      if (task.Status >= TaskStatus.Finish) task.CompleteOrCancelTasks(db);
+                      if (task.Type == TaskType.OutDepot && task.Status == TaskStatus.ConveyorExecution) WmsApi.SrmPickOutCompleted(task.ID);
+
+                      taskInfo = task;
                   });
-                if (!result) throw new KnownException("数据库提交事务错误", LogLevelEnum.High);
+                if (!result && taskInfo == null) throw new KnownException("数据库提交事务错误", LogLevelEnum.High);
+                //通知WMS任务完成
+                if (taskInfo.Status == TaskStatus.Finish) WmsApi.CompleteTask(taskInfo.ID);
                 // 写入信号
                 obj.Data.OkAck = 1;
             }
@@ -203,13 +217,15 @@ namespace WCS.WorkEngineering.Systems
                 var result = SqlSugarHelper.Do(db =>
                 {
                     //根据有货设备的任务号获取所有类型为入库状态为输送机执行中的任务
-                    var tasks = db.Default.Queryable<WCS_TaskInfo>().Where(v => v.Type == TaskType.EnterDepot && v.Status == TaskStatus.ConveyorExecution && arrIn.Select(p => p.Data.TaskNumber).Contains(v.ID));
+                    var tasks = db.Default.Queryable<WCS_TaskInfo>().Where(v => (v.Type == TaskType.EnterDepot || v.Type == TaskType.EmptyInit)
+                                                                              && v.Status == TaskStatus.ConveyorExecution
+                                                                              && arrIn.Select(p => p.Data.TaskNumber).Contains(v.ID));
                     //按条件先后排序获取一条排序后第一条结果1.优先级2.所在楼层与本次优先执行楼层 TODO:待验证排序结果
                     var task = tasks.OrderByDescending(v => v.Priority).OrderByDescending(v => v.Floor == floor ? 1 : 0).First() ?? throw new KnownException($"{obj.Entity.Code}未找到入库任务", LogLevelEnum.High);
                     //获取任务所有设备
                     station = arrIn.First(v => v.Data.TaskNumber == task.ID);
                     //获取当前货物巷道
-                    var res = WmsApi.GetLocalIn(task.ID, 3, station.Entity.Code);
+                    var res = WmsApi.GetLocalIn(task.ID, task.Device, station.Entity.Code);
                     var loc = res.ResData.CellNo.Split("-");
                     task.Status = TaskStatus.StackerExecution;
                     task.AddrTo = $"{loc[0]}-{loc[1]}-{loc[2]}";
@@ -234,48 +250,60 @@ namespace WCS.WorkEngineering.Systems
             else if (enterOrOut == 3 || !lastIsOut) //出库任务
             {
                 //判断本次优先执行楼层,并设置下次执行时优先楼层
+
                 var floor = obj.Entity.GetFlag<int>("FloorOut");
+
                 floor = floor % 2 + 1;
                 obj.Entity.SetFlag("FloorOut", floor);
 
                 //获取当前堆垛机所有的取货站台
-                var arrOut = PickUpDevices.First(v => v.Key == obj.Entity.Code).Value;
+                var arrOut = PutDevices.First(v => v.Key == obj.Entity.Code).Value;
+
                 if (!arrOut.Any()) throw new KnownException($"堆垛机{obj.Entity.Code}无放货路径点", LogLevelEnum.High);
 
                 //获取可以放货的设备集合
                 arrOut = arrOut.Where(v => !v.Data3.Status.HasFlag(StatusEunm.PH_Status) //无光电
-                                        && !v.Data3.Status.HasFlag(StatusEunm.Run) //未运行
-                                        && !v.Data3.Status.HasFlag(StatusEunm.OT_Status) //无任务
-                                        && !v.Data3.Status.HasFlag(StatusEunm.UnassignedTask) //未分配任务
-                                        && v.Data3.Status.HasFlag(StatusEunm.Auto)).ToList(); //自动
+                                                && !v.Data3.Status.HasFlag(StatusEunm.Run) //未运行
+                                                && !v.Data3.Status.HasFlag(StatusEunm.OT_Status) //无任务
+                                                && !v.Data3.Status.HasFlag(StatusEunm.UnassignedTask) //未分配任务
+
+                                                && v.Data3.Status.HasFlag(StatusEunm.Auto)).ToList(); //自动
+
                 if (!arrOut.Any()) throw new KnownException($"[{obj.Entity.Code}]等待出库任务输送到位", LogLevelEnum.Mid);
+
                 WCS_TaskInfo taskInfo = null;
                 string[] addrFrom = null;
 
                 var result = SqlSugarHelper.Do(db =>
-                {
-                    var allOutCode = arrOut.Select(v => v.Entity.Code).ToList();
-                    //按条件先后排序获取一条排序后第一条结果1.优先级2.所在楼层与本次优先执行楼层 TODO:待验证排序结果
-                    var task = db.Default.Queryable<WCS_TaskInfo>().Where(v => v.Type == TaskType.OutDepot && v.Status == TaskStatus.WaitingToExecute)
-                                                                   .Where(v => allOutCode.Contains(v.SrmStation))
-                                                                   .OrderByDescending(v => v.Priority)
-                                                                   .OrderByDescending(v => v.Floor == floor ? 1 : 0)
-                                                                   .First() ?? throw new KnownException($"{obj.Entity.Code}未找到出库任务", LogLevelEnum.High);
+               {
+                   var allOutCode = arrOut.Select(v => v.Entity.Code).ToList();
+                   //按条件先后排序获取一条排序后第一条结果1.优先级2.所在楼层与本次优先执行楼层 TODO:待验证排序结果
+                   var task = db.Default.Queryable<WCS_TaskInfo>().Where(v => v.Type == TaskType.OutDepot && v.Status == TaskStatus.WaitingToExecute)
+                                                                  .Where(v => allOutCode.Contains(v.SrmStation))
+                                                                  .OrderByDescending(v => v.Priority)
+                                                                  .OrderByDescending(v => v.Floor == floor ? 1 : 0)
+                                                                  .First() ?? throw new KnownException($"{obj.Entity.Code}未找到出库任务", LogLevelEnum.High);
+
+                   addrFrom = task.AddrFrom.Split("-");
+                   task.Status = TaskStatus.StackerExecution;
+                   task.LastInteractionPoint = task.Device;
+                   task.EditWho = "WCS";
+                   task.AddWCS_TASK_DTL(db, task.Device, task.SrmStation, "任务下发堆垛机执行");
+                   db.Default.Updateable(task).AddQueue();
+                   taskInfo = task;
+                   db.Default.SaveQueues();
+               });
 
-                    addrFrom = task.AddrFrom.Split("-");
-                    task.Status = TaskStatus.StackerExecution;
-                    task.LastInteractionPoint = task.Device;
-                    task.EditWho = "WCS";
-                    task.AddWCS_TASK_DTL(db, task.Device, task.SrmStation, "任务下发堆垛机执行");
-                    db.Default.Updateable(task).AddQueue();
-                    taskInfo = task;
-                    db.Default.SaveQueues();
-                });
                 if (taskInfo == null || !result) throw new KnownException("数据更新错误", LogLevelEnum.High);
+
                 obj.Data.TaskNumber = taskInfo.ID;
+
                 obj.Data.SLine = addrFrom[0].ToShort();
+
                 obj.Data.SCol = addrFrom[1].ToShort();
+
                 obj.Data.SLayer = addrFrom[2].ToShort();
+
                 obj.Data.ELine = taskInfo.SrmStation.ToShort();
                 obj.Data.ECol = taskInfo.AddrNext.ToShort();
                 obj.Data.VoucherNo++;
@@ -286,7 +314,8 @@ namespace WCS.WorkEngineering.Systems
 
         public override bool Select(Device dev)
         {
-            return dev.Code.Contains("SRM3");
+            return dev.Code == "SRM3";
+            //return dev.HasProtocol(typeof(ISRM520));
         }
     }
 }

+ 73 - 0
WCS.WorkEngineering/Systems/一楼入库工位处理系统.cs

@@ -0,0 +1,73 @@
+using ServiceCenter.SqlSugars;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity;
+using WCS.Entity.Protocol.BCR;
+using WCS.Entity.Protocol.Station;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.WebApi.Controllers;
+using WCS.WorkEngineering.Worlds;
+using WCS.WorkEngineering.Worlds.Logs;
+using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  入站站点交互系统
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("入站站点交互系统")]
+    public class 一楼入库工位处理系统 : DeviceSystem<Station>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        private List<BCR> BCRS = new List<BCR>();
+
+        public 一楼入库工位处理系统()
+        {
+            BCRS = Device.All.Where(v => v.HasProtocol<IBCR81>()).Select(v => new BCR(v, World)).ToList();
+        }
+
+        public override void Do(Station obj)
+        {
+            obj.StorageStationIsForbid();
+            //判断凭证号是否一致
+            if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521{obj.Data2.VoucherNo}", LogLevelEnum.High);
+            //设备是否停止运行
+            if (obj.Data3.Status.HasFlag(StatusEunm.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
+            if (!obj.Data3.Status.HasFlag(StatusEunm.PH_Status)) throw new KnownException("没有光电", LogLevelEnum.Low);
+            if (obj.Data2.TaskNumber != 0) throw new KnownException("有任务", LogLevelEnum.Low);
+            if (obj.Data2.Request != 1) throw new KnownException("没有请求", LogLevelEnum.Low);
+
+            WCS_TaskInfo task = null;
+            var result = SqlSugarHelper.Do(db =>
+            {
+                //获取RFID
+                var barcode = BCRS.GetBCRCode(obj.Entity.Code);
+                //跟据RFID获取对应的任务
+                task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.BarCode == barcode) ?? throw new KnownException($"未找到RFID:{barcode}对应WCS任务", LogLevelEnum.High);
+
+                if (task.Status != Entity.TaskStatus.AGVExecution) throw new KnownException($"任务:{task.ID}状态不是AGV执行中,请检查异常原因", LogLevelEnum.High);
+
+                //获取称重
+                var dev91 = Device.All.Where(v => v.Code == obj.Entity.Code).Select(v => new Device<IStation91>(v, this.World)).FirstOrDefault();
+                task.Weight = dev91.Data.Weight;
+                WmsApi.WcsUploadInfo(task.ID, (decimal)task.Weight, task.BarCode);
+
+                task.Status = Entity.TaskStatus.ConveyorExecution;
+                db.Default.Updateable(task).AddQueue();
+                task.AddWCS_TASK_DTL(db, obj.Entity.Code, "SRM", $"状态更新为{Entity.TaskStatus.ConveyorExecution},等待分配货位后堆垛机进行取货");
+                db.Default.SaveQueues();
+            });
+            if (task == null || !result) throw new KnownException("数据更新错误", LogLevelEnum.High);
+            obj.Data.TaskNumber = task.ID;
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.HasFlag(DeviceFlags.一楼入库口);
+        }
+    }
+}

+ 19 - 18
WCS.WorkEngineering/Systems/InboundSiteInteractionSystem.cs → WCS.WorkEngineering/Systems/二楼入库工位处理系统.cs

@@ -13,11 +13,11 @@ using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
 namespace WCS.WorkEngineering.Systems
 {
     /// <summary>
-    ///  入站站点交互系统
+    ///  二楼入库工位处理系统
     /// </summary>
     [BelongTo(typeof(MainWorld))]
-    [Description("入站站点交互系统")]
-    public class InboundSiteInteractionSystem : DeviceSystem<Station>
+    [Description("二楼入库工位处理系统")]
+    public class 二楼入库工位处理系统 : DeviceSystem<Station>
     {
         protected override bool ParallelDo => true;
 
@@ -25,7 +25,7 @@ namespace WCS.WorkEngineering.Systems
 
         private List<BCR> BCRS = new List<BCR>();
 
-        public InboundSiteInteractionSystem()
+        public 二楼入库工位处理系统()
         {
             BCRS = Device.All.Where(v => v.HasProtocol<IBCR81>()).Select(v => new BCR(v, World)).ToList();
         }
@@ -40,27 +40,28 @@ namespace WCS.WorkEngineering.Systems
             if (!obj.Data3.Status.HasFlag(StatusEunm.PH_Status)) throw new KnownException("没有光电", LogLevelEnum.Low);
             if (obj.Data2.TaskNumber != 0) throw new KnownException("有任务", LogLevelEnum.Low);
             if (obj.Data2.Request != 1) throw new KnownException("没有请求", LogLevelEnum.Low);
-            {
-            }
 
             WCS_TaskInfo task = null;
             var result = SqlSugarHelper.Do(db =>
             {
-                if (obj.Entity.HasFlag(DeviceFlags.扫码))
+                if (obj.Entity.Code == "1025")
                 {
-                    //获取RFID
-                    var barcode = BCRS.GetBCRCode(obj.Entity.Code);
-                    //跟据RFID获取对应的任务
-                    task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.BarCode == barcode) ?? throw new KnownException($"未找到RFID:{barcode}对应WCS任务", LogLevelEnum.High);
+                    var taskInfo = db.Default.Queryable<WCS_TaskInfo>().First(v => v.SrmStation == "1025" && v.Device == "SRM3" && v.Type == TaskType.EmptyInit && v.Status == Entity.TaskStatus.WaitingToExecute);
+                    if (taskInfo != null)
+                    {
+                        task = taskInfo;
+                        if (task.Type != TaskType.EmptyInit && task.Status != Entity.TaskStatus.WaitingToExecute) throw new KnownException($"任务:{task.ID}状态不是AGV执行中,请检查异常原因", LogLevelEnum.High);
+                    }
                 }
-                else
+
+                if (task == null)
                 {
-                    //TODO:跟据最近的当前站台的AGV任务来找到对应的WCS任务
+                    //跟据RFID获取对应的任务
+                    task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.BarCode == obj.Entity.Code) ?? throw new KnownException($"未找到任务号:{obj.Entity.Code}对应WCS任务", LogLevelEnum.High);
+                    if (task.Status != Entity.TaskStatus.AGVExecution) throw new KnownException($"任务:{task.ID}状态不是AGV执行中,请检查异常原因", LogLevelEnum.High);
                 }
 
-                if (task.Status != Entity.TaskStatus.AGVExecution) throw new KnownException($"任务:{task.ID}状态不是AGV执行中,请检查异常原因", LogLevelEnum.High);
-
-                if (obj.Entity.HasFlag(DeviceFlags.称重))
+                if (obj.Entity.Code == "1025")
                 {
                     //获取称重
                     var dev91 = Device.All.Where(v => v.Code == obj.Entity.Code).Select(v => new Device<IStation91>(v, this.World)).FirstOrDefault();
@@ -79,8 +80,8 @@ namespace WCS.WorkEngineering.Systems
 
         public override bool Select(Device dev)
         {
-            return dev.Code == "1015";
-            //return dev.HasFlag(DeviceFlags.巷道口, DeviceFlags.入库);
+            return dev.Code == "1025";
+            return dev.HasFlag(DeviceFlags.一楼入库口);
         }
     }
 }

+ 103 - 34
WCS.WorkEngineering/WebApi/Controllers/AgvController.cs

@@ -58,6 +58,8 @@ namespace WCS.WorkEngineering.WebApi.Controllers
             }
         }
 
+        private static object objlook = new object();
+
         /// <summary>
         ///  背负式agv请求出库任务
         /// </summary>
@@ -66,35 +68,68 @@ namespace WCS.WorkEngineering.WebApi.Controllers
         [HttpPost]
         public ApplyEmptySpoolResponse ApplyEmptySpool([FromBody] AgvFillEmptySpaceRequest reqDto)
         {
-            ApplyEmptySpoolResponse agvFill = new ApplyEmptySpoolResponse();
-            var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;
-
-            // 检测三个站台是否有货
-            obj = obj.Where(v => v.Entity.Code is "1012" or "1014" or "1016").Where(v => v.Data3.Status.HasFlag(StatusEunm.PH_Status)).ToList();
-            if (!obj.Any())
+            lock (objlook)
             {
-                agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
-                agvFill.ResMsg = "无空轮";
-                return agvFill;
-            }
+                ApplyEmptySpoolResponse agvFill = new ApplyEmptySpoolResponse();
 
-            var res = WmsApi.GetTunnelEmptyConCount();
+                if (!World.IsStart)
+                {
+                    agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
+                    agvFill.ResMsg = "WCS初始化中";
+                    return agvFill;
+                }
+                var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;
 
-            foreach (var item in res.ResDataList)
-            {
-                var station = Device.All.Where(v => v.Code == "TY" + item.Tunnel.ToString())
-                                        .Select(v => v.Targets).SelectMany(v => v)
-                                        .Where(v => v.HasProtocol(typeof(IStation520)))
-                                        .Where(v => v.Code is "1012" or "1014" or "1016")
-                                        .FirstOrDefault();
-                item.Tunnel = station.ToInt();
+                // 检测三个站台是否有货
+                obj = obj.Where(v => v.Entity.Code is "1012" or "1014" or "1016").Where(v => v.Data3.Status.HasFlag(StatusEunm.PH_Status)).ToList();
+                if (!obj.Any())
+                {
+                    agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
+                    agvFill.ResMsg = "无空轮";
+                    return agvFill;
+                }
+                SqlSugarHelper.Do(db =>
+                {
+                    var res = WmsApi.GetTunnelEmptyConCount();
+
+                    var agvStations = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2))
+                                      .Where(v => v.Status < AGVTaskStatus.Complete3 && v.TaskType == AGVTaskType.CallForMaterial).Select(v => v.Station).ToList();
+                    obj = obj.Where(v => !agvStations.Contains(v.Entity.Code)).ToList();
+                    if (!obj.Any())
+                    {
+                        agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
+                        agvFill.ResMsg = "无可用取货站点";
+                        return;
+                    }
+
+                    foreach (var item in res.ResDataList)
+                    {
+                        var station = Device.All.Where(v => v.Code == "TY" + item.Tunnel.ToString())
+                                                .Select(v => v.Targets).SelectMany(v => v)
+                                                .Where(v => v.HasProtocol(typeof(IStation520)))
+                                                .Where(v => v.Code is "1012" or "1014" or "1016")
+                                                .FirstOrDefault();
+                        item.Tunnel = station.ToInt();
+                    }
+                    var stationNo = res.ResDataList.OrderBy(v => v.Count).Select(v => v.Tunnel.ToString()).ToList();
+                    agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess;
+                    agvFill.LocCode = obj.MinBy(v => stationNo.IndexOf(v.Entity.Code)).Entity.Code;
+                    agvFill.SpoolType = "4";
+                    agvFill.ResMsg = "";
+                    var id = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(v => v.Take(1)).Max(v => v.ID);
+                    //创建对应的AGV任务
+                    db.Default.Insertable(new WCS_AgvTaskInfo()
+                    {
+                        ID = id + 1,
+                        TaskType = AGVTaskType.CallForMaterial,
+                        Status = AGVTaskStatus.NewBuild,
+                        Station = agvFill.LocCode,
+                        AddWho = "WCS"
+                    }).SplitTable().ExecuteCommand();
+                });
+
+                return agvFill;
             }
-            var stationNo = res.ResDataList.OrderBy(v => v.Count).Select(v => v.Tunnel.ToString()).ToList();
-            agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess;
-            agvFill.LocCode = obj.MinBy(v => stationNo.IndexOf(v.Entity.Code)).Entity.Code;
-            agvFill.SpoolType = "4";
-            agvFill.ResMsg = "";
-            return agvFill;
         }
 
         /// <summary>
@@ -105,18 +140,19 @@ namespace WCS.WorkEngineering.WebApi.Controllers
         [HttpPost]
         public AgvCallbackResponse AgvCallback([FromBody] AgvCallbackRequest reqDto)
         {
-            var msg = "成功";
-            var code = AgvResponseCode.Success;
+            var res = new AgvCallbackResponse() { code = AgvResponseCode.Success, message = "成功" };
+            WCS_TaskInfo taskInfo = null;
             try
             {
                 SqlSugarHelper.Do(db =>
                 {
                     //跟据AGVid找到对应的AGV任务
-                    var agvTask = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(1)).First(v => v.AgvID == reqDto.taskCode);
-                    if (agvTask == null)
+                    var agvTask = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2)).First(v => v.AgvID == reqDto.taskCode);
+                    if (agvTask == null && reqDto.method != "applySecurity")
                     {
-                        msg = "未找到对应的AGV任务";
-                        code = AgvResponseCode.Fail;
+                        res.code = AgvResponseCode.Fail;
+                        res.message = "未找到对应的AGV任务";
+                        return;
                     }
                     switch (reqDto.method)
                     {
@@ -126,10 +162,39 @@ namespace WCS.WorkEngineering.WebApi.Controllers
                             break;
 
                         case "applySecurity": //表示请求放货或取货
+                            if (reqDto.callCode is "1012" or "1014" or "1016")
+                            {
+                                agvTask = db.Default.Queryable<WCS_AgvTaskInfo>()
+                                                    .SplitTable(tabs => tabs.Take(2))
+                                                    .First(v => v.Status == AGVTaskStatus.NewBuild && v.TaskType == AGVTaskType.CallForMaterial && v.Station == reqDto.callCode);
+                                agvTask.AgvID = reqDto.taskCode;
+                                var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;
+                                var id = obj.FirstOrDefault(v => v.Entity.Code == agvTask.Station).Data.TaskNumber;
+                                agvTask.Position = id.ToString();
+                                var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == id);
+                                task.Status = Entity.TaskStatus.AGVExecution;
+                                task.AddWCS_TASK_DTL(db, agvTask.Station, "agv执行中");
+                            }
+                            if (agvTask == null)
+                            {
+                                res.code = AgvResponseCode.Fail;
+                                res.message = "未找到对应的AGV任务";
+                                return;
+                            }
                             agvTask.Status = AGVTaskStatus.RequestOrPermission2;
                             break;
 
                         case "hjend_2": //补空任务完成
+                            if (agvTask.TaskType == AGVTaskType.CallForMaterial)
+                            {
+                                var id = agvTask.Position.ToInt();
+                                var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == id);
+                                task.Status = Entity.TaskStatus.Finish;
+                                task.EedTime = DateTime.Now;
+                                task.AddWCS_TASK_DTL(db, "agv缓存区", "任务完成");
+                                task.CompleteOrCancelTasks(db);
+                                taskInfo = task;
+                            }
                             agvTask.Status = AGVTaskStatus.MissionCompleted;
                             break;
 
@@ -156,6 +221,10 @@ namespace WCS.WorkEngineering.WebApi.Controllers
                             agvTask.Status = AGVTaskStatus.MissionCompleted;
                             break;
 
+                        case "outbin": //小车退出取货位
+                            agvTask.Status = AGVTaskStatus.Complete3;
+                            break;
+
                         default:
                             break;
                     }
@@ -164,11 +233,11 @@ namespace WCS.WorkEngineering.WebApi.Controllers
             }
             catch (Exception ex)
             {
-                code = AgvResponseCode.Error;
-                msg = ex.Message;
+                res.code = AgvResponseCode.Error;
+                res.message = ex.Message;
             }
 
-            var res = new AgvCallbackResponse() { code = code, message = msg };
+            if (taskInfo != null) WmsApi.CompleteTask(taskInfo.ID);
 
             return res;
         }

+ 67 - 3
WCS.WorkEngineering/WebApi/Controllers/WmsApi.cs

@@ -1,4 +1,5 @@
-using ServiceCenter.Redis;
+using ServiceCenter.Extensions;
+using ServiceCenter.Redis;
 using ServiceCenter.WebApi;
 using WCS.WorkEngineering.WebApi.Models.WMS.Request;
 using WCS.WorkEngineering.WebApi.Models.WMS.Response;
@@ -113,12 +114,12 @@ namespace WCS.WorkEngineering.WebApi.Controllers
         /// <param name="device">设备号</param>
         /// <returns></returns>
         /// <exception cref="Exception"></exception>
-        public static SRes<ApplyStockInLocResponse> GetLocalIn(int wcsTaskNum, int tunnel, string device)
+        public static SRes<ApplyStockInLocResponse> GetLocalIn(int wcsTaskNum, string tunnel, string device)
         {
             var res = APICaller.CallApi2<SRes<ApplyStockInLocResponse>>(WMSUrl + "/api/Hj/ApplyStockInLoc", new ApplyStockInLocRequest
             {
                 TaskNum = wcsTaskNum,
-                TunnelNum = tunnel,
+                TunnelNum = tunnel.GetLastDigit(),
                 PickUpEquipmentNo = device.ToString(),
             });
             if (res.ResCode != ResponseStatusCodeEnum.Sucess)
@@ -128,6 +129,69 @@ namespace WCS.WorkEngineering.WebApi.Controllers
             return res;
         }
 
+        /// <summary>
+        ///  堆垛机出库任务执行完成
+        /// </summary>
+        /// <param name="taskNum"></param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes<int> SrmPickOutCompleted(int taskNum)
+        {
+            var res = APICaller.CallApi2<SRes<int>>(WMSUrl + "/api/Hj/SrmPickOutCompleted", new SrmPickOutCompletedRequest
+            {
+                TaskNum = taskNum,
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  一楼空工字轮申请出库
+        /// </summary>
+        /// <param name="outEndPostion">出库位置</param>
+        /// <returns></returns>
+        public static SRes ApplyStockOutTask(string outEndPostion) => ApplyStockOutTask(outEndPostion, 2);
+
+        /// <summary>
+        ///  申请出库任务
+        /// </summary>
+        /// <param name="outEndPostion">出库位置</param>
+        /// <param name="outType">出库类型</param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes ApplyStockOutTask(string outEndPostion, int outType)
+        {
+            var request = new ApplyStockOutTaskRequest
+            {
+                OutEndPostion = outEndPostion,
+                OutType = outType,
+                WarehouseCode = wareHouseId,
+            };
+            switch (outEndPostion)
+            {
+                case "1012":
+                    request.Tunnel = "1";
+                    break;
+
+                case "1014":
+                    request.Tunnel = "2";
+                    break;
+
+                case "1016":
+                    request.Tunnel = "3";
+                    break;
+            }
+            var res = APICaller.CallApi2<SRes>(WMSUrl + "/api/Hj/ApplyStockOutTask", request);
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
         /// <summary>
         ///  获取各巷道剩余空轮数量
         /// </summary>

+ 5 - 0
WCS.WorkEngineering/WebApi/Models/AGV/Request/AgvCallbackRequest.cs

@@ -7,6 +7,11 @@
         /// </summary>
         public string reqCode { get; set; }
 
+        /// <summary>
+        ///  请求站台
+        /// </summary>
+        public string callCode { get; set; }
+
         /// <summary>
         /// 请求时间戳,格式: “yyyy-MM-dd HH:mm:ss”
         /// </summary>

+ 1 - 1
WCS.WorkEngineering/WebApi/Models/AGV/Response/ApplyEmptySpoolResponse.cs

@@ -8,7 +8,7 @@ namespace WCS.WorkEngineering.WebApi.Models.AGV.Response
     public class ApplyEmptySpoolResponse
     {
         /// <summary>
-        ///  编号
+        ///  站台编号
         /// </summary>
         public string LocCode { get; set; }
 

+ 40 - 0
WCS.WorkEngineering/WebApi/Models/WMS/Request/ApplyStockOutTaskRequest.cs

@@ -0,0 +1,40 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace WCS.WorkEngineering.WebApi.Models.WMS.Request
+{
+    public class ApplyStockOutTaskRequest
+    {
+        /// <summary>
+        /// 出库位置
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public string OutEndPostion { get; set; }
+
+        /// <summary>
+        /// 出库类型(0.无效参数;1.物料出库;2.空托盘出库;3.空工字轮出库;)
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public int OutType { get; set; }
+
+        /// <summary>
+        /// 仓库编码
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public string WarehouseCode { get; set; }
+
+        /// <summary>
+        /// 巷道
+        /// </summary>
+        public string Tunnel { get; set; } = "";
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        public string Memo1 { get; set; } = "";
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        public string Memo2 { get; set; } = "";
+    }
+}

+ 2 - 2
WCS.WorkEngineering/WebApi/Models/WMS/Request/CompleteTaskRequest.cs

@@ -28,12 +28,12 @@ namespace WCS.WorkEngineering.WebApi.Models.WMS.Request
         /// <summary>
         /// 备用
         /// </summary>
-        public string Memo1 { get; set; }
+        public string Memo1 { get; set; } = "";
 
         /// <summary>
         /// 备用
         /// </summary>
-        public string Memo2 { get; set; }
+        public string Memo2 { get; set; } = "";
     }
 
     /// <summary>

+ 18 - 0
WCS.WorkEngineering/WebApi/Models/WMS/Request/SrmPickOutCompletedRequest.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WCS.WorkEngineering.WebApi.Models.WMS.Request
+{
+    public class SrmPickOutCompletedRequest
+    {
+        /// <summary>
+        /// WMS任务号
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public int TaskNum { get; set; }
+    }
+}

+ 7 - 4
WCS.WorkEngineering/WorkStart.cs

@@ -73,7 +73,7 @@ namespace WCS.WorkEngineering
 
             List<ShapeInfo> shapeInfo = new List<ShapeInfo>
             {
-                new ShapeInfo(new int[] { 1011, 1013, 1015, 1025 }, "10.30.36.51")
+                new ShapeInfo(new int[] { 1011, 1013, 1015,1021,1023, 1025 }, "10.30.36.51")
             };
 
             foreach (var item in shapeInfo)
@@ -123,11 +123,11 @@ namespace WCS.WorkEngineering
                 new RouteInfo("TY1", new string[] { "1011", "1021" }),
                 new RouteInfo("TY2", new string[] { "1013", "1023" }),
                 new RouteInfo("TY3", new string[] { "1015", "1025" }),
-                new RouteInfo("1011", new string[] { "TY1" }),
+                new RouteInfo("1012", new string[] { "TY1" }),
                 new RouteInfo("1022", new string[] { "TY1" }),
-                new RouteInfo("1013", new string[] { "TY2" }),
+                new RouteInfo("1014", new string[] { "TY2" }),
                 new RouteInfo("1024", new string[] { "TY2" }),
-                new RouteInfo("1015", new string[] { "TY3" }),
+                new RouteInfo("1016", new string[] { "TY3" }),
                 new RouteInfo("1026", new string[] { "TY3" })
             };
 
@@ -153,6 +153,9 @@ namespace WCS.WorkEngineering
                 { DeviceFlags.入库, new List<string>() { "1011", "1013", "1015", "1022", "1024", "1026" } },
                 { DeviceFlags.出库, new List<string>() { "1012", "1014", "1016", "1021", "1023", "1025" } },
                 { DeviceFlags.扫码, new List<string>() { "1011", "1013", "1015" } },
+                { DeviceFlags.一楼出库口, new List<string>() { "1012", "1014", "1016" } },
+                { DeviceFlags.一楼入库口, new List<string>() { "1011", "1013", "1015" } },
+                { DeviceFlags.二楼入库口, new List<string>() { "1021", "1023", "1025" } },
                 { DeviceFlags.称重, new List<string>() { "1011", "1013", "1015", "1025" } }
             };
 

+ 2 - 2
WCS.WorkEngineering/worlds/MainWorld.cs

@@ -59,8 +59,8 @@ namespace WCS.WorkEngineering.Worlds
                 var dir = $"Logs\\{DateTime.Now.ToString("yyyy-MM-dd")}\\{fst.Channel.World}\\{fst.Channel.System}\\";
                 if (!Directory.Exists(dir))
                     Directory.CreateDirectory(dir);
-
-                foreach (var log in Logs)
+                var logs = Logs.Where(v => v.Log.Level >= LogLevelEnum.Low);
+                foreach (var log in logs)
                 {
                     var msg = $"--------------------{log.Time}[{Thread.CurrentThread.ManagedThreadId}]--------------------\n{log}\n";
                     File.AppendAllText(Path.Combine(dir, $"{log.Log.Message.Split(":")[0]}.txt"), msg);