You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

339 lines
16 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
{
/// <summary>
/// 上件点线程
/// </summary>
public class UpLine : WcsServer
{
private readonly IHost _host;
private readonly Plc.S7.Plc _plc;
List<NodeSetting> 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);
}
}
/// <summary>
/// 启动线程
/// </summary>
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();
}
/// <summary>
/// 启动推送车辆到位队列
/// </summary>
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);
}
}
}
/// <summary>
/// 启动小车扫描监听队列
/// </summary>
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);
}
}
}
/// <summary>
/// 发车
/// </summary>
/// <param name="carlist"></param>
/// <param name="order_code"></param>
/// <param name="amount"></param>
/// <returns></returns>
public string SendCar(List<string> 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<DefaultDbContext>();
//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;
}
}
/// <summary>
/// 返回给客户端车辆到位及车辆信息
/// </summary>
/// <param name="name">无用参数</param>
/// <returns></returns>
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 "";
}
}
/// <summary>
/// 启动小车发出后清空预设点位线程
/// </summary>
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);
}
}
}
}
}