using Khd.Core.Domain.Dto.TaskType; using Khd.Core.Domain.Models; using Khd.Core.EntityFramework; using Khd.Core.Library; using Khd.Core.Library.Mapper; using Khd.Core.Plc.S7; using Khd.Core.Wcs.Global; using Masuit.Tools; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Khd.Core.Wcs.Wcs { /// /// 二楼小包出入口 /// public class SecondFloorLine { private readonly LoggerUtils _logger = new LoggerUtils(); private readonly IHost _host; int FloorNo { get; set; } public SecondFloorLine(IHost host, int floor) { this._host = host; FloorNo = floor; } /// /// 启动上件扫描监听 /// public void StartPoint() { Thread FlowPointThread = new Thread(MonitorInLocatorPoint); FlowPointThread.IsBackground = true; FlowPointThread.Name = "SecondFloorLine"; FlowPointThread.Start(); Console.WriteLine(DateTime.Now + ":二楼码垛输送线调度启动成功"); _logger.Info("二楼码垛输送线调度启动成功"); } public void MonitorInLocatorPoint() { using var scope = _host.Services.CreateScope(); using var dbContext = scope.ServiceProvider.GetRequiredService(); var rfidPoint = StaticData.BasePlcpointList.First(t => t.id == 52); var agvGetPoint = StaticData.BasePlcpointList.First(t => t.id == 53); var agvPutPoint = StaticData.BasePlcpointList.First(t => t.id == 54); BaseEquip agvEquip = StaticData.BaseEquip.First(t => t.objid == 8); BaseEquip endEquip = StaticData.BaseEquip.First(t => t.objid == 36); List canNotIn = new List(); while (true) { try { dbContext.ChangeTracker.Entries().ToList().ForEach(e => e.Reload()); var agvPutValue = StaticData.PlcDic[2].Read(agvPutPoint.plcpointAddress);//小包入口叫料 var agvGetValue = StaticData.PlcDic[2].Read(agvGetPoint.plcpointAddress);//小包出口的到位 var rfidValue = StaticData.PlcDic[2].ReadRFID(rfidPoint.plcpointAddress);//小包出口的RFID if (agvGetValue != null && agvPutValue != null && rfidValue != null)//读Plc { if (Convert.ToInt32(agvPutValue) == 0)//小包入口叫料 { bool canCreate = dbContext.WcsTask.Where(t => t.nextPointId == 8 || t.endPointId == endEquip.objid).Any();//有没有生成任务 //36 是小包入口的设备信息,8是二楼Agv设备 if (!canCreate)//没有任务 { BaseEquip? baseEquip = dbContext.BaseEquip.FirstOrDefault(t => t.equipType == 20 && t.emptyCount >= 1);//二楼周转区是否存在一个空托盘以上的 if (baseEquip != null)//二楼周转区有可以去小包入口的库位 { var wcsTask = new WcsTask() { objid = StaticData.SnowId.NextId(), endPointId = endEquip.objid,//小包入口 endPointNo = endEquip.equipNo, nextPointId = agvEquip.objid,//二楼叉车 nextPointNo = agvEquip.equipNo, currPointId = baseEquip.objid,//周转区库位 currPointNo = baseEquip.equipNo, taskStatus = 0, useFlag = 1, containerNo = null, createBy = "WCS", createTime = DateTime.Now, floorNo = 2, fromFloorNo = 2, isEmpty = "1", qty = baseEquip.emptyCount,//托盘的数量 taskType = StaticTaskType.SecondTransitToSmallPackage,//任务类型 }; dbContext.Add(wcsTask); WcsTaskLog wcsTaskLog = CoreMapper.Map(wcsTask); dbContext.Add(wcsTaskLog); dbContext.SaveChanges(); Console.WriteLine(DateTime.Now + ":二楼码垛输送线生成请求空托盘任务成功:" + wcsTask.objid); _logger.Info("二楼码垛输送线生成请求空托盘任务成功:" + wcsTask.objid); } else//二楼周转区没有空托盘 { baseEquip = dbContext.BaseEquip.FirstOrDefault(t => t.equipType == 15 && t.emptyCount == SystemData.maxTray);//三楼三个周转区是否存在空托盘 if (baseEquip != null)//如果三楼有空托盘 { BaseEquip ThirdLineEquip = dbContext.BaseEquip.First(t => t.objid == 3);//三楼接驳位 BaseEquip ThirdAgvEquip = StaticData.BaseEquip.First(t => t.objid == 9);//三楼叉车 if (ThirdLineEquip.equipStatus == 0)//三楼接驳位空闲 { //生成3楼Agv出库任务 WcsTask wcsTask = new WcsTask() { objid = StaticData.SnowId.NextId(), containerNo = null, createBy = "WCS", createTime = DateTime.Now, floorNo = 2, fromFloorNo = 3, isEmpty = "1", qty = SystemData.maxTray, taskType = StaticTaskType.ThirdTransitToSecond, currPointId = baseEquip.objid, currPointNo = baseEquip.equipNo, nextPointId = ThirdAgvEquip.objid, nextPointNo = ThirdAgvEquip.equipNo, endPointId = endEquip.objid, endPointNo = endEquip.equipNo, taskStatus = 0, useFlag = 1, }; dbContext.Add(wcsTask); WcsTaskLog wcsTaskLog = CoreMapper.Map(wcsTask); dbContext.Add(wcsTaskLog); dbContext.SaveChanges(); Console.WriteLine(DateTime.Now + ":二楼码垛输送线生成3楼Agv出库任务成功:" + wcsTask.objid); _logger.Info("二楼码垛输送线生成3楼Agv出库任务成功:" + wcsTask.objid); } } else { BaseEquip startEquip = dbContext.BaseEquip.First(t => t.objid == 40);//一楼的托盘库 if (startEquip.emptyCount > 1 && startEquip.emptyCount <= SystemData.maxTray) { BasePlcpoint basePlcpoint = StaticData.BasePlcpointList.First(t => t.plcpointNo == "someOut");//多个出 BasePlcpoint linesignal01 = StaticData.BasePlcpointList.First(t => t.plcpointNo == "linesignal01");//一楼接驳位到位 BasePlcpoint equipstate06 = StaticData.BasePlcpointList.First(t => t.plcpointNo == "equipstate06");//提升机状态 BasePlcpoint trayStatusValue = StaticData.BasePlcpointList.First(t => t.plcpointNo == "trayStatus");//提升机状态 BaseEquip lineEquip = dbContext.BaseEquip.First(t => t.objid == 1);//一楼接驳位 var lineSignal01Value = StaticData.PlcDic[0].Read(linesignal01.plcpointAddress); var equipstate06Value = StaticData.PlcDic[0].Read(equipstate06.plcpointAddress); if (FirstFloor.ReadEmptyLocation() && trayStatusValue != null && Convert.ToInt32(trayStatusValue) == 1 && Convert.ToInt32(lineSignal01Value) == 0 && Convert.ToInt32(equipstate06Value) == 0) { StaticData.PlcDic[0].WriteToPoint(basePlcpoint.plcpointAddress, "1", basePlcpoint.plcpointLength.ToString());//托盘库多个出 WcsTask wcsTaskManual = new WcsTask() { objid = StaticData.SnowId.NextId(), endPointId = endEquip.objid, endPointNo = endEquip.equipNo, nextPointId = lineEquip.objid, nextPointNo = lineEquip.equipNo, currPointId = lineEquip.objid, currPointNo = lineEquip.equipNo, taskStatus = 0, useFlag = 1, containerNo = null, createBy = "WCS", createTime = DateTime.Now, floorNo = endEquip.floorNo, fromFloorNo = 1, isEmpty = "1", qty = startEquip.emptyCount, taskType = StaticTaskType.SecondLiftToWaste, }; dbContext.Add(wcsTaskManual); WcsTaskLog wcsTaskLog = CoreMapper.Map(wcsTaskManual); dbContext.Add(wcsTaskLog); dbContext.SaveChanges(); Console.WriteLine(DateTime.Now + ":二楼码垛输送线生成手动托盘任务成功:" + wcsTaskManual.objid); _logger.Info("二楼码垛输送线生成手动托盘任务成功:" + wcsTaskManual.objid); } } else if (startEquip.emptyCount > SystemData.maxTray)//如果托盘库大于五个,出一个 { BasePlcpoint basePlcpoint = StaticData.BasePlcpointList.First(t => t.plcpointNo == "oneOut");//多个出 BasePlcpoint linesignal01 = StaticData.BasePlcpointList.First(t => t.plcpointNo == "linesignal01");//一楼接驳位到位 BasePlcpoint equipstate06 = StaticData.BasePlcpointList.First(t => t.plcpointNo == "equipstate06");//提升机状态 BasePlcpoint trayStatusValue = StaticData.BasePlcpointList.First(t => t.plcpointNo == "trayStatus");//提升机状态 BaseEquip lineEquip = dbContext.BaseEquip.First(t => t.objid == 1);//一楼接驳位 var lineSignal01Value = StaticData.PlcDic[0].Read(linesignal01.plcpointAddress); var equipstate06Value = StaticData.PlcDic[0].Read(equipstate06.plcpointAddress); if (FirstFloor.ReadEmptyLocation() && trayStatusValue != null && Convert.ToInt32(trayStatusValue) == 1 && Convert.ToInt32(lineSignal01Value) == 0 && Convert.ToInt32(equipstate06Value) == 0) { StaticData.PlcDic[0].WriteToPoint(basePlcpoint.plcpointAddress, "1", basePlcpoint.plcpointLength.ToString());//托盘库多个出 WcsTask wcsTaskManual = new WcsTask() { objid = StaticData.SnowId.NextId(), endPointId = endEquip.objid, endPointNo = endEquip.equipNo, nextPointId = lineEquip.objid, nextPointNo = lineEquip.equipNo, currPointId = lineEquip.objid, currPointNo = lineEquip.equipNo, taskStatus = 0, useFlag = 1, containerNo = null, createBy = "WCS", createTime = DateTime.Now, floorNo = endEquip.floorNo, fromFloorNo = 1, isEmpty = "1", qty = 1, taskType = StaticTaskType.SecondLiftToWaste, }; dbContext.Add(wcsTaskManual); WcsTaskLog wcsTaskLog = CoreMapper.Map(wcsTaskManual); dbContext.Add(wcsTaskLog); dbContext.SaveChanges(); Console.WriteLine(DateTime.Now + ":二楼码垛输送线生成手动托盘任务成功:" + wcsTaskManual.objid); _logger.Info("二楼码垛输送线生成手动托盘任务成功:" + wcsTaskManual.objid); } } else { //todo:没有空托盘 Console.WriteLine(DateTime.Now + ":二楼码垛输送线没有空托盘"); _logger.Info("二楼码垛输送线没有空托盘"); } } } } } if (Convert.ToInt32(agvGetValue) == 1 && !string.IsNullOrEmpty(rfidValue))//小包出口成品入口 { lock (SystemData.SecondTaskLock) { MesBasePalletInfo? mesBasePalletInfo = dbContext.MesBasePalletInfo.FirstOrDefault(t => t.palletInfoCode == rfidValue); if (mesBasePalletInfo != null) { MesBaseBarcodeInfo? mesBaseBarcodeInfo = dbContext.MesBaseBarcodeInfo.FirstOrDefault(t => t.barcodeInfo == mesBasePalletInfo.materialBarcode); if (mesBaseBarcodeInfo != null) { var wmsBaseLocations = dbContext.WmsBaseLocation .Where(t => t.warehouseFloor == FloorNo) .Where(t => t.activeFlag == "1") .Where(t => t.delFlag == "0") .Where(t => t.locationScrapType == "1") .Where(t => t.locationStatus == "1") .Where(t => t.warehouseId == 231) .ToList();//所有可用库位 var wmsProductStocks = dbContext.WmsProductStock .Where(t => t.warehouseId == 231) .ToList();//仓库的库存 WmsBaseLocation? wmsBaseLocation = null; if (wmsBaseLocations.Count > 0) { List containerCodes = wmsBaseLocations .Where(t => t.locDeep == 1) .Select(t => t.containerCode).ToList();//深库位的有托盘 containerCodes.RemoveAll(t => string.IsNullOrEmpty(t)); List productStocks = wmsProductStocks.Where(t => t.productId == mesBaseBarcodeInfo.materialId) .Where(t => t.saleOrderId == mesBaseBarcodeInfo.saleOrderId) .Where(t => t.palletInfoCode != null) .Where(t => containerCodes.Contains(t.palletInfoCode)).ToList(); var bill = from a in productStocks join b in wmsBaseLocations.Where(t => t.locDeep == 1) on a.palletInfoCode equals b.containerCode select new { b };//等于当前任务的物料的托盘的库位信息 var outBill = from a in bill//深库位托盘和当前任务绑定物料一致的托盘库位 from b in wmsBaseLocations//所有库位 where b.locDeep == 2//浅库位 && b.locRow == (a.b.locRow % 2 == 0 ? a.b.locRow - 1 : a.b.locRow + 1) //如果是4则找3,如果是1则找2 && a.b.locColumn == b.locColumn//列数相同 && string.IsNullOrEmpty(b.containerCode) select new { a.b };//在上面的基础上获取对应托盘的外侧库位的空库位信息 wmsBaseLocation ??= outBill.Where(t => !canNotIn.Contains(t.b.locationCode)).FirstOrDefault()?.b;//先找相同物料的外侧库位 wmsBaseLocation ??= wmsBaseLocations.Where(t => !canNotIn.Contains(t.locationCode)).Where(t => string.IsNullOrEmpty(t.containerCode)).FirstOrDefault(t => t.locDeep == 1);//找不到再找深库位 wmsBaseLocation ??= wmsBaseLocations.Where(t => !canNotIn.Contains(t.locationCode)).Where(t => string.IsNullOrEmpty(t.containerCode)).FirstOrDefault();//找不到再找任意库位 if (wmsBaseLocation != null)//如果找到库位,生成入库任务 { if (wmsBaseLocation.locDeep == 1) { var hasLocation = wmsBaseLocations .Where(t => t.locRow == (wmsBaseLocation.locRow % 2 == 1 ? (wmsBaseLocation.locRow + 1) : (wmsBaseLocation.locRow - 1))) .Where(t => t.locColumn == wmsBaseLocation.locColumn) .Where(t => !string.IsNullOrEmpty(t.containerCode) || t.locationStatus != "1") .Any(); if (hasLocation) { canNotIn.Add(wmsBaseLocation.locationCode); Console.WriteLine(DateTime.Now + $":目标库位{canNotIn.Join(",")}的浅库位库位状态异常,无法入库"); _logger.Info($"目标库位{canNotIn.Join(",")}的浅库位库位状态异常,无法入库"); continue; } } BaseEquip startEquip = StaticData.BaseEquip.First(t => t.objid == 37); var wcsTask = new WcsTask() { objid = StaticData.SnowId.NextId(), currPointId = startEquip.objid, currPointNo = startEquip.equipNo, nextPointId = agvEquip.objid, nextPointNo = agvEquip.equipNo, endPointId = wmsBaseLocation.locationId, endPointNo = wmsBaseLocation.locationCode, taskStatus = 0, useFlag = 1, containerNo = rfidValue, createBy = "WCS", createTime = DateTime.Now, floorNo = 2, fromFloorNo = 2, isEmpty = "0", taskType = StaticTaskType.SecondSmallPackageToStorage, qty = 1, }; SystemData.LockOutLocation(wmsBaseLocation, dbContext); dbContext.Add(wcsTask); WcsTaskLog wcsTaskLog = CoreMapper.Map(wcsTask); dbContext.Add(wcsTaskLog); dbContext.SaveChanges(); canNotIn.Clear(); Console.WriteLine(DateTime.Now + ":二楼码垛输送线生成入库托盘任务成功:" + wcsTask.objid); _logger.Info("二楼码垛输送线生成入库托盘任务成功:" + wcsTask.objid); } else { //报警 } } } } } } } } catch (Exception ex) { if (ex is PlcException) { } else { _logger.Error(ex.Message + "\n" + ex.StackTrace); } } finally { Thread.Sleep(1000); } } } } }