using AngleSharp.Dom; using Khd.Core.Domain.Dto.wcs; 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 Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Khd.Core.Domain.Dto.webapi; using Khd.Core.Plc.S7; using Khd.Core.Wcs.Wcs; using System.Data; using Microsoft.EntityFrameworkCore; using Z.EntityFramework.Plus; namespace Khd.Core.Wcs.Wcs { /// /// 流转点线程 /// public class FlowPoint { private readonly IHost _host; private readonly Plc.S7.Plc _plc; List ScanPoint { get; set; }//点位信息 BaseSitenode? sitenode { get; set; }//站台信息 NodeSetting? NodeSettingCarNo { get; set; } NodeSetting? NodeSettingCarState { get; set; } NodeSetting? NodeSettingCarRun { get; set; } NodeSetting? NodeSettingWcsState { get; set; } NodeSetting? NodeSettingWcsSend { get; set; } Thread FlowPointThread; public FlowPoint(IHost host, Plc.S7.Plc plc, string siteNo) { this._host = host; this._plc = plc; this.ScanPoint = StaticData.NodeSettingList.Where(t => t.siteNo == siteNo).ToList();//加载当前站点所对应的点位 this.sitenode = StaticData.SiteNodeList.FirstOrDefault(t => t.siteNo == siteNo);//获取当前站台信息 this.NodeSettingCarNo = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("carno")); this.NodeSettingCarState = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("carstate")); this.NodeSettingCarRun = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("carrun")); this.NodeSettingWcsState = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("plcsendK")); this.NodeSettingWcsSend = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("wcsend")); try { //默认启动,清理plc的上位机写入点位值 this._plc.Write(NodeSettingCarRun.plcpointAddress, MainCentralControl.QingKongDianWei); this._plc.Write(NodeSettingWcsSend.plcpointAddress, MainCentralControl.QingKongDianWei); } catch (Exception ex) { Console.WriteLine("站点" + siteNo + " 初始化数据异常" + ex.Message); LogManager.Error(ex); } } /// /// 启动上件扫描监听 /// public void StartPoint() { FlowPointThread = new Thread(MonitorInLocatorPoint); FlowPointThread.Start(); } public void MonitorInLocatorPoint() { while (true) { try { //通用逻辑下,根据上件记录表,可区分业务,入库,出库,回库 //- 入库 - 根据小车任务表,可区分流入哪个站点 //- 出库 - 根据小车任务表,可区分流入哪个站点 //- 回库 - 根据小车任务表,可区分流入哪个站点 //- 特殊逻辑:下一站点多个站点,按多条线缓存数优先进少的; var carno = this._plc.Read(NodeSettingCarNo.plcpointAddress); var carstate = this._plc.Read(NodeSettingCarState.plcpointAddress); var carrun = this._plc.Read(NodeSettingCarRun.plcpointAddress); var wcsstate = this._plc.Read(NodeSettingWcsState.plcpointAddress); var wcsend = this._plc.Read(NodeSettingWcsSend.plcpointAddress); if (carno != null && carstate != null && carrun != null && wcsstate != null && wcsend != null) { //清除点位信息 if (Convert.ToInt32(carno) == 0 && Convert.ToInt32(wcsend) == 1 && Convert.ToInt32(wcsstate) == 1) { if (this.sitenode.siteNo == "K48") { continue; } this._plc.Write(NodeSettingCarRun.plcpointAddress, MainCentralControl.QingKongDianWei); //清空小车去向点位 this._plc.Write(NodeSettingWcsSend.plcpointAddress, MainCentralControl.QingKongDianWei); //清空wcs处理完成点位 } //正常读到小车信息 if (Convert.ToInt32(carno) > 0 && Convert.ToInt32(wcsend) == 0 && Convert.ToInt32(wcsstate) == 0 && Convert.ToInt32(carstate) == 1 && Convert.ToInt32(carrun) == 0) { var carRun = GetTargetTo(this.sitenode.siteNo, Convert.ToInt32(carno)); if (string.IsNullOrEmpty(carRun)) { if (this.sitenode.siteNo =="K48") { continue; } Console.WriteLine($" FlowPoint类GetTargetTo方法去向返回{carRun},查看错误日志内容!"); Thread.Sleep(1000); continue; } var ToInt16carRun = MainCentralControl.getValue("2", carRun); this._plc.Write(this.NodeSettingCarRun.plcpointAddress, ToInt16carRun);//写入小车去向 this._plc.Write(this.NodeSettingWcsSend.plcpointAddress, MainCentralControl.WcsChuLiWanCheng);//写入wcs处理完成 LogManager.Info($"当前时间{DateTime.Now} >>> 挂具:{carno}经过站点:{this.sitenode.siteNo},WCS写入去向:{ToInt16carRun};"); } } } catch (Exception ex) { LogManager.Error(ex); } finally { Thread.Sleep(1000); } } } /// /// 根据上件点,物料号,获取下一点位信息 /// /// 交互所属站点 /// 到位挂具号码 /// 1:给予PLC去向方法 2:\给予PLC物料信息方法 /// public string GetTargetTo(string siteNo, int carno) { try { using var scope = _host.Services.CreateScope(); using var dbContext = scope.ServiceProvider.GetRequiredService(); if (siteNo == "K22") { var car_material = GetCarMessage(2, carno); var flag = GetFlag(1, "UpState"); if (!string.IsNullOrWhiteSpace(car_material) && (flag == "2" || flag == "1"))//挂具携带物料且上件点闸口正常时逻辑处理 { var CarRun = GetCarMessage(1, carno); return CarRun; } else if (string.IsNullOrWhiteSpace(car_material) && flag == "1")//挂具为空且上件点闸口维护损坏时逻辑处理 { var CarRun = GetFlag(2, "UpState"); return CarRun; } else if (string.IsNullOrWhiteSpace(car_material) && flag == "2")//空挂具走直通发往一线 { #region 代码注释折叠 //var BaseProductionOrderSplitModelXB1 = dbContext.BaseProductionOrderSplit.Where(t => t.lineCode.Contains("01")).ToList(); //var BaseProductionOrderSplitModelXB2 = dbContext.BaseProductionOrderSplit.Where(t => t.lineCode.Contains("02")).ToList(); //int xianbie1shuliang = BaseProductionOrderSplitModelXB1.Count;//线别01的数量 //int xianbie2shuliang = BaseProductionOrderSplitModelXB2.Count;//线别02的数量 //if (xianbie1shuliang == 0) //{ // return "1"; //} //if (xianbie2shuliang == 0) //{ // return "2"; //} //if (xianbie1shuliang != 0 && xianbie2shuliang != 0)//一线二线同时存在订单时 //{ // if (xianbie1shuliang < xianbie2shuliang) // { // return "1"; // } // else if (xianbie1shuliang > xianbie2shuliang) // { // return "2"; // } // else//一二线订单数量相等时 // { // return "2"; // } //} #endregion return "1"; } else if (car_material == null || flag == null)//某个字段逻辑处理出错后日志输入结果 { //if (string.IsNullOrWhiteSpace(car_material)) LogManager.Info($"错误日志输出 >>> 未查找到车辆与订单的绑定信息!"); //if (string.IsNullOrWhiteSpace(flag)) LogManager.Info($"错误日志输出 >>> 未查找到上件闸口状态信息!"); return null; } } else if (siteNo == "K18") { dbContext.BaseWaitdownline.Where(t => t.carNo == carno).Update(a => new BaseWaitdownline() { downline = 0 }); //修改车辆状态为未上线 (修改downline字段等于0) //flag == 2 上件点闸口正常时写弯通2,挂具返回上件点, //flag == 1上件点闸口人工维护损坏时写直通1,挂具返回K22流转点; var flag = GetFlag(1, "UpState"); return flag; } else if (siteNo == "K48") //如果是K46发过来的带件车辆逻辑处理 { var shifodaijian = GetCarMessage(2, carno); if (!string.IsNullOrWhiteSpace(shifodaijian)) { return "2"; } else { return ""; } } LogManager.Info("错误日志输出 >>> FlowPoint类GetTargetTo方法未确认返回值,从底部返回NULL!"); return null; /// /// 联查base_waitdownline 与 base_production_order_split,截取线别字段确定挂具在K22交互点去向 /// /// bianbie = 1 查找任务中的线别字段, bianbie = 2 查找车辆、Vin信息 /// 挂具号 /// string GetCarMessage(int bianbie, int CarNo) { var listWaitDownLine = dbContext.BaseWaitdownline.Where(t => t.isDelete == 0 && t.carNo == CarNo).ToList(); var listOrder = dbContext.BaseProductionOrderSplit.Where(t => t.isover == 0).ToList(); var resultList = (from waitdownline in listWaitDownLine join order in listOrder on waitdownline.materielNo equals order.orderCode select new BaseProductionOrderSplit { id = order.id, lineCode = order.lineCode, orderCode = order.orderCode }).ToList(); if (resultList?.Count > 0) { if (bianbie == 1) { string XianBie = resultList[0].lineCode; char lastChar = XianBie[XianBie.Length - 1]; var num = Char.GetNumericValue(lastChar).ToString(); //string qx = num == "1" ? "2" : "1"; return num; } else { var vin = resultList[0].orderCode; return vin; } } else { return null; } } /// /// K18流转点去向控制(上件点损坏时不返回上件) /// /// 查找字段辨别 1为查找闸口是否维护损坏, 2 为损坏时查找K22人工设定走向 /// 闸口名称 /// string GetFlag(int bianbie, string FlagName) { using var scope = _host.Services.CreateScope(); using var dbContext = scope.ServiceProvider.GetRequiredService(); var baseflag = dbContext.BaseAmima.Where(t => t.name == FlagName).ToList(); if (baseflag?.Count > 0) { if (bianbie == 1) { var flag = baseflag[0].password == "2" ? "2" : "1"; return flag;//返回上件损坏闸口值 } else { var flag = baseflag[0].direction.ToString() == "1" ? "1" : "2"; return flag;//返回上件损坏闸口值后维护K22去向 } } return null; } } catch (Exception ex) { LogManager.Info($"GetTargetTo 方法报错 >>> {ex.Message}"); return null; } } } }