diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs index acb9e72..2b4083c 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs @@ -24,7 +24,7 @@ namespace Modbus.Net.Modbus public ModbusAsciiInTcpProtocolLinker(string ip, int port) : base(ip, port) { - ((BaseConnector)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")), lengthCalc: content => { if (content[0] != 0x3a) return -1; for (int i = 1; i < content.Length; i++) { if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1; } return -1; }, waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : null)); + ((BaseConnector)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")), lengthCalc: content => { if (content[0] != 0x3a) return 0; for (int i = 1; i < content.Length; i++) { if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1; } return -1; }, waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : null)); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs index 5f6c274..63a336b 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs @@ -24,7 +24,7 @@ namespace Modbus.Net.Modbus public ModbusAsciiInUdpProtocolLinker(string ip, int port) : base(ip, port) { - ((BaseConnector)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")), lengthCalc: content => { if (content[0] != 0x3a) return -1; for (int i = 1; i < content.Length; i++) { if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1; } return -1; }, waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) : null)); + ((BaseConnector)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")), lengthCalc: content => { if (content[0] != 0x3a) return 0; for (int i = 1; i < content.Length; i++) { if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1; } return -1; }, waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) : null)); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs index 6eb76e4..6118389 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs @@ -16,7 +16,7 @@ namespace Modbus.Net.Modbus public ModbusAsciiProtocolLinker(string com, int slaveAddress) : base(com, slaveAddress) { - ((BaseConnector)BaseConnector).AddController(new MatchController(new ICollection<(int, int)>[] { new List<(int, int)> { (1, 1), (2, 2) }, new List<(int, int)> { (3, 3), (4, 4) } }, int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")), lengthCalc: content => { if (content[0] != 0x3a) return -1; for (int i = 1; i < content.Length; i++) { if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1; } return -1; }, waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : null)); + ((BaseConnector)BaseConnector).AddController(new MatchController(new ICollection<(int, int)>[] { new List<(int, int)> { (1, 1), (2, 2) }, new List<(int, int)> { (3, 3), (4, 4) } }, int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")), lengthCalc: content => { if (content[0] != 0x3a) return 0; for (int i = 1; i < content.Length; i++) { if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1; } return -1; }, waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : null)); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs index 39206eb..68e3709 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs @@ -24,7 +24,7 @@ namespace Modbus.Net.Modbus public ModbusRtuInTcpProtocolLinker(string ip, int port) : base(ip, port) { - ((BaseConnector)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")), lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 2 }, 5), waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : null)); + ((BaseConnector)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")), lengthCalc: content => { if (content[1] == 5 || content[1] == 6 || content[1] == 15 || content[1] == 16 || content[1] == 21) return 8; else return DuplicateWithCount.GetDuplcateFunc(new List { 2 }, 5).Invoke(content); }, waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : null)); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs index 0300faa..58bba98 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs @@ -24,7 +24,7 @@ namespace Modbus.Net.Modbus public ModbusRtuInUdpProtocolLinker(string ip, int port) : base(ip, port) { - ((BaseConnector)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")), lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 2 }, 5), waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) : null)); + ((BaseConnector)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")), lengthCalc: content => { if (content[1] == 5 || content[1] == 6 || content[1] == 15 || content[1] == 16 || content[1] == 21) return 8; else return DuplicateWithCount.GetDuplcateFunc(new List { 2 }, 5).Invoke(content); }, waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) : null)); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs index 95a315f..d9a2196 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs @@ -15,7 +15,7 @@ namespace Modbus.Net.Modbus public ModbusRtuProtocolLinker(string com, int slaveAddress) : base(com, slaveAddress) { - ((BaseConnector)BaseConnector).AddController(new MatchController(new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0) }, new List<(int, int)> { (1, 1) } }, int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")), lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 2 }, 5), waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : null)); + ((BaseConnector)BaseConnector).AddController(new MatchController(new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0) }, new List<(int, int)> { (1, 1) } }, int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")), lengthCalc: content => { if (content[1] == 5 || content[1] == 6 || content[1] == 15 || content[1] == 16 || content[1] == 21) return 8; else return DuplicateWithCount.GetDuplcateFunc(new List { 2 }, 5).Invoke(content); }, waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : null)); } /// diff --git a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs index f3238be..a76fd33 100644 --- a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs @@ -85,7 +85,19 @@ namespace Modbus.Net /// /// 缓冲的字节流 /// - private List _cachedBytes = new List(); + private static Dictionary> _cachedBytes = new Dictionary>(); + + private List CacheBytes + { + get + { + if (!_cachedBytes.ContainsKey(_com)) + { + _cachedBytes.Add(_com, new List()); + } + return _cachedBytes[_com]; + } + } /// /// 构造器 @@ -151,12 +163,12 @@ namespace Modbus.Net /// /// 连接中的连接器 /// - private static Dictionary Linkers { get; } = new Dictionary(); + private static HashSet<(string, string)> Linkers { get; } = new HashSet<(string, string)>(); /// /// 连接关键字(串口号:从站号) /// - public override string ConnectionToken => _slave + ":" + _com; + public override string ConnectionToken => _com + ":" + _slave; /// /// 获取当前连接器使用的串口 @@ -253,13 +265,14 @@ namespace Modbus.Net { if (disposing) { - // Release managed resources - Controller.SendStop(); + // Release managed resources } // Release unmanaged resources if (SerialPort != null) { - if (Linkers.Values.Count(p => p == _com) <= 1) + Linkers.Remove((_slave, _com)); + logger.LogInformation("Com connector {ConnectionToken} Removed", _com); + if (Linkers.Count(p => p.Item2 == _com) == 0) { if (SerialPort.IsOpen) { @@ -267,12 +280,12 @@ namespace Modbus.Net } SerialPort.Dispose(); logger.LogInformation("Com interface {Com} Disposed", _com); + Controller.SendStop(); + Controllers.Remove(_com); Connectors[_com] = null; Connectors.Remove(_com); ReceiveMsgThreadStop(); } - Linkers.Remove(_slave); - logger.LogInformation("Com connector {ConnectionToken} Removed", ConnectionToken); } } @@ -294,13 +307,13 @@ namespace Modbus.Net private void RefreshReceiveCount() { _receiveCount++; - logger.LogDebug("Com client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount); + logger.LogDebug("Com client {ConnectionToken} receive count: {SendCount}", _com, _receiveCount); } private void RefreshErrorCount() { _errorCount++; - logger.LogDebug("Com client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount); + logger.LogDebug("Com client {ConnectionToken} error count: {ErrorCount}", _com, _errorCount); } /// @@ -310,7 +323,7 @@ namespace Modbus.Net { if (SerialPort != null && !SerialPort.IsOpen) SerialPort.Dispose(); - return SerialPort != null && SerialPort.IsOpen && Linkers.ContainsKey(_slave); + return SerialPort != null && SerialPort.IsOpen && Linkers.Contains((_slave, _com)); } } @@ -336,9 +349,9 @@ namespace Modbus.Net ReadTimeout = TimeoutTime }); } - if (!Linkers.ContainsKey(_slave)) + if (!Linkers.Contains((_slave, _com))) { - Linkers.Add(_slave, _com); + Linkers.Add((_slave, _com)); } if (!SerialPort.IsOpen) { @@ -352,13 +365,13 @@ namespace Modbus.Net } } - logger.LogInformation("Com client {ConnectionToken} connect success", ConnectionToken); + logger.LogInformation("Com client {ConnectionToken} connect success", _com); return true; } catch (Exception e) { - logger.LogError(e, "Com client {ConnectionToken} connect error", ConnectionToken); + logger.LogError(e, "Com client {ConnectionToken} connect error", _com); Dispose(); return false; } @@ -373,7 +386,7 @@ namespace Modbus.Net /// public override bool Disconnect() { - if (Linkers.ContainsKey(_slave) && Connectors.ContainsKey(_com)) + if (Linkers.Contains((_slave, _com)) && Connectors.ContainsKey(_com)) try { Dispose(); @@ -419,7 +432,7 @@ namespace Modbus.Net } catch (Exception err) { - logger.LogError(err, "Com client {ConnectionToken} open error", ConnectionToken); + logger.LogError(err, "Com client {ConnectionToken} open error", _com); Dispose(); try { @@ -427,7 +440,7 @@ namespace Modbus.Net } catch (Exception err2) { - logger.LogError(err2, "Com client {ConnectionToken} open error", ConnectionToken); + logger.LogError(err2, "Com client {ConnectionToken} open error", _com); Dispose(); } } @@ -463,7 +476,7 @@ namespace Modbus.Net /// protected override void ReceiveMsgThreadStart() { - _receiveThread = Task.Run(() => ReceiveMessage()); + _receiveThread = Task.Run(ReceiveMessage); } /// @@ -483,36 +496,42 @@ namespace Modbus.Net if (returnBytes != null) { - logger.LogDebug("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken, + logger.LogDebug("Com client {ConnectionToken} receive msg length: {Length}", _com, returnBytes.Length); logger.LogDebug( - $"Com client {ConnectionToken} receive msg: {string.Concat(returnBytes.Select(p => " " + p.ToString("X2")))}"); + $"Com client {_com} receive msg: {string.Concat(returnBytes.Select(p => " " + p.ToString("X2")))}"); - lock (_cachedBytes) + lock (CacheBytes) { - _cachedBytes.AddRange(returnBytes); + CacheBytes.AddRange(returnBytes); } - var isMessageConfirmed = Controller.ConfirmMessage(_cachedBytes.ToArray()); - foreach (var confirmed in isMessageConfirmed) - { - if (confirmed.Item2 == false) - { - //主动传输事件 - } - lock (_cachedBytes) - { - _cachedBytes.RemoveRange(0, confirmed.Item1.Length); - } - } - if (isMessageConfirmed.Count > 0 && _cachedBytes.Count > 0) + var isMessageConfirmed = Controller.ConfirmMessage(CacheBytes.ToArray()); + if (isMessageConfirmed == null) { logger.LogError("Com client {ConnectionToken} cached msg error: {Length}", ConnectionToken, - _cachedBytes.Count); + CacheBytes.Count); logger.LogError( - $"Com client {ConnectionToken} cached msg: {string.Concat(_cachedBytes.Select(p => " " + p.ToString("X2")))}"); - lock (_cachedBytes) + $"Com client {ConnectionToken} cached msg: {string.Concat(CacheBytes.Select(p => " " + p.ToString("X2")))}"); + lock (CacheBytes) { - _cachedBytes.Clear(); + CacheBytes.Clear(); + } + } + else + { + foreach (var confirmed in isMessageConfirmed) + { + if (confirmed.Item2) + { + lock (CacheBytes) + { + CacheBytes.RemoveRange(0, confirmed.Item1.Length); + } + } + else if (confirmed.Item2 == false) + { + //主动传输事件 + } } } RefreshReceiveCount(); @@ -542,7 +561,7 @@ namespace Modbus.Net } catch (Exception e) { - logger.LogError(e, "Com client {ConnectionToken} read error", ConnectionToken); + logger.LogError(e, "Com client {ConnectionToken} read error", _com); RefreshErrorCount(); Dispose(); return null; diff --git a/Modbus.Net/Modbus.Net/Connector/TcpConnector.cs b/Modbus.Net/Modbus.Net/Connector/TcpConnector.cs index b859afa..081a6ad 100644 --- a/Modbus.Net/Modbus.Net/Connector/TcpConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/TcpConnector.cs @@ -236,15 +236,18 @@ namespace Modbus.Net logger.LogDebug( $"Tcp client {ConnectionToken} receive: {String.Concat(receiveBytes.Select(p => " " + p.ToString("X2")))}"); var isMessageConfirmed = Controller.ConfirmMessage(receiveBytes); - foreach (var confirmed in isMessageConfirmed) + if (isMessageConfirmed != null) { - if (confirmed.Item2 == false) + foreach (var confirmed in isMessageConfirmed) { - var sendMessage = InvokeReturnMessage(confirmed.Item1); - //主动传输事件 - if (sendMessage != null) + if (confirmed.Item2 == false) { - await SendMsgWithoutConfirm(sendMessage); + var sendMessage = InvokeReturnMessage(confirmed.Item1); + //主动传输事件 + if (sendMessage != null) + { + await SendMsgWithoutConfirm(sendMessage); + } } } } diff --git a/Modbus.Net/Modbus.Net/Connector/UdpConnector.cs b/Modbus.Net/Modbus.Net/Connector/UdpConnector.cs index 0f2cb5d..c1775a8 100644 --- a/Modbus.Net/Modbus.Net/Connector/UdpConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/UdpConnector.cs @@ -217,15 +217,18 @@ namespace Modbus.Net logger.LogDebug( $"Udp client {ConnectionToken} receive: {String.Concat(receiveBytes.Select(p => " " + p.ToString("X2")))}"); var isMessageConfirmed = Controller.ConfirmMessage(receiveBytes); - foreach (var confirmed in isMessageConfirmed) + if (isMessageConfirmed != null) { - if (confirmed.Item2 == false) + foreach (var confirmed in isMessageConfirmed) { - var sendMessage = InvokeReturnMessage(confirmed.Item1); - //主动传输事件 - if (sendMessage != null) + if (confirmed.Item2 == false) { - await SendMsgWithoutConfirm(sendMessage); + var sendMessage = InvokeReturnMessage(confirmed.Item1); + //主动传输事件 + if (sendMessage != null) + { + await SendMsgWithoutConfirm(sendMessage); + } } } } diff --git a/Modbus.Net/Modbus.Net/Controller/BaseController.cs b/Modbus.Net/Modbus.Net/Controller/BaseController.cs index ee4da80..7b25098 100644 --- a/Modbus.Net/Modbus.Net/Controller/BaseController.cs +++ b/Modbus.Net/Modbus.Net/Controller/BaseController.cs @@ -112,6 +112,7 @@ namespace Modbus.Net var length = LengthCalc?.Invoke(receiveMessageCopy); List duplicatedMessages; if (length == null || length == -1) return ans; + if (length == 0) return null; else { duplicatedMessages = new List(); @@ -122,6 +123,7 @@ namespace Modbus.Net if (receiveMessageCopy.Length == 0) break; length = LengthCalc?.Invoke(receiveMessageCopy); if (length == -1) break; + if (length == 0) return null; } } foreach (var message in duplicatedMessages)