using ServiceCenter.Extensions; using ServiceCenter.Logs; using ServiceCenter.SqlSugars; using System.ComponentModel; using WCS.Core; using WCS.Entity; using WCS.WorkEngineering.Extensions; using WCS.WorkEngineering.Protocol.BCR; 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 { /// /// 一楼入库巷道分配处理系统 /// [BelongTo(typeof(MainWorld))] [Description("一楼入库巷道分配处理系统")] public class 一楼入库巷道分配处理系统 : DeviceSystem { protected override bool ParallelDo => true; protected override bool SaveLogsToFile => true; private List> BCRS = new List>(); private List devs = new List(); private List sta = new List(); private List srms = new List(); public 一楼入库巷道分配处理系统() { BCRS = Device.All.Where(v => v.HasProtocol()).Select(x=>new Device(x,World)).ToList(); devs = Device.All.Where(v => v.HasFlag(DeviceFlags.入库, DeviceFlags.巷道口)).Select(v => new Station(v, this.World)).ToList(); sta = Device.All.Where(v => v.HasFlag(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(); } public override void Do(Station obj) { obj.入库站点是否被禁止(); obj.入库站点是否满足执行条件(); WCS_TaskInfo task = null;//处理完成的任务 WCS_TaskInfo taskInfo = null; try { SqlSugarHelper.Do(_db => { var db = _db.Default; //扫码信号交互 var agvTaskCur = db.Queryable().SplitTable().First(v => v.AgvStatus == AGVTaskStatus.RequestOrPermission1 && v.Status != AGVTaskStatus.Complete1 && v.Position == obj.Entity.Code); if (agvTaskCur != null) { var dev = sta.Find(v => v.Entity.Code == obj.Entity.Code); var taskCur = db.Queryable().First(v => v.AgvTaskID == agvTaskCur.ID); if (taskCur != null && dev.Data2.GoodsStart == 0) { obj.Data.GoodsStart = obj.Entity.Code.ToShort(); } } else { return; } //获取RFID var barentity = BCRS.Where(p => p.Entity.Code == "BCR" + obj.Entity.Code).First(); var bardata = barentity.Data; var barcode = bardata.Content.Trim().Split('\0')[0]; if(string.IsNullOrEmpty(barcode)) throw new KnownException($"条码为空,请检查", LogLevelEnum.High); if (!barcode.StartsWith("PT") && !barcode.StartsWith("Test")) throw new KnownException($"条码{barcode}无法识别", LogLevelEnum.High); //根据agv任务找到对应wcs任务并赋值 if (db.Queryable().SplitTable().Count(v => v.AgvStatus == AGVTaskStatus.RequestOrPermission1 && v.Status != AGVTaskStatus.Complete1 && v.Position == obj.Entity.Code) > 1) { throw new KnownException($"未分配巷道任务数异常,请检查现场情况", LogLevelEnum.High); } var agvTask = db.Queryable().SplitTable().First(v => v.AgvStatus == AGVTaskStatus.RequestOrPermission1 && v.Status != AGVTaskStatus.Complete1 && v.Position == obj.Entity.Code); if (agvTask == null) throw new KnownException($"未找到对应agv任务,条码{barcode}", LogLevelEnum.High); taskInfo = db.Queryable().First(v => v.AgvTaskID == agvTask.ID) ?? throw new KnownException($"未找到agv任务{agvTask.ID}对应WCS任务", LogLevelEnum.High); if (taskInfo.BarCode.StartsWith("PT") && taskInfo.BarCode != barcode) throw new KnownException($"条码{barcode}读取有误,请检查条码", LogLevelEnum.High); taskInfo.BarCode = barcode; //分配巷道,agv目标站台 if (agvTaskCur.WorkShop == 1) { barcode = ""; } var res = WmsApi.GetTunnelPriorityList(taskInfo.ID,barcode); var tunnelNo = res.ResData.Split(",").Select(v => "TY" + v).ToList(); //开始获取堆垛机与可用站台信息 var agvs = db.Queryable().Where(v => v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot).SplitTable(v => v.Take(2)).ToList(); var stations = devs.Where(v => v.Entity.Code is "1001" or "1003" or "1005" or "1007").ToList(); //筛选出可用站台 if (agvs == null) { stations = stations.Where(v => v.Data.VoucherNo == v.Data2.VoucherNo && v.Data3.Status.HasFlag(StationStatus.Auto)) .Where(v => !v.Data3.Status.HasFlag(StationStatus.PH_Status) && !v.Data3.Status.HasFlag(StationStatus.OT_Status)) .Where(v => !v.Data3.Status.HasFlag(StationStatus.Run)) .ToList(); // 筛选出可用站台 } else { stations = stations.Where(v => v.Data.VoucherNo == v.Data2.VoucherNo && v.Data3.Status.HasFlag(StationStatus.Auto)) .Where(v => !v.Data3.Status.HasFlag(StationStatus.PH_Status) && !v.Data3.Status.HasFlag(StationStatus.OT_Status)) .Where(v => !v.Data3.Status.HasFlag(StationStatus.Run)) .Where(v => !agvs.Select(a => a.Position).Contains(v.Entity.Code)).ToList(); // 筛选出可用站台 } if (!stations.Any()) { World.Log($"无可用站台", LogLevelEnum.Mid); return; } //可用堆垛机 var tunnelList = stations.Select(v => v.Entity.Sources).SelectMany(v => v).Where(v => v.IsTunnel()).ToList();//上一个地址是巷道的 var tunnel = stations.Select(v => v.Entity.Sources).SelectMany(v => v).Where(v => v.IsTunnel())//上一个地址是巷道的 .Select(v => v.Sources).SelectMany(v => v).Where(v => v.HasProtocol(typeof(ISRM520))) //筛选出堆垛机 .Select(v => new SRM(v, this.World)) //转换为SRM .Where(v => !v.Data2.Status.HasFlag(SrmStatus.Alarm) && v.Data2.AutoStatus == SrmAutoStatus.Automatic)//筛选出可用堆垛机 .Select(v => v.Entity.Sources).SelectMany(v => v).Where(v => v.IsTunnel()) .Where(v => tunnelList.Select(s => s.Code).Contains(v.Code)) .Where(v => tunnelNo.Contains(v.Code)) .MinBy(v => tunnelNo.IndexOf(v.Code));//按照巷道优先级排序 if (tunnel == null) { World.Log($"无可用巷道", LogLevelEnum.Mid); return; }; //筛选出堆垛机的放货站台 var nextPos = stations.FirstOrDefault(v => v.Entity.Sources.Where(t => t.IsTunnel()).Where(t => t.Code== tunnel.Code).Any()); if (nextPos == null) { World.Log($"无可用放货站台,请检查", LogLevelEnum.Mid); return; }; agvTask.Status = AGVTaskStatus.Complete1; agvTask.Position = nextPos.Entity.Code; agvTask.EditTime = DateTime.Now; db.Updateable(agvTask).SplitTable().ExecuteCommand(); AgvApi.ContinueTask(agvTask.AgvID, nextPos.Entity.Code); taskInfo.Status = Entity.TaskStatus.AGVExecution; taskInfo.Tunnel = tunnel.Code.GetLastDigit().ToString(); string srm = ""; if (tunnel.Code.GetLastDigit() > 2) { srm = "SRM2"; } else { srm = "SRM1"; } taskInfo.Device = srm; ; taskInfo.SrmStation = nextPos.Entity.Code; taskInfo.AddrNext = tunnel.Code; db.Updateable(taskInfo).ExecuteCommand(); taskInfo.AddWCS_TASK_DTL(_db, obj.Entity.Code, "SRM", $"任务分配巷道[{tunnel.Code}],目标站台[{nextPos.Entity.Code}]"); var taskCur1 = db.Queryable().First(v => v.AgvTaskID == agvTaskCur.ID); var dev1 = sta.Find(v => v.Entity.Code == obj.Entity.Code); //条码已读且请求信号还在 if (taskCur1 != null && !taskCur1.BarCode.StartsWith("Test")) { if (dev1 != null && dev1.Data2.GoodsStart == obj.Entity.Code.ToShort()) { obj.Data.GoodsStart = 0; } } task = taskInfo; if (task == null) throw new Exception(); }); } catch (Exception ex) { throw new KnownException(ex.Message, LogLevelEnum.High); } } public override bool Select(Device dev) { return dev.HasFlag(DeviceFlags.检测门); } } }