|
@@ -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 出库
|