diff --git a/Modbus.Net/Modbus.Net.PersistedTests/Modbus.Net.PersistedTests.csproj b/Modbus.Net/Modbus.Net.PersistedTests/Modbus.Net.PersistedTests.csproj
new file mode 100644
index 0000000..6e5b5b1
--- /dev/null
+++ b/Modbus.Net/Modbus.Net.PersistedTests/Modbus.Net.PersistedTests.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net45; netcoreapp2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Modbus.Net/Modbus.Net.PersistedTests/Program.cs b/Modbus.Net/Modbus.Net.PersistedTests/Program.cs
new file mode 100644
index 0000000..9157bce
--- /dev/null
+++ b/Modbus.Net/Modbus.Net.PersistedTests/Program.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Modbus.Net.Modbus;
+using Serilog;
+
+namespace Modbus.Net.PersistedTests
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Log.Logger = new LoggerConfiguration().MinimumLevel.Verbose().WriteTo.Console().CreateLogger();
+
+ IMachineProperty machine = new ModbusMachine(1, ModbusType.Rtu, "COM1",
+ new List()
+ {
+ new AddressUnit()
+ {
+ Id = "1",
+ Area = "4X",
+ Address = 1,
+ Name = "test 1",
+ DataType = typeof(ushort)
+ },
+ new AddressUnit()
+ {
+ Id = "2",
+ Area = "4X",
+ Address = 2,
+ Name = "test 2",
+ DataType = typeof(ushort)
+ },
+ new AddressUnit()
+ {
+ Id = "3",
+ Area = "4X",
+ Address = 3,
+ Name = "test 3",
+ DataType = typeof(ushort)
+ },
+ }, true, 2, 1);
+ IMachineProperty machine2 = new ModbusMachine(2, ModbusType.Rtu, "COM1",
+ new List()
+ {
+ new AddressUnit()
+ {
+ Id = "1",
+ Area = "4X",
+ Address = 11,
+ Name = "test 1",
+ DataType = typeof(ushort)
+ },
+ new AddressUnit()
+ {
+ Id = "2",
+ Area = "4X",
+ Address = 12,
+ Name = "test 2",
+ DataType = typeof(ushort)
+ },
+ new AddressUnit()
+ {
+ Id = "3",
+ Area = "4X",
+ Address = 13,
+ Name = "test 3",
+ DataType = typeof(ushort)
+ },
+ }, true, 3, 1);
+ IMachineProperty machine3 = new ModbusMachine(3, ModbusType.Rtu, "COM1",
+ new List()
+ {
+ new AddressUnit()
+ {
+ Id = "1",
+ Area = "4X",
+ Address = 21,
+ Name = "test 1",
+ DataType = typeof(ushort)
+ },
+ new AddressUnit()
+ {
+ Id = "2",
+ Area = "4X",
+ Address = 22,
+ Name = "test 2",
+ DataType = typeof(ushort)
+ },
+ new AddressUnit()
+ {
+ Id = "3",
+ Area = "4X",
+ Address = 23,
+ Name = "test 3",
+ DataType = typeof(ushort)
+ },
+ }, true, 4, 1);
+
+ TaskManager manager = new TaskManager(20, true);
+ manager.AddMachines(new List>{machine, machine2, machine3});
+ Random r = new Random();
+ manager.InvokeTimerAll(new TaskItemSetData(()=>new Dictionary
+ {
+ {
+ "4X 1.0", r.Next()%65536
+ },
+ {
+ "4X 2.0", r.Next()%65536
+ },
+ {
+ "4X 3.0", r.Next()%65536
+ },
+ {
+ "4X 11.0", r.Next()%65536
+ },
+ {
+ "4X 12.0", r.Next()%65536
+ },
+ {
+ "4X 13.0", r.Next()%65536
+ },
+ {
+ "4X 21.0", r.Next()%65536
+ },
+ {
+ "4X 22.0", r.Next()%65536
+ },
+ {
+ "4X 23.0", r.Next()%65536
+ },
+ }, MachineSetDataType.Address, 10000, 10000));
+ Thread.Sleep(5000);
+ manager.InvokeTimerAll(new TaskItemGetData(data =>
+ {
+ foreach (var dataInner in data.ReturnValues)
+ {
+ Console.WriteLine(dataInner.Key + " " + dataInner.Value.PlcValue);
+ }
+
+ }, MachineGetDataType.Address, 10000, 10000));
+
+ Console.Read();
+ Console.Read();
+ }
+ }
+}
diff --git a/Modbus.Net/Modbus.Net.sln b/Modbus.Net/Modbus.Net.sln
index 94c1d72..4eac7b8 100644
--- a/Modbus.Net/Modbus.Net.sln
+++ b/Modbus.Net/Modbus.Net.sln
@@ -30,6 +30,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrossLamp", "..\Samples\Cro
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnyType", "..\Samples\AnyType\AnyType.csproj", "{25FABD48-D82E-4E08-91A4-46F7057EC954}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus.Net.PersistedTests", "Modbus.Net.PersistedTests\Modbus.Net.PersistedTests.csproj", "{5BFCA3D4-D809-485E-B69C-6F80A6A917D4}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -72,6 +74,10 @@ Global
{25FABD48-D82E-4E08-91A4-46F7057EC954}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25FABD48-D82E-4E08-91A4-46F7057EC954}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25FABD48-D82E-4E08-91A4-46F7057EC954}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5BFCA3D4-D809-485E-B69C-6F80A6A917D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5BFCA3D4-D809-485E-B69C-6F80A6A917D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5BFCA3D4-D809-485E-B69C-6F80A6A917D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5BFCA3D4-D809-485E-B69C-6F80A6A917D4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -82,6 +88,7 @@ Global
{2D939825-8459-438A-AC82-4C67A73E373E} = {145DA93A-6768-4D98-8512-AB22339933F7}
{41F40C27-AB1A-4153-BBAD-BFC7BD57B380} = {145DA93A-6768-4D98-8512-AB22339933F7}
{25FABD48-D82E-4E08-91A4-46F7057EC954} = {145DA93A-6768-4D98-8512-AB22339933F7}
+ {5BFCA3D4-D809-485E-B69C-6F80A6A917D4} = {D8DD32FC-CF39-4A1A-8FBF-9E82C5278C34}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF00D64E-3C70-474A-8A81-E9E48017C4B5}
diff --git a/Modbus.Net/Modbus.Net/BaseConnector.cs b/Modbus.Net/Modbus.Net/BaseConnector.cs
index de185da..85c5792 100644
--- a/Modbus.Net/Modbus.Net/BaseConnector.cs
+++ b/Modbus.Net/Modbus.Net/BaseConnector.cs
@@ -30,7 +30,7 @@ namespace Modbus.Net
///
/// 传输控制器
///
- protected IController Controller { get; set; }
+ protected virtual IController Controller { get; set; }
///
/// 标识Connector的连接关键字
diff --git a/Modbus.Net/Modbus.Net/BaseController.cs b/Modbus.Net/Modbus.Net/BaseController.cs
index 9547bcd..4eb02e6 100644
--- a/Modbus.Net/Modbus.Net/BaseController.cs
+++ b/Modbus.Net/Modbus.Net/BaseController.cs
@@ -30,7 +30,7 @@ namespace Modbus.Net
WaitingMessages = new List();
}
- ///
+ ///
public MessageWaitingDef AddMessage(byte[] sendMessage)
{
var def = new MessageWaitingDef
@@ -40,8 +40,11 @@ namespace Modbus.Net
SendMutex = new AutoResetEvent(false),
ReceiveMutex = new AutoResetEvent(false)
};
- AddMessageToList(def);
- return def;
+ if (AddMessageToList(def))
+ {
+ return def;
+ }
+ return null;
}
///
@@ -49,10 +52,10 @@ namespace Modbus.Net
///
protected abstract void SendingMessageControlInner();
- ///
+ ///
public abstract void SendStop();
- ///
+ ///
public void SendStart()
{
if (SendingThread == null)
@@ -61,7 +64,7 @@ namespace Modbus.Net
}
}
- ///
+ ///
public void Clear()
{
lock (WaitingMessages)
@@ -74,11 +77,16 @@ namespace Modbus.Net
/// Ϣӵ
///
/// ҪӵϢϢ
- protected virtual void AddMessageToList(MessageWaitingDef def)
+ protected virtual bool AddMessageToList(MessageWaitingDef def)
{
lock (WaitingMessages)
{
- WaitingMessages.Add(def);
+ if (WaitingMessages.FirstOrDefault(p => p.Key == def.Key) == null)
+ {
+ WaitingMessages.Add(def);
+ return true;
+ }
+ return false;
}
}
@@ -89,7 +97,7 @@ namespace Modbus.Net
/// Ϣļؼ
protected abstract string GetKeyFromMessage(byte[] message);
- ///
+ ///
public bool ConfirmMessage(byte[] receiveMessage)
{
var def = GetMessageFromWaitingList(receiveMessage);
diff --git a/Modbus.Net/Modbus.Net/ComConnector.cs b/Modbus.Net/Modbus.Net/ComConnector.cs
index cb998ae..1f35cc2 100644
--- a/Modbus.Net/Modbus.Net/ComConnector.cs
+++ b/Modbus.Net/Modbus.Net/ComConnector.cs
@@ -108,6 +108,28 @@ namespace Modbus.Net
private static Dictionary Connectors { get; } = new Dictionary()
;
+ private static Dictionary Controllers { get; } = new Dictionary()
+ ;
+
+ ///
+ protected override IController Controller {
+ get
+ {
+ if (Controllers.ContainsKey(_com))
+ {
+ return Controllers[_com];
+ }
+ return null;
+ }
+ set
+ {
+ if (!Controllers.ContainsKey(_com))
+ {
+ Controllers.Add(_com, value);
+ }
+ }
+ }
+
///
/// 连接中的连接器
///
@@ -272,9 +294,7 @@ namespace Modbus.Net
#region 发送接收数据
- ///
- /// 是否正在连接
- ///
+ ///
public override bool IsConnected
{
get
@@ -293,31 +313,33 @@ namespace Modbus.Net
{
try
{
- if (!Connectors.ContainsKey(_com))
+ lock (Connectors)
{
- Connectors.Add(_com, new SerialPortLock
+ if (!Connectors.ContainsKey(_com))
{
- PortName = _com,
- BaudRate = _baudRate,
- Parity = _parity,
- StopBits = _stopBits,
- DataBits = _dataBits,
- ReadTimeout = _timeoutTime
- });
- }
- if (!Linkers.ContainsKey(_slave))
- {
- Linkers.Add(_slave, _com);
- }
- if (!SerialPort.IsOpen)
- {
- lock (SerialPort)
+ Connectors.Add(_com, new SerialPortLock
+ {
+ PortName = _com,
+ BaudRate = _baudRate,
+ Parity = _parity,
+ StopBits = _stopBits,
+ DataBits = _dataBits,
+ ReadTimeout = _timeoutTime
+ });
+ }
+ if (!Linkers.ContainsKey(_slave))
{
- SerialPort.Open();
- ReceiveMsgThreadStart();
+ Linkers.Add(_slave, _com);
+ }
+ if (!SerialPort.IsOpen)
+ {
+ lock (SerialPort)
+ {
+ SerialPort.Open();
+ ReceiveMsgThreadStart();
+ }
}
}
-
Controller.SendStart();
Log.Information("Com client {ConnectionToken} connect success", ConnectionToken);
@@ -331,19 +353,13 @@ namespace Modbus.Net
}
}
- ///
- /// 连接串口
- ///
- /// 是否连接成功
+ ///
public override Task ConnectAsync()
{
return Task.FromResult(Connect());
}
- ///
- /// 断开串口
- ///
- /// 是否断开成功
+ ///
public override bool Disconnect()
{
if (Linkers.ContainsKey(_slave) && Connectors.ContainsKey(_com))
@@ -415,15 +431,11 @@ namespace Modbus.Net
return AsyncHelper.RunSync(() => SendMsgAsync(message));
}
- ///
- /// 发送数据,需要返回
- ///
- /// 发送的数据
- /// 是否发送成功
+ ///
public override async Task SendMsgAsync(byte[] message)
{
CheckOpen();
- var task = SendMsgInner(message).WithCancellation(new CancellationTokenSource(10000).Token);
+ var task = SendMsgInner(message).WithCancellation(new CancellationTokenSource(100000).Token);
var ans = await task;
if (task.IsCanceled)
{
@@ -434,38 +446,35 @@ namespace Modbus.Net
}
private async Task SendMsgInner(byte[] message)
- {
- var messageSendingdef = Controller.AddMessage(message);
- messageSendingdef.SendMutex.WaitOne();
- await SendMsgWithoutConfirm(message);
- messageSendingdef.ReceiveMutex.WaitOne();
- return messageSendingdef;
- }
-
- ///
- /// 发送数据,不确认
- ///
- /// 需要发送的数据
- protected override async Task SendMsgWithoutConfirm(byte[] message)
{
using (await SerialPort.Lock.LockAsync())
{
- try
- {
- Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken,
- message.Length);
- Log.Verbose(
- $"Com client {ConnectionToken} send msg: {String.Concat(message.Select(p => " " + p.ToString("X2")))}");
- await Task.Run(()=>SerialPort.Write(message, 0, message.Length));
- }
- catch (Exception err)
- {
- Log.Error(err, "Com client {ConnectionToken} send msg error", ConnectionToken);
- }
- RefreshSendCount();
+ var messageSendingdef = Controller.AddMessage(message);
+ messageSendingdef.SendMutex.WaitOne();
+ await SendMsgWithoutConfirm(message);
+ messageSendingdef.ReceiveMutex.WaitOne();
+ return messageSendingdef;
}
}
+ ///
+ protected override async Task SendMsgWithoutConfirm(byte[] message)
+ {
+ try
+ {
+ Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken,
+ message.Length);
+ Log.Verbose(
+ $"Com client {ConnectionToken} send msg: {String.Concat(message.Select(p => " " + p.ToString("X2")))}");
+ await Task.Run(() => SerialPort.Write(message, 0, message.Length));
+ }
+ catch (Exception err)
+ {
+ Log.Error(err, "Com client {ConnectionToken} send msg error", ConnectionToken);
+ }
+ RefreshSendCount();
+ }
+
///
protected override void ReceiveMsgThreadStart()
{
@@ -497,8 +506,9 @@ namespace Modbus.Net
{
//主动传输事件
}
- }
- RefreshReceiveCount();
+
+ RefreshReceiveCount();
+ }
Thread.Sleep(500);
}
@@ -515,9 +525,8 @@ namespace Modbus.Net
{
CheckOpen();
- byte[] data;
Thread.Sleep(100);
- var i = ReadComm(out data, 10, 5000, 1000);
+ var i = ReadComm(out var data, 10, 5000, 1000);
if (i > 0)
{
var returndata = new byte[i];
diff --git a/Modbus.Net/Modbus.Net/FifoController.cs b/Modbus.Net/Modbus.Net/FifoController.cs
index bb1296e..bb4c99d 100644
--- a/Modbus.Net/Modbus.Net/FifoController.cs
+++ b/Modbus.Net/Modbus.Net/FifoController.cs
@@ -31,7 +31,7 @@ namespace Modbus.Net
AcquireTime = acquireTime;
}
- ///
+ ///
protected override void SendingMessageControlInner()
{
try
@@ -54,14 +54,9 @@ namespace Modbus.Net
if (_currentSendingPos != null)
{
_currentSendingPos.SendMutex.Set();
- if (WaitingMessages.Count <= 1)
- {
- _currentSendingPos = null;
- }
- else
- {
- _currentSendingPos = WaitingMessages[WaitingMessages.IndexOf(_currentSendingPos) + 1];
- }
+ _currentSendingPos = WaitingMessages.Count <= 1
+ ? null
+ : WaitingMessages[WaitingMessages.IndexOf(_currentSendingPos) + 1];
}
}
}
@@ -77,19 +72,19 @@ namespace Modbus.Net
}
- ///
+ ///
public override void SendStop()
{
_taskCancel = true;
}
- ///
+ ///
protected override string GetKeyFromMessage(byte[] message)
{
return null;
}
- ///
+ ///
protected override MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage)
{
return WaitingMessages.FirstOrDefault();
diff --git a/Modbus.Net/Modbus.Net/MatchController.cs b/Modbus.Net/Modbus.Net/MatchController.cs
index 48f7e02..8fed36a 100644
--- a/Modbus.Net/Modbus.Net/MatchController.cs
+++ b/Modbus.Net/Modbus.Net/MatchController.cs
@@ -38,7 +38,7 @@ namespace Modbus.Net
AcquireTime = acquireTime;
}
- ///
+ ///
protected override void SendingMessageControlInner()
{
try
@@ -61,14 +61,9 @@ namespace Modbus.Net
if (_currentSendingPos != null)
{
_currentSendingPos.SendMutex.Set();
- if (WaitingMessages.Count <= 1)
- {
- _currentSendingPos = null;
- }
- else
- {
- _currentSendingPos = WaitingMessages[WaitingMessages.IndexOf(_currentSendingPos) + 1];
- }
+ _currentSendingPos = WaitingMessages.Count <= 1
+ ? null
+ : WaitingMessages[WaitingMessages.IndexOf(_currentSendingPos) + 1];
}
}
}
@@ -84,13 +79,13 @@ namespace Modbus.Net
}
- ///
+ ///
public override void SendStop()
{
_taskCancel = false;
}
- ///
+ ///
protected override string GetKeyFromMessage(byte[] message)
{
string ans = "";
@@ -106,7 +101,7 @@ namespace Modbus.Net
return ans;
}
- ///
+ ///
protected override MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage)
{
var returnKey = GetKeyFromMessage(receiveMessage);
diff --git a/Modbus.Net/Modbus.Net/TaskManager.cs b/Modbus.Net/Modbus.Net/TaskManager.cs
index d47a530..ef0c7cf 100644
--- a/Modbus.Net/Modbus.Net/TaskManager.cs
+++ b/Modbus.Net/Modbus.Net/TaskManager.cs
@@ -691,7 +691,7 @@ namespace Modbus.Net
/// 多台设备
public void AddMachines(IEnumerable machines)
{
- base.AddMachines(machines);
+ base.AddMachines(machines);
}
///
@@ -699,9 +699,9 @@ namespace Modbus.Net
///
/// 设备Id
/// 获取的设备
- public BaseMachine GetMachineById(string id)
+ public new BaseMachine GetMachineById(string id)
{
- return base.GetMachineById(id) as BaseMachine;
+ return base.GetMachineById(id) as BaseMachine;
}
///
@@ -709,9 +709,9 @@ namespace Modbus.Net
///
/// 通讯标志
/// 获取的设备
- public BaseMachine GetMachineByConnectionToken(string connectionToken)
+ public new BaseMachine GetMachineByConnectionToken(string connectionToken)
{
- return base.GetMachineByConnectionToken(connectionToken) as BaseMachine;
+ return base.GetMachineByConnectionToken(connectionToken) as BaseMachine;
}
}
@@ -808,8 +808,7 @@ namespace Modbus.Net
/// 添加一台设备
///
/// 设备
- public void AddMachine(BaseMachine machine)
- where TUnitKey : IEquatable
+ public void AddMachine(IMachineProperty machine)
{
machine.KeepConnect = KeepConnect;
lock (_machines)
@@ -822,7 +821,7 @@ namespace Modbus.Net
/// 添加多台设备
///
/// 设备的列表
- public void AddMachines(IEnumerable> machines)
+ public void AddMachines(IEnumerable> machines)
where TUnitKey : IEquatable
{
foreach (var machine in machines)
@@ -832,11 +831,9 @@ namespace Modbus.Net
///
/// 通过Id获取设备
///
- /// 设备地址Id的类型
/// 设备的Id
/// 获取设备
- public BaseMachine GetMachineById(TMachineKey id)
- where TUnitKey : IEquatable
+ public IMachineProperty GetMachineById(TMachineKey id)
{
try
{
@@ -845,7 +842,7 @@ namespace Modbus.Net
{
machine = _machines.SingleOrDefault(p => p.Machine.Id.Equals(id));
}
- return machine?.Machine as BaseMachine;
+ return machine?.Machine;
}
catch (Exception e)
{
@@ -857,11 +854,9 @@ namespace Modbus.Net
///
/// 通过通讯标志获取设备
///
- /// 设备地址Id的类型
/// 通讯标志
/// 获取的数据
- public BaseMachine GetMachineByConnectionToken(string connectionToken)
- where TUnitKey : IEquatable
+ public IMachineProperty GetMachineByConnectionToken(string connectionToken)
{
try
{
@@ -870,7 +865,7 @@ namespace Modbus.Net
{
machine = _machines.SingleOrDefault(p => p.Machine.ConnectionToken == connectionToken && p.Machine.IsConnected);
}
- return machine?.Machine as BaseMachine;
+ return machine?.Machine;
}
catch (Exception e)
{