2017-12-25 update 1 Serial Port Multistation fix

This commit is contained in:
parallelbgls
2017-12-25 17:16:46 +08:00
parent d3e25ea820
commit 7ad440c9e5
9 changed files with 291 additions and 117 deletions

View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net45; netcoreapp2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Modbus.Net.Modbus\Modbus.Net.Modbus.csproj" />
<ProjectReference Include="..\Modbus.Net.Siemens\Modbus.Net.Siemens.csproj" />
<ProjectReference Include="..\Modbus.Net\Modbus.Net.csproj" />
</ItemGroup>
</Project>

View File

@@ -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<int> machine = new ModbusMachine<int, string>(1, ModbusType.Rtu, "COM1",
new List<AddressUnit>()
{
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<int> machine2 = new ModbusMachine<int, string>(2, ModbusType.Rtu, "COM1",
new List<AddressUnit>()
{
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<int> machine3 = new ModbusMachine<int, string>(3, ModbusType.Rtu, "COM1",
new List<AddressUnit>()
{
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<int> manager = new TaskManager<int>(20, true);
manager.AddMachines<string>(new List<IMachineProperty<int>>{machine, machine2, machine3});
Random r = new Random();
manager.InvokeTimerAll(new TaskItemSetData(()=>new Dictionary<string, double>
{
{
"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();
}
}
}

View File

@@ -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}

View File

@@ -30,7 +30,7 @@ namespace Modbus.Net
/// <summary>
/// 传输控制器
/// </summary>
protected IController Controller { get; set; }
protected virtual IController Controller { get; set; }
/// <summary>
/// 标识Connector的连接关键字

View File

@@ -30,7 +30,7 @@ namespace Modbus.Net
WaitingMessages = new List<MessageWaitingDef>();
}
/// <inheritdoc cref="IController.AddMessage(byte[])" />
/// <inheritdoc />
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;
}
/// <summary>
@@ -49,10 +52,10 @@ namespace Modbus.Net
/// </summary>
protected abstract void SendingMessageControlInner();
/// <inheritdoc cref="IController.SendStop" />
/// <inheritdoc />
public abstract void SendStop();
/// <inheritdoc cref="IController.SendStart" />
/// <inheritdoc />
public void SendStart()
{
if (SendingThread == null)
@@ -61,7 +64,7 @@ namespace Modbus.Net
}
}
/// <inheritdoc cref="IController.Clear" />
/// <inheritdoc />
public void Clear()
{
lock (WaitingMessages)
@@ -74,11 +77,16 @@ namespace Modbus.Net
/// 将信息添加到队列
/// </summary>
/// <param name="def">需要添加的信息信息</param>
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
/// <returns>信息的检索关键字</returns>
protected abstract string GetKeyFromMessage(byte[] message);
/// <inheritdoc cref="IController.ConfirmMessage(byte[])" />
/// <inheritdoc />
public bool ConfirmMessage(byte[] receiveMessage)
{
var def = GetMessageFromWaitingList(receiveMessage);

View File

@@ -108,6 +108,28 @@ namespace Modbus.Net
private static Dictionary<string, SerialPortLock> Connectors { get; } = new Dictionary<string, SerialPortLock>()
;
private static Dictionary<string, IController> Controllers { get; } = new Dictionary<string, IController>()
;
/// <inheritdoc />
protected override IController Controller {
get
{
if (Controllers.ContainsKey(_com))
{
return Controllers[_com];
}
return null;
}
set
{
if (!Controllers.ContainsKey(_com))
{
Controllers.Add(_com, value);
}
}
}
/// <summary>
/// 连接中的连接器
/// </summary>
@@ -272,9 +294,7 @@ namespace Modbus.Net
#region
/// <summary>
/// 是否正在连接
/// </summary>
/// <inheritdoc />
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
}
}
/// <summary>
/// 连接串口
/// </summary>
/// <returns>是否连接成功</returns>
/// <inheritdoc />
public override Task<bool> ConnectAsync()
{
return Task.FromResult(Connect());
}
/// <summary>
/// 断开串口
/// </summary>
/// <returns>是否断开成功</returns>
/// <inheritdoc />
public override bool Disconnect()
{
if (Linkers.ContainsKey(_slave) && Connectors.ContainsKey(_com))
@@ -415,15 +431,11 @@ namespace Modbus.Net
return AsyncHelper.RunSync(() => SendMsgAsync(message));
}
/// <summary>
/// 发送数据,需要返回
/// </summary>
/// <param name="message">发送的数据</param>
/// <returns>是否发送成功</returns>
/// <inheritdoc />
public override async Task<byte[]> 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<MessageWaitingDef> SendMsgInner(byte[] message)
{
var messageSendingdef = Controller.AddMessage(message);
messageSendingdef.SendMutex.WaitOne();
await SendMsgWithoutConfirm(message);
messageSendingdef.ReceiveMutex.WaitOne();
return messageSendingdef;
}
/// <summary>
/// 发送数据,不确认
/// </summary>
/// <param name="message">需要发送的数据</param>
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;
}
}
/// <inheritdoc />
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();
}
/// <inheritdoc />
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];

View File

@@ -31,7 +31,7 @@ namespace Modbus.Net
AcquireTime = acquireTime;
}
/// <inheritdoc cref="BaseController.SendingMessageControlInner"/>
/// <inheritdoc />
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
}
/// <inheritdoc cref="BaseController.SendStop"/>
/// <inheritdoc />
public override void SendStop()
{
_taskCancel = true;
}
/// <inheritdoc cref="BaseController.GetKeyFromMessage(byte[])"/>
/// <inheritdoc />
protected override string GetKeyFromMessage(byte[] message)
{
return null;
}
/// <inheritdoc cref="BaseController.GetMessageFromWaitingList(byte[])"/>
/// <inheritdoc />
protected override MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage)
{
return WaitingMessages.FirstOrDefault();

View File

@@ -38,7 +38,7 @@ namespace Modbus.Net
AcquireTime = acquireTime;
}
/// <inheritdoc cref="BaseController.SendingMessageControlInner" />
/// <inheritdoc />
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
}
/// <inheritdoc cref="BaseController.SendStop" />
/// <inheritdoc />
public override void SendStop()
{
_taskCancel = false;
}
/// <inheritdoc cref="BaseController.GetKeyFromMessage(byte[])" />
/// <inheritdoc />
protected override string GetKeyFromMessage(byte[] message)
{
string ans = "";
@@ -106,7 +101,7 @@ namespace Modbus.Net
return ans;
}
/// <inheritdoc cref="BaseController.GetMessageFromWaitingList(byte[])" />
/// <inheritdoc />
protected override MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage)
{
var returnKey = GetKeyFromMessage(receiveMessage);

View File

@@ -691,7 +691,7 @@ namespace Modbus.Net
/// <param name="machines">多台设备</param>
public void AddMachines(IEnumerable<BaseMachine> machines)
{
base.AddMachines(machines);
base.AddMachines<string>(machines);
}
/// <summary>
@@ -699,9 +699,9 @@ namespace Modbus.Net
/// </summary>
/// <param name="id">设备Id</param>
/// <returns>获取的设备</returns>
public BaseMachine GetMachineById(string id)
public new BaseMachine GetMachineById(string id)
{
return base.GetMachineById<string>(id) as BaseMachine;
return base.GetMachineById(id) as BaseMachine;
}
/// <summary>
@@ -709,9 +709,9 @@ namespace Modbus.Net
/// </summary>
/// <param name="connectionToken">通讯标志</param>
/// <returns>获取的设备</returns>
public BaseMachine GetMachineByConnectionToken(string connectionToken)
public new BaseMachine GetMachineByConnectionToken(string connectionToken)
{
return base.GetMachineByConnectionToken<string>(connectionToken) as BaseMachine;
return base.GetMachineByConnectionToken(connectionToken) as BaseMachine;
}
}
@@ -808,8 +808,7 @@ namespace Modbus.Net
/// 添加一台设备
/// </summary>
/// <param name="machine">设备</param>
public void AddMachine<TUnitKey>(BaseMachine<TMachineKey, TUnitKey> machine)
where TUnitKey : IEquatable<TUnitKey>
public void AddMachine(IMachineProperty<TMachineKey> machine)
{
machine.KeepConnect = KeepConnect;
lock (_machines)
@@ -822,7 +821,7 @@ namespace Modbus.Net
/// 添加多台设备
/// </summary>
/// <param name="machines">设备的列表</param>
public void AddMachines<TUnitKey>(IEnumerable<BaseMachine<TMachineKey, TUnitKey>> machines)
public void AddMachines<TUnitKey>(IEnumerable<IMachineProperty<TMachineKey>> machines)
where TUnitKey : IEquatable<TUnitKey>
{
foreach (var machine in machines)
@@ -832,11 +831,9 @@ namespace Modbus.Net
/// <summary>
/// 通过Id获取设备
/// </summary>
/// <typeparam name="TUnitKey">设备地址Id的类型</typeparam>
/// <param name="id">设备的Id</param>
/// <returns>获取设备</returns>
public BaseMachine<TMachineKey, TUnitKey> GetMachineById<TUnitKey>(TMachineKey id)
where TUnitKey : IEquatable<TUnitKey>
public IMachineProperty<TMachineKey> 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<TMachineKey, TUnitKey>;
return machine?.Machine;
}
catch (Exception e)
{
@@ -857,11 +854,9 @@ namespace Modbus.Net
/// <summary>
/// 通过通讯标志获取设备
/// </summary>
/// <typeparam name="TUnitKey">设备地址Id的类型</typeparam>
/// <param name="connectionToken">通讯标志</param>
/// <returns>获取的数据</returns>
public BaseMachine<TMachineKey, TUnitKey> GetMachineByConnectionToken<TUnitKey>(string connectionToken)
where TUnitKey : IEquatable<TUnitKey>
public IMachineProperty<TMachineKey> 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<TMachineKey, TUnitKey>;
return machine?.Machine;
}
catch (Exception e)
{