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 System; using System.Collections.Generic; using System.Linq; using System.Security.Policy; using System.Text; using System.Threading.Tasks; using Thrift.Server; using Thrift.Transport; using ThriftService; using static AngleSharp.Css.Values.CssRadialGradientValue; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Thrift.Protocol; using System.Security.Cryptography.Xml; using Z.EntityFramework.Plus; using System.Net.NetworkInformation; namespace Khd.Core.Wcs.Wcs { /// /// 上件点线程 /// public class UpLine : WcsServer { 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; } NodeSetting? NodeSettingWcsSendMaterial { get; set; } NodeSetting? NodeSettingPLCSendSendMaterialstate { get; set; } public UpLine(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")); this.NodeSettingWcsSendMaterial = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("wcssendmessage")); this.NodeSettingPLCSendSendMaterialstate = this.ScanPoint.FirstOrDefault(t => t.plcpointNo.Contains("plcsendmessage")); try { //默认启动,清理plc的上位机写入点位值 this._plc.Write(NodeSettingCarRun.plcpointAddress, MainCentralControl.QingKongDianWei); this._plc.Write(NodeSettingWcsSend.plcpointAddress, MainCentralControl.QingKongDianWei); this._plc.Write(NodeSettingWcsSendMaterial.plcpointAddress, MainCentralControl.QingKongDianWei); } catch (Exception ex) { Console.WriteLine("站点" + siteNo + " 初始化数据异常" + ex.Message); LogManager.Error(ex); } } /// /// 启动线程 /// public void StartPoint() { Thread TestThread1 = new Thread(new ParameterizedThreadStart(StartScanThrift)); TestThread1.IsBackground = true; TestThread1.Start(this.sitenode); Thread TestThread2 = new Thread(new ParameterizedThreadStart(StartSendCarThrift)); TestThread2.IsBackground = true; TestThread2.Start(this.sitenode); Thread TestThread3 = new Thread(ClearSendCar); TestThread3.IsBackground = true; TestThread3.Start(); } /// /// 启动推送车辆到位队列 /// private void StartScanThrift(object NodeSettingModel) { var sitenodemodel = NodeSettingModel as BaseSitenode; int TSpoint = Convert.ToInt32(sitenodemodel.thriftPort); string IpAddress = sitenodemodel.siteIpaddress; TTransport transport = new TSocket(IpAddress, TSpoint); while (true) { try { //启动thrift 推送服务 //推送车辆到位情况 transport.Open(); TProtocol protocol = new TBinaryProtocol(transport); WcsThrift.Client client = new WcsThrift.Client(protocol); client.hello(ReceiveCarNo("")); } catch (Exception ex) { LogManager.Info($"wcs上件控制类推送车辆到位信息Thrift方法报错 >>> {ex.Message}"); } finally { transport.Close(); Thread.Sleep(1000); } } } /// /// 启动小车扫描监听队列 /// private void StartSendCarThrift(object NodeSettingModel) { SendCar(null, null, null); var sitenodemodel = NodeSettingModel as BaseSitenode; int JSport = Convert.ToInt32(sitenodemodel.siteServerport); while (true) { try { //启动thrift接收服务 //接收挂具与Vin物料信息,上件绑定信息 WcsServer wcsServer = new WcsServer(); wcsServer.SendCarEvent += SendCar; WcsThrift.Processor processor = new WcsThrift.Processor(wcsServer); TServerTransport serverTransport = new TServerSocket(JSport); TServer server = new TSimpleServer(processor, serverTransport); Console.WriteLine($"站点:{this.sitenode.siteNo},当前时间:{DateTime.Now},接收客户端发车方法启动.. "); server.Serve(); } catch (Exception ex) { LogManager.Info($"wcs上件控制类控制发车Thrift方法报错 >>> {ex.Message}"); } finally { Thread.Sleep(1000); } } } /// /// 发车 /// /// /// /// /// public string SendCar(List carlist, string order_code, string amount) { #region 测试屏蔽 //Console.WriteLine($"服务端发车触发 >>> carlist[0]:{carlist.FirstOrDefault()},vin条码:{order_code},车辆长度:{amount}"); //return "11"; #endregion //通用逻辑:(1 是否空车 2 物料号 3 上件数量) // 通用逻辑下,下一站点固定(配置) // -判断小车是否到位,小车已下发去向,清空下发数据信息 // - 判断 小车是否到位,小车未下发去向 // - 进库区判断: 库存是否满; // -特殊逻辑:下一站点多个站点,按多条线缓存数优先进少的;按物料 + 属性区分进哪个站点,可配置 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) == 0 && Convert.ToInt32(wcsstate) == 0 && Convert.ToInt32(carstate) == 1 && Convert.ToInt32(carrun) == 0) { //根据上件点,物料号,获取下一点位信息 var TargetTo = GetTargetTo(Convert.ToInt32(carno), order_code, this.sitenode.siteNo); //业务处理 if (string.IsNullOrWhiteSpace(TargetTo) || string.IsNullOrWhiteSpace(order_code)) { //if (string.IsNullOrWhiteSpace(TargetTo)) LogManager.Info($"错误日志输出 >>> 站点:{this.sitenode.siteNo},挂具:{carno}上件车辆去向有误!"); //if (string.IsNullOrWhiteSpace(order_code)) LogManager.Info($"错误日志输出 >>> 站点:{this.sitenode.siteNo},挂具:{carno}Thrift传输Vin码为空!"); Thread.Sleep(1000); return null; } //写入PLC var ToInt16QuXiang = MainCentralControl.getValue("2", TargetTo); var ToInt16ChangDu = MainCentralControl.getValue("2", amount); this._plc.Write(this.NodeSettingCarRun.plcpointAddress, ToInt16QuXiang);//写入小车去向 this._plc.Write(this.NodeSettingWcsSend.plcpointAddress, MainCentralControl.WcsChuLiWanCheng);//写入wms处理完成 this._plc.Write(this.NodeSettingWcsSendMaterial.plcpointAddress, ToInt16ChangDu);//写入车身长度 LogManager.Info($"当前时间 :{DateTime.Now} >>> 上件站点 :{this.sitenode.siteNo}发车 ,挂具号:{carno},去向:{ToInt16QuXiang},Wcs处理完成:{MainCentralControl.WcsChuLiWanCheng},vin条码:{order_code},车身长度:{ToInt16ChangDu}"); return "1";//发车成功反馈 } } } catch (Exception ex) { LogManager.Error(ex); } finally { Thread.Sleep(1000); } return null; } //根据上件点,物料号,获取下一点位信息 public string GetTargetTo(int carno, string materialNo, string sideno) { try { if (string.IsNullOrWhiteSpace(materialNo) || string.IsNullOrWhiteSpace(sideno)) { return null; } using var scope = _host.Services.CreateScope(); using var dbContext = scope.ServiceProvider.GetRequiredService(); //1 读出点位信息,下一站点 //2 根据物料查下一站点 var WaitdownlineModel = dbContext.BaseWaitdownline.Where(t => t.carNo == carno).FirstOrDefault(); var basecarModel = dbContext.BaseCar.Where(t => t.carNo == carno).FirstOrDefault(); var orderModel = dbContext.BaseProductionOrderSplit.Where(t => t.orderCode == materialNo).FirstOrDefault(); if (WaitdownlineModel == null && basecarModel != null && orderModel != null)//Waitdownline不存在当前车辆信息 { //添加挂具与物料绑定信息 BaseWaitdownline waitdownModel = new() { id = Guid.NewGuid(), carId = basecarModel.id, carNo = basecarModel.carNo, carName = basecarModel.carName, downline = 1, materielNo = materialNo, materielNum = 1, isDelete = 0, createTime = DateTime.Now, createBy = sideno, definefield1 = orderModel.lineCode }; dbContext.Add(waitdownModel); dbContext.SaveChanges(); } else//Waitdownline存在当前车辆信息即改 { //base_waitdownline表中挂具与任务VIN码绑定,修改车辆线上状态为已上线 dbContext.BaseWaitdownline.Where(t => t.carNo == carno).Update(a => new BaseWaitdownline() { materielNo = materialNo, materielNum = 1, downline = 1, createBy = sideno, createTime = DateTime.Now, isDelete = 0, definefield1 = orderModel.lineCode }); } return "1"; } catch (Exception ex) { LogManager.Info($"UpLine类GetTargetTo方法报错 >>> {ex.Message}"); return null; } } /// /// 返回给客户端车辆到位及车辆信息 /// /// 无用参数 /// public string ReceiveCarNo(string name) { 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) { return ""; } //正常读到小车信息 if (Convert.ToInt32(carno) > 0 && Convert.ToInt32(wcsend) == 0 && Convert.ToInt32(wcsstate) == 0 && Convert.ToInt32(carstate) == 1 && Convert.ToInt32(carrun) == 0) { string TuiSongCarNo = carno.ToString(); return TuiSongCarNo; } } Thread.Sleep(1000); return ""; } catch (Exception ex) { LogManager.Info($""); return ""; } } /// /// 启动小车发出后清空预设点位线程 /// private void ClearSendCar() { 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 (Convert.ToInt32(carno) == 0 && Convert.ToInt32(wcsend) == 1 && Convert.ToInt32(wcsstate) == 1) { this._plc.Write(NodeSettingCarRun.plcpointAddress, MainCentralControl.QingKongDianWei); this._plc.Write(NodeSettingWcsSend.plcpointAddress, MainCentralControl.QingKongDianWei); this._plc.Write(NodeSettingWcsSendMaterial.plcpointAddress, MainCentralControl.QingKongDianWei); } } catch (Exception ex) { LogManager.Info($"发车后清空点位线程报错 >>> {ex.Message}"); } finally { Thread.Sleep(1000); } } } } }