林豪 左 3 vuotta sitten
vanhempi
commit
e2ebc0c4e1

+ 2 - 3
Projects/永冠OPP/WCS.Entity.Protocol/Station/IStation521.cs

@@ -66,7 +66,7 @@ namespace WCS.Entity.Protocol
         无 = 0,
         扫码入库 = 1,
         请求分配目标地址 = 2,
-        出库完成请求 = 3,
+        月台出库口任务完成 = 3,
         堆垛机放货完成请求目标地址 = 4,
     }
 
@@ -78,9 +78,8 @@ namespace WCS.Entity.Protocol
         无 = 0,
         扫码入库 = 1,
         分配目标地址 = 2,
-        出库完成请求 = 3,
+        月台出库口任务完成 = 3,
         堆垛机放货完成请求目标地址 = 4,
-        AGV放货完成 = 5,
     }
 
     /// <summary>

+ 23 - 16
Projects/永冠OPP/WCS.Entity.Protocol/Station/WCS_Station521.cs

@@ -1,31 +1,38 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.Serialization;
-using System.Text;
+using System.Runtime.Serialization;
 
 namespace WCS.Entity.Protocol.Station
 {
+    [DataContract]
     public class WCS_Station521 : WCS_PROTOCOLDATA, IStation521
     {
         [DataMember(Order = 0)]
-        public int Tasknum { get   ; set   ; }
+        public int Tasknum { get; set; }
+
         [DataMember(Order = 1)]
-        public int Goodscode { get   ; set   ; }
-        [DataMember(Order =2)]
-        public short Goodsnum { get   ; set   ; }
+        public int Goodscode { get; set; }
+
+        [DataMember(Order = 2)]
+        public short Goodsnum { get; set; }
+
         [DataMember(Order = 3)]
-        public short GoodsSize { get   ; set   ; }
+        public short GoodsSize { get; set; }
+
         [DataMember(Order = 4)]
-        public short Goodsstart { get   ; set   ; }
+        public short Goodsstart { get; set; }
+
         [DataMember(Order = 5)]
-        public short Goodsend { get   ; set   ; }
+        public short Goodsend { get; set; }
+
         [DataMember(Order = 6)]
-        public IstationRequest Request { get   ; set   ; }
+        public IstationRequest Request { get; set; }
+
         [DataMember(Order = 7)]
-        public IstationCmdType CmdType { get   ; set   ; }
+        public IstationCmdType CmdType { get; set; }
+
         [DataMember(Order = 8)]
-        public short VoucherNo { get   ; set   ; }
+        public short VoucherNo { get; set; }
+
         [DataMember(Order = 9)]
-        public IstationStatus Status { get   ; set   ; }
+        public IstationStatus Status { get; set; }
     }
-}
+}

+ 176 - 18
Projects/永冠OPP/WCS.Service/Extensions/DeviceExtension.cs

@@ -13,6 +13,8 @@ namespace WCS.Service.Extensions
     /// </summary>
     public class StationDeviceGroup : DeviceGroup<IStation520, IStation521, IStation523>
     {
+        private List<RGVDevice> RGVs;
+
         public StationDeviceGroup(WCS_DEVICE entity) : base(entity)
         {
         }
@@ -29,12 +31,12 @@ namespace WCS.Service.Extensions
             if (Items.Any(v => v.Data3.Status.HasFlag(StationStatus.运行状态位))) return true;
             //设备组中没有设备有光带信息
             if (!Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态))) return true;
-            //有光电无任务
-            if (Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum < 10000))
-                throw new Exception(LogHelper.SpliceLogMessage("有光电无任务", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
-            //有光电有任务无请求
-            if (Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum < 10000 && (type != IstationRequest.无 && v.Data2.Request != type)))
-                throw new Exception(LogHelper.SpliceLogMessage("有光电有任务分配目标地址请求请求", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
+            ////有光电无任务
+            //if (Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum < 10000))
+            //    throw new Exception(LogHelper.SpliceLogMessage("有光电无任务", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
+            ////有光电有任务无请求
+            //if (Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum < 10000 && (type != IstationRequest.无 && v.Data2.Request != type)))
+            //    throw new Exception(LogHelper.SpliceLogMessage($"有光电有任务无 {type} 请求", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
 
             return false;
         }
@@ -46,9 +48,10 @@ namespace WCS.Service.Extensions
         /// <returns></returns>
         public List<Device<IStation520, IStation521, IStation523>> RGVGetTaskedDevice()
         {
-            return Items.Where(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum > 10000)
+            var a = Items.Where(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum > 10000)
                         .Where(v => v.Entity.CODE.ToShort() != v.Data2.Goodsend && v.Data2.Goodsend != 0)
                         .ToList();
+            return a.Count == 0 ? null : a;
         }
 
         /// <summary>
@@ -58,9 +61,37 @@ namespace WCS.Service.Extensions
         /// <returns></returns>
         public List<Device<IStation520, IStation521, IStation523>> TaskedDeviceGetNextAddress()
         {
-            return Items.Where(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum > 10000)
+            var a = Items.Where(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum > 10000)
                         .Where(v => v.Data2.Goodsend.ToString() == v.Entity.CODE && v.Data2.Goodsend != 0)
                         .ToList();
+            return a.Count == 0 ? null : a;
+        }
+
+        public float Position { get; }
+        public float Length { get; }
+
+        public RGVDevice NextRGV()
+        {
+            return new RGVDevice(new WCS_DEVICE());
+        }
+
+        public float Distance(RGVDevice rgv)
+        {
+            return Math.Abs((Position - rgv.Position + Length) % Length);
+        }
+
+        public RGVDevice CurrentRGV()
+        {
+            return new RGVDevice(new WCS_DEVICE());
+        }
+
+        /// <summary>
+        ///
+        /// </summary>
+        /// <returns></returns>
+        public bool NeedRgv()
+        {
+            return true;
         }
     }
 
@@ -88,9 +119,29 @@ namespace WCS.Service.Extensions
                 throw new Exception(LogHelper.SpliceLogMessage($"等待任务[{Data2.Tasknum}]执行", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
             //没有光电
             if (!Data2.Status.HasFlag(IstationStatus.光电状态)) return true;
-            ////没有任务号
-            //if (Data2.Tasknum > 10000)
-            //    throw new Exception(LogHelper.SpliceLogMessage($"已生成", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
+            //没有任务号
+            switch (type)
+            {
+                case IstationRequest.无:
+                    if (Data2.Tasknum > 10000)
+                        throw new Exception(LogHelper.SpliceLogMessage($"设备已有任务任务", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
+                    break;
+
+                case IstationRequest.扫码入库:
+                    if (Data2.Tasknum > 10000)
+                        throw new Exception(LogHelper.SpliceLogMessage($"设备已有任务任务", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
+                    break;
+
+                case IstationRequest.堆垛机放货完成请求目标地址:
+                    if (Data2.Tasknum < 10000)
+                        throw new Exception(LogHelper.SpliceLogMessage($"设备无任务信息", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
+                    break;
+
+                case IstationRequest.请求分配目标地址:
+                    if (Data2.Tasknum < 10000)
+                        throw new Exception(LogHelper.SpliceLogMessage($"设备无任务信息", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
+                    break;
+            }
             //没有请求
             if (type != IstationRequest.无 && Data2.Request != type)
                 throw new Exception(LogHelper.SpliceLogMessage($"有光电有任务无 {type}", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
@@ -116,9 +167,116 @@ namespace WCS.Service.Extensions
         /// </summary>
         private static List<RGVStationLocation> PullFilm = new List<RGVStationLocation>();
 
+        public float Position
+        {
+            get
+            {
+                return Data2.Position;
+            }
+        }
+
+        private static List<RGVDevice> AllRGVList
+        {
+            get; set;
+        }
+
+        static RGVDevice()
+        {
+            AllRGVList = Device.Where(v => v.IsRGV() && v.CODE != "RGV8").Select(v => v.Create<RGVDevice>()).ToList();
+        }
+
+        public float Length { get; }
+
+        public List<RGVDevice> RGVList
+        {
+            get
+            {
+                return AllRGVList.Where(v => v.Entity.PROTOCOLS.Any(d => Entity.PROTOCOLS.Any(e => e.DB.ID == d.DB.ID)))
+                    .Where(v => v.Entity.CODE != Entity.CODE).ToList();
+            }
+        }
+
         public RGVDevice(WCS_DEVICE entity) : base(entity)
         {
         }
+
+        /// <summary>
+        /// 前一个RGV
+        /// </summary>
+        /// <returns></returns>
+        public RGVDevice Before()
+        {
+            var arr = AllRGVList.OrderBy(v => v.Position);
+            var rgv = arr.FirstOrDefault(v => v.Position > Position);
+            if (rgv == null)
+                rgv = arr.LastOrDefault(v => v.Position < Position);
+            return rgv;
+        }
+
+        /// <summary>
+        /// 后一个RGV
+        /// </summary>
+        /// <returns></returns>
+        public RGVDevice After()
+        {
+            return new RGVDevice(new WCS_DEVICE());
+        }
+
+        /// <summary>
+        /// 两个RGV之间的距离
+        /// </summary>
+        /// <param name="after"></param>
+        /// <returns></returns>
+        public float Distance(RGVDevice after)
+        {
+            return Math.Abs((Position - after.Position + Length) % Length);
+        }
+
+        /// <summary>
+        /// 是否可用
+        /// </summary>
+        /// <returns></returns>
+        public bool Valid()
+        {
+            return true;
+        }
+
+        /// <summary>
+        /// 移动
+        /// </summary>
+        /// <param name="addr"></param>
+        public void Move(StationDeviceGroup addr)
+        {
+        }
+
+        /// <summary>
+        /// 选择出库
+        /// </summary>
+        /// <param name="addr"></param>
+        public void Pick(StationDeviceGroup addr)
+        {
+        }
+
+        public void Put()
+        {
+        }
+
+        public RGVDevice[] RgvAfter(float distance)
+        {
+            return AllRGVList.Where(v => Distance(v) < distance).ToArray();
+        }
+
+        public bool StopedByMe(RGVDevice rgv)
+        {
+            var target = rgv.Data2.DestPosition_1;
+            var station = Device.Find($"G{target}").Create<StationDeviceGroup>();
+            return station.Distance(this) < station.Distance(rgv);
+        }
+
+        public StationDeviceGroup NextStation()
+        {
+            return new StationDeviceGroup(new WCS_DEVICE());
+        }
     }
 
     /// <summary>
@@ -144,21 +302,21 @@ namespace WCS.Service.Extensions
 
     public class RGVStationLocation
     {
-        public RGVStationLocation(string a, string b, string c, string d)
+        public RGVStationLocation(string station, string stationLocation, string startingPoint, string endPoint)
         {
-            Station = a;
-            StationLocation = b;
-            StartingPoint = c;
-            EndPoint = d;
+            Station = station;
+            StationLocation = stationLocation;
+            StartingPoint = startingPoint;
+            EndPoint = endPoint;
         }
 
         /// <summary>
-        /// 输送机设备号
+        /// 输送机设备组编
         /// </summary>
         public string Station { get; set; }
 
         /// <summary>
-        /// 输送机位置
+        /// 输送机在环轨中的位置
         /// </summary>
         public string StationLocation { get; set; }
 

+ 5 - 0
Projects/永冠OPP/WCS.Service/Worker.cs

@@ -91,6 +91,11 @@ namespace WCS.Service
                 Device.AddFlag(DF.一楼RGV放货, "G1035", "G1044", "G1053", "G1062");
                 Device.AddFlag(DF.堆垛机, "SRM1", "SRM2", "SRM3", "SRM4", "SRM5", "SRM6", "SRM7", "SRM8");
                 Device.AddFlag(DF.SRM取货, "G1040", "G1042", "G1049", "G1051", "G1058", "G1060", "G1067");
+                Device.AddFlag(DF.SRM取货, "G1040", "G1042", "G1049", "G1051", "G1058", "G1060", "G1067");
+                Device.AddFlag(DF.月台出货, "G1469", "G1561", "G1538", "G1574", "G1509");
+                Device.AddFlag(DF.月台区, "G1469", "G1561", "G1538", "G1574", "G1509");
+                Device.AddFlag(DF.RGV1, "G1244");
+                Device.AddFlag(DF.RGV2, "G1244");
 
                 #endregion 设备扩展数据配置
 

+ 1 - 1
Projects/永冠OPP/WCS.Service/Works/RGV/RGVWorks.cs

@@ -26,7 +26,7 @@ namespace WCS.Service.Works.RGV
             if (obj.WhetherToExecute()) return;
 
             //筛选出有任务号和起始及目标地址的设备
-            var dev = obj.RGVGetTaskedDevice();
+            var dev = obj.RGVGetTaskedDevice() ?? throw new Exception(LogHelper.SpliceLogMessage("无可用任务", rgv.Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
 
             DB.Do(db =>
             {

+ 20 - 22
Projects/永冠OPP/WCS.Service/Works/SRM/SRMWork.cs

@@ -50,7 +50,7 @@ namespace WCS.Service.Works.SRM
                     for (int i = 0; i < taskIds.Length; i++)
                     {
                         //判断当前工位是否有完成任务
-                        if (taskIds[i] == 0) return;
+                        if (taskIds[i] == 0) continue;
                         //获取当前工位的目标地址
                         var ELine = i == 0 ? obj.Data.ELine_1.ToString() : obj.Data.ELine_2.ToString();
                         task = db.Default.Set<WCS_TASK>().Find(taskIds[i]);
@@ -96,8 +96,6 @@ namespace WCS.Service.Works.SRM
                 return;
             }
 
-            //var tunnel =  obj.Data2.Tunnel;
-
             if (obj.Data2.Mode_1 != SCMode.远程) return;
 
             if (obj.Data2.Status_1 != SCRunStatus.空闲) return;
@@ -234,7 +232,7 @@ namespace WCS.Service.Works.SRM
                         var tunnel = dev2.Entity.ROUTES.First().NEXT.CODE;
                         var task2 = db.Default.Set<WCS_TASK>().FirstOrDefault(v => v.STATUS < TaskStatus.堆垛机执行 && v.ID == dev2.Data2.Tasknum);
                         if (task2 == null) throw new Exception(LogHelper.SpliceLogMessage($"设备有光电有任务且不在运行状态,但WCS找不到任务{dev2.Data2.Tasknum}", dev2.Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
-                        var loc = WMS.GetLocalIn(task2.WMSTASK, tunnel, dev1.Entity.CODE, Entity.WareCellForkNum.货叉2);
+                        var loc = WMS.GetLocalIn(task2.WMSTASK, tunnel, dev2.Entity.CODE, Entity.WareCellForkNum.货叉2);
                         var locno = string.Format("{0}-{1}-{2}", loc.Row, loc.Colomn, loc.Layer);
                         var oldTask = task2.STATUS;
                         task2.UPDATETIME = DateTime.Now;
@@ -255,7 +253,7 @@ namespace WCS.Service.Works.SRM
                         obj.Data.ELayer_2 = loc.Layer;
                     }
                     if (dev1IsThereATask) obj.Data.VoucherNo_1++;
-                    if (dev1IsThereATask) obj.Data.VoucherNo_2++;
+                    if (dev2IsThereATask) obj.Data.VoucherNo_2++;
                 });
 
                 #endregion 入库
@@ -332,6 +330,7 @@ namespace WCS.Service.Works.SRM
                     //连续两次只发一个任务的情况暂时不考虑
                     //同时对结果进行排序,分组后取第一组任务
                     //TODO:暂时不确定排序后进行分组是否会完全打乱排序,先按照这种按时执行,后续有异常再更改
+                    //TODO:暂时维考虑二楼环穿
                     var item = q.Where(v => db.Default.Set<WCS_TASK>()
                                         .Where(d => d.TYPE == TaskType.出库)
                                         .Where(d => d.STATUS > TaskStatus.新建)
@@ -352,8 +351,7 @@ namespace WCS.Service.Works.SRM
                     //获取两个个可执行任务,此时这两个任务的目标地址是一致的
                     var tasks = item.Select(v => v).Take(2);
                     //根据任务的目标地址获取对应的设备组
-                    // TODO:暂时随便写的筛选条件
-                    var devs = Device.Find("1246").Create<StationDeviceGroup>().Items.OrderByDescending(v => v.Entity.CODE).ToArray();
+                    var devs = Device.Find($"G{tasks.OrderBy(v => v.ADDRTO).FirstOrDefault().ADDRTO}").Create<StationDeviceGroup>().Items.OrderByDescending(v => v.Entity.CODE).ToArray();
                     var dev1 = devs[0];
                     var dev2 = devs[1];
 
@@ -363,29 +361,29 @@ namespace WCS.Service.Works.SRM
                         //判断当前任务为二工位还是一工位
                         var addrFrom = task.ADDRFROM.Split("-");
                         if (addrFrom[2].ToShort().OddNumberOrEven())
-                        {
-                            obj.Data.TaskID_1 = task.ID;
-                            obj.Data.SLine_1 = addrFrom[1].ToShort();
-                            obj.Data.SCol_1 = addrFrom[2].ToShort();
-                            obj.Data.SLayer_1 = addrFrom[3].ToShort();
-                            obj.Data.ELine_1 = dev1.Entity.CODE.ToShort();
-                            obj.Data.ECol_1 = 0;
-                            obj.Data.ELayer_1 = 0;
-                            obj.Data.VoucherNo_1++;
-                            next = dev1.Entity.CODE;
-                        }
-                        else
                         {
                             obj.Data.TaskID_2 = task.ID;
-                            obj.Data.SLine_2 = addrFrom[1].ToShort();
-                            obj.Data.SCol_2 = addrFrom[2].ToShort();
-                            obj.Data.SLayer_2 = addrFrom[3].ToShort();
+                            obj.Data.SLine_2 = addrFrom[0].ToShort();
+                            obj.Data.SCol_2 = addrFrom[1].ToShort();
+                            obj.Data.SLayer_2 = addrFrom[2].ToShort();
                             obj.Data.ELine_2 = dev2.Entity.CODE.ToShort();
                             obj.Data.ECol_2 = 0;
                             obj.Data.ELayer_2 = 0;
                             obj.Data.VoucherNo_2++;
                             next = dev2.Entity.CODE;
                         }
+                        else
+                        {
+                            obj.Data.TaskID_1 = task.ID;
+                            obj.Data.SLine_1 = addrFrom[0].ToShort();
+                            obj.Data.SCol_1 = addrFrom[1].ToShort();
+                            obj.Data.SLayer_1 = addrFrom[2].ToShort();
+                            obj.Data.ELine_1 = dev1.Entity.CODE.ToShort();
+                            obj.Data.ECol_1 = 0;
+                            obj.Data.ELayer_1 = 0;
+                            obj.Data.VoucherNo_1++;
+                            next = dev1.Entity.CODE;
+                        }
                         var oldTaskSTATUS = task.STATUS;
                         task.STARTTIME = DateTime.Now;
                         task.UPDATETIME = DateTime.Now;

+ 1 - 2
Projects/永冠OPP/WCS.Service/Works/Station/一楼入库.cs

@@ -81,8 +81,7 @@ namespace WCS.Service.Works.Station
             if (obj.WhetherToExecute(IstationRequest.请求分配目标地址)) return;
 
             //获取需要进行巷道分配的设备
-            var devs = obj.TaskedDeviceGetNextAddress();
-            if (devs.Count == 0) return;
+            var devs = obj.TaskedDeviceGetNextAddress() ?? throw new Exception(LogHelper.SpliceLogMessage("无可用任务", obj.Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
 
             DB.Do(db =>
             {

+ 32 - 1
Projects/永冠OPP/WCS.Service/Works/Station/一楼出库.cs

@@ -1,9 +1,11 @@
 using DBHelper;
+using System;
 using System.Linq;
 using WCS.Core;
 using WCS.Entity;
 using WCS.Entity.Protocol;
 using WCS.Service.Extensions;
+using WCS.Service.Helpers;
 
 namespace WCS.Service.Works.Station
 {
@@ -12,7 +14,7 @@ namespace WCS.Service.Works.Station
     {
         protected override void Do(StationDevice obj)
         {
-            if (obj.WhetherToExecute(WCS.Entity.Protocol.IstationRequest.堆垛机放货完成请求目标地址)) return;
+            if (obj.WhetherToExecute(IstationRequest.堆垛机放货完成请求目标地址)) return;
             //找到当前站台为当前设备且任务为堆垛机完成的任务
             DB.Do(db =>
             {
@@ -31,4 +33,33 @@ namespace WCS.Service.Works.Station
             return dev.Is(DF.SRM放货);
         }
     }
+
+    [WorkTitle(typeof(ProductHandler), "月台出货口完成任务")]
+    public class 月台完成任务 : Work<StationDeviceGroup>
+    {
+        protected override void Do(StationDeviceGroup obj)
+        {
+            if (obj.WhetherToExecute()) return;
+            //找到当前站台为当前设备且任务为堆垛机完成的任务
+            DB.Do(db =>
+            {
+                foreach (var dev in obj.Items)
+                {
+                    if (dev.Data2.Tasknum < 10000) continue;
+                    if (dev.Data2.Request != IstationRequest.月台出库口任务完成) continue;
+                    var task = db.Default.Set<WCS_TASK>().Find(dev.Data2.Tasknum);
+                    if (task.STATUS != TaskStatus.堆垛机完成) throw new Exception(LogHelper.SpliceLogMessage($"{task.ID}任务状态错误", dev.Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
+                    task.STATUS = TaskStatus.已完成;
+                    db.Default.SaveChanges();
+                    dev.Data.CmdType = IstationCmdType.月台出库口任务完成;
+                    dev.Data.VoucherNo++;
+                }
+            });
+        }
+
+        protected override bool SelectDevice(WCS_DEVICE dev)
+        {
+            return dev.Is(DF.月台出货);
+        }
+    }
 }

+ 4 - 0
WCS.Core/Device.cs

@@ -167,4 +167,8 @@ public enum DF
     组盘 = 1 << 8,
     一楼RGV放货 = 1 << 9,
     堆垛机 = 1 << 10,
+    月台出货 = 1 << 11,
+    月台区 = 1 << 12,
+    RGV1 = 1 << 13,
+    RGV2 = 1 << 14,
 }