Fix Bugs in modbus rtu
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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<int> { 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<int> { 2 }, 5).Invoke(content); }, waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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<int> { 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<int> { 2 }, 5).Invoke(content); }, waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) : null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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<int> { 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<int> { 2 }, 5).Invoke(content); }, waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -85,7 +85,19 @@ namespace Modbus.Net
|
||||
/// <summary>
|
||||
/// 缓冲的字节流
|
||||
/// </summary>
|
||||
private List<byte> _cachedBytes = new List<byte>();
|
||||
private static Dictionary<string, List<byte>> _cachedBytes = new Dictionary<string, List<byte>>();
|
||||
|
||||
private List<byte> CacheBytes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_cachedBytes.ContainsKey(_com))
|
||||
{
|
||||
_cachedBytes.Add(_com, new List<byte>());
|
||||
}
|
||||
return _cachedBytes[_com];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造器
|
||||
@@ -151,12 +163,12 @@ namespace Modbus.Net
|
||||
/// <summary>
|
||||
/// 连接中的连接器
|
||||
/// </summary>
|
||||
private static Dictionary<string, string> Linkers { get; } = new Dictionary<string, string>();
|
||||
private static HashSet<(string, string)> Linkers { get; } = new HashSet<(string, string)>();
|
||||
|
||||
/// <summary>
|
||||
/// 连接关键字(串口号:从站号)
|
||||
/// </summary>
|
||||
public override string ConnectionToken => _slave + ":" + _com;
|
||||
public override string ConnectionToken => _com + ":" + _slave;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前连接器使用的串口
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -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
|
||||
/// <inheritdoc />
|
||||
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
|
||||
/// <inheritdoc />
|
||||
protected override void ReceiveMsgThreadStart()
|
||||
{
|
||||
_receiveThread = Task.Run(() => ReceiveMessage());
|
||||
_receiveThread = Task.Run(ReceiveMessage);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ namespace Modbus.Net
|
||||
var length = LengthCalc?.Invoke(receiveMessageCopy);
|
||||
List<byte[]> duplicatedMessages;
|
||||
if (length == null || length == -1) return ans;
|
||||
if (length == 0) return null;
|
||||
else
|
||||
{
|
||||
duplicatedMessages = new List<byte[]>();
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user