using ServiceCenter.Extensions; using ServiceCenter.SqlSugars; using System.ComponentModel; using WCS.Core; using WCS.Entity; using WCS.Entity.Protocol.SRM; using WCS.Entity.Protocol.Station; using WCS.WorkEngineering.Extensions; using WCS.WorkEngineering.Worlds; using WCS.WorkEngineering.Worlds.Logs; using KnownException = WCS.WorkEngineering.Worlds.Logs.KnownException; namespace WCS.WorkEngineering.Systems { /// /// 堆垛机系统 /// [BelongTo(typeof(MainWorld))] [Description("堆垛机系统")] public class SrmSystems : DeviceSystem> { /// /// 取货点设备集合 /// private List> PickUpDevices; /// /// 放货设备 /// private List> PutDevices; public SrmSystems() { //分拣库1 PickUpDevices = World.Devices.Where(v => v.Code is "" or "") .Select(v => new Device(v)).ToList(); PutDevices = World.Devices.Where(v => v.Code is "" or "") .Select(v => new Device(v)).ToList(); //分拣库2 PickUpDevices = World.Devices.Where(v => v.Code is "" or "") .Select(v => new Device(v)).ToList(); PutDevices = World.Devices.Where(v => v.Code is "" or "") .Select(v => new Device(v)).ToList(); //分拣库3 PickUpDevices = World.Devices.Where(v => v.Code is "" or "") .Select(v => new Device(v)).ToList(); PutDevices = World.Devices.Where(v => v.Code is "" or "") .Select(v => new Device(v)).ToList(); } protected override bool ParallelDo => true; protected override bool SaveLogsToFile => true; public override void Do(Device obj) { //判断堆垛机是否报警 if (obj.Data2.Status.HasFlag(SrmStatus.Alarm)) throw new KnownException(obj.Data3.Alarm.ToString(), LogLevelEnum.High); //判断DB520 完成任务确认清除信号 是否为1 if (obj.Data.OkAck == 1) throw new KnownException("任务完成确认信号未清除", LogLevelEnum.Mid); //判断完成任务号是否大于0 if (obj.Data2.TaskFinishiId > 0) { SqlSugarHelper.Do(db => { //根据DB521任务号获取对应任务 var task = db.Default.Queryable().First(v => v.ID == obj.Data2.TaskFinishiId) ?? throw new KnownException($"未找到任务{obj.Data2.TaskFinishiId}", LogLevelEnum.High); if (task.STATUS != Entity.TaskStatus.StackerExecution) throw new KnownException($"任务{task.ID}状态是{task.STATUS.Description()}.堆垛机完成任务需要对应任务状态处于堆垛机执行中", LogLevelEnum.High); //根据任务类型做不同的处理 switch (task.TYPE) { case TaskType.EnterDepot: //完成任务 task.STATUS = Entity.TaskStatus.Finish; task.UPDATETIME = DateTime.Now; task.ENDTIME = DateTime.Now; task.AddWCS_TASK_DTL(db, task.ADDRTO, "入库任务结束"); break; case TaskType.OutDepot: task.STATUS = Entity.TaskStatus.ConveyorInProgress; task.UPDATETIME = DateTime.Now; task.AddWCS_TASK_DTL(db, task.SRMSTATION, "出库任务到达放货站台"); break; case TaskType.TransferDepot: task.STATUS = Entity.TaskStatus.Finish; task.UPDATETIME = DateTime.Now; task.ENDTIME = DateTime.Now; task.AddWCS_TASK_DTL(db, task.ADDRTO, "移库任务结束"); break; } db.Default.Updateable(task).AddQueue(); db.Default.SaveQueues(); obj.Data.OkAck = 1; }); } //堆垛机是否可以下发任务 if (obj.Data2.VoucherNo != obj.Data.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo},DB521:{obj.Data2.VoucherNo}", LogLevelEnum.Mid); if (obj.Data2.AutoStatus != SrmAutoStatus.Automatic) throw new KnownException($"堆垛机处于{obj.Data2.AutoStatus}模式", LogLevelEnum.Low); if (obj.Data2.RunStatus != SrmRunStatus.Idle) throw new KnownException($"堆垛机处于{obj.Data2.RunStatus}状态", LogLevelEnum.High); //默认没有移库任务 bool isTransfer = false; //出入库优先级任务 1:无优先 2:入库 3:出库 int enterOrOut = 1; //再检查是否有等待执行的货物 SqlSugarHelper.Do(db => { //获取当前堆垛机的所有未完成任务 var tasks = db.Default.Queryable().Where(v => v.STATUS < Entity.TaskStatus.Finish && (v.DEVICE == obj.Entity.Code)); //任务集合是否有处于堆垛机执行状态的任务 if (tasks.Any(v => v.STATUS == Entity.TaskStatus.StackerExecution)) throw new KnownException($"有任务处于堆垛机执行状态", LogLevelEnum.High); //判断是否存在调整优先级任务 if (!tasks.Any(v => v.TYPE != TaskType.TransferDepot && v.STATUS < Entity.TaskStatus.StackerExecution && v.Priority > 0)) { //不存在调整优先级任务,判断是否存在移库任务 isTransfer = tasks.Any(v => v.TYPE == TaskType.TransferDepot && v.STATUS == Entity.TaskStatus.NewBuild); } else //存在调整优先级任务 { //获取出库任务中新建状态最大优先级 var outPriorityNewBuild = tasks.Where(v => v.TYPE == TaskType.OutDepot && v.STATUS == Entity.TaskStatus.NewBuild).Max(v => v.Priority); //获取入库任务中最后一个交互点是取货点任务的最大优先级 var enterPriority = tasks.Where(v => v.TYPE == TaskType.EnterDepot && v.STATUS < Entity.TaskStatus.StackerExecution && PickUpDevices.Any(p => p.Entity.Code == v.LastInteractionPoint)) .Max(v => v.Priority); //出入库最大优先级相加大于零 if (outPriorityNewBuild + enterPriority > 0) { //出入库优先级任务 1:无优先 2:入库 3:出库 enterOrOut = enterPriority > outPriorityNewBuild ? 2 : 3; } } }); #region 移库 if (isTransfer) { SqlSugarHelper.Do(db => { //获取一条当前堆垛机优先级最高的新建移库任务 var task = db.Default.Queryable().Where(v => v.DEVICE == obj.Entity.Code && v.TYPE == TaskType.TransferDepot && v.STATUS == Entity.TaskStatus.NewBuild) .OrderByDescending(v => v.Priority) .First() ?? throw new KnownException("未找到移库任务", LogLevelEnum.High); //任务状态改为堆垛机执行中 task.STATUS = Entity.TaskStatus.StackerExecution; task.STARTTIME = DateTime.Now; task.UPDATETIME = DateTime.Now; task.AddWCS_TASK_DTL(db, task.ADDRFROM, task.DEVICE, $"堆垛机{obj.Entity.Code}开始执行任务"); db.Default.Updateable(task).AddQueue(); db.Default.SaveQueues(); var addrFrom = task.ADDRFROM.Split("-"); var addrTo = task.ADDRTO.Split("-"); //下发任务 obj.Data.TaskNumber = task.ID; obj.Data.RowPos1 = addrFrom[0].ToShort(); obj.Data.TravelPos1 = addrFrom[1].ToShort(); obj.Data.LiftPos1 = addrFrom[2].ToShort(); obj.Data.RowPos2 = addrTo[0].ToShort(); obj.Data.TravelPos2 = addrTo[1].ToShort(); obj.Data.LiftPos2 = addrTo[2].ToShort(); obj.Data.VoucherNo++; }); } #endregion 移库 #region 出入库 //上一个周期是不是出库任务 第一次获取返回结果会是false var lastIsOut = obj.Entity.Get("LastIsOut"); obj.Entity.Set("LastIsOut", !lastIsOut); //入库任务优先 或 上一个周期是出库任务并且出库任务无优先 if (enterOrOut == 2 || (lastIsOut && enterOrOut == 1)) //入库任务 { //判断本次优先执行楼层,并设置下次执行时优先楼层 var floor = obj.Entity.Get("Floor"); floor = floor % 2 + 1; obj.Entity.Set("Floor", floor); } else if (enterOrOut == 3 || !lastIsOut) //出库任务 { } #endregion 出入库 } public override bool Select(Device dev) { return dev.Code.Contains("SRM"); } } }