using PlcSiemens.Core.Extension; using ServiceCenter.Extensions; using ServiceCenter.Logs; using ServiceCenter.SqlSugars; using System.ComponentModel; using System.Threading.Tasks; using WCS.Core; using WCS.Entity; using WCS.WorkEngineering.Extensions; using WCS.WorkEngineering.Protocol.SRM; using WCS.WorkEngineering.Protocol.Station; using WCS.WorkEngineering.WebApi.Controllers; using WCS.WorkEngineering.Worlds; using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags; namespace WCS.WorkEngineering.Systems { /// /// Agv交互系统 /// [BelongTo(typeof(MainWorld))] [Description("Agv交互系统")] public class AgvSystems : DeviceSystem { protected override bool ParallelDo => true; protected override bool SaveLogsToFile => true; private List devs = new List(); private List devsOut = new List(); private List srms = new List(); public AgvSystems() { devs = Device.All.Where(v => v.HasFlag(DeviceFlags.入库, DeviceFlags.巷道口)).Select(v => new Station(v, this.World)).ToList(); srms = Device.All.Where(v => v.HasProtocol(typeof(ISRM520))).Select(v => new SRM(v, this.World)).ToList(); devsOut = Device.All.Where(v => v.HasFlag(DeviceFlags.一楼出库口)).Select(v => new Station(v, this.World)).ToList(); } public override void Do(Station obj) { if (obj.Entity.HasFlag(DeviceFlags.出库)) { List agvTaskInfos = new List(); //获取所有未结束的AGV叫料、搬运任务 SqlSugarHelper.Do(db => { agvTaskInfos = db.Default.Queryable().Where(v => v.Status < AGVTaskStatus.MissionCompleted && (v.TaskType == AGVTaskType.CallMaterial || v.TaskType == AGVTaskType.Transport)).SplitTable(tabs => tabs.Take(2)).OrderBy(v => v.AddTime).ToList(); }); //有需要处理的AGV任务 if (agvTaskInfos.Any()) { this.ExRecord(obj.Entity.Code, "可用出库AGV任务列表", agvTaskInfos.Select(v => v.ID).ToList()); List taskInfos = new List(); foreach (var agv in agvTaskInfos) { try { SqlSugarHelper.Do(db => { //出库叫料任务 if (agv.TaskType == AGVTaskType.CallMaterial) { var task = db.Default.Queryable().First(v => v.AgvTaskID == agv.ID); if (task == null) throw new Exception($"AGV任务{agv.ID}未找到对应WCS任务"); //取货点安全交互 if (agv.AgvStatus == AGVTaskStatus.RequestOrPermission2 && agv.Status != AGVTaskStatus.Complete) { agv.Status = AGVTaskStatus.Complete; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); task.AddWCS_TASK_DTL(db, "agv", $"允许AGV任务{agv.ID}在站台{agv.Station}取货"); AgvApi.ContinueTask(agv.AgvID, agv.Station); } else if (agv.AgvStatus == AGVTaskStatus.LeaveGet) { agv.Status = AGVTaskStatus.Execution; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); //WmsApi.PinkuInfoManagement(task.ID); } else if (agv.AgvStatus == AGVTaskStatus.PutRequestOrPermission && agv.Status != AGVTaskStatus.PutRequestOrPermission) { string endPos = ""; if (task.AddrTo == "1021" || task.AddrTo == "1022" || task.AddrTo == "1023" || task.AddrTo == "1024") { endPos = "PT" + task.AddrTo; } else { endPos = task.AddrTo; } agv.Status = AGVTaskStatus.PutRequestOrPermission; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); task.AddWCS_TASK_DTL(db, "agv", $"允许AGV任务{agv.ID}放货,目标站台{endPos}"); AgvApi.ContinueTask(agv.AgvID, endPos); } //完成任务 else if (agv.AgvStatus == AGVTaskStatus.MissionCompleted && agv.Status != AGVTaskStatus.MissionCompleted) { if (agv.TaskType is AGVTaskType.CallMaterial) { //更新AGV任务状态 agv.Status = AGVTaskStatus.MissionCompleted; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); //更新WCS任务状态 task.Status = Entity.TaskStatus.Finish; task.EedTime = DateTime.Now; db.Default.Updateable(task).ExecuteCommand(); task.AddWCS_TASK_DTL(db, "agv", "任务完成"); task.CompleteOrCancelTasks(db); taskInfos.Add(task); } } } else if (agv.TaskType == AGVTaskType.Transport)//搬运任务,判断是WCS还是WMS创建 { //终点安全交互 if (agv.WorkShop == 111) { var taskInfo = db.Default.Queryable().First(v => v.AgvTaskID == agv.ID); if (taskInfo == null) throw new Exception($"未找到AGV任务{agv.ID}对应WCS任务"); if (agv.AgvStatus == AGVTaskStatus.LeaveGet && agv.AgvStatus != AGVTaskStatus.Execution) { agv.Status = AGVTaskStatus.Execution; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); WmsApi.PinkuInfoManagement(taskInfo.ID); } else if (agv.AgvStatus == AGVTaskStatus.PutRequestOrPermission && agv.Status != AGVTaskStatus.PutRequestOrPermission) { agv.Status = AGVTaskStatus.PutRequestOrPermission; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); string endPos = ""; if (agv.Position == "1012" || agv.Position == "1014" || agv.Position == "1016") { endPos = "PT" + agv.Position; } else { endPos = agv.Position; } taskInfo.AddWCS_TASK_DTL(db, "agv", $"允许AGV任务{agv.ID}放货,目标站台{endPos}"); AgvApi.ContinueTask(agv.AgvID, endPos); } //完成任务 else if (agv.AgvStatus == AGVTaskStatus.MissionCompleted && agv.Status != AGVTaskStatus.MissionCompleted) { if (agv.Position == "1002" || agv.Position == "1004" || agv.Position == "1006" || agv.Position == "1008") { //写入货架信号 var dev = devsOut.Find(v => v.Entity.Code == agv.Position); dev.Data.GoodsStart = agv.Position.ToShort(); } //更新AGV任务状态 agv.Status = AGVTaskStatus.MissionCompleted; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); //更新WCS任务状态 taskInfo.Status = Entity.TaskStatus.Finish; taskInfo.EedTime = DateTime.Now; db.Default.Updateable(taskInfo).ExecuteCommand(); taskInfo.AddWCS_TASK_DTL(db, "agv", "任务完成"); taskInfo.CompleteOrCancelTasks(db); taskInfos.Add(taskInfo); } } else if(agv.WorkShop == 222) { //取货点安全交互 if (agv.AgvStatus == AGVTaskStatus.RequestOrPermission2 && agv.Status != AGVTaskStatus.Complete) { //var dev = devs.Find(v => v.Entity.Code == agv.Position); //if (dev.Data.VoucherNo != dev.Data2.VoucherNo) throw new Exception($"AGV请求取货,但{dev.Entity.Code}凭证号不一致"); //if (!dev.Data3.Status.HasFlag(StationStatus.Auto)) throw new Exception($"AGV请求取货,但{dev.Entity.Code}不在自动状态"); //if (!(dev.Data3.Status.HasFlag(StationStatus.PH_Status) && !dev.Data3.Status.HasFlag(StationStatus.OT_Status))) throw new Exception($"AGV请求取货,但{dev.Entity.Code}光电状态不满足"); //if (dev.Data3.Status.HasFlag(StationStatus.Run)) throw new Exception($"AGV请求取货,但{dev.Entity.Code}在运行状态"); string startPos = agv.Station; if (agv.Station == "1011" || agv.Station == "1013" || agv.Station == "1015" || agv.Station == "1021" || agv.Station == "1022" || agv.Station == "1023" || agv.Station == "1024") { startPos = "PT" + agv.Station; } agv.Status = AGVTaskStatus.Complete; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); AgvApi.ContinueTask(agv.AgvID, agv.Station); } else if (agv.AgvStatus == AGVTaskStatus.PutRequestOrPermission && agv.Status != AGVTaskStatus.PutRequestOrPermission) { string endPos = agv.Position; if (agv.Position == "1012" || agv.Position == "1014" || agv.Position == "1016") { endPos = "PT" + agv.Position; } agv.Status = AGVTaskStatus.PutRequestOrPermission; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); AgvApi.ContinueTask(agv.AgvID, endPos); } //完成任务 else if (agv.AgvStatus == AGVTaskStatus.MissionCompleted && agv.Status != AGVTaskStatus.MissionCompleted) { //任务完成清除货架信号 var dev = devs.Find(v => v.Entity.Code == agv.Station); dev.Data.GoodsStart = 0; if (agv.Position == "1002" || agv.Position == "1004" || agv.Position == "1006" || agv.Position == "1008") { //写入货架信号 var dev1 = devsOut.Find(v => v.Entity.Code == agv.Position); dev1.Data.GoodsStart = agv.Position.ToShort(); } //更新AGV任务状态 agv.Status = AGVTaskStatus.MissionCompleted; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); } } //起点安全交互 if (agv.WorkShop == 333) { var taskInfo = db.Default.Queryable().First(v => v.AgvTaskID == agv.ID); if (taskInfo == null) throw new Exception($"未找到AGV任务{agv.ID}对应WCS任务"); //取货点安全交互 if (agv.AgvStatus == AGVTaskStatus.RequestOrPermission2 && agv.Status != AGVTaskStatus.Complete) { agv.Status = AGVTaskStatus.Complete; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); string startPos = ""; if (taskInfo.AddrFrom == "1021" || taskInfo.AddrFrom == "1022" || taskInfo.AddrFrom == "1023" || taskInfo.AddrFrom == "1024") { startPos = "PT" + taskInfo.AddrFrom; } else { startPos = taskInfo.AddrFrom; } taskInfo.AddWCS_TASK_DTL(db, "agv", $"允许AGV任务{agv.ID}在站台{startPos}取货"); AgvApi.ContinueTask(agv.AgvID, startPos); } else if (agv.AgvStatus == AGVTaskStatus.LeaveGet) { agv.Status = AGVTaskStatus.Execution; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); WmsApi.PinkuInfoManagement(taskInfo.ID); } //完成任务 else if (agv.AgvStatus == AGVTaskStatus.MissionCompleted && agv.Status != AGVTaskStatus.MissionCompleted) { var dev = devs.Find(v => v.Entity.Code == agv.Station); if (dev != null) { dev.Data.GoodsStart = 0; } //更新AGV任务状态 agv.Status = AGVTaskStatus.MissionCompleted; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); //更新WCS任务状态 taskInfo.Status = Entity.TaskStatus.Finish; taskInfo.EedTime = DateTime.Now; db.Default.Updateable(taskInfo).ExecuteCommand(); taskInfo.AddWCS_TASK_DTL(db, "agv", "任务完成"); taskInfo.CompleteOrCancelTasks(db); taskInfos.Add(taskInfo); } } } }); } catch (Exception ex) { World.Log(ex.Message, LogLevelEnum.Mid); this.ExRecord(obj.Entity.Code, ex.Message); continue; } } foreach (var item in taskInfos) { WmsApi.CompleteTask(item.ID); } } } else if (obj.Entity.HasFlag(DeviceFlags.入库)) { List agvTaskInfos = new List(); //获取所有未结束的入库AGV任务 SqlSugarHelper.Do(db => { agvTaskInfos = db.Default.Queryable().Where(v => v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot).SplitTable(tabs => tabs.Take(2)).OrderBy(v => v.EditTime).ToList(); }); if (agvTaskInfos.Any()) { this.ExRecord(obj.Entity.Code, "可用入库AGV任务列表", agvTaskInfos.Select(v => v.ID).ToList()); foreach (var agv in agvTaskInfos) { try { SqlSugarHelper.Do(db => { //找到对应WCS任务 var task = db.Default.Queryable().First(v => v.AgvTaskID == agv.ID); if (task == null) throw new Exception($"AGV任务{agv.ID}未找到对应WCS任务"); #region 开始跟据AGV状态做出处理 //agv取货完成 if (agv.AgvStatus == AGVTaskStatus.LeaveGet && agv.Status != AGVTaskStatus.Execution) { agv.Status = AGVTaskStatus.Execution; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); //通知WMS取货完成 WmsApi.PinkuInfoManagement(task.ID); } else if (agv.AgvStatus == AGVTaskStatus.RequestOrPermission2 && agv.Status != AGVTaskStatus.Complete) { agv.Status = AGVTaskStatus.Complete; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); } //放货点安全交互 else if (agv.AgvStatus == AGVTaskStatus.PutRequestOrPermission && agv.Status != AGVTaskStatus.PutRequestOrPermission) { if (agv.Position.IsNullOrEmpty()) throw new Exception($"无有效放货地址"); var dev = devs.Find(v => v.Entity.Code == agv.Position); if (dev.Data.VoucherNo != dev.Data2.VoucherNo) throw new Exception($"AGV请求放货,但{dev.Entity.Code}凭证号不一致"); if (!dev.Data3.Status.HasFlag(StationStatus.Auto)) throw new Exception($"AGV请求放货,但{dev.Entity.Code}不在自动状态"); if (dev.Data3.Status.HasFlag(StationStatus.PH_Status) || dev.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new Exception($"AGV请求放货,{dev.Entity.Code}不满足放货条件,请检查光电状态"); if (dev.Data3.Status.HasFlag(StationStatus.Run)) throw new Exception($"AGV请求放货,但{dev.Entity.Code}在运行状态"); agv.Status = AGVTaskStatus.PutRequestOrPermission; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); //调继续执行任务接口 AgvApi.ContinueTask(agv.AgvID, agv.Position); } //完成任务 else if (agv.AgvStatus == AGVTaskStatus.MissionCompleted && agv.Status != AGVTaskStatus.MissionCompleted) { var dev = devs.Find(v => v.Entity.Code == agv.Position); dev.Data.TaskNumber = task.ID; dev.Data.VoucherNo++; agv.Status = AGVTaskStatus.MissionCompleted; db.Default.Updateable(agv).SplitTable().ExecuteCommand(); } #endregion 开始跟据AGV状态做出处理 }); } catch (Exception ex) { World.Log(ex.Message, LogLevelEnum.Mid); this.ExRecord(obj.Entity.Code, ex.Message); continue; } } } } } public override bool Select(Device dev) { return dev.Code is "1001" or "1002"; } } }