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.检测门);
}
}
}