液晶标签协议对接!
This commit is contained in:
@ -2,6 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.ComponentModel.Design;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using TouchSocket.Core;
|
||||
using TouchSocket.Sockets;
|
||||
using WCS.BLL.Tool;
|
||||
@ -19,8 +20,8 @@ namespace WCS.BLL
|
||||
public string BindIPHost { get; set; } = "127.0.0.1:20003";
|
||||
|
||||
public string ShelfTypeName { get; set; }
|
||||
public bool IsOnline { get; set; } = false;
|
||||
|
||||
public bool IsReceivedClientOnline { get; set; } = false;
|
||||
public bool IsSendClientOnline { get; set; } = false;
|
||||
//第一次连接是否已连接
|
||||
public bool IsFirstConnected { get; set; } = false;
|
||||
|
||||
@ -31,13 +32,14 @@ namespace WCS.BLL
|
||||
//协议数据部分长度
|
||||
public readonly int DataLength = 10;
|
||||
|
||||
public ConcurrentDictionary<int, MessageDto> MessageList { get; set; } = new ConcurrentDictionary<int, MessageDto>();
|
||||
|
||||
public TcpClient tcpClient { get; set; }
|
||||
|
||||
public TcpClient tcpSendClient { get; set; }
|
||||
|
||||
//同步发送等待客户端 等待上一条指令发送成功并收到响应之后才发送下一条指令
|
||||
public IWaitingClient<TcpClient> waitClient;
|
||||
|
||||
public TcpClient tcpReceiveClient { get; set; }
|
||||
|
||||
public object receivdLockObject = new object();
|
||||
public object sendLockObject = new object();
|
||||
|
||||
@ -45,7 +47,8 @@ namespace WCS.BLL
|
||||
{
|
||||
try
|
||||
{
|
||||
tcpClient.Connect();//调用连接,当连接不成功时,会抛出异常。
|
||||
tcpSendClient.Connect();//调用连接,当连接不成功时,会抛出异常。
|
||||
tcpReceiveClient.Connect();
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
@ -67,16 +70,15 @@ namespace WCS.BLL
|
||||
BindIPHost = bindIPHost;
|
||||
ShelfTypeName = shelfTypeName;
|
||||
|
||||
tcpClient = new TcpClient();
|
||||
|
||||
tcpSendClient = new TcpClient();
|
||||
tcpReceiveClient = new TcpClient();
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(BindIPHost))
|
||||
{
|
||||
//载入配置
|
||||
tcpClient.Setup(new TouchSocketConfig()
|
||||
tcpSendClient.Setup(new TouchSocketConfig()
|
||||
.SetRemoteIPHost(new IPHost(RemoteIPHost))
|
||||
//.SetBindIPHost(BindIPHost)
|
||||
.ConfigurePlugins(a =>
|
||||
{
|
||||
//配置断线重连
|
||||
@ -89,7 +91,7 @@ namespace WCS.BLL
|
||||
a.AddConsoleLogger();
|
||||
}));
|
||||
|
||||
var waitClient = tcpClient.CreateWaitingClient(new WaitingOptions()
|
||||
waitClient = tcpSendClient.CreateWaitingClient(new WaitingOptions()
|
||||
{
|
||||
FilterFunc = response => //设置用于筛选的fun委托,当返回为true时,才会响应返回
|
||||
{
|
||||
@ -101,11 +103,26 @@ namespace WCS.BLL
|
||||
}
|
||||
});
|
||||
|
||||
tcpReceiveClient.Setup(new TouchSocketConfig()
|
||||
.SetRemoteIPHost(new IPHost(RemoteIPHost))
|
||||
//.SetBindIPHost(BindIPHost)
|
||||
.ConfigurePlugins(a =>
|
||||
{
|
||||
//配置断线重连
|
||||
a.UseReconnection(-1, true, 1000);
|
||||
a.Add<HeartbeatAndReceivePlugin>();
|
||||
})
|
||||
.ConfigureContainer(a =>
|
||||
{
|
||||
//添加控制台日志注入
|
||||
a.AddConsoleLogger();
|
||||
}));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//载入配置
|
||||
tcpClient.Setup(new TouchSocketConfig()
|
||||
tcpSendClient.Setup(new TouchSocketConfig()
|
||||
.SetRemoteIPHost(new IPHost(RemoteIPHost))
|
||||
.SetBindIPHost(new IPHost(BindIPHost))
|
||||
.ConfigurePlugins(a =>
|
||||
@ -119,124 +136,110 @@ namespace WCS.BLL
|
||||
//添加控制台日志注入
|
||||
a.AddConsoleLogger();
|
||||
}));
|
||||
|
||||
waitClient = tcpSendClient.CreateWaitingClient(new WaitingOptions()
|
||||
{
|
||||
FilterFunc = response => //设置用于筛选的fun委托,当返回为true时,才会响应返回
|
||||
{
|
||||
if (response.Data.Length == 13)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
tcpReceiveClient.Setup(new TouchSocketConfig()
|
||||
.SetRemoteIPHost(new IPHost(RemoteIPHost))
|
||||
//.SetBindIPHost(BindIPHost)
|
||||
.ConfigurePlugins(a =>
|
||||
{
|
||||
//配置断线重连
|
||||
a.UseReconnection(-1, true, 1000);
|
||||
a.Add<HeartbeatAndReceivePlugin>();
|
||||
})
|
||||
.ConfigureContainer(a =>
|
||||
{
|
||||
//添加控制台日志注入
|
||||
a.AddConsoleLogger();
|
||||
}));
|
||||
}
|
||||
|
||||
//添加接收事件 匹配已发送的指令
|
||||
tcpClient.Received += (client, e) =>
|
||||
{
|
||||
var data = e.ByteBlock.Buffer.Take((int)e.ByteBlock.Length).ToArray();
|
||||
Task.Run(() =>
|
||||
{
|
||||
Logs.Write($"【校验发送接收 开始】{ShelfTypeName}" + BitConverter.ToString(data), LogsType.InstructionResend);
|
||||
if (ShelfTypeName == "信息化货架")
|
||||
{
|
||||
//协议拆包
|
||||
var len = data.Length;
|
||||
//灯控制统一返回的是 FF-00-00-0A-00-02-D7-B5
|
||||
if (len == 8)
|
||||
{
|
||||
if (data[4] == 0x00 && data[0] == 0xFF && data[1] == 0x00 && (data[5] == 0x01 || data[5] == 0x02))
|
||||
{
|
||||
//查询当前板子是否有待验证的指令
|
||||
var message = new MessageDto();
|
||||
var firstMessage = MessageList.Select(t => new { Id = t.Key, Value = t.Value })
|
||||
.OrderBy(t => t.Value.CreateTime)
|
||||
.FirstOrDefault();
|
||||
if (firstMessage != null)
|
||||
{
|
||||
MessageList.TryRemove(firstMessage.Id, out message);
|
||||
Logs.Write($"【信息化货架】以下指令已不重发:{BitConverter.ToString(firstMessage.Value.Message)}", LogsType.InstructionResend);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ShelfTypeName == "液晶货架")
|
||||
{
|
||||
Logs.Write($"【液晶货架】接收到指令{BitConverter.ToString(data)}", LogsType.InstructionResend);
|
||||
}
|
||||
//智能货架
|
||||
else
|
||||
{
|
||||
var len = data.Length;
|
||||
for (int index = 0; index < data.Length - PreFixLength; index++)
|
||||
{
|
||||
//协议拆包 通过前缀校验是否为完整数据包
|
||||
var prefixInData = data.Skip(index).Take(PreFixLength);
|
||||
var isEqual = prefixInData.SequenceEqual(Prefix);
|
||||
if (isEqual)
|
||||
{
|
||||
var dataTemp = data.Skip(index).Take(PreFixLength + DataLength).ToArray();
|
||||
if (dataTemp.Length < PreFixLength + DataLength)//拆包后不满足一条指令的长度
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//获取返回指令的板子ID
|
||||
var boardId = (dataTemp[PreFixLength + 0] << 8) + dataTemp[PreFixLength + 1];
|
||||
//查询当前板子是否有待验证的指令
|
||||
var message = new MessageDto();
|
||||
MessageList.TryGetValue(boardId, out message);
|
||||
//功能位校验 功能位相同视为已响应指令 删除对应的指令
|
||||
if (message?.Message[PreFixLength + 2] == dataTemp[PreFixLength + 2])
|
||||
{
|
||||
MessageList.TryRemove(boardId, out message);
|
||||
}
|
||||
index += (PreFixLength + DataLength - 2);//每次循环index会+1 所以这里-1
|
||||
}
|
||||
}
|
||||
}
|
||||
Logs.Write($"【校验发送接收 结束】{ShelfTypeName}" + BitConverter.ToString(data), LogsType.InstructionResend);
|
||||
});
|
||||
return null;
|
||||
};
|
||||
|
||||
tcpClient.Connected += (client, e) =>
|
||||
{
|
||||
this.IsOnline = true;
|
||||
return EasyTask.CompletedTask;
|
||||
};
|
||||
|
||||
tcpClient.Disconnected += (client, e) =>
|
||||
{
|
||||
this.IsOnline = false;
|
||||
return EasyTask.CompletedTask;
|
||||
};
|
||||
|
||||
////配置数据重发机制
|
||||
//Task.Run(async () =>
|
||||
//tcpReceiveClient.Received += (client, e) =>
|
||||
//{
|
||||
// while (true)
|
||||
// var data = e.ByteBlock.Buffer.Take((int)e.ByteBlock.Length).ToArray();
|
||||
// Task.Run(() =>
|
||||
// {
|
||||
// try
|
||||
// Logs.Write($"【校验发送接收 开始】{ShelfTypeName}" + BitConverter.ToString(data), LogsType.InstructionResend);
|
||||
// if (ShelfTypeName == "信息化货架")
|
||||
// {
|
||||
// //TODO如果指令已发两次 则取消重发
|
||||
// await Task.Delay(100);
|
||||
// if (MessageList.Count > 0)
|
||||
// //协议拆包
|
||||
// var len = data.Length;
|
||||
// //灯控制统一返回的是 FF-00-00-0A-00-02-D7-B5
|
||||
// if (len == 8)
|
||||
// {
|
||||
// var failedMessage = MessageList.Where(t => t.Value.LastSendTime < DateTime.Now.AddSeconds(-1))
|
||||
// .ToList();
|
||||
// foreach (var message in failedMessage)
|
||||
// if (data[4] == 0x00 && data[0] == 0xFF && data[1] == 0x00 && (data[5] == 0x01 || data[5] == 0x02))
|
||||
// {
|
||||
// Logs.Write("【指令重发】" + BitConverter.ToString(message.Value.Message) + "指令超时1s未响应", LogsType.InstructionResend);
|
||||
// }
|
||||
// MessageList.RemoveWhen(t => t.Value.SendTimes >= 2);
|
||||
// foreach (var item in MessageList)
|
||||
// {
|
||||
// if (item.Value.LastSendTime < DateTime.Now.AddSeconds(-1))
|
||||
// {
|
||||
|
||||
// Send(item.Value.Message);
|
||||
// item.Value.SendTimes++;
|
||||
// item.Value.LastSendTime = DateTime.Now;
|
||||
// Logs.Write("【指令重发】" + BitConverter.ToString(item.Value.Message) + "已进行重发", LogsType.InstructionResend);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch
|
||||
// else if (ShelfTypeName == "液晶标签货架")
|
||||
// {
|
||||
// Logs.Write($"【液晶标签货架】接收到指令{BitConverter.ToString(data)}", LogsType.InstructionResend);
|
||||
// }
|
||||
// }
|
||||
//});
|
||||
// //智能货架
|
||||
// else
|
||||
// {
|
||||
// var len = data.Length;
|
||||
// for (int index = 0; index < data.Length - PreFixLength; index++)
|
||||
// {
|
||||
// //协议拆包 通过前缀校验是否为完整数据包
|
||||
// var prefixInData = data.Skip(index).Take(PreFixLength);
|
||||
// var isEqual = prefixInData.SequenceEqual(Prefix);
|
||||
// if (isEqual)
|
||||
// {
|
||||
// var dataTemp = data.Skip(index).Take(PreFixLength + DataLength).ToArray();
|
||||
// if (dataTemp.Length < PreFixLength + DataLength)//拆包后不满足一条指令的长度
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// //获取返回指令的板子ID
|
||||
// var boardId = (dataTemp[PreFixLength + 0] << 8) + dataTemp[PreFixLength + 1];
|
||||
// index += (PreFixLength + DataLength - 2);//每次循环index会+1 所以这里-1
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Logs.Write($"【校验发送接收 结束】{ShelfTypeName}" + BitConverter.ToString(data), LogsType.InstructionResend);
|
||||
// });
|
||||
// return null;
|
||||
//};
|
||||
|
||||
tcpSendClient.Connected += (client, e) =>
|
||||
{
|
||||
this.IsSendClientOnline = true;
|
||||
return EasyTask.CompletedTask;
|
||||
};
|
||||
|
||||
tcpSendClient.Disconnected += (client, e) =>
|
||||
{
|
||||
this.IsSendClientOnline = false;
|
||||
return EasyTask.CompletedTask;
|
||||
};
|
||||
|
||||
tcpReceiveClient.Connected += (client, e) =>
|
||||
{
|
||||
this.IsReceivedClientOnline = true;
|
||||
return EasyTask.CompletedTask;
|
||||
};
|
||||
|
||||
tcpReceiveClient.Disconnected += (client, e) =>
|
||||
{
|
||||
this.IsReceivedClientOnline = false;
|
||||
ReConnectAsync();
|
||||
return EasyTask.CompletedTask;
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -245,7 +248,10 @@ namespace WCS.BLL
|
||||
|
||||
public void ReConnectAsync()
|
||||
{
|
||||
tcpClient.TryConnectAsync();
|
||||
if (IsSendClientOnline == false)
|
||||
tcpSendClient.TryConnectAsync();
|
||||
if (IsReceivedClientOnline == false)
|
||||
tcpReceiveClient.TryConnectAsync();
|
||||
}
|
||||
|
||||
|
||||
@ -255,25 +261,15 @@ namespace WCS.BLL
|
||||
{
|
||||
var boardId = (message[3] << 8) + message[4];
|
||||
|
||||
if (boardId != 2047 && IsReSend == false)
|
||||
{
|
||||
MessageList.TryAdd(boardId, new MessageDto()
|
||||
{
|
||||
ID = boardId,
|
||||
Message = message,
|
||||
SendTimes = 1
|
||||
});
|
||||
}
|
||||
|
||||
lock (sendLockObject)
|
||||
{
|
||||
tcpClient.Send(message);
|
||||
tcpReceiveClient.Send(message);
|
||||
|
||||
var clientIpHost = tcpClient.IP + ":" + tcpClient.Port;
|
||||
Logs.Write($"【发送{clientIpHost}】{BitConverter.ToString(message)}", LogsType.Instructions);
|
||||
var clientIpHost = tcpReceiveClient.IP + ":" + tcpReceiveClient.Port;
|
||||
Logs.Write($"【发送{clientIpHost}】{BitConverter.ToString(message)}", LogsType.Instructions);
|
||||
|
||||
//发送自带15ms间隔
|
||||
Thread.Sleep(18);
|
||||
//发送自带10ms间隔
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -282,6 +278,7 @@ namespace WCS.BLL
|
||||
//因异常断连时(网线已经被断了) 手动重连一次
|
||||
if (ex is NotConnectedException)
|
||||
{
|
||||
IsReceivedClientOnline = false;
|
||||
Task.Run(() =>
|
||||
{
|
||||
ReConnectAsync();
|
||||
@ -295,10 +292,9 @@ namespace WCS.BLL
|
||||
{
|
||||
try
|
||||
{
|
||||
var boardId = (message[3] << 8) + message[4];
|
||||
lock (sendLockObject)
|
||||
{
|
||||
var clientIpHost = tcpClient.IP + ":" + tcpClient.Port;
|
||||
var clientIpHost = tcpSendClient.IP + ":" + tcpSendClient.Port;
|
||||
Logs.Write($"【同步等待发送{clientIpHost}】{BitConverter.ToString(message)}", LogsType.Instructions);
|
||||
|
||||
waitClient.SendThenReturn(message);
|
||||
@ -311,6 +307,38 @@ namespace WCS.BLL
|
||||
//因异常断连时(网线已经被断了) 手动重连一次
|
||||
if (ex is NotConnectedException)
|
||||
{
|
||||
IsSendClientOnline = false;
|
||||
Task.Run(() =>
|
||||
{
|
||||
ReConnectAsync();
|
||||
});
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public void SendThenReturnList(List<byte[]> messages, bool IsReSend = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (sendLockObject)
|
||||
{
|
||||
foreach (var message in messages)
|
||||
{
|
||||
var clientIpHost = tcpSendClient.IP + ":" + tcpSendClient.Port;
|
||||
Logs.Write($"【同步等待发送{clientIpHost}】{BitConverter.ToString(message)}", LogsType.Instructions);
|
||||
waitClient.SendThenReturn(message);
|
||||
Thread.Sleep(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logs.Write("【同步等待发送指令时发生异常】" + ex.Message, LogsType.Instructions);
|
||||
//因异常断连时(网线已经被断了) 手动重连一次
|
||||
if (ex is NotConnectedException)
|
||||
{
|
||||
IsSendClientOnline = false;
|
||||
Task.Run(() =>
|
||||
{
|
||||
ReConnectAsync();
|
||||
@ -340,26 +368,64 @@ namespace WCS.BLL
|
||||
return message;
|
||||
}
|
||||
|
||||
public List<byte[]> GenerateMessageList(int boardId, byte[] data, string message)
|
||||
{
|
||||
var list = new List<byte[]>();
|
||||
//去除不满足ASCII的数据
|
||||
message = Regex.Replace(message, @"[^\u0000-\u007F]+", string.Empty);
|
||||
//总共发的数据位数
|
||||
data[1] = Convert.ToByte(message.Length);
|
||||
//数据发送总帧数
|
||||
var messageCount = Math.Ceiling((decimal)message.Length / 6);
|
||||
|
||||
for (int i = 0; i < messageCount; i++)
|
||||
{
|
||||
var tempmessage = string.Empty;
|
||||
//不是最后一条指令
|
||||
if (i != messageCount - 1)
|
||||
{
|
||||
tempmessage = message.Substring(i * 6, 6);
|
||||
var charArray = tempmessage.ToCharArray();
|
||||
for (int index = 0; index < 6; index++)
|
||||
{
|
||||
data[2 + index] = Convert.ToByte(charArray[index]);
|
||||
}
|
||||
}
|
||||
//最后一条指令
|
||||
else
|
||||
{
|
||||
tempmessage = message.Substring(i * 6, message.Length % 6 == 0 ? 6 : message.Length % 6);
|
||||
var charArray = tempmessage.ToCharArray();
|
||||
//先把所有数据位置为0
|
||||
for (int index = 0; index < 6; index++)
|
||||
{
|
||||
data[2 + index] = 0x00;
|
||||
}
|
||||
//有数据的置为对应的数据
|
||||
for (int index = 0; index < charArray.Length; index++)
|
||||
{
|
||||
data[2 + index] = Convert.ToByte(charArray[index]);
|
||||
}
|
||||
}
|
||||
list.Add(GenerateMessage(boardId, data));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private string CharToAscii(char chr)
|
||||
{
|
||||
return ((int)chr).ToString("X").PadLeft(2, '0');
|
||||
}
|
||||
|
||||
private byte[] StrToToHexByte(string hexString)
|
||||
{
|
||||
hexString = hexString.Replace(" ", string.Empty);
|
||||
if ((hexString.Length % 2) != 0)
|
||||
hexString = "0" + hexString;
|
||||
byte[] returnBytes = new byte[hexString.Length / 2];
|
||||
for (int i = 0; i < returnBytes.Length; i++)
|
||||
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
|
||||
return returnBytes;
|
||||
}
|
||||
}
|
||||
|
||||
//发送指令的记录
|
||||
public class MessageDto
|
||||
{
|
||||
public int ID { get; set; }
|
||||
/// <summary>
|
||||
/// 最后一次发送时间
|
||||
/// </summary>
|
||||
public DateTime LastSendTime { get; set; } = DateTime.Now;
|
||||
|
||||
public DateTime CreateTime { get; set; } = DateTime.Now;
|
||||
/// <summary>
|
||||
/// 发送内容
|
||||
/// </summary>
|
||||
public byte[] Message { get; set; }
|
||||
/// <summary>
|
||||
/// 发送次数
|
||||
/// </summary>
|
||||
public int SendTimes { get; set; } = 0;//第几次发送
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user