From 1bfa89757cc48133c6419a07e85cd1c0bd0e3e79 Mon Sep 17 00:00:00 2001 From: "LAPTOP-NLSJV9RB\\91647" <916477576@qq.com> Date: Wed, 27 Mar 2024 13:40:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dto/webapi/genAgvSchedulingTask.cs | 22 +- src/Khd.Core.Domain/Models/WmsBaseLocation.cs | 9 +- src/Khd.Core.Wcs/Khd.Core.Wcs.csproj | 1 + src/Khd.Core.Wcs/Wcs/CreateTaskByRecord.cs | 64 +-- src/Khd.Core.Wcs/Wcs/SecondFloorAGV.cs | 468 ++++++++++++++++++ src/Khd.Core.Wcs/Wcs/SecondFloorLine.cs | 233 +++++++++ src/Khd.Core.Wcs/Wcs/SecondFloorPoint.cs | 149 ++++++ ...econdThirdFloorAGV.cs => ThirdFloorAGV.cs} | 6 +- ...dThirdFloorPoint.cs => ThirdFloorPoint.cs} | 6 +- 9 files changed, 887 insertions(+), 71 deletions(-) create mode 100644 src/Khd.Core.Wcs/Wcs/SecondFloorAGV.cs create mode 100644 src/Khd.Core.Wcs/Wcs/SecondFloorLine.cs create mode 100644 src/Khd.Core.Wcs/Wcs/SecondFloorPoint.cs rename src/Khd.Core.Wcs/Wcs/{SecondThirdFloorAGV.cs => ThirdFloorAGV.cs} (99%) rename src/Khd.Core.Wcs/Wcs/{SecondThirdFloorPoint.cs => ThirdFloorPoint.cs} (98%) diff --git a/src/Khd.Core.Domain/Dto/webapi/genAgvSchedulingTask.cs b/src/Khd.Core.Domain/Dto/webapi/genAgvSchedulingTask.cs index aad5202..c7a6dc1 100644 --- a/src/Khd.Core.Domain/Dto/webapi/genAgvSchedulingTask.cs +++ b/src/Khd.Core.Domain/Dto/webapi/genAgvSchedulingTask.cs @@ -52,20 +52,12 @@ namespace Khd.Core.Domain.Dto.webapi /// /// 位置路径:AGV关键路径位置集合,与任务类型中模板配置的位置路径一一对应。待现场地图部署、配置完成后可获取。 /// - public string positionCodePath { get; set; } - /// - /// 货架编号,不指定货架可以为空 - /// - public string podCode { get; set; } + public List positionCodePath { get; set; } /// /// “180”,”0”,”90”,”-90” 分别对应地图的”左”,”右”,”上”,”下” ,不指定方向可以为空 /// public string podDir { get; set; } /// - /// 货架类型, 传空时表示随机找个货架 - /// - public string podTyp { get; set; } - /// /// 物料批次或货架上的物料唯一编码, /// public string materialLot { get; set; } @@ -99,6 +91,18 @@ namespace Khd.Core.Domain.Dto.webapi public string positionSelStrategy { get; set; } public string data { get; set; } } + public class Position + { + /// + /// 货架编号,不指定货架可以为空 + /// + public string podCode { get; set; } + /// + /// 货架类型, 传空时表示随机找个货架 + /// + public string podTyp { get; set; } + + } public class ReponseMessage { diff --git a/src/Khd.Core.Domain/Models/WmsBaseLocation.cs b/src/Khd.Core.Domain/Models/WmsBaseLocation.cs index e396fae..f30c543 100644 --- a/src/Khd.Core.Domain/Models/WmsBaseLocation.cs +++ b/src/Khd.Core.Domain/Models/WmsBaseLocation.cs @@ -27,11 +27,16 @@ namespace Khd.Core.Domain.Models /// [Column("warehouse_id")] public long warehouseId { get; set; } - + + /// + /// agv的点位编码 + /// + [Column("agv_position_code")] + public string agvPositionCode { get; set; } /// /// 库位编码 /// - [Column("location_code")] + [Column("location_code")] public string locationCode { get; set; } /// diff --git a/src/Khd.Core.Wcs/Khd.Core.Wcs.csproj b/src/Khd.Core.Wcs/Khd.Core.Wcs.csproj index 6ccdfe6..3887259 100644 --- a/src/Khd.Core.Wcs/Khd.Core.Wcs.csproj +++ b/src/Khd.Core.Wcs/Khd.Core.Wcs.csproj @@ -11,6 +11,7 @@ + diff --git a/src/Khd.Core.Wcs/Wcs/CreateTaskByRecord.cs b/src/Khd.Core.Wcs/Wcs/CreateTaskByRecord.cs index 830f9ff..113ccff 100644 --- a/src/Khd.Core.Wcs/Wcs/CreateTaskByRecord.cs +++ b/src/Khd.Core.Wcs/Wcs/CreateTaskByRecord.cs @@ -84,7 +84,10 @@ namespace Khd.Core.Wcs.Wcs { try { - CreateTask(); + //原料&辅料出库 + CreateRawTask(); + //成品&半成品出库 + CreateProductTask(); } catch (Exception ex) { @@ -96,37 +99,6 @@ namespace Khd.Core.Wcs.Wcs } } } - - private void CreateTask() - { - using var scope = _host.Services.CreateScope(); - using var dbContext = scope.ServiceProvider.GetRequiredService(); - - try - { - - //入库 - var rawInstock = dbContext.WmsProductInstock.Where(t => t.taskCode == "1").ToList(); - if (rawInstock.Count > 0) - { - foreach (var item in rawInstock) - { - } - - } - - //原料&辅料出库 - CreateMaterialTask(); - //成品&半成品出库 - CreateProductTask(); - } - catch (Exception ex) - { - //LogManager.Info($"错误日志输出 >>> OutWarePoint类 WriteMaterialMessage 方法报错 {ex}"); - LogManager.Error(ex); - } - - } /// /// 成品出库 /// @@ -182,28 +154,23 @@ namespace Khd.Core.Wcs.Wcs dbContext.Add(newTask); dbContext.SaveChanges(); } - //回写出库记录表 - //item.executeStatus = "1"; - //item.updateDate = DateTime.Now; - //dbContext.WmsProductOutstock.Update(item); - //dbContext.SaveChanges(); + //回写wms记录表 dbContext.WmsProductOutstock.Where(t => t.productOutstockId == item.productOutstockId).Update(t => new WmsProductOutstock() { executeStatus = "1", updateDate = DateTime.Now }); } - } - public void CreateMaterialTask() + public void CreateRawTask() { using var scope = _host.Services.CreateScope(); using var dbContext = scope.ServiceProvider.GetRequiredService(); - + //原材料库存 var rawStock = dbContext.WmsRawStock.Where(t => t.activeFlag == "0").ToList(); + //原材料出库记录 var rawOutStock = dbContext.WmsRawOutstock.Where(t => t.executeStatus == "0").ToList(); - foreach (var item in rawOutStock) { //自动获取id @@ -223,8 +190,7 @@ namespace Khd.Core.Wcs.Wcs createTime = DateTime.Now }; dbContext.Add(stockLock); - //var palletInfo = StaticData.MesBasePalletInfo.Where(t => t.materialId == item.productId).FirstOrDefault() ; - if (true)//辅料 + if (item.warehouseId==5)//五楼辅料出库 { //辅料出库时,需创建订单表数据 orderID = id.NextId(); @@ -239,11 +205,6 @@ namespace Khd.Core.Wcs.Wcs }; dbContext.Add(order); } - else - { - //半成品 - - } var dic = StaticData.BaseDictionary.Where(t => t.dicKey == "TaskType" && t.ud1 == "O").FirstOrDefault(); WcsTask rawTask = new() { @@ -264,16 +225,11 @@ namespace Khd.Core.Wcs.Wcs }; dbContext.Add(rawTask); - //获取最早入库时间 var firstDate = rawStock.Where(t => t.materialId == item.productId && t.warehouseId == item.warehouseId).OrderBy(t => t.createDate).FirstOrDefault(); var rkDate = firstDate.createDate; - //回写出库记录表 - //item.executeStatus = "1"; - //item.updateDate = DateTime.Now; - //dbContext.WmsProductOutstock.Update(item); - //dbContext.SaveChanges(); + //回写wms出库记录表 dbContext.WmsRawOutstock.Where(t => t.rawOutstockId == item.rawOutstockId).Update(t => new WmsProductOutstock() { executeStatus = "1", diff --git a/src/Khd.Core.Wcs/Wcs/SecondFloorAGV.cs b/src/Khd.Core.Wcs/Wcs/SecondFloorAGV.cs new file mode 100644 index 0000000..26a4c1d --- /dev/null +++ b/src/Khd.Core.Wcs/Wcs/SecondFloorAGV.cs @@ -0,0 +1,468 @@ +using Khd.Core.Domain.Dto.webapi; +using Khd.Core.Domain.Models; +using Khd.Core.EntityFramework; +using Khd.Core.Wcs.Global; +using Masuit.Tools.Logging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Z.EntityFramework.Plus; + +namespace Khd.Core.Wcs.Wcs +{ + /// + /// 二楼AGV调度 + /// + public class SecondFloorAGV + { + List ScanPoint { get; set; }//点位信息 + private readonly IHost _host; + private readonly Plc.S7.Plc _plc; + BasePlcpoint? LineRFID { get; set; } + BasePlcpoint? LineWcsrun { get; set; } + BasePlcpoint? LineSignal { get; set; } + BasePlcpoint? LineIsPallet { get; set; } + BasePlcpoint? LineSerialNO { get; set; } + BasePlcpoint? LineFeedSeriaNo { get; set; } + Thread FlowPointThread; + int FloorNo { get; set; } + string EquipNo = ""; + List taskInType = new List { 1, 3, 5, 7 }; + List taskOutType = new List { 2, 4, 6, 8 }; + public SecondFloorAGV(IHost host, Plc.S7.Plc plc, int floor, string equipNo) + { + this._host = host; + this._plc = plc; + FloorNo = floor; + EquipNo = equipNo; + this.ScanPoint = StaticData.BasePlcpointList.Where(t => t.floorNo == floor).ToList();//加载当前站点所对应的点位 + //this.LineRFID = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("RFID")); + //this.LineWcsrun = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("wcsrun")); + //this.LineSignal = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("linesignal")); + this.LineIsPallet = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("ispallet")); + //this.LineSerialNO = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("serialno")); + //this.LineFeedSeriaNo = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("feedserialno")); + + //var IsPallet = this._plc.Read(LineIsPallet.plcpointAddress); + try + { + //默认启动,清理plc的上位机写入点位值 + this._plc.Write(LineRFID.plcpointAddress, MainCentralControl.QingKongDianWei); + } + catch (Exception ex) + { + Console.WriteLine("楼层" + floor + " 初始化数据异常" + ex.Message); + LogManager.Error(ex); + } + } + /// + /// 启动上件扫描监听 + /// + public void StartPoint() + { + + FlowPointThread = new Thread(MonitorInLocatorPoint); + FlowPointThread.Start(); + } + + public void MonitorInLocatorPoint() + { + using var scope = _host.Services.CreateScope(); + using var dbContext = scope.ServiceProvider.GetRequiredService(); + List taskInType = new List { 1, 3, 5, 7 }; + List taskOutType = new List { 2, 4, 6, 8 }; + while (true) + { + try + { + var taskList = GetTask(FloorNo, EquipNo); + if (taskList.Count == 0) + { + LogManager.Info(FloorNo + "楼AGV无任务"); + } + foreach (var item in taskList) + { + if (taskInType.Contains(item.taskType.GetValueOrDefault()))//入库 + { + var loc = dbContext.WmsBaseLocation.Where(t => t.activeFlag == "1").ToList(); + + //2楼成品 + if (item.taskType == 5|| item.taskType==11 )//成品入库||成品移库 + { + var stock = dbContext.WmsProductStock.Where(t => t.activeFlag == "1").ToList(); + //获取有物料的库位 + var locStock = from l in loc + join s in stock on l.locationCode equals s.locationCode + select new + { + LocId = l.locationId, + locCode = l.locationCode, + LocDeep = l.locDeep, + productBatch = s.productBatch + }; + //获取空库位 + var nullLocList = loc.Where(r => !locStock.Select(t => t.locCode).Contains(r.locationCode) && r.warehouseId == 1).ToList(); + var location = nullLocList.OrderBy(t => t.locColumn).FirstOrDefault(); + + item.currPointId = 8; + item.currPointNo = "AGV01"; + item.nextPointId = location.locationId; + item.nextPointNo = location.locationCode; + //dbContext.Update(item); + } + //下发agv出库指令 + SendAndUpdateTask(item); + } + else + { + var locList = dbContext.WmsBaseLocation.Where(t => t.activeFlag == "1").ToList(); + //出库 + if (item.taskType == 6)//成品出库 + { + //获取库存 + var proStock = dbContext.WmsProductStock.Where(t => t.activeFlag == "1" && t.stockType == "3").ToList(); + + var dic = dbContext.BaseDictionary.Where(t => t.dicKey == "OutStockDate").FirstOrDefault(); + var DateRange = Convert.ToInt32(dic.dicValue); + var stockList = from t in proStock.Where(r => r.productId == item.materialId) + join b in locList on t.locationCode equals b.locationCode + into temp + from newStock in temp.DefaultIfEmpty() + select new + { + proID = t.productStockId, + locID = newStock.locationId, + locCode = t.locationCode, + layerNum = newStock.layerNum, + locColumn = newStock.locColumn, + locRow = newStock.locRow, + locDeep = newStock.locDeep, + inStockDate = newStock.createTime, + }; + //先查出最早入库时间 + var inStockModel = stockList.OrderBy(t => t.inStockDate).FirstOrDefault(); + var inStockDate = inStockModel.inStockDate; + //查出符合条件的成品 + var outStockList = stockList.Where(t => t.inStockDate >= inStockDate && t.inStockDate <= inStockDate.GetValueOrDefault().AddDays(DateRange)).ToList(); + var outModel = outStockList.OrderBy(t => t.locColumn).ThenByDescending(t => t.locDeep).FirstOrDefault(); + if (outModel.locDeep == 1) + { + //自动获取id + Jc.SnowId.JcSnowId id = new Jc.SnowId.JcSnowId(1, 1); + var objid = id.NextId(); + var isExiStock = stockList.Where(t=>t.locRow==outModel.locRow && t.locColumn==outModel.locColumn && t.locDeep ==2).FirstOrDefault(); + if (isExiStock != null) + { + //创建成品移库任务 + WcsTask newTask = new() + { + objid = objid, + taskType = 11, + containerNo = "", + taskStatus = 0, + materialId = isExiStock.locID, + qty = 1, + startPointId = isExiStock.locID, + startPointNo = "", + currPointId = isExiStock.locID, + currPointNo = "", + }; + dbContext.Add(newTask); + dbContext.SaveChanges(); + return; + } + } + //锁定库位 + dbContext.WmsBaseLocation.Where(t => t.locationCode == outModel.locCode).Update(t => new WmsBaseLocation() + { + locationStatus = "1", + updateTime = DateTime.Now, + updateBy = "agv出库", + }); + //下发agv出库指令 + SendAndUpdateTask(item); + } + } + } + } + catch (Exception ex) + { + LogManager.Error(ex); + } + finally + { + Thread.Sleep(1000); + } + } + } + + public List GetTask(int floorNo, string equipNo) + { + using var scope = _host.Services.CreateScope(); + using var dbContext = scope.ServiceProvider.GetRequiredService(); + List wcsTask = new List(); + var wareHouseList = StaticData.WmsBaseWarehouse.ToList(); + var equip = StaticData.BaseEquip.Where(t => t.floorNo == floorNo && t.equipType == 4).FirstOrDefault(); + try + { + //获取条码号,如果该条码任务存在就继续任务,如果条码不存在,创建入库任务并调度agv + var taskList = StaticData.WcsTask.Where(t => t.nextPointId == equip.objid && t.currPointId != equip.objid && (t.taskType==1|| t.taskType == 2|| t.taskType == 5 || t.taskType == 6)).ToList(); + if (taskList.Count() == 0) + { return null; } + wcsTask = taskList; + } + catch (Exception ex) + { + LogManager.Info(floorNo + "楼AGV异常" + ex.Message); + throw; + } + return wcsTask; + } + public void SendAndUpdateTask(WcsTask task) + { + //获取 + if (task == null) return; + using var scope = _host.Services.CreateScope(); + using var dbContext = scope.ServiceProvider.GetRequiredService(); + WcsToWms wcsToWms = new WcsToWms(); + //首先判断是否已下发指令 + var cmd = dbContext.WcsCmd.Where(t => t.taskId == task.objid).FirstOrDefault(); + var locList = dbContext.WmsBaseLocation.Where(t => t.activeFlag == "1").ToList(); + //指令表存在说明已下发 + if (cmd == null) + { //获取下发agv指令 + string ip = ""; int port = 0; string url = ""; + RequestAGVTaskDto agvtask = new RequestAGVTaskDto(); + agvtask.reqCode = task.objid.ToString(); + //var json = JsonConvert.SerializeObject(agvtask); + //HttpHelper.SendPostMessage(ip, port, url, json); + agvtask.positionCodePath = new List(); + Position p = new Position(); + WmsBaseLocation putPos = new WmsBaseLocation(); //放料点 + WmsBaseLocation setPos = new WmsBaseLocation(); //取料点 + if (task.taskType == 5) //入库 + { + setPos = locList.Where(t => t.locationId == task.nextPointId).FirstOrDefault(); + } + else + { + setPos = locList.Where(t => t.locationId == task.nextPointId).FirstOrDefault(); + } + putPos = locList.Where(t => t.locationId == task.nextPointId).FirstOrDefault(); + p.podCode = setPos.agvPositionCode; + p.podTyp = ""; + agvtask.positionCodePath.Add(p); + p.podCode = putPos.agvPositionCode; + p.podTyp = ""; + //取料点 + agvtask.positionCodePath.Add(p); + agvtask.taskTyp = ""; + //给agv创建任务 + wcsToWms.genAgvSchedulingTask(agvtask); + //未下发给agv下发指令 + WcsCmd taskCmd = new WcsCmd() + { + taskId = task.objid, + cmdType = task.taskType, + serialNo = task.serialNo, + equipmentNo = task.equipmentNo, + cmdStatus = 1, + createBy = FloorNo + "楼AGV", + createTime = DateTime.Now, + }; + dbContext.Add(taskCmd); + dbContext.SaveChanges(); + } + else + { + //获取接驳位是否有托盘 + var IsPallet = this._plc.Read(this.LineIsPallet.plcpointAddress); + if (cmd.sendFlag == 0) + { + if (taskInType.Contains(task.taskType.GetValueOrDefault()))//入库 + { + //入库时有托盘继续任务 + if (Convert.ToInt32(IsPallet) == 1) + { + continueTaskDto continueTask = new continueTaskDto(); + continueTask.taskCode = task.objid.ToString(); + wcsToWms.continueTask(continueTask); + //未下发给agv下发指令 + WcsCmd taskCmd = new WcsCmd() + { + taskId = task.objid, + sendFlag = 1, + createBy = FloorNo + "楼AGV", + createTime = DateTime.Now, + }; + dbContext.Update(taskCmd); + dbContext.SaveChanges(); + } + } + else + { + //出库时没有托盘继续任务 + if (Convert.ToInt32(IsPallet) == 0) + { + continueTaskDto continueTask = new continueTaskDto(); + continueTask.taskCode = task.objid.ToString(); + wcsToWms.continueTask(continueTask); + //更新任务 + dbContext.WcsCmd.Where(t => t.taskId == task.objid).Update(t => new WcsCmd() + { + sendFlag = 1, + updateTime = DateTime.Now, + updateBy = "agv出库", + }); + } + } + } + } + //更新任务表 + dbContext.WcsTask.Where(t => t.objid == task.objid).Update(t => new WcsTask() + { + currPointId = task.currPointId, + currPointNo = task.currPointNo, + nextPointId = task.nextPointId, + nextPointNo= task.nextPointNo, + updateTime = DateTime.Now, + updateBy = "agv出库", + }) ; + } + ///// + ///// 下发任务 + ///// + ///// + //public void SendTask1(WcsTask task) + //{ + // using var scope = _host.Services.CreateScope(); + // using var dbContext = scope.ServiceProvider.GetRequiredService(); + // //入库类型 + // //List taskInType = new List { 1, 3, 5, 7 }; + // //List taskOutType = new List { 2, 4, 6, 8 }; + // //获取 + // if (task == null) return; + // if (taskInType.Contains(task.taskType.GetValueOrDefault()))//入库 + // { + // WcsToWms wcsToWms = new WcsToWms(); + // //首先判断是否已下发指令 + // var cmd = StaticData.WcsCmd.Where(t => t.taskId == task.objid).FirstOrDefault(); + // //指令表存在说明已下发 + // if (cmd == null) + // { //获取下发agv指令 + // string ip = ""; int port = 0; string url = ""; + // RequestAGVTaskDto agvtask = new RequestAGVTaskDto(); + // agvtask.reqCode = task.serialNo.ToString(); + // //var json = JsonConvert.SerializeObject(agvtask); + // //HttpHelper.SendPostMessage(ip, port, url, json); + // wcsToWms.genAgvSchedulingTask(agvtask); + // //未下发给agv下发指令 + // WcsCmd taskCmd = new WcsCmd() + // { + // taskId = task.objid, + // cmdType = task.taskType, + // serialNo = task.serialNo, + // equipmentNo = task.equipmentNo, + // cmdStatus = 1, + // createBy = FloorNo + "楼AGV", + // createTime = DateTime.Now, + // }; + // dbContext.Add(taskCmd); + // dbContext.SaveChanges(); + // } + // else + // { + + // var IsPallet = this._plc.Read(this.LineIsPallet.plcpointAddress); + // if (cmd.sendFlag == 0) + // { + // if (Convert.ToInt32(IsPallet) == 1) + // { + + // continueTaskDto continueTask = new continueTaskDto(); + // continueTask.taskCode = task.objid.ToString(); + // wcsToWms.continueTask(continueTask); + // //未下发给agv下发指令 + // WcsCmd taskCmd = new WcsCmd() + // { + // taskId = task.objid, + // cmdType = task.taskType, + // serialNo = task.serialNo, + // equipmentNo = task.equipmentNo, + // sendFlag = 1, + // createBy = FloorNo + "楼AGV", + // createTime = DateTime.Now, + // }; + // dbContext.Update(taskCmd); + // dbContext.SaveChanges(); + + // } + // } + // } + + // } + // else + // { + // var locList = dbContext.WmsBaseLocation.Where(t => t.activeFlag == "1").ToList(); + // //出库 + // if (task.taskType == 6)//成品出库 + // { + // //获取库存 + // var proStock = dbContext.WmsProductStock.Where(t => t.activeFlag == "1" && t.stockType == "3" && t.productId == task.materialId).ToList(); + + // var dic = dbContext.BaseDictionary.Where(t => t.dicKey == "OutStockDate").FirstOrDefault(); + // var DateRange = Convert.ToInt32(dic.dicValue); + // var stockList = from t in proStock + // join b in locList on t.locationCode equals b.locationCode + // into temp + // from newStock in temp.DefaultIfEmpty() + // select new + // { + // proID = t.productStockId, + // locID = newStock.locationId, + // locCode = t.locationCode, + // layerNum = newStock.layerNum, + // locColumn = newStock.locColumn, + // locRow = newStock.locRow, + // locDeep = newStock.locDeep, + // inStockDate = newStock.createTime, + // }; + // //先查出最早入库时间 + // var inStockModel = stockList.OrderBy(t => t.inStockDate).FirstOrDefault(); + // var inStockDate = inStockModel.inStockDate; + // //查出符合条件的成品 + // var outStockList = stockList.Where(t => t.inStockDate >= inStockDate && t.inStockDate <= inStockDate.GetValueOrDefault().AddDays(DateRange)).ToList(); + // var outModel = outStockList.OrderBy(t => t.locColumn).ThenByDescending(t => t.locDeep).FirstOrDefault(); + + + // dbContext.WmsBaseLocation.Where(t => t.locationCode == outModel.locCode).Update(t => new WmsBaseLocation() + // { + // locationStatus = "1", + // updateTime = DateTime.Now, + // updateBy = "agv出库", + // }); + + // dbContext.WcsTask.Where(t => t.objid == task.objid).Update(t => new WcsTask() + // { + // currPointId = outModel.locID, + // currPointNo = outModel.locCode, + // updateTime = DateTime.Now, + // updateBy = "agv出库", + // }); + // //下发agv出库指令 + + + // } + // else if (task.taskType == 2)//原材料出库 + // { + + // } + // } + //} + } +} diff --git a/src/Khd.Core.Wcs/Wcs/SecondFloorLine.cs b/src/Khd.Core.Wcs/Wcs/SecondFloorLine.cs new file mode 100644 index 0000000..02ca2ee --- /dev/null +++ b/src/Khd.Core.Wcs/Wcs/SecondFloorLine.cs @@ -0,0 +1,233 @@ +using Khd.Core.Domain.Dto.webapi; +using Khd.Core.Domain.Models; +using Khd.Core.EntityFramework; +using Khd.Core.Wcs.Global; +using Masuit.Tools.Logging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Z.EntityFramework.Plus; + +namespace Khd.Core.Wcs.Wcs +{ + /// + /// 二楼码垛输送线调度 + /// + public class SecondFloorPoint + { + List ScanPoint { get; set; }//点位信息 + private readonly IHost _host; + private readonly Plc.S7.Plc _plc; + BasePlcpoint? LineRFID { get; set; } + BasePlcpoint? LineWcsrun { get; set; } + BasePlcpoint? LineSignal { get; set; } + BasePlcpoint? LineIsPallet { get; set; } + BasePlcpoint? LineSerialNO { get; set; } + BasePlcpoint? LineFeedSeriaNo { get; set; } + Thread FlowPointThread; + int FloorNo { get; set; } + string EquipNo = ""; + public SecondFloorPoint(IHost host, Plc.S7.Plc plc, int floor, string equipNo) + { + this._host = host; + this._plc = plc; + FloorNo = floor; + EquipNo = equipNo; + this.ScanPoint = StaticData.BasePlcpointList.Where(t => t.floorNo == floor).ToList();//加载当前站点所对应的点位 + this.LineRFID = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("RFID")); + this.LineWcsrun = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("wcsrun")); + this.LineSignal = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("linesignal")); + this.LineIsPallet = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("ispallet")); + this.LineSerialNO = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("serialno")); + this.LineFeedSeriaNo = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("feedserialno")); + + //var lineRFID = this._plc.Read(NodeSettingCarNo.plcpointAddress); + try + { + //默认启动,清理plc的上位机写入点位值 + this._plc.Write(LineRFID.plcpointAddress, MainCentralControl.QingKongDianWei); + } + catch (Exception ex) + { + Console.WriteLine("楼层" + floor + " 初始化数据异常" + ex.Message); + LogManager.Error(ex); + } + } + /// + /// 启动上件扫描监听 + /// + public void StartPoint() + { + + FlowPointThread = new Thread(MonitorInLocatorPoint); + FlowPointThread.Start(); + } + + public void MonitorInLocatorPoint() + { + using var scope = _host.Services.CreateScope(); + using var dbContext = scope.ServiceProvider.GetRequiredService(); + while (true) + { + try + { + //入库任务 + var rfid = this._plc.Read(LineRFID.plcpointAddress); + var isSignal = this._plc.Read(LineSignal.plcpointAddress); //到位信号 + var isPallet = this._plc.Read(LineIsPallet.plcpointAddress);//是否有托盘 + if (rfid != null && isSignal != null && isPallet != null) + { + //正常读到输送线信息 有到位信号,并且有托盘,获取条码信息 + if (Convert.ToInt32(isSignal) > 0 && Convert.ToInt32(isPallet) == 1) + { + //获取条码信息 + var palletNo = Convert.ToString(rfid); + //获取入库任务 + var wcsTask = GetTask(palletNo, FloorNo, EquipNo); + //判断是否为出库任务 + if ( wcsTask.taskType == 5) + { + var nextEquip = StaticData.BaseEquip.Where(t=>t.floorNo==FloorNo && t.equipType==4).FirstOrDefault(); + //更新任务下一点位为AGV + wcsTask.nextPointId = nextEquip.objid; + wcsTask.nextPointNo = nextEquip.equipNo; + wcsTask.updateTime = DateTime.Now; + wcsTask.updateBy = FloorNo+"楼输送线"; + dbContext.Update(wcsTask); + dbContext.SaveChanges(); + ////入库任务 + ////下发agv任务 + //SendTask(wcsTask); + } + } + } + } + catch (Exception ex) + { + LogManager.Error(ex); + } + finally + { + Thread.Sleep(1000); + } + } + } + //获取输送线上的任务 + public WcsTask GetTask(string containerNo, int floorNo, string equipNo) + { + using var scope = _host.Services.CreateScope(); + using var dbContext = scope.ServiceProvider.GetRequiredService(); + var wcsTask = new WcsTask(); + var wareHouseList = StaticData.WmsBaseWarehouse.ToList(); + try + { + //获取条码号,如果该条码任务存在就继续任务,如果条码不存在,创建入库任务并调度agv + var task = StaticData.WcsTask.Where(t => t.containerNo == containerNo).FirstOrDefault(); + if (task == null) + { + var palletInfo = StaticData.MesBasePalletInfo.Where(t => t.palletInfoCode == containerNo).FirstOrDefault(); + //查询该条码绑定的物料信息 + var material = StaticData.WmsWarehouseMaterial.Where(t => t.storageId == palletInfo.materialId).FirstOrDefault(); + var wareHouse = wareHouseList.Where(t => t.warehouseId == material.warehouseId).FirstOrDefault(); + var dic = StaticData.BaseDictionary.Where(t => t.dicKey == "TaskType" && t.ud1 == "I" && t.dicField == wareHouse.warehouseInstockType).FirstOrDefault(); + var equip = StaticData.BaseEquip.ToList(); + var startEquip = equip.Where(t => t.equipNo == equipNo).FirstOrDefault(); + var endPoint = wareHouseList.Where(t => t.warehouseFloor == floorNo).FirstOrDefault(); + //var currEquip= + if (palletInfo != null) + { + //自动获取id + Jc.SnowId.JcSnowId id = new Jc.SnowId.JcSnowId(1, 1); + var objid = id.NextId(); + WcsTask newTask = new() + { + objid = objid, + taskType = Convert.ToInt32(dic.dicValue), + containerNo = containerNo, + taskStatus = 0, + materialId = material.storageId, + qty = Convert.ToInt32(palletInfo.bindAmount), + startPointId = startEquip.objid, + startPointNo = equipNo, + currPointId = startEquip.objid, + currPointNo = equipNo, + endPointId = endPoint.warehouseId, + endPointNo = endPoint.warehouseCode, + }; + dbContext.Add(newTask); + dbContext.SaveChanges(); + + wcsTask = newTask; + } + else + { + LogManager.Info(floorNo + "楼接驳位,托盘"+ containerNo + "未绑定!" ); + } + } + else + { + wcsTask = StaticData.WcsTask.Where(t => t.currPointNo == equipNo).FirstOrDefault(); + } + } + catch (Exception ex) + { + LogManager.Info(floorNo + "楼接驳位异常"+ ex.Message); + throw; + } + return wcsTask; + } + /// + /// 下发任务 + /// + /// + public void SendTask(WcsTask task) + { + using var scope = _host.Services.CreateScope(); + using var dbContext = scope.ServiceProvider.GetRequiredService(); + //入库类型 + List taskInType = new List { 1, 3, 5, 7 }; + List taskOutType = new List { 2, 4, 6, 8 }; + try + { + //获取 + if (task == null) return; + if (taskInType.Contains(task.taskType.GetValueOrDefault())) + { + //首先判断是否已下发指令 + var cmd = StaticData.WcsCmd.Where(t => t.taskId == task.objid).FirstOrDefault(); + //指令表存在说明已下发 + if (cmd != null) return; + //获取下发agv指令 + string ip = ""; int port = 0; string url = ""; + RequestAGVTaskDto agvtask = new RequestAGVTaskDto(); + agvtask.reqCode = task.serialNo.ToString(); + var json = JsonConvert.SerializeObject(agvtask); + HttpHelper.SendPostMessage(ip, port, url, json); + //未下发给agv下发指令 + WcsCmd taskCmd = new WcsCmd() + { + taskId = task.objid, + cmdType = task.taskType, + serialNo = task.serialNo, + equipmentNo = task.equipmentNo, + cmdStatus = 1, + createBy = "", + createTime = DateTime.Now, + }; + dbContext.Add(taskCmd); + dbContext.SaveChanges(); + } + } + catch (Exception) + { + + throw; + } + } + } +} diff --git a/src/Khd.Core.Wcs/Wcs/SecondFloorPoint.cs b/src/Khd.Core.Wcs/Wcs/SecondFloorPoint.cs new file mode 100644 index 0000000..b9c09c8 --- /dev/null +++ b/src/Khd.Core.Wcs/Wcs/SecondFloorPoint.cs @@ -0,0 +1,149 @@ +using Khd.Core.Domain.Dto.webapi; +using Khd.Core.Domain.Models; +using Khd.Core.EntityFramework; +using Khd.Core.Wcs.Global; +using Masuit.Tools.Logging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Z.EntityFramework.Plus; + +namespace Khd.Core.Wcs.Wcs +{ + /// + /// 二楼接驳位调度 + /// + public class SecondFloorLine + { + List ScanPoint { get; set; }//点位信息 + private readonly IHost _host; + private readonly Plc.S7.Plc _plc; + BasePlcpoint? LineRFID { get; set; } + BasePlcpoint? LineWcsrun { get; set; } + BasePlcpoint? LineSignal { get; set; } + BasePlcpoint? LineIsPallet { get; set; } + BasePlcpoint? LineSerialNO { get; set; } + BasePlcpoint? LineFeedSeriaNo { get; set; } + Thread FlowPointThread; + int FloorNo { get; set; } + string EquipNo = ""; + public SecondFloorLine(IHost host, Plc.S7.Plc plc, int floor, string equipNo) + { + this._host = host; + this._plc = plc; + FloorNo = floor; + EquipNo = equipNo; + this.ScanPoint = StaticData.BasePlcpointList.Where(t => t.floorNo == floor).ToList();//加载当前站点所对应的点位 + this.LineRFID = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("RFID")); + this.LineWcsrun = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("wcsrun")); + this.LineSignal = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("linesignal")); + this.LineIsPallet = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("ispallet")); + this.LineSerialNO = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("serialno")); + this.LineFeedSeriaNo = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("feedserialno")); + + //var lineRFID = this._plc.Read(NodeSettingCarNo.plcpointAddress); + try + { + //默认启动,清理plc的上位机写入点位值 + this._plc.Write(LineRFID.plcpointAddress, MainCentralControl.QingKongDianWei); + } + catch (Exception ex) + { + Console.WriteLine("楼层" + floor + " 初始化数据异常" + ex.Message); + LogManager.Error(ex); + } + } + /// + /// 启动上件扫描监听 + /// + public void StartPoint() + { + + FlowPointThread = new Thread(MonitorInLocatorPoint); + FlowPointThread.Start(); + } + + public void MonitorInLocatorPoint() + { + using var scope = _host.Services.CreateScope(); + using var dbContext = scope.ServiceProvider.GetRequiredService(); + while (true) + { + try + { + //入库任务 + var rfid = this._plc.Read(LineRFID.plcpointAddress); + var isSignal = this._plc.Read(LineSignal.plcpointAddress); + var isPallet = this._plc.Read(LineIsPallet.plcpointAddress); + if (rfid != null && isSignal != null && isPallet != null) + { + //正常读到输送线信息 有到位信号,并且有托盘,获取条码信息 + if (Convert.ToInt32(isSignal) > 0 && Convert.ToInt32(isPallet) == 1) + { + //获取条码信息 + var palletNo = Convert.ToString(rfid); + //获取入库任务 + var wcsTask = GetTask(palletNo, FloorNo, EquipNo); + //判断是否为出库任务 + if (wcsTask.taskType == 3) + { + this._plc.Write(LineWcsrun.plcpointAddress, 1); + //更新任务 + dbContext.WcsTask.Where(t => t.objid == wcsTask.objid).Update(t => new WcsTask() + { + currPointId = 2, + currPointNo = "F02", + //提升机 + nextPointId = 6, + nextPointNo = "T01", + updateTime = DateTime.Now, + updateBy = "二楼接驳位", + }); + } + } + } + } + catch (Exception ex) + { + LogManager.Error(ex); + } + finally + { + Thread.Sleep(1000); + } + } + } + //获取输送线上的任务 + public WcsTask GetTask(string containerNo, int floorNo, string equipNo) + { + using var scope = _host.Services.CreateScope(); + using var dbContext = scope.ServiceProvider.GetRequiredService(); + var wcsTask = new WcsTask(); + var wareHouseList = StaticData.WmsBaseWarehouse.ToList(); + try + { + //获取条码号,如果该条码任务存在就继续任务,如果条码不存在,创建入库任务并调度agv + var task = StaticData.WcsTask.Where(t => t.containerNo == containerNo).FirstOrDefault(); + if (task == null) + { + wcsTask = task; + } + else + { + wcsTask = StaticData.WcsTask.Where(t => t.currPointNo == equipNo).FirstOrDefault(); + } + } + catch (Exception ex) + { + LogManager.Info(floorNo + "楼接驳位异常" + ex.Message); + throw; + } + return wcsTask; + } + } +} diff --git a/src/Khd.Core.Wcs/Wcs/SecondThirdFloorAGV.cs b/src/Khd.Core.Wcs/Wcs/ThirdFloorAGV.cs similarity index 99% rename from src/Khd.Core.Wcs/Wcs/SecondThirdFloorAGV.cs rename to src/Khd.Core.Wcs/Wcs/ThirdFloorAGV.cs index 4dd1c08..18e5c0d 100644 --- a/src/Khd.Core.Wcs/Wcs/SecondThirdFloorAGV.cs +++ b/src/Khd.Core.Wcs/Wcs/ThirdFloorAGV.cs @@ -16,9 +16,9 @@ using Z.EntityFramework.Plus; namespace Khd.Core.Wcs.Wcs { /// - /// 二楼调度 + /// 三楼agv调度 /// - public class SecondThirdFloorAGV + public class ThirdFloorAGV { List ScanPoint { get; set; }//点位信息 private readonly IHost _host; @@ -34,7 +34,7 @@ namespace Khd.Core.Wcs.Wcs string EquipNo = ""; List taskInType = new List { 1, 3, 5, 7 }; List taskOutType = new List { 2, 4, 6, 8 }; - public SecondThirdFloorAGV(IHost host, Plc.S7.Plc plc, int floor, string equipNo) + public ThirdFloorAGV(IHost host, Plc.S7.Plc plc, int floor, string equipNo) { this._host = host; this._plc = plc; diff --git a/src/Khd.Core.Wcs/Wcs/SecondThirdFloorPoint.cs b/src/Khd.Core.Wcs/Wcs/ThirdFloorPoint.cs similarity index 98% rename from src/Khd.Core.Wcs/Wcs/SecondThirdFloorPoint.cs rename to src/Khd.Core.Wcs/Wcs/ThirdFloorPoint.cs index 8f36d30..4bbb4b2 100644 --- a/src/Khd.Core.Wcs/Wcs/SecondThirdFloorPoint.cs +++ b/src/Khd.Core.Wcs/Wcs/ThirdFloorPoint.cs @@ -15,9 +15,9 @@ using System.Threading.Tasks; namespace Khd.Core.Wcs.Wcs { /// - /// 二楼调度 + /// 三楼接驳位调度 /// - public class SecondThirdFloorPoint + public class ThirdFloorPoint { List ScanPoint { get; set; }//点位信息 private readonly IHost _host; @@ -31,7 +31,7 @@ namespace Khd.Core.Wcs.Wcs Thread FlowPointThread; int FloorNo { get; set; } string EquipNo = ""; - public SecondThirdFloorPoint(IHost host, Plc.S7.Plc plc, int floor, string equipNo) + public ThirdFloorPoint(IHost host, Plc.S7.Plc plc, int floor, string equipNo) { this._host = host; this._plc = plc;