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);
}
}
}
}
}