2024-05-14 16:30:56 +08:00
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
using WcsMain.Tcp.Entity;
|
|
|
|
|
|
using WcsMain.Tcp.Entity.Message;
|
|
|
|
|
|
using WcsMain.WcsAttribute.AutoFacAttribute;
|
|
|
|
|
|
|
|
|
|
|
|
namespace WcsMain.Tcp.Client;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 专用与连接 PLC 的Tcp客户端
|
|
|
|
|
|
/// </summary>
|
2024-05-28 16:53:50 +08:00
|
|
|
|
public class PlcTcpClient : BaseTcpClient
|
2024-05-14 16:30:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 存储收到的消息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private Dictionary<string, MsgInfo> msgInfos = [];
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 重写检测离线方法 ---- 上一次传输数据的时间和当前时间差 3 秒判断断开
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public async override void MonitorServeConnectedAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (tcpServeConnectionDatas.Count < 1) return;
|
|
|
|
|
|
CancellationTokenSource cts = new();
|
|
|
|
|
|
PeriodicTimer timer = new(new TimeSpan(0, 0, 0, 1, 0));
|
|
|
|
|
|
while (await timer.WaitForNextTickAsync(cts.Token))
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var tcpServe in tcpServeConnectionDatas)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (tcpServe.IsConnected == Enum.General.TrueFalseEnum.FALSE || tcpServe.IsConnected == default) continue;
|
|
|
|
|
|
// 计算上一次接收消息的时间和当前的时间差,超过三秒判断断开
|
|
|
|
|
|
var lastRevMsgTime = tcpServe.RecvMsgTime;
|
|
|
|
|
|
var timespan = DateTime.Now - lastRevMsgTime;
|
|
|
|
|
|
var timespanSeconds = timespan.TotalSeconds;
|
|
|
|
|
|
if (timespanSeconds > 3) // 心跳超时时间
|
|
|
|
|
|
{
|
|
|
|
|
|
tcpServe.TcpClient?.Close();
|
|
|
|
|
|
tcpServe.IsConnected = Enum.General.TrueFalseEnum.FALSE;
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 发送信息到指定别称的客户端
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="value"></param>
|
|
|
|
|
|
/// <param name="displayName"></param>
|
|
|
|
|
|
/// <param name="timeout"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public PlcTcpClientSendResult SendWithResult(string? value, string? displayName, int timeout)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(displayName))
|
|
|
|
|
|
{
|
|
|
|
|
|
return new() { Success = false, Exception = new Exception("传入的参数为空") };
|
|
|
|
|
|
}
|
|
|
|
|
|
MsgHeader? header = GetMsgHeader(value);
|
|
|
|
|
|
if(header == default || string.IsNullOrEmpty(header.MsgId)) return new() { Success = false, Exception = new Exception("发送的信息不是标准报文格式") };
|
|
|
|
|
|
Stopwatch stopwatch = Stopwatch.StartNew();
|
|
|
|
|
|
var sendResult = Send(value, displayName); // 发送消息
|
|
|
|
|
|
if(!sendResult.Success) return new() { Success = sendResult.Success, Exception = sendResult.Exception }; // 发送失败
|
|
|
|
|
|
MsgInfo? msgInfo = default;
|
|
|
|
|
|
while (stopwatch.ElapsedMilliseconds < timeout)
|
|
|
|
|
|
{
|
|
|
|
|
|
bool exist = msgInfos.TryGetValue(header.MsgId, out msgInfo);
|
|
|
|
|
|
if (exist) break;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(msgInfo == default) return new() { Success = false, Exception = new Exception("发送的信息不是标准报文格式"), UseTime = stopwatch.ElapsedMilliseconds};
|
|
|
|
|
|
return new()
|
|
|
|
|
|
{
|
|
|
|
|
|
Success = true,
|
|
|
|
|
|
ResponseData = msgInfo,
|
|
|
|
|
|
UseTime = stopwatch.ElapsedMilliseconds
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取msg的Header
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="value"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public MsgHeader? GetMsgHeader(string? value)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrEmpty(value)) return default;
|
2024-05-28 16:53:50 +08:00
|
|
|
|
if (!Regex.IsMatch(value, "^<.+\\>$")) return default;
|
2024-05-14 16:30:56 +08:00
|
|
|
|
string[] msgDatas = value.Split(';');
|
|
|
|
|
|
if(msgDatas.Length < 4 ) return default;
|
|
|
|
|
|
var msgHeader = new MsgHeader()
|
|
|
|
|
|
{
|
|
|
|
|
|
MsgType = msgDatas[0].Replace("<", ""),
|
|
|
|
|
|
ClientId = msgDatas[1],
|
|
|
|
|
|
MsgId = msgDatas[2],
|
|
|
|
|
|
MsgTag = msgDatas[3],
|
|
|
|
|
|
};
|
|
|
|
|
|
return msgHeader;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|