|
@@ -0,0 +1,308 @@
|
|
|
+using DBHelper;
|
|
|
+using Newtonsoft.Json;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
+using WCS.Core;
|
|
|
+using WCS.Entity;
|
|
|
+using WCS.Entity.Protocol;
|
|
|
+using WCS.Service.Extensions;
|
|
|
+using WCS.Service.Handlers;
|
|
|
+
|
|
|
+namespace WCS.Service.Works.Station
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// 涂布堆垛机放货分配目标地址
|
|
|
+ /// </summary>
|
|
|
+ [WorkTitle(typeof(CoatingHandler), "涂布堆垛机放货分配目标地址")]
|
|
|
+ public class 涂布堆垛机放货分配目标地址 : DeviceWork<StationDevice>
|
|
|
+ {
|
|
|
+ protected override void Do(StationDevice obj)
|
|
|
+ {
|
|
|
+ obj.EX(obj =>
|
|
|
+ {
|
|
|
+ obj.WhetherToExecute(IstationRequest.堆垛机放货完成请求目标地址);
|
|
|
+ //找到当前站台为当前设备且任务为堆垛机完成的任务
|
|
|
+ DB.Do(db =>
|
|
|
+ {
|
|
|
+ var task = db.Default.Set<WCS_TASK>().FirstOrDefault(v => v.TYPE == TaskType.出库 && v.SRMSTATION == obj.Entity.CODE && v.STATUS == TaskStatus.堆垛机完成);
|
|
|
+ var tasks = db.Default.Set<WCS_TASK>().Where(v => v.TaskGroupKey == task.TaskGroupKey);
|
|
|
+ if (tasks.Any(v => v.STATUS != TaskStatus.堆垛机完成 && v.STATUS != TaskStatus.执行中))
|
|
|
+ throw new WarnException("任务异常,同组任务状态不为堆垛机完成或执行中");
|
|
|
+ if (task == null) throw new WarnException("WCS无该任务信息");
|
|
|
+ if (task.SRMSTATION != obj.Entity.CODE && task.STATUS != TaskStatus.堆垛机完成) throw new WarnException("任务状态不是堆垛机完成");
|
|
|
+ task.STATUS = TaskStatus.执行中;
|
|
|
+ db.Default.SaveChanges();
|
|
|
+ task.CreateStatusLog(db, $"状态由[{TaskStatus.堆垛机完成}]变更为[{task.STATUS}]-{obj.Entity.Code}", this.GetType());
|
|
|
+ //开始写入目标地址
|
|
|
+ obj.Data.Tasknum = task.ID;
|
|
|
+ obj.Data.Goodsstart = obj.Entity.CODE.ToShort();
|
|
|
+ obj.Data.Goodsend = task.ADDRNEXT.ToShort();
|
|
|
+ obj.Data.CmdType = IstationCmdType.堆垛机放货完成请求目标地址;
|
|
|
+ obj.Data.VoucherNo++;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override bool SelectDevice(WCS_DEVICE dev)
|
|
|
+ {
|
|
|
+ return dev.Is(DF.SRM涂布放货);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 涂布出库分配出库口
|
|
|
+ /// </summary>
|
|
|
+ [WorkTitle(typeof(CoatingHandler), "涂布出库分配出库口")]
|
|
|
+ public class 涂布出库分配出库口 : DeviceWork<StationDevice>
|
|
|
+ {
|
|
|
+ protected override void Do(StationDevice obj)
|
|
|
+ {
|
|
|
+ obj.EX(obj =>
|
|
|
+ {
|
|
|
+ if (!obj.Data2.Status.HasFlag(IstationStatus.光电状态)) throw new DoException("无光电");
|
|
|
+ if (obj.Data3.Status.HasFlag(StationStatus.运行状态位)) throw new DoException("设备运行中");
|
|
|
+ if (obj.Data.VoucherNo != obj.Data2.VoucherNo)
|
|
|
+ throw new WarnException($"等待任务[{obj.Data2.Tasknum}]执行--凭证号不一致[{obj.Data.VoucherNo}][{obj.Data2.VoucherNo}]");
|
|
|
+ if (obj.Data2.Tasknum < 10000) throw new DoException("无任务");
|
|
|
+ if (obj.Data2.Request != IstationRequest.请求分配目标地址) throw new WarnException("有任务无请求");
|
|
|
+
|
|
|
+ DB.Do(db =>
|
|
|
+ {
|
|
|
+ var task = db.Default.Set<WCS_TASK>().FirstOrDefault(v => v.TYPE == TaskType.出库 && v.SRMSTATION == obj.Entity.CODE && v.STATUS == WCS.Entity.TaskStatus.堆垛机完成);
|
|
|
+ if (task == null) throw new WarnException("WCS无该任务信息");
|
|
|
+ task.ADDRNEXT = "G1";
|
|
|
+ db.Default.SaveChanges();
|
|
|
+ task.CreateStatusLog(db, $"分配目标地址{task.ADDRNEXT}", this.GetType());
|
|
|
+ //开始写入目标地址
|
|
|
+ obj.Data.Tasknum = task.ID;
|
|
|
+ obj.Data.Goodsstart = obj.Entity.CODE.ToShort();
|
|
|
+ obj.Data.Goodsend = task.ADDRNEXT.ToShort();
|
|
|
+ obj.Data.CmdType = IstationCmdType.堆垛机放货完成请求目标地址;
|
|
|
+ obj.Data.VoucherNo++;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override bool SelectDevice(WCS_DEVICE dev)
|
|
|
+ {
|
|
|
+ return dev.Is(DF.涂布出库RGV取货站台);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 涂布出库分配AGV取货点
|
|
|
+ /// </summary>
|
|
|
+ [WorkTitle(typeof(CoatingHandler), "涂布出库分配AGV取货点")]
|
|
|
+ public class 涂布出库分配AGV取货点 : DeviceWork<StationDevice>
|
|
|
+ {
|
|
|
+ protected override void Do(StationDevice obj)
|
|
|
+ {
|
|
|
+ obj.EX(obj =>
|
|
|
+ {
|
|
|
+ if (!obj.Data2.Status.HasFlag(IstationStatus.光电状态)) throw new DoException("无光电");
|
|
|
+ if (obj.Data3.Status.HasFlag(StationStatus.运行状态位)) throw new DoException("设备运行中");
|
|
|
+ if (obj.Data.VoucherNo != obj.Data2.VoucherNo)
|
|
|
+ throw new WarnException($"等待任务[{obj.Data2.Tasknum}]执行--凭证号不一致[{obj.Data.VoucherNo}][{obj.Data2.VoucherNo}]");
|
|
|
+ if (obj.Data2.Tasknum < 10000) throw new DoException("无任务");
|
|
|
+ if (obj.Data2.Request != IstationRequest.请求分配目标地址) throw new WarnException("有任务无请求");
|
|
|
+
|
|
|
+ DB.Do(db =>
|
|
|
+ {
|
|
|
+ var task = db.Default.Set<WCS_TASK>().FirstOrDefault(v => v.TYPE == TaskType.出库 && v.SRMSTATION == obj.Entity.CODE && v.STATUS == WCS.Entity.TaskStatus.执行中);
|
|
|
+ if (task == null) throw new WarnException("WCS无该任务信息");
|
|
|
+ var addNext = "";
|
|
|
+ if (obj.Entity.CODE == "1340")
|
|
|
+ {
|
|
|
+ var Station1343 = Device.Find("1343").Create<StationDevice>();
|
|
|
+ addNext = "1343";
|
|
|
+ if (Station1343.Data2.Status.HasFlag(IstationStatus.光电状态) && Station1343.Data3.Status.HasFlag(StationStatus.运行状态位))
|
|
|
+ addNext = "1340";
|
|
|
+ }
|
|
|
+ else if (obj.Entity.CODE == "1341")
|
|
|
+ {
|
|
|
+ var Station1344 = Device.Find("1344").Create<StationDevice>();
|
|
|
+ addNext = "1344";
|
|
|
+ if (Station1344.Data2.Status.HasFlag(IstationStatus.光电状态) && Station1344.Data3.Status.HasFlag(StationStatus.运行状态位))
|
|
|
+ addNext = "1341";
|
|
|
+ }
|
|
|
+
|
|
|
+ //全部统一分配目标地址至
|
|
|
+ task.ADDRNEXT = addNext;
|
|
|
+ db.Default.SaveChanges();
|
|
|
+ task.CreateStatusLog(db, $"状态由[{WCS.Entity.TaskStatus.堆垛机完成}]变更为[{task.STATUS}]-{obj.Entity.Code}", this.GetType());
|
|
|
+ //开始写入目标地址
|
|
|
+ obj.Data.Tasknum = task.ID;
|
|
|
+ obj.Data.Goodsstart = obj.Entity.CODE.ToShort();
|
|
|
+ obj.Data.Goodsend = task.ADDRNEXT.ToShort();
|
|
|
+ obj.Data.CmdType = IstationCmdType.堆垛机放货完成请求目标地址;
|
|
|
+ obj.Data.VoucherNo++;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override bool SelectDevice(WCS_DEVICE dev)
|
|
|
+ {
|
|
|
+ return dev.CODE == "1340" || dev.CODE == "1341";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 涂布叫料
|
|
|
+ /// </summary>
|
|
|
+ [WorkTitle(typeof(CoatingHandler), "涂布叫料")]
|
|
|
+ public class 涂布叫料 : Work<StationDeviceGroup>
|
|
|
+ {
|
|
|
+ protected override void Do(StationDeviceGroup obj)
|
|
|
+ {
|
|
|
+ obj.EX(obj =>
|
|
|
+ {
|
|
|
+ var station = obj.Entity.CODE;
|
|
|
+
|
|
|
+ #region 处理新增叫料任务
|
|
|
+
|
|
|
+ DB.Do(db =>
|
|
|
+ {
|
|
|
+ //找到所有的AGV任务
|
|
|
+ var agvTasks = db.Default.Set<WCS_AGVTask>().Where(v => v.Station == station && v.TaskType == AGVTaskType.叫料)
|
|
|
+ .Where(v => v.Status < AGVTaskStatus.完成).ToArray();
|
|
|
+
|
|
|
+ foreach (var agvtask in agvTasks)
|
|
|
+ {
|
|
|
+ var position = agvtask.Position;
|
|
|
+ if (!ProtocolProxy.AllDatas.ContainsKey(position))
|
|
|
+ ProtocolProxy.AllDatas[position] = new ProdLineData();
|
|
|
+ var pld = ProtocolProxy.AllDatas[position] as ProdLineData;
|
|
|
+ pld.Frame = LogicHandler.Frame;
|
|
|
+ pld.Code = position;
|
|
|
+ pld.TaskList.Add(agvtask);
|
|
|
+
|
|
|
+ if (Ltc.Do(agvtask, agvtask => agvtask.Status == AGVTaskStatus.新建))
|
|
|
+ {
|
|
|
+ var qty = db.Default.Set<WCS_AGVTask>().Where(v => v.TaskType == AGVTaskType.叫料 && v.Status > AGVTaskStatus.新建 && v.Status < AGVTaskStatus.完成)
|
|
|
+ .Where(v => v.Position == agvtask.Position).Count();
|
|
|
+ //TODO:暂时不考虑单卷叫料
|
|
|
+ if (Ltc.Do(qty, OutTaskQty => OutTaskQty > 8))
|
|
|
+ {
|
|
|
+ throw new Exception($"{agvtask.Position}正在执行的叫料任务数量已达{qty},暂停出库");
|
|
|
+ }
|
|
|
+ //涂布叫料默认目标地址G1340,到达G1340后再决定是否要继续前进一步
|
|
|
+ var res = WMS.GetOutTask(agvtask.Position, "G1340");
|
|
|
+ res.ForEach(outTask =>
|
|
|
+ {
|
|
|
+ var srm = Device.Find(outTask.TunnelNum).ROUTES.Where(v => v.NEXT.IsSC()).Select(v => v.NEXT).FirstOrDefault();
|
|
|
+
|
|
|
+ var loc = string.Format("{0}-{1}-{2}", outTask.Row, outTask.Colomn, outTask.Layer);
|
|
|
+
|
|
|
+ var task = new WCS_TASK
|
|
|
+ {
|
|
|
+ TYPE = TaskType.出库,
|
|
|
+ STATUS = WCS.Entity.TaskStatus.新建,
|
|
|
+ ADDRFROM = loc,
|
|
|
+ ADDRTO = "G1340",
|
|
|
+ BARCODE = outTask.ContainerBarCode,
|
|
|
+ TUNNEL = outTask.TunnelNum,
|
|
|
+ WMSTASK = int.Parse(outTask.WMSTaskNum),
|
|
|
+ UPDATEUSER = "WCS",
|
|
|
+ SRMSTATION = outTask.Memo1,
|
|
|
+ DEVICE = srm.CODE,
|
|
|
+ //ADDRCURRENT = loc,
|
|
|
+ AgvTask = agvtask.ID,
|
|
|
+ };
|
|
|
+ db.Default.Set<WCS_TASK>().Add(task);
|
|
|
+ db.Default.SaveChanges();
|
|
|
+
|
|
|
+ agvtask.Status = AGVTaskStatus.确认;
|
|
|
+ agvtask.UpdateTime = DateTime.Now;
|
|
|
+ db.Default.SaveChanges();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ else if (Ltc.Do(agvtask, v => v.AGVStatus == AGVTaskStatus.完成))
|
|
|
+ {
|
|
|
+ agvtask.Status = agvtask.AGVStatus;
|
|
|
+ agvtask.UpdateTime = DateTime.Now;
|
|
|
+ db.Default.SaveChanges();
|
|
|
+ }
|
|
|
+ else if (Ltc.Do(agvtask, v => v.AGVStatus == AGVTaskStatus.取消))
|
|
|
+ {
|
|
|
+ agvtask.Status = agvtask.AGVStatus;
|
|
|
+ agvtask.UpdateTime = DateTime.Now;
|
|
|
+ db.Default.SaveChanges();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ #endregion 处理新增叫料任务
|
|
|
+
|
|
|
+ //空闲自动,停止运行
|
|
|
+ if (obj.Items.Any(v => v.Data2.VoucherNo != v.Data.VoucherNo)) throw new WarnException("等待执行任务");
|
|
|
+ if (obj.Items.Any(v => !v.Data3.Status.HasFlag(StationStatus.自动))) return;
|
|
|
+ if (obj.Items.Any(v => v.Data3.Status.HasFlag(StationStatus.运行状态位))) throw new WarnException("设备运行中");
|
|
|
+ if (obj.Items.Any(v => !v.Data2.Status.HasFlag(IstationStatus.光电状态))) throw new DoException("没有光电");
|
|
|
+
|
|
|
+ var taskIds = new List<int>();
|
|
|
+ obj.Items.ToList().ForEach(dev => taskIds.Add(dev.Data2.Tasknum));
|
|
|
+ DB.Do(db =>
|
|
|
+ {
|
|
|
+ var taskList = db.Default.Set<WCS_TASK>().Where(v => taskIds.Contains(v.ID));
|
|
|
+ if (taskList == null) throw new WarnException($"WCS任务号{JsonConvert.SerializeObject(taskIds)}不存在");
|
|
|
+ if (taskList.Any(v => v.TYPE != TaskType.出库)) throw new WarnException("有任务的类型不是出库");
|
|
|
+ if (taskList.Any(v => v.AgvTask == 0)) throw new WarnException("人工出库任务,请手动搬走");
|
|
|
+ var agvtask = db.Default.Set<WCS_AGVTask>().Find(taskList.FirstOrDefault().AgvTask);
|
|
|
+ if (agvtask == null) throw new WarnException($"AGV任务号{taskList.FirstOrDefault().AgvTask}不存在");
|
|
|
+
|
|
|
+ if (agvtask.Status == AGVTaskStatus.确认)
|
|
|
+ {
|
|
|
+ var flag = db.Default.Set<WCS_AGVTask>().Where(v => v.TaskType == AGVTaskType.叫料)
|
|
|
+ .Where(v => v.Status > AGVTaskStatus.确认 && v.Status < AGVTaskStatus.取放完成).Count();
|
|
|
+ if (flag > 2) throw new Exception("有2未完成的AGV出库任务");
|
|
|
+
|
|
|
+ taskList.ToList().ForEach(task =>
|
|
|
+ {
|
|
|
+ task.STATUS = WCS.Entity.TaskStatus.已完成;
|
|
|
+ task.UPDATETIME = DateTime.Now;
|
|
|
+ task.ENDTIME = DateTime.Now;
|
|
|
+ });
|
|
|
+
|
|
|
+ agvtask.Station = obj.Entity.CODE;
|
|
|
+ agvtask.Status = AGVTaskStatus.执行;
|
|
|
+ agvtask.UpdateTime = DateTime.Now;
|
|
|
+ db.Default.SaveChanges();
|
|
|
+ }
|
|
|
+ else if (agvtask.Status < agvtask.AGVStatus)
|
|
|
+ {
|
|
|
+ if (agvtask.AGVStatus == AGVTaskStatus.请求_允许)
|
|
|
+ {
|
|
|
+ if (agvtask.Status < AGVTaskStatus.执行) throw new WarnException($"AGV状态错误-{agvtask.Status}");
|
|
|
+ if (obj.Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.RES1))) throw new WarnException("任务清零信号未清除");
|
|
|
+
|
|
|
+ agvtask.Status = agvtask.AGVStatus;
|
|
|
+ agvtask.UpdateTime = DateTime.Now;
|
|
|
+ db.Default.SaveChanges();
|
|
|
+ }
|
|
|
+ else if (agvtask.AGVStatus == AGVTaskStatus.取放完成)
|
|
|
+ {
|
|
|
+ if (obj.Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.RES1))) throw new WarnException("任务清零信号未清除");
|
|
|
+ if (obj.Items.Any(v => !v.Data2.Status.HasFlag(IstationStatus.光电状态))) throw new WarnException("AGV取货完成后依然有光电信号");
|
|
|
+ if (agvtask.Status < AGVTaskStatus.请求_允许) throw new WarnException("AGV任务状态有误");
|
|
|
+
|
|
|
+ agvtask.Status = agvtask.AGVStatus;
|
|
|
+ agvtask.UpdateTime = DateTime.Now;
|
|
|
+ db.Default.SaveChanges();
|
|
|
+
|
|
|
+ obj.Items.ToList().ForEach(dev =>
|
|
|
+ {
|
|
|
+ dev.Data2.Status = IstationStatus.RES1;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override bool SelectDevice(WCS_DEVICE dev)
|
|
|
+ {
|
|
|
+ return dev.CODE == "G1340" || dev.CODE == "G1343";
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|