2018-01-04 Update 1 Add Siemens Connection AsyncLock
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Nito.AsyncEx;
|
||||||
|
|
||||||
namespace Modbus.Net.Siemens
|
namespace Modbus.Net.Siemens
|
||||||
{
|
{
|
||||||
@@ -9,6 +10,7 @@ namespace Modbus.Net.Siemens
|
|||||||
public class SiemensPpiProtocol : SiemensProtocol
|
public class SiemensPpiProtocol : SiemensProtocol
|
||||||
{
|
{
|
||||||
private readonly string _com;
|
private readonly string _com;
|
||||||
|
private readonly AsyncLock _lock = new AsyncLock();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造函数
|
/// 构造函数
|
||||||
@@ -71,15 +73,17 @@ namespace Modbus.Net.Siemens
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>是否连接成功</returns>
|
/// <returns>是否连接成功</returns>
|
||||||
public override async Task<bool> ConnectAsync()
|
public override async Task<bool> ConnectAsync()
|
||||||
|
{
|
||||||
|
IOutputStruct outputStruct;
|
||||||
|
using (await _lock.LockAsync())
|
||||||
{
|
{
|
||||||
if (ProtocolLinker.IsConnected) return true;
|
if (ProtocolLinker.IsConnected) return true;
|
||||||
if (!await ProtocolLinker.ConnectAsync()) return false;
|
if (!await ProtocolLinker.ConnectAsync()) return false;
|
||||||
var inputStruct = new ComCreateReferenceSiemensInputStruct(SlaveAddress, MasterAddress);
|
var inputStruct = new ComCreateReferenceSiemensInputStruct(SlaveAddress, MasterAddress);
|
||||||
var outputStruct =
|
outputStruct =
|
||||||
(await (await
|
(await (await
|
||||||
ForceSendReceiveAsync(this[typeof(ComCreateReferenceSiemensProtocol)],
|
ForceSendReceiveAsync(this[typeof(ComCreateReferenceSiemensProtocol)],
|
||||||
inputStruct)).
|
inputStruct)).SendReceiveAsync(this[typeof(ComConfirmMessageSiemensProtocol)], answer =>
|
||||||
SendReceiveAsync(this[typeof(ComConfirmMessageSiemensProtocol)], answer =>
|
|
||||||
answer != null
|
answer != null
|
||||||
? new ComConfirmMessageSiemensInputStruct(SlaveAddress, MasterAddress)
|
? new ComConfirmMessageSiemensInputStruct(SlaveAddress, MasterAddress)
|
||||||
: null)).Unwrap<ComConfirmMessageSiemensOutputStruct>();
|
: null)).Unwrap<ComConfirmMessageSiemensOutputStruct>();
|
||||||
@@ -87,6 +91,7 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
ProtocolLinker.Disconnect();
|
ProtocolLinker.Disconnect();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return outputStruct != null;
|
return outputStruct != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Nito.AsyncEx;
|
||||||
|
|
||||||
namespace Modbus.Net.Siemens
|
namespace Modbus.Net.Siemens
|
||||||
{
|
{
|
||||||
@@ -17,6 +18,7 @@ namespace Modbus.Net.Siemens
|
|||||||
private readonly byte _tdpuSize;
|
private readonly byte _tdpuSize;
|
||||||
private readonly ushort _tsapDst;
|
private readonly ushort _tsapDst;
|
||||||
private int _connectTryCount;
|
private int _connectTryCount;
|
||||||
|
private readonly AsyncLock _lock = new AsyncLock();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造函数
|
/// 构造函数
|
||||||
@@ -142,25 +144,31 @@ namespace Modbus.Net.Siemens
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>设备是否连接成功</returns>
|
/// <returns>设备是否连接成功</returns>
|
||||||
public override async Task<bool> ConnectAsync()
|
public override async Task<bool> ConnectAsync()
|
||||||
|
{
|
||||||
|
IOutputStruct outputStruct;
|
||||||
|
using (await _lock.LockAsync())
|
||||||
{
|
{
|
||||||
_connectTryCount++;
|
_connectTryCount++;
|
||||||
if (ProtocolLinker.IsConnected) return true;
|
if (ProtocolLinker.IsConnected) return true;
|
||||||
if (!await ProtocolLinker.ConnectAsync()) return false;
|
if (!await ProtocolLinker.ConnectAsync()) return false;
|
||||||
_connectTryCount = 0;
|
_connectTryCount = 0;
|
||||||
var inputStruct = new CreateReferenceSiemensInputStruct(_tdpuSize, _taspSrc, _tsapDst);
|
var inputStruct = new CreateReferenceSiemensInputStruct(_tdpuSize, _taspSrc, _tsapDst);
|
||||||
var outputStruct =
|
outputStruct =
|
||||||
//先建立连接,然后建立设备的引用
|
//先建立连接,然后建立设备的引用
|
||||||
(await (await
|
(await (await
|
||||||
ForceSendReceiveAsync(this[typeof(CreateReferenceSiemensProtocol)], inputStruct)).SendReceiveAsync(
|
ForceSendReceiveAsync(this[typeof(CreateReferenceSiemensProtocol)], inputStruct))
|
||||||
|
.SendReceiveAsync(
|
||||||
this[typeof(EstablishAssociationSiemensProtocol)], answer =>
|
this[typeof(EstablishAssociationSiemensProtocol)], answer =>
|
||||||
answer != null ?
|
answer != null
|
||||||
new EstablishAssociationSiemensInputStruct(0x0101, _maxCalling,
|
? new EstablishAssociationSiemensInputStruct(0x0101, _maxCalling,
|
||||||
_maxCalled,
|
_maxCalled,
|
||||||
_maxPdu) : null)).Unwrap<EstablishAssociationSiemensOutputStruct>();
|
_maxPdu)
|
||||||
|
: null)).Unwrap<EstablishAssociationSiemensOutputStruct>();
|
||||||
if (outputStruct == null && ProtocolLinker.IsConnected)
|
if (outputStruct == null && ProtocolLinker.IsConnected)
|
||||||
{
|
{
|
||||||
ProtocolLinker.Disconnect();
|
ProtocolLinker.Disconnect();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return outputStruct != null;
|
return outputStruct != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -401,9 +401,10 @@ namespace Modbus.Net
|
|||||||
/// <param name="returnFunc">返回值的处理函数</param>
|
/// <param name="returnFunc">返回值的处理函数</param>
|
||||||
/// <param name="getDataType">返回值的键类型</param>
|
/// <param name="getDataType">返回值的键类型</param>
|
||||||
/// <param name="timeout">任务的超时时间</param>
|
/// <param name="timeout">任务的超时时间</param>
|
||||||
public TaskItemGetData(Action<DataReturnDef> returnFunc, MachineGetDataType getDataType, int timeout = 100000)
|
/// <param name="reName">重命名,对单个设备使用多个GetData时必须填写不同的字符串</param>
|
||||||
|
public TaskItemGetData(Action<DataReturnDef> returnFunc, MachineGetDataType getDataType, int timeout = 100000, string reName = null)
|
||||||
{
|
{
|
||||||
Name = "GetDatas";
|
Name = reName ?? "GetDatas";
|
||||||
TimeoutTime = timeout;
|
TimeoutTime = timeout;
|
||||||
Invoke = async (machine, tasks, parameters, timeoutTime) =>
|
Invoke = async (machine, tasks, parameters, timeoutTime) =>
|
||||||
{
|
{
|
||||||
@@ -442,8 +443,9 @@ namespace Modbus.Net
|
|||||||
/// <param name="getCycle">循环间隔(毫秒)</param>
|
/// <param name="getCycle">循环间隔(毫秒)</param>
|
||||||
/// <param name="sleepCycle">设备离线时的循环间隔(毫秒)</param>
|
/// <param name="sleepCycle">设备离线时的循环间隔(毫秒)</param>
|
||||||
/// <param name="timeout">任务的超时时间</param>
|
/// <param name="timeout">任务的超时时间</param>
|
||||||
|
/// <param name="reName">重命名,对单个设备使用多个GetData时必须填写不同的字符串</param>
|
||||||
public TaskItemGetData(Action<DataReturnDef> returnFunc, MachineGetDataType getDataType, int getCycle,
|
public TaskItemGetData(Action<DataReturnDef> returnFunc, MachineGetDataType getDataType, int getCycle,
|
||||||
int sleepCycle, int timeout = 100000) : this(returnFunc, getDataType, timeout)
|
int sleepCycle, int timeout = 100000, string reName = null) : this(returnFunc, getDataType, timeout, reName)
|
||||||
{
|
{
|
||||||
TimerDisconnectedTime = sleepCycle;
|
TimerDisconnectedTime = sleepCycle;
|
||||||
TimerTime = getCycle;
|
TimerTime = getCycle;
|
||||||
@@ -462,9 +464,10 @@ namespace Modbus.Net
|
|||||||
/// <param name="setDataType">写入值的键类型</param>
|
/// <param name="setDataType">写入值的键类型</param>
|
||||||
/// <param name="returnFunc">返回值的处理函数</param>
|
/// <param name="returnFunc">返回值的处理函数</param>
|
||||||
/// <param name="timeout">任务的超时时间</param>
|
/// <param name="timeout">任务的超时时间</param>
|
||||||
public TaskItemSetData(Func<Dictionary<string, double>> values, MachineSetDataType setDataType, int timeout = 100000, Action<bool> returnFunc = null)
|
/// <param name="reName">重命名,对单个设备使用多个GetData时必须填写不同的字符串</param>
|
||||||
|
public TaskItemSetData(Func<Dictionary<string, double>> values, MachineSetDataType setDataType, int timeout = 100000, Action<bool> returnFunc = null, string reName = null)
|
||||||
{
|
{
|
||||||
Name = "SetDatas";
|
Name = reName ?? "SetDatas";
|
||||||
TimeoutTime = timeout;
|
TimeoutTime = timeout;
|
||||||
Invoke = async (machine, tasks, parameters, timeoutTime) =>
|
Invoke = async (machine, tasks, parameters, timeoutTime) =>
|
||||||
{
|
{
|
||||||
@@ -499,9 +502,10 @@ namespace Modbus.Net
|
|||||||
/// <param name="getCycle">循环间隔(毫秒)</param>
|
/// <param name="getCycle">循环间隔(毫秒)</param>
|
||||||
/// <param name="sleepCycle">设备离线时的循环间隔(毫秒)</param>
|
/// <param name="sleepCycle">设备离线时的循环间隔(毫秒)</param>
|
||||||
/// <param name="timeout">任务的超时时间</param>
|
/// <param name="timeout">任务的超时时间</param>
|
||||||
|
/// <param name="reName">重命名,对单个设备使用多个GetData时必须填写不同的字符串</param>
|
||||||
public TaskItemSetData(Func<Dictionary<string, double>> values, MachineSetDataType setDataType, int getCycle,
|
public TaskItemSetData(Func<Dictionary<string, double>> values, MachineSetDataType setDataType, int getCycle,
|
||||||
int sleepCycle, int timeout = 100000, Action<bool> returnFunc = null)
|
int sleepCycle, int timeout = 100000, Action<bool> returnFunc = null, string reName = null)
|
||||||
: this(values, setDataType, timeout, returnFunc)
|
: this(values, setDataType, timeout, returnFunc, reName)
|
||||||
{
|
{
|
||||||
TimerDisconnectedTime = sleepCycle;
|
TimerDisconnectedTime = sleepCycle;
|
||||||
TimerTime = getCycle;
|
TimerTime = getCycle;
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
if (_socketClient.Connected)
|
if (_socketClient.Connected)
|
||||||
{
|
{
|
||||||
_socketClient?.GetStream().Dispose();
|
_socketClient.GetStream().Dispose();
|
||||||
}
|
}
|
||||||
_socketClient?.Close();
|
_socketClient?.Close();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user