Browse Source

出库任务加锁,共用一个出口的所有堆垛机同一时间只能有一个在执行出库任务

林豪 左 3 years ago
parent
commit
e630f5bf4a

+ 56 - 0
Projects/永冠OPP/WCS.Service/Extensions/DeviceExtension.cs

@@ -536,6 +536,62 @@ namespace WCS.Service.Extensions
                 }
             });
         }
+
+        /// <summary>
+        /// 执行出库任务
+        /// </summary>
+        /// <param name="act"></param>
+        public void EXOutStock(Action<SRMDevice> act)
+        {
+            try
+            {
+                if (ExDevice.Any(v => v == Entity.CODE)) return;
+                if (Entity.CODE == "SRM3" || Entity.CODE == "SRM4")
+                {
+                    AddExDevice("SRM3");
+                    AddExDevice("SRM4");
+                }
+                if (Entity.CODE == "SRM5" || Entity.CODE == "SRM6")
+                {
+                    AddExDevice("SRM5");
+                    AddExDevice("SRM6");
+                }
+                if (Entity.CODE == "SRM7" || Entity.CODE == "SRM8")
+                {
+                    AddExDevice("SRM7");
+                    AddExDevice("SRM8");
+                }
+                act(this);
+            }
+            catch (WarnException ex)
+            {
+                InfoLog.INFO_WARN($"[{Entity.CODE}]--{ex.Message}");
+            }
+            catch (Exception ex)
+            {
+                Ltc.Log(ex.GetBaseException().Message);
+                InfoLog.INFO_ERROR($"[{Entity.CODE}]--{ex.Message}--{ex.StackTrace}");
+                LogHelper.AddWCS_EXCEPTION(ex.Message, Entity.CODE, WCS_EXCEPTIONTYPE.无.ToString());
+            }
+            finally
+            {
+                if (Entity.CODE == "SRM3" || Entity.CODE == "SRM4")
+                {
+                    RemoveExDevice("SRM3");
+                    RemoveExDevice("SRM4");
+                }
+                if (Entity.CODE == "SRM5" || Entity.CODE == "SRM6")
+                {
+                    RemoveExDevice("SRM5");
+                    RemoveExDevice("SRM6");
+                }
+                if (Entity.CODE == "SRM7" || Entity.CODE == "SRM8")
+                {
+                    RemoveExDevice("SRM7");
+                    RemoveExDevice("SRM8");
+                }
+            }
+        }
     }
 
     /// <summary>

+ 132 - 131
Projects/永冠OPP/WCS.Service/Works/SRM/SRMWork.cs

@@ -222,149 +222,150 @@ namespace WCS.Service.Works.SRM
                 floor = floor % 2 + 1;
                 obj.Entity.Set("LastFloor", floor);
 
-                //获取当前堆垛机所有的放货点
-                var list = obj.GetDeliveryPoint();
-
-                list = list.Where(v =>
+                obj.EXOutStock(obj =>
                 {
-                    //true:满足条件  false:不满足条件
-                    //返回结果为无货的设备  默认无货
-                    var res = true;
-                    //放货点是否有货
-                    if (v.Data.VoucherNo != v.Data2.VoucherNo) res = false;
-                    else if (v.Data3.Status.HasFlag(StationStatus.运行状态位)) res = false;
-                    else if (v.Data2.Status.HasFlag(IstationStatus.光电状态)) res = false;
-                    else if (v.Data2.Request == IstationRequest.堆垛机放货完成请求目标地址) res = false;
-                    else if (v.Data2.Tasknum > 10000) res = false;
-                    //TODO:因放货设备过短且无动力,因此需要占用对应旋转台   后续考虑优化方式
-                    if (res)
+                    //获取当前堆垛机所有的放货点
+                    var list = obj.GetDeliveryPoint();
+
+                    list = list.Where(v =>
                     {
-                        List<StationDevice> moveDevs = null;
-                        if (v.Entity.CODE is "1473" or "1474" or "1475" or "1476")
-                            moveDevs = Device.Find("1471", "1472").Select(p => p.Create<StationDevice>()).ToList();
-                        else if (v.Entity.CODE is "1491" or "1492" or "1493" or "1494")
-                            moveDevs = Device.Find("1489", "1490").Select(p => p.Create<StationDevice>()).ToList();
-                        else if (v.Entity.CODE is "1520" or "1521" or "1522" or "1523")
-                            moveDevs = Device.Find("1518", "1519").Select(p => p.Create<StationDevice>()).ToList();
-                        else if (v.Entity.CODE is "1545" or "1546")
-                            moveDevs = Device.Find("1543", "1544").Select(p => p.Create<StationDevice>()).ToList();
-                        else if (v.Entity.CODE is "1555" or "1556")
-                            moveDevs = Device.Find("1551", "1553").Select(p => p.Create<StationDevice>()).ToList();
-                        //如果放货点有移动设备 旋转台的两个设备必须都以停止运行 并无任务及请求
-                        if (moveDevs != null)
+                        //true:满足条件  false:不满足条件
+                        //返回结果为无货的设备  默认无货
+                        var res = true;
+                        //放货点是否有货
+                        if (v.Data.VoucherNo != v.Data2.VoucherNo) res = false;
+                        else if (v.Data3.Status.HasFlag(StationStatus.运行状态位)) res = false;
+                        else if (v.Data2.Status.HasFlag(IstationStatus.光电状态)) res = false;
+                        else if (v.Data2.Request == IstationRequest.堆垛机放货完成请求目标地址) res = false;
+                        else if (v.Data2.Tasknum > 10000) res = false;
+                        //TODO:因放货设备过短且无动力,因此需要占用对应旋转台   后续考虑优化方式
+                        if (res)
                         {
-                            if (moveDevs.Any(p => p.Data.VoucherNo != p.Data2.VoucherNo)) res = false;
-                            else if (moveDevs.Any(p => p.Data3.Status.HasFlag(StationStatus.有货状态位))) res = false;
-                            else if (moveDevs.Any(p => p.Data2.Status.HasFlag(IstationStatus.光电状态))) res = false;
-                            else if (moveDevs.Any(p => p.Data2.Tasknum > 10000)) res = false;
+                            List<StationDevice> moveDevs = null;
+                            if (v.Entity.CODE is "1473" or "1474" or "1475" or "1476")
+                                moveDevs = Device.Find("1471", "1472").Select(p => p.Create<StationDevice>()).ToList();
+                            else if (v.Entity.CODE is "1491" or "1492" or "1493" or "1494")
+                                moveDevs = Device.Find("1489", "1490").Select(p => p.Create<StationDevice>()).ToList();
+                            else if (v.Entity.CODE is "1520" or "1521" or "1522" or "1523")
+                                moveDevs = Device.Find("1518", "1519").Select(p => p.Create<StationDevice>()).ToList();
+                            else if (v.Entity.CODE is "1545" or "1546")
+                                moveDevs = Device.Find("1543", "1544").Select(p => p.Create<StationDevice>()).ToList();
+                            else if (v.Entity.CODE is "1555" or "1556")
+                                moveDevs = Device.Find("1551", "1553").Select(p => p.Create<StationDevice>()).ToList();
+                            //如果放货点有移动设备 旋转台的两个设备必须都以停止运行 并无任务及请求
+                            if (moveDevs != null)
+                            {
+                                if (moveDevs.Any(p => p.Data.VoucherNo != p.Data2.VoucherNo)) res = false;
+                                else if (moveDevs.Any(p => p.Data3.Status.HasFlag(StationStatus.有货状态位))) res = false;
+                                else if (moveDevs.Any(p => p.Data2.Status.HasFlag(IstationStatus.光电状态))) res = false;
+                                else if (moveDevs.Any(p => p.Data2.Tasknum > 10000)) res = false;
+                            }
                         }
-                    }
-                    return res;
-                }).ToList();
+                        return res;
+                    }).ToList();
 
-                //没有可用货位
-                if (list.Count == 0) return;
+                    //没有可用货位
+                    if (list.Count == 0) return;
 
-                //可用设备的编号组
-                var empties = list.Select(v => v.Entity.CODE).ToArray();
-                //月台所有设备当前有的任务号
-                var taskidList = DockDevs.Select(v => v.Data2.Tasknum).Where(v => v > 10000).ToList();
-                //堆垛机设备
-                var sc = obj.Entity.CODE;
-                DB.Do(db =>
-                {
-                    //堆垛机当前是否有正在执行的任务
-                    if (db.Default.Set<WCS_TASK>().Any(d => d.DEVICE == sc && d.STATUS == TaskStatus.堆垛机执行))
-                        throw new Exception(LogHelper.SpliceLogMessage($"[{deviceCode}]有正在执行的出库任务", deviceCode, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
-                    //找出等待执行的出库任务
-                    var q = db.Default.Set<WCS_TASK>().Where(v => v.STATUS == TaskStatus.新建)
-                                                      .Where(v => v.DEVICE == sc)
-                                                      .Where(v => v.TYPE == TaskType.出库)
-                                                      .Where(v => !db.Default.Set<WCS_TASK>().Any(d => d.DEVICE == sc && d.STATUS == TaskStatus.堆垛机执行)).ToList();
-                    //同一个目标地址同时只能有4(双工位,每一节设备可以存放两个任务)个正在执行的任务
-                    //考虑到有可能出现一次只发一个任务的情况,因此判断条件为3
-                    //连续两次只发一个任务的情况暂时不考虑
-                    //同时对结果进行排序,分组后取第一组任务
-                    //TODO:暂时不确定排序后进行分组是否会完全打乱排序,先按照这种按时执行,后续有异常再更改
-                    //TODO:暂时维考虑二楼环穿
-                    var outDepot = q.Where(v => db.Default.Set<WCS_TASK>()
-                                        .Where(d => d.TYPE == TaskType.出库)
-                                        .Where(d => d.STATUS > TaskStatus.新建)
-                                        .Where(d => d.STATUS < TaskStatus.已完成 || taskidList.Contains(d.ID))
-                                        .Where(d => d.ADDRTO == v.ADDRTO && d.FLOOR == v.FLOOR)
-                                        .Count() < 3)
-                                .OrderByDescending(v => v.Priority)
-                                .ThenBy(v => v.FLOOR == floor ? 0 : 1)
-                                .ThenBy(v => v.CREATETIME)
-                                .GroupBy(v => v.ADDRTO)
-                                .FirstOrDefault();
-
-                    if (outDepot == null)
+                    //可用设备的编号组
+                    var empties = list.Select(v => v.Entity.CODE).ToArray();
+                    //月台所有设备当前有的任务号
+                    var taskidList = DockDevs.Select(v => v.Data2.Tasknum).Where(v => v > 10000).ToList();
+                    //堆垛机设备
+                    var sc = obj.Entity.CODE;
+                    DB.Do(db =>
                     {
-                        Ltc.Log($"{deviceCode}无出库任务可执行");
-                        return;
-                    }
-                    //获取两个个可执行任务,此时这两个任务的目标地址是一致的
-                    var tasks = outDepot.Select(v => v).ToList().GetOutTask();
+                        //堆垛机当前是否有正在执行的任务
+                        if (db.Default.Set<WCS_TASK>().Any(d => d.DEVICE == sc && d.STATUS == TaskStatus.堆垛机执行))
+                            throw new Exception(LogHelper.SpliceLogMessage($"[{deviceCode}]有正在执行的出库任务", deviceCode, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
+                        //找出等待执行的出库任务
+                        var q = db.Default.Set<WCS_TASK>().Where(v => v.STATUS == TaskStatus.新建)
+                                                          .Where(v => v.DEVICE == sc)
+                                                          .Where(v => v.TYPE == TaskType.出库)
+                                                          .Where(v => !db.Default.Set<WCS_TASK>().Any(d => d.DEVICE == sc && d.STATUS == TaskStatus.堆垛机执行)).ToList();
+                        //同一个目标地址同时只能有4(双工位,每一节设备可以存放两个任务)个正在执行的任务
+                        //考虑到有可能出现一次只发一个任务的情况,因此判断条件为3
+                        //连续两次只发一个任务的情况暂时不考虑
+                        //同时对结果进行排序,分组后取第一组任务
+                        //TODO:暂时不确定排序后进行分组是否会完全打乱排序,先按照这种按时执行,后续有异常再更改
+                        //TODO:暂时维考虑二楼环穿
+                        var outDepot = q.Where(v => db.Default.Set<WCS_TASK>()
+                                            .Where(d => d.TYPE == TaskType.出库)
+                                            .Where(d => d.STATUS > TaskStatus.新建)
+                                            .Where(d => d.STATUS < TaskStatus.已完成 || taskidList.Contains(d.ID))
+                                            .Where(d => d.ADDRTO == v.ADDRTO && d.FLOOR == v.FLOOR)
+                                            .Count() < 3)
+                                    .OrderByDescending(v => v.Priority)
+                                    .ThenBy(v => v.FLOOR == floor ? 0 : 1)
+                                    .ThenBy(v => v.CREATETIME)
+                                    .GroupBy(v => v.ADDRTO)
+                                    .FirstOrDefault();
 
-                    //根据任务的目标地址获取对应的设备组
-                    var devs = Device.Find($"{tasks.OrderBy(v => v.ADDRTO).FirstOrDefault().ADDRTO}").Create<StationDeviceGroup>().Items.OrderByDescending(v => v.Entity.CODE).ToArray();
-                    var dev1 = devs[0];
-                    var dev2 = devs[1];
-                    if (obj.Data2.Mode_1 != SCMode.远程) return;
-                    if (obj.Data2.Status_1 != SCRunStatus.空闲) return;
-
-                    for (int i = 0; i < tasks.Length; i++)
-                    {
-                        var item = tasks[i];
-                        var task = db.Default.Set<WCS_TASK>().Find(item.ID);
-                        //找到所有可用到达目的地的取货点,必定是一个设备组
-                        var a = Device.Where(v => v.ROUTES.Any(p => p.NEXT.CODE == task.ADDRTO));
-                        var oldTaskSTATUS = task.STATUS;
-                        task.STARTTIME = DateTime.Now;
-                        task.UPDATETIME = DateTime.Now;
-                        task.STATUS = WCS.Entity.TaskStatus.堆垛机执行;
-                        task.DEVICE = obj.Entity.CODE;
-                        //获取到站台的下一个地址
-                        if (Device.Find(task.SRMSTATION).ROUTES.Any(v => v.NEXT == dev1.Entity)) task.ADDRNEXT = dev1.Entity.CODE;
-                        else task.ADDRNEXT = dev2.Entity.CODE;
-                        db.Default.SaveChanges();
-                        Uploader.Upload(db);
-                        var msg = "";
-                        if (item.Col.OddNumberOrEven())
-                            msg = $"状态由[{oldTaskSTATUS}]变更为[{task.STATUS}][{obj.Data.SLine_1}-{obj.Data.SCol_1}-{obj.Data.SLayer_1}][{obj.Data.ELine_1}][{obj.Data.VoucherNo_1}]";
-                        else
-                            msg = $"状态由[{oldTaskSTATUS}]变更为[{task.STATUS}][{obj.Data.SLine_2}-{obj.Data.SCol_2}-{obj.Data.SLayer_2}][{obj.Data.ELine_2}][{obj.Data.VoucherNo_2}]";
-                        task.CreateStatusLog(db, msg, this.GetType());
-
-                        //判断当前任务为二工位还是一工位
-                        if (item.Col.OddNumberOrEven())
+                        if (outDepot == null)
                         {
-                            InfoLog.INFO_SRMINFO($"写入堆垛机[{obj.Entity.CODE}]1工位-开始:[{obj.Data.TaskID_1}][{obj.Data.SLine_1}][{obj.Data.SCol_1}][{obj.Data.SLayer_1}][{obj.Data.ELine_1}][{obj.Data.VoucherNo_1}]");
-                            obj.Data.TaskID_1 = item.ID;
-                            obj.Data.SLine_1 = item.Line;
-                            obj.Data.SCol_1 = item.Col;
-                            obj.Data.SLayer_1 = item.Layer;
-                            obj.Data.ELine_1 = task.SRMSTATION.ToShort();
-                            obj.Data.ECol_1 = 0;
-                            obj.Data.ELayer_1 = 0;
-                            obj.Data.VoucherNo_1++;
-                            InfoLog.INFO_SRMINFO($"写入堆垛机[{obj.Entity.CODE}]1工位-结束:[{obj.Data.TaskID_1}][{obj.Data.SLine_1}][{obj.Data.SCol_1}][{obj.Data.SLayer_1}][{obj.Data.ELine_1}][{obj.Data.VoucherNo_1}]");
+                            Ltc.Log($"{deviceCode}无出库任务可执行");
+                            return;
                         }
-                        else
+                        //获取两个个可执行任务,此时这两个任务的目标地址是一致的
+                        var tasks = outDepot.Select(v => v).ToList().GetOutTask();
+
+                        //根据任务的目标地址获取对应的设备组
+                        var devs = Device.Find($"{tasks.OrderBy(v => v.ADDRTO).FirstOrDefault().ADDRTO}").Create<StationDeviceGroup>().Items.OrderByDescending(v => v.Entity.CODE).ToArray();
+                        var dev1 = devs[0];
+                        var dev2 = devs[1];
+
+                        for (int i = 0; i < tasks.Length; i++)
                         {
-                            InfoLog.INFO_SRMINFO($"写入堆垛机[{obj.Entity.CODE}]2工位-开始:[{obj.Data.TaskID_2}][{obj.Data.SLine_2}][{obj.Data.SCol_2}][{obj.Data.SLayer_2}][{obj.Data.ELine_2}][{obj.Data.VoucherNo_2}]");
-                            obj.Data.TaskID_2 = item.ID;
-                            obj.Data.SLine_2 = item.Line;
-                            obj.Data.SCol_2 = item.Col;
-                            obj.Data.SLayer_2 = item.Layer;
-                            obj.Data.ELine_2 = task.SRMSTATION.ToShort();
-                            obj.Data.ECol_2 = 0;
-                            obj.Data.ELayer_2 = 0;
-                            obj.Data.VoucherNo_2++;
-                            InfoLog.INFO_SRMINFO($"写入堆垛机[{obj.Entity.CODE}]2工位-结束:[{obj.Data.TaskID_2}][{obj.Data.SLine_2}][{obj.Data.SCol_2}][{obj.Data.SLayer_2}][{obj.Data.ELine_2}][{obj.Data.VoucherNo_2}]");
+                            var item = tasks[i];
+                            var task = db.Default.Set<WCS_TASK>().Find(item.ID);
+                            //找到所有可用到达目的地的取货点,必定是一个设备组
+                            var a = Device.Where(v => v.ROUTES.Any(p => p.NEXT.CODE == task.ADDRTO));
+                            var oldTaskSTATUS = task.STATUS;
+                            task.STARTTIME = DateTime.Now;
+                            task.UPDATETIME = DateTime.Now;
+                            task.STATUS = WCS.Entity.TaskStatus.堆垛机执行;
+                            task.DEVICE = obj.Entity.CODE;
+                            //获取到站台的下一个地址
+                            if (Device.Find(task.SRMSTATION).ROUTES.Any(v => v.NEXT == dev1.Entity)) task.ADDRNEXT = dev1.Entity.CODE;
+                            else task.ADDRNEXT = dev2.Entity.CODE;
+                            db.Default.SaveChanges();
+                            Uploader.Upload(db);
+                            var msg = "";
+                            if (item.Col.OddNumberOrEven())
+                                msg = $"状态由[{oldTaskSTATUS}]变更为[{task.STATUS}][{obj.Data.SLine_1}-{obj.Data.SCol_1}-{obj.Data.SLayer_1}][{obj.Data.ELine_1}][{obj.Data.VoucherNo_1}]";
+                            else
+                                msg = $"状态由[{oldTaskSTATUS}]变更为[{task.STATUS}][{obj.Data.SLine_2}-{obj.Data.SCol_2}-{obj.Data.SLayer_2}][{obj.Data.ELine_2}][{obj.Data.VoucherNo_2}]";
+                            task.CreateStatusLog(db, msg, this.GetType());
+
+                            //判断当前任务为二工位还是一工位
+                            if (item.Col.OddNumberOrEven())
+                            {
+                                InfoLog.INFO_SRMINFO($"写入堆垛机[{obj.Entity.CODE}]1工位-开始:[{obj.Data.TaskID_1}][{obj.Data.SLine_1}][{obj.Data.SCol_1}][{obj.Data.SLayer_1}][{obj.Data.ELine_1}][{obj.Data.VoucherNo_1}]");
+                                obj.Data.TaskID_1 = item.ID;
+                                obj.Data.SLine_1 = item.Line;
+                                obj.Data.SCol_1 = item.Col;
+                                obj.Data.SLayer_1 = item.Layer;
+                                obj.Data.ELine_1 = task.SRMSTATION.ToShort();
+                                obj.Data.ECol_1 = 0;
+                                obj.Data.ELayer_1 = 0;
+                                obj.Data.VoucherNo_1++;
+                                InfoLog.INFO_SRMINFO($"写入堆垛机[{obj.Entity.CODE}]1工位-结束:[{obj.Data.TaskID_1}][{obj.Data.SLine_1}][{obj.Data.SCol_1}][{obj.Data.SLayer_1}][{obj.Data.ELine_1}][{obj.Data.VoucherNo_1}]");
+                            }
+                            else
+                            {
+                                InfoLog.INFO_SRMINFO($"写入堆垛机[{obj.Entity.CODE}]2工位-开始:[{obj.Data.TaskID_2}][{obj.Data.SLine_2}][{obj.Data.SCol_2}][{obj.Data.SLayer_2}][{obj.Data.ELine_2}][{obj.Data.VoucherNo_2}]");
+                                obj.Data.TaskID_2 = item.ID;
+                                obj.Data.SLine_2 = item.Line;
+                                obj.Data.SCol_2 = item.Col;
+                                obj.Data.SLayer_2 = item.Layer;
+                                obj.Data.ELine_2 = task.SRMSTATION.ToShort();
+                                obj.Data.ECol_2 = 0;
+                                obj.Data.ELayer_2 = 0;
+                                obj.Data.VoucherNo_2++;
+                                InfoLog.INFO_SRMINFO($"写入堆垛机[{obj.Entity.CODE}]2工位-结束:[{obj.Data.TaskID_2}][{obj.Data.SLine_2}][{obj.Data.SCol_2}][{obj.Data.SLayer_2}][{obj.Data.ELine_2}][{obj.Data.VoucherNo_2}]");
+                            }
                         }
-                    }
+                    });
                 });
 
                 #endregion 出库