Explorar o código

单例锁使用redis卡控,更新巷道分配逻辑

林豪 左 %!s(int64=3) %!d(string=hai) anos
pai
achega
d4beff75e6

+ 16 - 1
Projects/永冠OPP/WCS.Service/Extensions/TaskExtension.cs

@@ -1,4 +1,5 @@
-using System;
+using DBHelper;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using WCS.Core;
@@ -61,6 +62,20 @@ namespace WCS.Service.Extensions
                     break;
             }
         }
+
+        /// <summary>
+        /// 有效任务数是否符合任务组任务数
+        /// </summary>
+        /// <param name="tasks"></param>
+        /// <param name="executable"></param>
+        /// <param name="db"></param>
+        public static void ValidTaskCheck(this List<WCS_TASK> tasks, int executable, DB db)
+        {
+            var task = tasks.FirstOrDefault();
+            var taskCount = db.Default.Set<WCS_TASK>().Count(v => v.TaskGroupKey == task.TaskGroupKey);
+            //开始检查任务数是否匹配
+            if (executable != taskCount) throw new WarnException($"可执行数{executable},任务组任务数{taskCount},数量不匹配");
+        }
     }
 
     public enum SrmIndex

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

@@ -158,16 +158,117 @@ namespace WCS.Service.Works.Station
         }
     }
 
+    //[WorkTitle(typeof(ProductHandler), "一楼分配巷道")]
+    //internal class 巷道分配 : Work<StationDeviceGroup>
+    //{
+    //    private readonly string ConvGroup_1030 = "G1030";
+    //    private readonly string Conv_1030 = "1030";
+    //    private readonly string RGV8 = "RGV8";
+
+    //    protected override bool SelectDevice(WCS_DEVICE dev)
+    //    {
+    //        return dev.CODE == ConvGroup_1030;
+    //    }
+
+    //    protected override void Do(StationDeviceGroup obj)
+    //    {
+    //        obj.EX(obj =>
+    //        {
+    //            var code = obj.Entity.CODE;
+    //            //当前组有一个运行的设备就停止执行
+    //            foreach (var item in obj.Items)
+    //            {
+    //                var dev = Device.Find(item.Entity.CODE).Create<StationDevice>();
+    //                if (!dev.Data2.Status.HasFlag(IstationStatus.光电状态)) throw new DoException("无光电");
+    //                if (dev.Data.VoucherNo != dev.Data2.VoucherNo)
+    //                    throw new WarnException($"等待任务[{dev.Data2.Tasknum}]执行--凭证号不一致[{dev.Data.VoucherNo}][{dev.Data2.VoucherNo}]");
+    //                if (dev.Data3.Status.HasFlag(StationStatus.运行状态位)) throw new WarnException("设备运行中");
+    //                if (dev.Data2.Tasknum > 10000 && dev.Data2.Request != IstationRequest.请求分配目标地址)
+    //                    throw new WarnException("有任务无请求");
+    //            }
+
+    //            //获取需要进行巷道分配的设备
+    //            var devs = obj.TaskedDeviceGetNextAddress() ?? throw new WarnException("无可用任务");
+
+    //            DB.Do(db =>
+    //            {
+    //                var taskIds = devs.Select(p => p.Data2.Tasknum);
+    //                var tasks = db.Default.Set<WCS_TASK>().Where(p => taskIds.Any(v => v == p.ID)).ToList();
+    //                var res = WMS.GetTunnelList(tasks.Select(v => v.WMSTASK.ToString()).ToList(), code);
+    //                if (string.IsNullOrEmpty(res.TunnelNum)) throw new WarnException($"WMS未返回巷道");
+    //                var tunnelNo = res.TunnelNum.Split(',').Select(v => "TY" + v).ToList();
+
+    //                var tunnels = Device.Where(v => tunnelNo.Contains(v.CODE)).ToList();
+
+    //                List<TunnelInfo> tunnelInfos = new List<TunnelInfo>();
+    //                foreach (var item in tunnels)
+    //                {
+    //                    //当前巷道的取货点
+    //                    var allIn = Device.Where(v => v.Is(DF.SRM二级品取货)) //一楼所有取货点
+    //                                      .Where(v => v.ROUTES.Any(p => p.NEXT == item)) //下一个点为当前巷道的取货点
+    //                                      .Select(v => v.CODE)
+    //                                      .ToList();
+    //                    var putStation = Device.Where(v => v.IsConv() && v.ROUTES.Any(p => p.NEXT != null && allIn.Contains(p.NEXT.CODE))) //下一个目标地址包含取货点的设备
+    //                                  .Select(v => v.Create<StationDevice>()) //取所有可以到达取货点设备的信息
+    //                                  .Where(v => !v.Data3.Status.HasFlag(StationStatus.运行状态位) && !v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum < 10000)//筛选出空闲的路径点,此处因输送机都是一个动力,因此可以先找路径点再找设备组
+    //                                  .Distinct()
+    //                                  .FirstOrDefault();//去一次重
+    //                    if (putStation == null) continue;
+    //                    var taskInStation = Device.Where(p => p.CODE.StartsWith("G") && p.DEVICEGROUP.Any(d => d.MEMBER == putStation.Entity)).OrderBy(p => p.CODE).FirstOrDefault();
+    //                    //RGV是否有正在前往这个地址的任务
+    //                    var rgv8 = Device.Find(RGV8).Create<RGVDevice>();
+    //                    if (!rgv8.Data2.SystemStatus.HasFlag(WCS.Entity.Protocol.RGV.RGVRunStatus.空闲)
+    //                      && !rgv8.Data2.WorkMode.HasFlag(WCS.Entity.Protocol.RGV.RGVMode.自动)
+    //                      && rgv8.Data2.DestPosition_1 == taskInStation.CODE.Replace("G", "").ToShort()) continue;
+    //                    tunnelInfos.Add(new TunnelInfo
+    //                    {
+    //                        Tunnel = item,
+    //                        taskIN = taskInStation, //找到放货点设备所在组
+    //                        SRM = Device.Where(p => p.IsSC()).FirstOrDefault(p => item.ROUTES.Any(d => d.NEXT.CODE == p.CODE)).Create<SRMDevice>()
+    //                    });
+    //                }
+    //                //筛选出优先级最高的可用巷道
+    //                var tunnelInfo = tunnelInfos.Where(v => { try { return v.SRM.Data3.SCAlarm == 0 && v.SRM.Data2.SRMMode == SCMode.远程 && v.SRM.Data2.SRMStatus == SCRunStatus.空闲; } catch { return false; } })
+    //                                            .Where(v => !db.Default.Set<WCS_TASK>().Any(p => p.Priority > 0 && p.DEVICE == v.SRM.Entity.CODE && p.STATUS < TaskStatus.堆垛机完成))
+    //                                            .OrderBy(v => tunnelNo.IndexOf(v.Tunnel.CODE)).FirstOrDefault();
+    //                if (tunnelInfo == null) throw new WarnException("无可用巷道");
+
+    //                //开始向设备中写入任务信息
+    //                foreach (var item in devs)
+    //                {
+    //                    var dev = Device.Find(item.Entity.CODE).Create<StationDevice>();
+    //                    var task = tasks.FirstOrDefault(p => p.ID == dev.Data2.Tasknum);
+    //                    if (task == null) throw new WarnException($"WCS无该任务{dev.Data2.Tasknum}--{dev.Entity.CODE}");
+
+    //                    task.DEVICE = tunnelInfo.SRM.Entity.CODE;
+    //                    task.TUNNEL = tunnelInfo.Tunnel.CODE;
+    //                    task.ADDRNEXT = tunnelInfo.taskIN.CODE;
+    //                    task.TaskGroupKey = res.WMSTaskGroupKey;
+    //                    task.ADDRTO = task.DEVICE;
+    //                    db.Default.SaveChanges();
+
+    //                    var msg = $"下达从{Conv_1030}移动至{dev.Data.Goodsend}的PLC指令。同时将任务分配至[{ task.TUNNEL }]-[{task.DEVICE}]";
+    //                    msg += $"[{dev.Data.Tasknum}][{Conv_1030}][{dev.Data.Goodsend}][{tunnelInfo.SRM.Entity.CODE}][{dev.Data.VoucherNo}[{dev.Data2.VoucherNo}]";
+
+    //                    task.CreateStatusLog(db, msg, this.GetType());
+
+    //                    dev.Data.Tasknum = task.ID;
+    //                    dev.Data.Goodsstart = Conv_1030.ToShort();
+    //                    dev.Data.Goodsend = tunnelInfo.taskIN.CODE.Replace("G", "").ToShort();
+    //                    dev.Data.CmdType = IstationCmdType.分配目标地址;
+    //                    dev.Data.VoucherNo++;
+    //                }
+    //            });
+    //        });
+    //    }
+    //}
+
     [WorkTitle(typeof(ProductHandler), "一楼分配巷道")]
     internal class 巷道分配 : Work<StationDeviceGroup>
     {
-        private readonly string ConvGroup_1030 = "G1030";
-        private readonly string Conv_1030 = "1030";
-        private readonly string RGV8 = "RGV8";
-
         protected override bool SelectDevice(WCS_DEVICE dev)
         {
-            return dev.CODE == ConvGroup_1030;
+            return dev.CODE == "G1030";
         }
 
         protected override void Do(StationDeviceGroup obj)
@@ -175,26 +276,25 @@ namespace WCS.Service.Works.Station
             obj.EX(obj =>
             {
                 var code = obj.Entity.CODE;
-                //当前组有一个运行的设备就停止执行
-                foreach (var item in obj.Items)
-                {
-                    var dev = Device.Find(item.Entity.CODE).Create<StationDevice>();
-                    if (!dev.Data2.Status.HasFlag(IstationStatus.光电状态)) throw new DoException("无光电");
-                    if (dev.Data.VoucherNo != dev.Data2.VoucherNo)
-                        throw new WarnException($"等待任务[{dev.Data2.Tasknum}]执行--凭证号不一致[{dev.Data.VoucherNo}][{dev.Data2.VoucherNo}]");
-                    if (dev.Data3.Status.HasFlag(StationStatus.运行状态位)) throw new WarnException("设备运行中");
-                    if (dev.Data2.Tasknum > 10000 && dev.Data2.Request != IstationRequest.请求分配目标地址)
-                        throw new WarnException("有任务无请求");
-                }
-
-                //获取需要进行巷道分配的设备
-                var devs = obj.TaskedDeviceGetNextAddress() ?? throw new WarnException("无可用任务");
+                //两个设备都必须满足的条件
+                if (obj.Items.Any(v => v.Data.VoucherNo != v.Data2.VoucherNo)) return;
+                if (obj.Items.Any(v => v.Data3.Status.HasFlag(StationStatus.运行状态位))) return;
 
+                //成功分配巷道的任务的任务
+                var finishTaskList = new List<Tuple<int, StationDevice>>();
+
+                //变更数据库信息
                 DB.Do(db =>
                 {
-                    var taskIds = devs.Select(p => p.Data2.Tasknum);
-                    var tasks = db.Default.Set<WCS_TASK>().Where(p => taskIds.Any(v => v == p.ID)).ToList();
-                    var res = WMS.GetTunnelList(tasks.Select(v => v.WMSTASK.ToString()).ToList(), code);
+                    var devs = obj.Items.Where(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Request == IstationRequest.请求分配目标地址)
+                                           .Where(v => v.Data2.Tasknum > 10000 && v.Data2.Goodsend != 0);
+                    if (!devs.Any()) return; //无可执行任务
+                    var taskIds = devs.Select(dev => dev.Data2.Tasknum).ToList();
+                    var taskList = db.Default.Set<WCS_TASK>().Where(v => taskIds.Contains(v.ID)).ToList();
+
+                    taskList.ValidTaskCheck(devs.Count(), db);
+
+                    var res = WMS.GetTunnelList(taskList.Select(v => v.WMSTASK.ToString()).ToList(), code);
                     if (string.IsNullOrEmpty(res.TunnelNum)) throw new WarnException($"WMS未返回巷道");
                     var tunnelNo = res.TunnelNum.Split(',').Select(v => "TY" + v).ToList();
 
@@ -216,7 +316,7 @@ namespace WCS.Service.Works.Station
                         if (putStation == null) continue;
                         var taskInStation = Device.Where(p => p.CODE.StartsWith("G") && p.DEVICEGROUP.Any(d => d.MEMBER == putStation.Entity)).OrderBy(p => p.CODE).FirstOrDefault();
                         //RGV是否有正在前往这个地址的任务
-                        var rgv8 = Device.Find(RGV8).Create<RGVDevice>();
+                        var rgv8 = Device.Find("RGV8").Create<RGVDevice>();
                         if (!rgv8.Data2.SystemStatus.HasFlag(WCS.Entity.Protocol.RGV.RGVRunStatus.空闲)
                           && !rgv8.Data2.WorkMode.HasFlag(WCS.Entity.Protocol.RGV.RGVMode.自动)
                           && rgv8.Data2.DestPosition_1 == taskInStation.CODE.Replace("G", "").ToShort()) continue;
@@ -233,11 +333,11 @@ namespace WCS.Service.Works.Station
                                                 .OrderBy(v => tunnelNo.IndexOf(v.Tunnel.CODE)).FirstOrDefault();
                     if (tunnelInfo == null) throw new WarnException("无可用巷道");
 
-                    //开始向设备中写入任务信息
+                    //开始变更任务信息
                     foreach (var item in devs)
                     {
                         var dev = Device.Find(item.Entity.CODE).Create<StationDevice>();
-                        var task = tasks.FirstOrDefault(p => p.ID == dev.Data2.Tasknum);
+                        var task = taskList.FirstOrDefault(p => p.ID == dev.Data2.Tasknum);
                         if (task == null) throw new WarnException($"WCS无该任务{dev.Data2.Tasknum}--{dev.Entity.CODE}");
 
                         task.DEVICE = tunnelInfo.SRM.Entity.CODE;
@@ -245,18 +345,27 @@ namespace WCS.Service.Works.Station
                         task.ADDRNEXT = tunnelInfo.taskIN.CODE;
                         task.TaskGroupKey = res.WMSTaskGroupKey;
                         task.ADDRTO = task.DEVICE;
-                        db.Default.SaveChanges();
-
-                        var msg = $"下达从{Conv_1030}移动至{dev.Data.Goodsend}的PLC指令。同时将任务分配至[{ task.TUNNEL }]-[{task.DEVICE}]";
-                        msg += $"[{dev.Data.Tasknum}][{Conv_1030}][{dev.Data.Goodsend}][{tunnelInfo.SRM.Entity.CODE}][{dev.Data.VoucherNo}[{dev.Data2.VoucherNo}]";
-
+                        var msg = $"下达从G1030移动至{dev.Data.Goodsend}的PLC指令。同时将任务分配至[{ task.TUNNEL }]-[{task.DEVICE}]";
+                        msg += $"[{dev.Data.Tasknum}][G1030][{dev.Data.Goodsend}][{tunnelInfo.SRM.Entity.CODE}][{dev.Data.VoucherNo}[{dev.Data2.VoucherNo}]";
                         task.CreateStatusLog(db, msg, this.GetType());
+                        finishTaskList.Add(new Tuple<int, StationDevice>(task.ID, item.Entity.Create<StationDevice>()));
+                    }
+                    db.Default.SaveChanges();
+                });
 
-                        dev.Data.Tasknum = task.ID;
-                        dev.Data.Goodsstart = Conv_1030.ToShort();
-                        dev.Data.Goodsend = tunnelInfo.taskIN.CODE.Replace("G", "").ToShort();
-                        dev.Data.CmdType = IstationCmdType.分配目标地址;
-                        dev.Data.VoucherNo++;
+                // 开始将任务信息写入到设备
+                DB.Do(db =>
+                {
+                    foreach (var finishTask in finishTaskList)
+                    {
+                        var task = db.Default.Set<WCS_TASK>().Find(finishTask.Item1);
+                        if (task == null) continue;
+
+                        finishTask.Item2.Data.Tasknum = task.ID;
+                        finishTask.Item2.Data.Goodsstart = 1030;
+                        finishTask.Item2.Data.Goodsend = task.ADDRNEXT.Replace("G", "").ToShort();
+                        finishTask.Item2.Data.CmdType = IstationCmdType.分配目标地址;
+                        finishTask.Item2.Data.VoucherNo++;
                     }
                 });
             });