From 7da1b7ea2abd2e13994115f7645a2ef9f0861f35 Mon Sep 17 00:00:00 2001 From: luosheng Date: Tue, 28 Mar 2023 10:56:21 +0800 Subject: [PATCH] Add Modbus TCP transaction ID. --- .../ModbusProtocolLinkerBytesExtend.cs | 21 +++++++--- .../ModbusTcpMatchDirectlySendController.cs | 41 +++++++++++++++++++ .../ModbusTcpProtocolLinker.cs | 2 +- 3 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 Modbus.Net/Modbus.Net.Modbus/ModbusTcpMatchDirectlySendController.cs diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs index 662ac5f..c7fff30 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusProtocolLinkerBytesExtend.cs @@ -50,6 +50,9 @@ namespace Modbus.Net.Modbus /// public class ModbusTcpProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend { + private static ushort _sendCount = 0; + private static readonly object _counterLock = new object(); + /// /// 协议扩展,协议内容发送前调用 /// @@ -57,13 +60,19 @@ namespace Modbus.Net.Modbus /// 扩展后的协议内容 public byte[] BytesExtend(byte[] content) { - //Modbus/Tcp协议扩张,前面加6个字节,前面4个为0,后面两个为协议整体内容的长度 + //Modbus/Tcp协议扩张,前面加6个字节,前面2个为事务编号,中间两个为0,后面两个为协议整体内容的长度 var newFormat = new byte[6 + content.Length]; - var tag = 0; - var leng = (ushort)content.Length; - Array.Copy(BigEndianValueHelper.Instance.GetBytes(tag), 0, newFormat, 0, 4); - Array.Copy(BigEndianValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2); - Array.Copy(content, 0, newFormat, 6, content.Length); + lock (_counterLock) + { + var transaction = (ushort)(_sendCount % 65536 + 1); + var tag = (ushort)0; + var leng = (ushort)content.Length; + Array.Copy(BigEndianValueHelper.Instance.GetBytes(transaction), 0, newFormat, 0, 2); + Array.Copy(BigEndianValueHelper.Instance.GetBytes(tag), 0, newFormat, 2, 2); + Array.Copy(BigEndianValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2); + Array.Copy(content, 0, newFormat, 6, content.Length); + _sendCount++; + } return newFormat; } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpMatchDirectlySendController.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpMatchDirectlySendController.cs new file mode 100644 index 0000000..9ff030f --- /dev/null +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpMatchDirectlySendController.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Modbus.Net +{ + /// + /// 匹配控制器,载入队列后直接发送 + /// + public class ModbusTcpMatchDirectlySendController : MatchDirectlySendController + { + /// + public ModbusTcpMatchDirectlySendController(ICollection<(int, int)>[] keyMatches, + Func lengthCalc = null, int? waitingListMaxCount = null) : base(keyMatches, + lengthCalc, waitingListMaxCount) + { + } + + /// + protected override MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage) + { + MessageWaitingDef ans; + if (receiveMessage[0] == 0 && receiveMessage[1] == 0) + { + lock (WaitingMessages) + { + ans = WaitingMessages.FirstOrDefault(); + } + } + else + { + var returnKey = GetKeyFromMessage(receiveMessage); + lock (WaitingMessages) + { + ans = WaitingMessages.FirstOrDefault(p => returnKey.HasValue && p.Key == returnKey.Value.Item2); + } + } + return ans; + } + } +} diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs index 20b8429..bf34fcb 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs @@ -23,7 +23,7 @@ namespace Modbus.Net.Modbus /// 端口 public ModbusTcpProtocolLinker(string ip, int port) : base(ip, port) { - ((IConnectorWithController)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")), lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 4, 5 }, 6), waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : null)); + ((IConnectorWithController)BaseConnector).AddController(new ModbusTcpMatchDirectlySendController(new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0), (1, 1) } }, lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 4, 5 }, 6), waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : null)); } ///