2017-05-03 update 1 Base Connector Template (Not Test)
This commit is contained in:
@@ -45,4 +45,18 @@ namespace Modbus.Net.OPC
|
|||||||
|
|
||||||
public Node RootNodeBase => RootNode;
|
public Node RootNodeBase => RootNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class OpcParamIn
|
||||||
|
{
|
||||||
|
public bool IsRead { get; set; }
|
||||||
|
public string Tag { get; set; }
|
||||||
|
public char Split { get; set; }
|
||||||
|
public object SetValue { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OpcParamOut
|
||||||
|
{
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public byte[] Value { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
public abstract class OpcConnector : BaseConnector
|
public abstract class OpcConnector : BaseConnector<OpcParamIn, OpcParamOut>
|
||||||
{
|
{
|
||||||
protected IClientExtend Client;
|
protected IClientExtend Client;
|
||||||
|
|
||||||
@@ -39,17 +39,17 @@ namespace Modbus.Net.OPC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool SendMsgWithoutReturn(byte[] message)
|
public override bool SendMsgWithoutReturn(OpcParamIn message)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task<bool> SendMsgWithoutReturnAsync(byte[] message)
|
public override Task<bool> SendMsgWithoutReturnAsync(OpcParamIn message)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] SendMsg(byte[] message)
|
public override OpcParamOut SendMsg(OpcParamIn message)
|
||||||
{
|
{
|
||||||
return AsyncHelper.RunSync(() => SendMsgAsync(message));
|
return AsyncHelper.RunSync(() => SendMsgAsync(message));
|
||||||
}
|
}
|
||||||
@@ -88,82 +88,41 @@ namespace Modbus.Net.OPC
|
|||||||
return tagSplitList.ToArray();
|
return tagSplitList.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<byte[]> SendMsgAsync(byte[] message)
|
public override async Task<OpcParamOut> SendMsgAsync(OpcParamIn message)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var pos = 0;
|
if (message.IsRead)
|
||||||
var protocal = BigEndianValueHelper.Instance.GetByte(message, ref pos);
|
|
||||||
if (protocal == 0)
|
|
||||||
{
|
{
|
||||||
var tagBytes = new byte[message.Length - 6];
|
var split = message.Split;
|
||||||
Array.Copy(message, 1, tagBytes, 0, tagBytes.Length);
|
var tag = message.Tag;
|
||||||
pos += tagBytes.Length;
|
var tagSplit = SplitTag(tag, split);
|
||||||
pos += 4;
|
|
||||||
var split = Encoding.UTF8.GetString(new[] { message[pos] });
|
|
||||||
var tag = Encoding.UTF8.GetString(tagBytes);
|
|
||||||
var tagSplit = SplitTag(tag, split[0]);
|
|
||||||
var rootDirectory = await Client.ExploreFolderAsync("");
|
var rootDirectory = await Client.ExploreFolderAsync("");
|
||||||
var answerTag = await SearchTag(tagSplit, split[0], 0, rootDirectory);
|
var answerTag = await SearchTag(tagSplit, split, 0, rootDirectory);
|
||||||
if (answerTag != null)
|
if (answerTag != null)
|
||||||
{
|
{
|
||||||
var result = await Client.ReadAsync<object>(answerTag);
|
var result = await Client.ReadAsync<object>(answerTag);
|
||||||
return BigEndianValueHelper.Instance.GetBytes(result, result.GetType());
|
return new OpcParamOut
|
||||||
|
{
|
||||||
|
Success = true,
|
||||||
|
Value = BigEndianValueHelper.Instance.GetBytes(result, result.GetType())
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return Encoding.ASCII.GetBytes("NoData");
|
return new OpcParamOut()
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Value = Encoding.ASCII.GetBytes("NoData")
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var index = 0;
|
var tag = message.Tag;
|
||||||
for (var i = 1; i < message.Length - 3; i++)
|
var split = message.Split;
|
||||||
{
|
var value = message.SetValue;
|
||||||
if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff &&
|
|
||||||
message[i + 3] == 0x00)
|
|
||||||
{
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var index2 = 0;
|
|
||||||
for (var i = index + 4; i < message.Length - 3; i++)
|
|
||||||
{
|
|
||||||
if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff &&
|
|
||||||
message[i + 3] == 0x00)
|
|
||||||
{
|
|
||||||
index2 = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var index3 = 0;
|
|
||||||
for (var i = index2 + 4; i < message.Length - 3; i++)
|
|
||||||
{
|
|
||||||
if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff &&
|
|
||||||
message[i + 3] == 0x00)
|
|
||||||
{
|
|
||||||
index3 = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var tagBytes = new byte[index - 1];
|
|
||||||
Array.Copy(message, 1, tagBytes, 0, tagBytes.Length);
|
|
||||||
var tag = Encoding.UTF8.GetString(tagBytes);
|
|
||||||
var splitBytes = new byte[index2 - index - 4];
|
|
||||||
Array.Copy(message, index + 4, splitBytes, 0, splitBytes.Length);
|
|
||||||
var split = Encoding.UTF8.GetString(splitBytes);
|
|
||||||
var typeBytes = new byte[index3 - index2 - 4];
|
|
||||||
Array.Copy(message, index2 + 4, typeBytes, 0, typeBytes.Length);
|
|
||||||
var type = Type.GetType(Encoding.UTF8.GetString(typeBytes));
|
|
||||||
var valueBytes = new byte[message.Length - index3 - 4];
|
|
||||||
Array.Copy(message, index3 + 4, valueBytes, 0, valueBytes.Length);
|
|
||||||
int mainpos = 0, subpos = 0;
|
|
||||||
var value = BigEndianValueHelper.Instance.GetValue(valueBytes, ref mainpos, ref subpos, type);
|
|
||||||
|
|
||||||
var rootDirectory = await Client.ExploreFolderAsync("");
|
var rootDirectory = await Client.ExploreFolderAsync("");
|
||||||
var tagSplit = SplitTag(tag, split[0]);
|
var tagSplit = SplitTag(tag, split);
|
||||||
var answerTag = await SearchTag(tagSplit, split[0], 0, rootDirectory);
|
var answerTag = await SearchTag(tagSplit, split, 0, rootDirectory);
|
||||||
if (answerTag != null)
|
if (answerTag != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -173,17 +132,30 @@ namespace Modbus.Net.OPC
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
AddInfo("opc write exception:" + e.Message);
|
AddInfo("opc write exception:" + e.Message);
|
||||||
return new byte[] { 0 };
|
return new OpcParamOut()
|
||||||
}
|
{
|
||||||
return new byte[] {1};
|
Success = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return new OpcParamOut()
|
||||||
|
{
|
||||||
|
Success = true
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return new byte[] {0};
|
return new OpcParamOut()
|
||||||
|
{
|
||||||
|
Success = false
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
AddInfo("opc client exception:" + e.Message);
|
AddInfo("opc client exception:" + e.Message);
|
||||||
return Encoding.ASCII.GetBytes("NoData");
|
return new OpcParamOut()
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Value = Encoding.ASCII.GetBytes("NoData")
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Modbus.Net.OPC
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opc Da协议连接器
|
/// Opc Da协议连接器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OpcDaProtocalLinker : ProtocalLinker
|
public class OpcDaProtocalLinker : OpcProtocalLinker
|
||||||
{
|
{
|
||||||
public OpcDaProtocalLinker() : this(ConfigurationManager.OpcDaHost)
|
public OpcDaProtocalLinker() : this(ConfigurationManager.OpcDaHost)
|
||||||
{
|
{
|
||||||
@@ -15,14 +15,5 @@ namespace Modbus.Net.OPC
|
|||||||
{
|
{
|
||||||
BaseConnector = OpcDaConnector.Instance(host);
|
BaseConnector = OpcDaConnector.Instance(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool? CheckRight(byte[] content)
|
|
||||||
{
|
|
||||||
if (content != null && content.Length == 6 && Encoding.ASCII.GetString(content) == "NoData")
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return base.CheckRight(content);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ namespace Modbus.Net.OPC
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opc协议
|
/// Opc协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class OpcProtocal : BaseProtocal
|
public abstract class OpcProtocal : BaseProtocal<OpcParamIn, OpcParamOut, ProtocalUnit<OpcParamIn, OpcParamOut>>
|
||||||
{
|
{
|
||||||
protected OpcProtocal() : base(0, 0, Endian.BigEndianLsb)
|
protected OpcProtocal() : base(0, 0, Endian.BigEndianLsb)
|
||||||
{
|
{
|
||||||
@@ -16,14 +16,14 @@ namespace Modbus.Net.OPC
|
|||||||
|
|
||||||
public class ReadRequestOpcInputStruct : IInputStruct
|
public class ReadRequestOpcInputStruct : IInputStruct
|
||||||
{
|
{
|
||||||
public ReadRequestOpcInputStruct(string tag, string split)
|
public ReadRequestOpcInputStruct(string tag, char split)
|
||||||
{
|
{
|
||||||
Tag = tag;
|
Tag = tag;
|
||||||
Split = split;
|
Split = split;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Tag { get; }
|
public string Tag { get; }
|
||||||
public string Split { get; }
|
public char Split { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReadRequestOpcOutputStruct : IOutputStruct
|
public class ReadRequestOpcOutputStruct : IOutputStruct
|
||||||
@@ -36,17 +36,22 @@ namespace Modbus.Net.OPC
|
|||||||
public byte[] GetValue { get; private set; }
|
public byte[] GetValue { get; private set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReadRequestOpcProtocal : ProtocalUnit, ISpecialProtocalUnit
|
public class ReadRequestOpcProtocal : ProtocalUnit<OpcParamIn, OpcParamOut>, ISpecialProtocalUnit
|
||||||
{
|
{
|
||||||
public override byte[] Format(IInputStruct message)
|
public override OpcParamIn Format(IInputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (ReadRequestOpcInputStruct) message;
|
var r_message = (ReadRequestOpcInputStruct) message;
|
||||||
return Format((byte) 0x00, Encoding.UTF8.GetBytes(r_message.Tag), 0x00ffff00, Encoding.UTF8.GetBytes(r_message.Split));
|
return new OpcParamIn()
|
||||||
|
{
|
||||||
|
IsRead = true,
|
||||||
|
Tag = r_message.Tag,
|
||||||
|
Split = r_message.Split
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IOutputStruct Unformat(byte[] messageBytes, ref int pos)
|
public override IOutputStruct Unformat(OpcParamOut messageBytes, ref int pos)
|
||||||
{
|
{
|
||||||
return new ReadRequestOpcOutputStruct(messageBytes);
|
return new ReadRequestOpcOutputStruct(messageBytes.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +61,7 @@ namespace Modbus.Net.OPC
|
|||||||
|
|
||||||
public class WriteRequestOpcInputStruct : IInputStruct
|
public class WriteRequestOpcInputStruct : IInputStruct
|
||||||
{
|
{
|
||||||
public WriteRequestOpcInputStruct(string tag, string split, object setValue)
|
public WriteRequestOpcInputStruct(string tag, char split, object setValue)
|
||||||
{
|
{
|
||||||
Tag = tag;
|
Tag = tag;
|
||||||
Split = split;
|
Split = split;
|
||||||
@@ -64,7 +69,7 @@ namespace Modbus.Net.OPC
|
|||||||
}
|
}
|
||||||
|
|
||||||
public string Tag { get; }
|
public string Tag { get; }
|
||||||
public string Split { get; }
|
public char Split { get; }
|
||||||
public object SetValue { get; }
|
public object SetValue { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,20 +83,23 @@ namespace Modbus.Net.OPC
|
|||||||
public bool WriteResult { get; private set; }
|
public bool WriteResult { get; private set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WriteRequestOpcProtocal : ProtocalUnit, ISpecialProtocalUnit
|
public class WriteRequestOpcProtocal : ProtocalUnit<OpcParamIn, OpcParamOut>, ISpecialProtocalUnit
|
||||||
{
|
{
|
||||||
public override byte[] Format(IInputStruct message)
|
public override OpcParamIn Format(IInputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (WriteRequestOpcInputStruct) message;
|
var r_message = (WriteRequestOpcInputStruct) message;
|
||||||
var tag = Encoding.UTF8.GetBytes(r_message.Tag);
|
return new OpcParamIn()
|
||||||
var fullName = Encoding.UTF8.GetBytes(r_message.SetValue.GetType().FullName);
|
{
|
||||||
var split = Encoding.UTF8.GetBytes(r_message.Split);
|
IsRead = false,
|
||||||
return Format((byte) 0x01, tag, 0x00ffff00, split, 0x00ffff00, fullName, 0x00ffff00, r_message.SetValue);
|
Tag = r_message.Tag,
|
||||||
|
Split = r_message.Split,
|
||||||
|
SetValue = r_message.SetValue
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IOutputStruct Unformat(byte[] messageBytes, ref int pos)
|
public override IOutputStruct Unformat(OpcParamOut messageBytes, ref int pos)
|
||||||
{
|
{
|
||||||
var ansByte = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var ansByte = BigEndianValueHelper.Instance.GetByte(messageBytes.Value, ref pos);
|
||||||
var ans = ansByte != 0;
|
var ans = ansByte != 0;
|
||||||
return new WriteRequestOpcOutputStruct(ans);
|
return new WriteRequestOpcOutputStruct(ans);
|
||||||
}
|
}
|
||||||
|
|||||||
24
Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs
Normal file
24
Modbus.Net/Modbus.Net.OPC/OpcProtocalLinker.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Modbus.Net.OPC
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Opc协议连接器
|
||||||
|
/// </summary>
|
||||||
|
public abstract class OpcProtocalLinker : ProtocalLinker<OpcParamIn, OpcParamOut>
|
||||||
|
{
|
||||||
|
public override bool? CheckRight(OpcParamOut content)
|
||||||
|
{
|
||||||
|
if (content == null || !content.Success) return false;
|
||||||
|
if (content.Value.Length == 6 && Encoding.ASCII.GetString(content.Value) == "NoData")
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return base.CheckRight(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ namespace Modbus.Net.OPC
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opc Da协议连接器
|
/// Opc Da协议连接器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OpcUaProtocalLinker : ProtocalLinker
|
public class OpcUaProtocalLinker : OpcProtocalLinker
|
||||||
{
|
{
|
||||||
public OpcUaProtocalLinker() : this(ConfigurationManager.OpcUaHost)
|
public OpcUaProtocalLinker() : this(ConfigurationManager.OpcUaHost)
|
||||||
{
|
{
|
||||||
@@ -19,14 +19,5 @@ namespace Modbus.Net.OPC
|
|||||||
{
|
{
|
||||||
BaseConnector = OpcUaConnector.Instance(host);
|
BaseConnector = OpcUaConnector.Instance(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool? CheckRight(byte[] content)
|
|
||||||
{
|
|
||||||
if (content != null && content.Length == 6 && Encoding.ASCII.GetString(content) == "NoData")
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return base.CheckRight(content);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
public abstract class OpcUtility : BaseUtility
|
public abstract class OpcUtility : BaseUtility<OpcParamIn, OpcParamOut>
|
||||||
{
|
{
|
||||||
protected OpcUtility(string connectionString) : base(0, 0)
|
protected OpcUtility(string connectionString) : base(0, 0)
|
||||||
{
|
{
|
||||||
@@ -30,7 +30,7 @@ namespace Modbus.Net.OPC
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var split = GetSeperator?.Invoke() ?? '/';
|
var split = GetSeperator?.Invoke() ?? '/';
|
||||||
var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress, split.ToString());
|
var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress, split);
|
||||||
var readRequestOpcOutputStruct =
|
var readRequestOpcOutputStruct =
|
||||||
await
|
await
|
||||||
Wrapper.SendReceiveAsync<ReadRequestOpcOutputStruct>(Wrapper[typeof(ReadRequestOpcProtocal)], readRequestOpcInputStruct);
|
Wrapper.SendReceiveAsync<ReadRequestOpcOutputStruct>(Wrapper[typeof(ReadRequestOpcProtocal)], readRequestOpcInputStruct);
|
||||||
@@ -47,7 +47,7 @@ namespace Modbus.Net.OPC
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var split = GetSeperator?.Invoke() ?? '/';
|
var split = GetSeperator?.Invoke() ?? '/';
|
||||||
var writeRequestOpcInputStruct = new WriteRequestOpcInputStruct(startAddress, split.ToString(), setContents[0]);
|
var writeRequestOpcInputStruct = new WriteRequestOpcInputStruct(startAddress, split, setContents[0]);
|
||||||
var writeRequestOpcOutputStruct =
|
var writeRequestOpcOutputStruct =
|
||||||
await
|
await
|
||||||
Wrapper.SendReceiveAsync<WriteRequestOpcOutputStruct>(Wrapper[typeof(WriteRequestOpcProtocal)], writeRequestOpcInputStruct);
|
Wrapper.SendReceiveAsync<WriteRequestOpcOutputStruct>(Wrapper[typeof(WriteRequestOpcProtocal)], writeRequestOpcInputStruct);
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ namespace Modbus.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设备的连接器
|
/// 设备的连接器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected BaseUtility BaseUtility { get; set; }
|
public IUtilityProperty BaseUtility { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设备的Id
|
/// 设备的Id
|
||||||
@@ -254,7 +254,7 @@ namespace Modbus.Net
|
|||||||
//获取数据
|
//获取数据
|
||||||
var datas =
|
var datas =
|
||||||
await
|
await
|
||||||
BaseUtility.GetDatasAsync(
|
BaseUtility.InvokeUtilityMethod<IUtilityData, Task<byte[]>>("GetDatasAsync",
|
||||||
AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address,
|
AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address,
|
||||||
communicateAddress.SubAddress),
|
communicateAddress.SubAddress),
|
||||||
(int)
|
(int)
|
||||||
@@ -454,7 +454,7 @@ namespace Modbus.Net
|
|||||||
var addressStart = AddressFormater.FormatAddress(communicateAddress.Area,
|
var addressStart = AddressFormater.FormatAddress(communicateAddress.Area,
|
||||||
communicateAddress.Address);
|
communicateAddress.Address);
|
||||||
|
|
||||||
var datasReturn = await BaseUtility.GetDatasAsync(
|
var datasReturn = await BaseUtility.InvokeUtilityMethod<IUtilityData, Task<byte[]>>("GetDatasAsync",
|
||||||
AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0),
|
AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0),
|
||||||
(int)
|
(int)
|
||||||
Math.Ceiling(communicateAddress.GetCount*
|
Math.Ceiling(communicateAddress.GetCount*
|
||||||
@@ -544,7 +544,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
//写入数据
|
//写入数据
|
||||||
await
|
await
|
||||||
BaseUtility.SetDatasAsync(addressStart,
|
BaseUtility.InvokeUtilityMethod<IUtilityData, Task<bool>>("SetDatasAsync",addressStart,
|
||||||
valueHelper.ByteArrayToObjectArray(datas,
|
valueHelper.ByteArrayToObjectArray(datas,
|
||||||
new KeyValuePair<Type, int>(communicateAddress.DataType, communicateAddress.GetCount)));
|
new KeyValuePair<Type, int>(communicateAddress.DataType, communicateAddress.GetCount)));
|
||||||
}
|
}
|
||||||
@@ -580,27 +580,6 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 调用Utility中的方法
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TUtilityMethod">Utility实现的接口名称</typeparam>
|
|
||||||
/// <typeparam name="TReturnType">返回值的类型</typeparam>
|
|
||||||
/// <param name="methodName">方法的名称</param>
|
|
||||||
/// <param name="parameters">方法的参数</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public TReturnType InvokeUtilityMethod<TUtilityMethod, TReturnType>(string methodName,
|
|
||||||
params object[] parameters) where TUtilityMethod : IUtilityMethod
|
|
||||||
{
|
|
||||||
if (BaseUtility is TUtilityMethod)
|
|
||||||
{
|
|
||||||
Type t = typeof(TUtilityMethod);
|
|
||||||
object returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray())
|
|
||||||
.Invoke(BaseUtility, parameters);
|
|
||||||
return (TReturnType) returnValue;
|
|
||||||
}
|
|
||||||
throw new InvalidCastException($"Utility未实现{typeof(TUtilityMethod).Name}的接口");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 调用Machine中的方法
|
/// 调用Machine中的方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -865,6 +844,11 @@ namespace Modbus.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
bool KeepConnect { get; set; }
|
bool KeepConnect { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备的连接器
|
||||||
|
/// </summary>
|
||||||
|
IUtilityProperty BaseUtility { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 调用Machine中的方法
|
/// 调用Machine中的方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -877,15 +861,10 @@ namespace Modbus.Net
|
|||||||
params object[] parameters) where TMachineMethod : IMachineMethod;
|
params object[] parameters) where TMachineMethod : IMachineMethod;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 调用Utility中的方法
|
/// 连接设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TUtilityMethod">Utility实现的接口名称</typeparam>
|
/// <returns>是否连接成功</returns>
|
||||||
/// <typeparam name="TReturnType">返回值的类型</typeparam>
|
bool Connect();
|
||||||
/// <param name="methodName">方法的名称</param>
|
|
||||||
/// <param name="parameters">方法的参数</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
TReturnType InvokeUtilityMethod<TUtilityMethod, TReturnType>(string methodName,
|
|
||||||
params object[] parameters) where TUtilityMethod : IUtilityMethod;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 连接设备
|
/// 连接设备
|
||||||
|
|||||||
@@ -8,66 +8,18 @@ namespace Modbus.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基本协议
|
/// 基本协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BaseProtocal
|
public abstract class BaseProtocal : BaseProtocal<byte[], byte[], ProtocalUnit>
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 构造器
|
|
||||||
/// </summary>
|
|
||||||
protected BaseProtocal(byte slaveAddress, byte masterAddress, Endian endian)
|
|
||||||
{
|
|
||||||
Endian = endian;
|
|
||||||
Protocals = new Dictionary<string, ProtocalUnit>();
|
|
||||||
SlaveAddress = slaveAddress;
|
|
||||||
MasterAddress = masterAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Endian Endian { get; set; }
|
|
||||||
|
|
||||||
public byte SlaveAddress { get; set; }
|
|
||||||
public byte MasterAddress { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议的连接器
|
/// 协议的连接器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ProtocalLinker ProtocalLinker { get; protected set; }
|
public new ProtocalLinker ProtocalLinker { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议
|
/// 构造器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type">协议的类的GetType</param>
|
protected BaseProtocal(byte slaveAddress, byte masterAddress, Endian endian) : base(slaveAddress, masterAddress, endian)
|
||||||
/// <returns>协议的实例</returns>
|
|
||||||
public ProtocalUnit this[Type type]
|
|
||||||
{
|
{
|
||||||
get
|
|
||||||
{
|
|
||||||
var protocalName = type.FullName;
|
|
||||||
if (Protocals.ContainsKey(protocalName))
|
|
||||||
{
|
|
||||||
return Protocals[protocalName];
|
|
||||||
}
|
|
||||||
//自动寻找存在的协议并将其加载
|
|
||||||
var protocalUnit =
|
|
||||||
Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as ProtocalUnit;
|
|
||||||
if (protocalUnit == null) throw new InvalidCastException("没有相应的协议内容");
|
|
||||||
protocalUnit.Endian = Endian;
|
|
||||||
Register(protocalUnit);
|
|
||||||
return Protocals[protocalName];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 协议集合
|
|
||||||
/// </summary>
|
|
||||||
protected Dictionary<string, ProtocalUnit> Protocals { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 注册一个协议
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="linkProtocal">需要注册的协议</param>
|
|
||||||
protected void Register(ProtocalUnit linkProtocal)
|
|
||||||
{
|
|
||||||
if (linkProtocal == null) return;
|
|
||||||
Protocals.Add(linkProtocal.GetType().FullName, linkProtocal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -85,7 +37,7 @@ namespace Modbus.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">写入的内容,使用对象数组描述</param>
|
/// <param name="content">写入的内容,使用对象数组描述</param>
|
||||||
/// <returns>从设备获取的字节流</returns>
|
/// <returns>从设备获取的字节流</returns>
|
||||||
public virtual async Task<byte[]> SendReceiveAsync(params object[] content)
|
public override async Task<byte[]> SendReceiveAsync(params object[] content)
|
||||||
{
|
{
|
||||||
if (ProtocalLinker == null || !ProtocalLinker.IsConnected)
|
if (ProtocalLinker == null || !ProtocalLinker.IsConnected)
|
||||||
{
|
{
|
||||||
@@ -97,6 +49,72 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 基本协议
|
||||||
|
/// </summary>
|
||||||
|
public abstract class BaseProtocal<TParamIn, TParamOut, TProtocalUnit> where TProtocalUnit : ProtocalUnit<TParamIn, TParamOut>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造器
|
||||||
|
/// </summary>
|
||||||
|
protected BaseProtocal(byte slaveAddress, byte masterAddress, Endian endian)
|
||||||
|
{
|
||||||
|
Endian = endian;
|
||||||
|
Protocals = new Dictionary<string, TProtocalUnit>();
|
||||||
|
SlaveAddress = slaveAddress;
|
||||||
|
MasterAddress = masterAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Endian Endian { get; set; }
|
||||||
|
|
||||||
|
public byte SlaveAddress { get; set; }
|
||||||
|
public byte MasterAddress { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议的连接器
|
||||||
|
/// </summary>
|
||||||
|
public ProtocalLinker<TParamIn, TParamOut> ProtocalLinker { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">协议的类的GetType</param>
|
||||||
|
/// <returns>协议的实例</returns>
|
||||||
|
public TProtocalUnit this[Type type]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var protocalName = type.FullName;
|
||||||
|
if (Protocals.ContainsKey(protocalName))
|
||||||
|
{
|
||||||
|
return Protocals[protocalName];
|
||||||
|
}
|
||||||
|
//自动寻找存在的协议并将其加载
|
||||||
|
var protocalUnit =
|
||||||
|
Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit;
|
||||||
|
if (protocalUnit == null) throw new InvalidCastException("没有相应的协议内容");
|
||||||
|
protocalUnit.Endian = Endian;
|
||||||
|
Register(protocalUnit);
|
||||||
|
return Protocals[protocalName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议集合
|
||||||
|
/// </summary>
|
||||||
|
protected Dictionary<string, TProtocalUnit> Protocals { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册一个协议
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="linkProtocal">需要注册的协议</param>
|
||||||
|
protected void Register(TProtocalUnit linkProtocal)
|
||||||
|
{
|
||||||
|
if (linkProtocal == null) return;
|
||||||
|
Protocals.Add(linkProtocal.GetType().FullName, linkProtocal);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送协议,通过传入需要使用的协议内容和输入结构
|
/// 发送协议,通过传入需要使用的协议内容和输入结构
|
||||||
@@ -104,7 +122,7 @@ namespace Modbus.Net
|
|||||||
/// <param name="unit">协议的实例</param>
|
/// <param name="unit">协议的实例</param>
|
||||||
/// <param name="content">输入信息的结构化描述</param>
|
/// <param name="content">输入信息的结构化描述</param>
|
||||||
/// <returns>输出信息的结构化描述</returns>
|
/// <returns>输出信息的结构化描述</returns>
|
||||||
public virtual IOutputStruct SendReceive(ProtocalUnit unit, IInputStruct content)
|
public virtual IOutputStruct SendReceive(TProtocalUnit unit, IInputStruct content)
|
||||||
{
|
{
|
||||||
return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content));
|
return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content));
|
||||||
}
|
}
|
||||||
@@ -116,7 +134,7 @@ namespace Modbus.Net
|
|||||||
/// <param name="content">输入信息的结构化描述</param>
|
/// <param name="content">输入信息的结构化描述</param>
|
||||||
/// <returns>输出信息的结构化描述</returns>
|
/// <returns>输出信息的结构化描述</returns>
|
||||||
/// <typeparam name="T">IOutputStruct的具体类型</typeparam>
|
/// <typeparam name="T">IOutputStruct的具体类型</typeparam>
|
||||||
public virtual T SendReceive<T>(ProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct
|
public virtual T SendReceive<T>(TProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct
|
||||||
{
|
{
|
||||||
return AsyncHelper.RunSync(() => SendReceiveAsync<T>(unit, content));
|
return AsyncHelper.RunSync(() => SendReceiveAsync<T>(unit, content));
|
||||||
}
|
}
|
||||||
@@ -127,7 +145,7 @@ namespace Modbus.Net
|
|||||||
/// <param name="unit">协议的实例</param>
|
/// <param name="unit">协议的实例</param>
|
||||||
/// <param name="content">输入信息的结构化描述</param>
|
/// <param name="content">输入信息的结构化描述</param>
|
||||||
/// <returns>输出信息的结构化描述</returns>
|
/// <returns>输出信息的结构化描述</returns>
|
||||||
public virtual async Task<IOutputStruct> SendReceiveAsync(ProtocalUnit unit, IInputStruct content)
|
public virtual async Task<IOutputStruct> SendReceiveAsync(TProtocalUnit unit, IInputStruct content)
|
||||||
{
|
{
|
||||||
return await SendReceiveAsync<IOutputStruct>(unit, content);
|
return await SendReceiveAsync<IOutputStruct>(unit, content);
|
||||||
}
|
}
|
||||||
@@ -139,13 +157,13 @@ namespace Modbus.Net
|
|||||||
/// <param name="content">输入信息的结构化描述</param>
|
/// <param name="content">输入信息的结构化描述</param>
|
||||||
/// <returns>输出信息的结构化描述</returns>
|
/// <returns>输出信息的结构化描述</returns>
|
||||||
/// <typeparam name="T">IOutputStruct的具体类型</typeparam>
|
/// <typeparam name="T">IOutputStruct的具体类型</typeparam>
|
||||||
public virtual async Task<T> SendReceiveAsync<T>(ProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct
|
public virtual async Task<T> SendReceiveAsync<T>(TProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct
|
||||||
{
|
{
|
||||||
var t = 0;
|
var t = 0;
|
||||||
var formatContent = unit.Format(content);
|
var formatContent = unit.Format(content);
|
||||||
if (formatContent != null)
|
if (formatContent != null)
|
||||||
{
|
{
|
||||||
byte[] receiveContent;
|
TParamOut receiveContent;
|
||||||
//如果为特别处理协议的话,跳过协议扩展收缩
|
//如果为特别处理协议的话,跳过协议扩展收缩
|
||||||
if (unit is ISpecialProtocalUnit)
|
if (unit is ISpecialProtocalUnit)
|
||||||
{
|
{
|
||||||
@@ -163,6 +181,11 @@ namespace Modbus.Net
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual async Task<byte[]> SendReceiveAsync(params object[] content)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议连接开始
|
/// 协议连接开始
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,28 +1,59 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 端格式
|
||||||
|
/// </summary>
|
||||||
public enum Endian
|
public enum Endian
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 小端
|
||||||
|
/// </summary>
|
||||||
LittleEndianLsb,
|
LittleEndianLsb,
|
||||||
|
/// <summary>
|
||||||
|
/// 大端-小端位
|
||||||
|
/// </summary>
|
||||||
BigEndianLsb,
|
BigEndianLsb,
|
||||||
|
/// <summary>
|
||||||
|
/// 大端-大端位
|
||||||
|
/// </summary>
|
||||||
BigEndianMsb
|
BigEndianMsb
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 基础Api入口
|
||||||
|
/// </summary>
|
||||||
|
public abstract class BaseUtility : BaseUtility<byte[], byte[]>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造器
|
||||||
|
/// </summary>
|
||||||
|
protected BaseUtility(byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议收发主体
|
||||||
|
/// </summary>
|
||||||
|
protected new BaseProtocal Wrapper;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基础Api入口
|
/// 基础Api入口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BaseUtility : IUtilityData
|
public abstract class BaseUtility<TParamIn, TParamOut> : IUtilityProperty, IUtilityData
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议收发主体
|
/// 协议收发主体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected BaseProtocal Wrapper;
|
protected BaseProtocal<TParamIn, TParamOut, ProtocalUnit<TParamIn, TParamOut>> Wrapper;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造器
|
/// 构造器
|
||||||
@@ -34,9 +65,18 @@ namespace Modbus.Net
|
|||||||
AddressTranslator = new AddressTranslatorBase();
|
AddressTranslator = new AddressTranslatorBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接字符串
|
||||||
|
/// </summary>
|
||||||
protected string ConnectionString { get; set; }
|
protected string ConnectionString { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从站号
|
||||||
|
/// </summary>
|
||||||
public byte SlaveAddress { get; set; }
|
public byte SlaveAddress { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 主站号
|
||||||
|
/// </summary>
|
||||||
public byte MasterAddress { get; set; }
|
public byte MasterAddress { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -241,5 +281,80 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
return Wrapper.Disconnect();
|
return Wrapper.Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调用Utility中的方法
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TUtilityMethod">Utility实现的接口名称</typeparam>
|
||||||
|
/// <typeparam name="TReturnType">返回值的类型</typeparam>
|
||||||
|
/// <param name="methodName">方法的名称</param>
|
||||||
|
/// <param name="parameters">方法的参数</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TReturnType InvokeUtilityMethod<TUtilityMethod, TReturnType>(string methodName,
|
||||||
|
params object[] parameters) where TUtilityMethod : IUtilityMethod
|
||||||
|
{
|
||||||
|
if (this is TUtilityMethod)
|
||||||
|
{
|
||||||
|
Type t = typeof(TUtilityMethod);
|
||||||
|
object returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray())
|
||||||
|
.Invoke(this, parameters);
|
||||||
|
return (TReturnType)returnValue;
|
||||||
|
}
|
||||||
|
throw new InvalidCastException($"Utility未实现{typeof(TUtilityMethod).Name}的接口");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Api入口的抽象
|
||||||
|
/// </summary>
|
||||||
|
public interface IUtilityProperty
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 协议是否遵循小端格式
|
||||||
|
/// </summary>
|
||||||
|
Endian Endian { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备是否已经连接
|
||||||
|
/// </summary>
|
||||||
|
bool IsConnected { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 标识设备的连接关键字
|
||||||
|
/// </summary>
|
||||||
|
string ConnectionToken { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 地址翻译器
|
||||||
|
/// </summary>
|
||||||
|
AddressTranslator AddressTranslator { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接设备
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>设备是否连接成功</returns>
|
||||||
|
bool Connect();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接设备
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>设备是否连接成功</returns>
|
||||||
|
Task<bool> ConnectAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 断开设备
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>设备是否断开成功</returns>
|
||||||
|
bool Disconnect();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调用Utility中的方法
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TUtilityMethod">Utility实现的接口名称</typeparam>
|
||||||
|
/// <typeparam name="TReturnType">返回值的类型</typeparam>
|
||||||
|
/// <param name="methodName">方法的名称</param>
|
||||||
|
/// <param name="parameters">方法的参数</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
TReturnType InvokeUtilityMethod<TUtilityMethod, TReturnType>(string methodName,
|
||||||
|
params object[] parameters) where TUtilityMethod : IUtilityMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,14 +3,22 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议转换的接口
|
/// 协议转换的接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IProtocalFormatting
|
public interface IProtocalFormatting : IProtocalFormatting<byte[], byte[]>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议转换的接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IProtocalFormatting<out TParamIn, in TParamOut>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从输入结构格式化
|
/// 从输入结构格式化
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">结构化的输入数据</param>
|
/// <param name="message">结构化的输入数据</param>
|
||||||
/// <returns>格式化后的字节流</returns>
|
/// <returns>格式化后的字节流</returns>
|
||||||
byte[] Format(IInputStruct message);
|
TParamIn Format(IInputStruct message);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从对象的参数数组格式化
|
/// 从对象的参数数组格式化
|
||||||
@@ -25,6 +33,15 @@
|
|||||||
/// <param name="messageBytes">返回数据的字节流</param>
|
/// <param name="messageBytes">返回数据的字节流</param>
|
||||||
/// <param name="pos">转换标记位</param>
|
/// <param name="pos">转换标记位</param>
|
||||||
/// <returns>结构化的输出数据</returns>
|
/// <returns>结构化的输出数据</returns>
|
||||||
IOutputStruct Unformat(byte[] messageBytes, ref int pos);
|
IOutputStruct Unformat(TParamOut messageBytes, ref int pos);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 把仪器返回的内容填充到输出结构中
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageBytes">返回数据的字节流</param>
|
||||||
|
/// <param name="pos">转换标记位</param>
|
||||||
|
/// <typeparam name="T">IOutputStruct的具体类型</typeparam>
|
||||||
|
/// <returns>结构化的输出数据</returns>
|
||||||
|
T Unformat<T>(TParamOut messageBytes, ref int pos) where T : class, IOutputStruct;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,9 +7,72 @@ namespace Modbus.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基本的协议连接器
|
/// 基本的协议连接器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ProtocalLinker
|
public abstract class ProtocalLinker : ProtocalLinker<byte[], byte[]>
|
||||||
{
|
{
|
||||||
protected BaseConnector BaseConnector;
|
protected new BaseConnector BaseConnector;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送并接收数据
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">发送协议的内容</param>
|
||||||
|
/// <returns>接收协议的内容</returns>
|
||||||
|
public override async Task<byte[]> SendReceiveAsync(byte[] content)
|
||||||
|
{
|
||||||
|
var extBytes = BytesExtend(content);
|
||||||
|
var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes);
|
||||||
|
return receiveBytes == null ? null : receiveBytes.Length == 0 ? receiveBytes : BytesDecact(receiveBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送并接收数据,不进行协议扩展和收缩,用于特殊协议
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">发送协议的内容</param>
|
||||||
|
/// <returns>接收协议的内容</returns>
|
||||||
|
public override async Task<byte[]> SendReceiveWithoutExtAndDecAsync(byte[] content)
|
||||||
|
{
|
||||||
|
//发送数据
|
||||||
|
var receiveBytes = await BaseConnector.SendMsgAsync(content);
|
||||||
|
//容错处理
|
||||||
|
var checkRight = CheckRight(receiveBytes);
|
||||||
|
return checkRight == null ? new byte[0] : (!checkRight.Value ? null : receiveBytes);
|
||||||
|
//返回字符
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议内容扩展,发送时根据需要扩展
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">扩展前的基本协议内容</param>
|
||||||
|
/// <returns>扩展后的协议内容</returns>
|
||||||
|
public override byte[] BytesExtend(byte[] content)
|
||||||
|
{
|
||||||
|
//自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
|
||||||
|
var bytesExtend =
|
||||||
|
Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) as
|
||||||
|
IProtocalLinkerBytesExtend;
|
||||||
|
return bytesExtend?.BytesExtend(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议内容缩减,接收时根据需要缩减
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">缩减前的完整协议内容</param>
|
||||||
|
/// <returns>缩减后的协议内容</returns>
|
||||||
|
public override byte[] BytesDecact(byte[] content)
|
||||||
|
{
|
||||||
|
//自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
|
||||||
|
var bytesExtend =
|
||||||
|
Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) as
|
||||||
|
IProtocalLinkerBytesExtend;
|
||||||
|
return bytesExtend?.BytesDecact(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 基本的协议连接器
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ProtocalLinker<TParamIn, TParamOut>
|
||||||
|
{
|
||||||
|
protected BaseConnector<TParamIn, TParamOut> BaseConnector;
|
||||||
|
|
||||||
public string ConnectionToken => BaseConnector.ConnectionToken;
|
public string ConnectionToken => BaseConnector.ConnectionToken;
|
||||||
|
|
||||||
@@ -50,7 +113,7 @@ namespace Modbus.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">发送协议的内容</param>
|
/// <param name="content">发送协议的内容</param>
|
||||||
/// <returns>接收协议的内容</returns>
|
/// <returns>接收协议的内容</returns>
|
||||||
public virtual byte[] SendReceive(byte[] content)
|
public virtual TParamOut SendReceive(TParamIn content)
|
||||||
{
|
{
|
||||||
return AsyncHelper.RunSync(() => SendReceiveAsync(content));
|
return AsyncHelper.RunSync(() => SendReceiveAsync(content));
|
||||||
}
|
}
|
||||||
@@ -60,11 +123,12 @@ namespace Modbus.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">发送协议的内容</param>
|
/// <param name="content">发送协议的内容</param>
|
||||||
/// <returns>接收协议的内容</returns>
|
/// <returns>接收协议的内容</returns>
|
||||||
public virtual async Task<byte[]> SendReceiveAsync(byte[] content)
|
public virtual async Task<TParamOut> SendReceiveAsync(TParamIn content)
|
||||||
{
|
{
|
||||||
var extBytes = BytesExtend(content);
|
var extBytes = BytesExtend(content);
|
||||||
var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes);
|
var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes);
|
||||||
return receiveBytes == null ? null : receiveBytes.Length == 0 ? receiveBytes : BytesDecact(receiveBytes);
|
if (receiveBytes != null) return receiveBytes;
|
||||||
|
throw new NullReferenceException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -72,7 +136,7 @@ namespace Modbus.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">发送协议的内容</param>
|
/// <param name="content">发送协议的内容</param>
|
||||||
/// <returns>接收协议的内容</returns>
|
/// <returns>接收协议的内容</returns>
|
||||||
public virtual byte[] SendReceiveWithoutExtAndDec(byte[] content)
|
public virtual TParamOut SendReceiveWithoutExtAndDec(TParamIn content)
|
||||||
{
|
{
|
||||||
return AsyncHelper.RunSync(() => SendReceiveWithoutExtAndDecAsync(content));
|
return AsyncHelper.RunSync(() => SendReceiveWithoutExtAndDecAsync(content));
|
||||||
}
|
}
|
||||||
@@ -82,14 +146,15 @@ namespace Modbus.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">发送协议的内容</param>
|
/// <param name="content">发送协议的内容</param>
|
||||||
/// <returns>接收协议的内容</returns>
|
/// <returns>接收协议的内容</returns>
|
||||||
public virtual async Task<byte[]> SendReceiveWithoutExtAndDecAsync(byte[] content)
|
public virtual async Task<TParamOut> SendReceiveWithoutExtAndDecAsync(TParamIn content)
|
||||||
{
|
{
|
||||||
//发送数据
|
//发送数据
|
||||||
var receiveBytes = await BaseConnector.SendMsgAsync(content);
|
var receiveBytes = await BaseConnector.SendMsgAsync(content);
|
||||||
//容错处理
|
//容错处理
|
||||||
var checkRight = CheckRight(receiveBytes);
|
var checkRight = CheckRight(receiveBytes);
|
||||||
return checkRight == null ? new byte[0] : (!checkRight.Value ? null : receiveBytes);
|
|
||||||
//返回字符
|
//返回字符
|
||||||
|
if (checkRight == true) return receiveBytes;
|
||||||
|
throw new NullReferenceException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -97,7 +162,7 @@ namespace Modbus.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">接收协议的内容</param>
|
/// <param name="content">接收协议的内容</param>
|
||||||
/// <returns>协议是否是正确的</returns>
|
/// <returns>协议是否是正确的</returns>
|
||||||
public virtual bool? CheckRight(byte[] content)
|
public virtual bool? CheckRight(TParamOut content)
|
||||||
{
|
{
|
||||||
if (content != null) return true;
|
if (content != null) return true;
|
||||||
Disconnect();
|
Disconnect();
|
||||||
@@ -109,13 +174,9 @@ namespace Modbus.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">扩展前的基本协议内容</param>
|
/// <param name="content">扩展前的基本协议内容</param>
|
||||||
/// <returns>扩展后的协议内容</returns>
|
/// <returns>扩展后的协议内容</returns>
|
||||||
public byte[] BytesExtend(byte[] content)
|
public virtual TParamIn BytesExtend(TParamIn content)
|
||||||
{
|
{
|
||||||
//自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
|
throw new NotImplementedException();
|
||||||
var bytesExtend =
|
|
||||||
Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) as
|
|
||||||
IProtocalLinkerBytesExtend;
|
|
||||||
return bytesExtend?.BytesExtend(content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -123,13 +184,9 @@ namespace Modbus.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">缩减前的完整协议内容</param>
|
/// <param name="content">缩减前的完整协议内容</param>
|
||||||
/// <returns>缩减后的协议内容</returns>
|
/// <returns>缩减后的协议内容</returns>
|
||||||
public byte[] BytesDecact(byte[] content)
|
public virtual TParamOut BytesDecact(TParamOut content)
|
||||||
{
|
{
|
||||||
//自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
|
throw new NotImplementedException();
|
||||||
var bytesExtend =
|
|
||||||
Activator.CreateInstance(GetType().GetTypeInfo().Assembly.GetType(GetType().FullName + "BytesExtend")) as
|
|
||||||
IProtocalLinkerBytesExtend;
|
|
||||||
return bytesExtend?.BytesDecact(content);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,15 @@ namespace Modbus.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议单元
|
/// 协议单元
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ProtocalUnit : IProtocalFormatting
|
public abstract class ProtocalUnit : ProtocalUnit<byte[], byte[]>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议单元
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ProtocalUnit<TParamIn, TParamOut> : IProtocalFormatting<TParamIn, TParamOut>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否为小端格式
|
/// 是否为小端格式
|
||||||
@@ -17,7 +25,7 @@ namespace Modbus.Net
|
|||||||
/// </summary>s
|
/// </summary>s
|
||||||
/// <param name="message">结构化的输入数据</param>
|
/// <param name="message">结构化的输入数据</param>
|
||||||
/// <returns>格式化后的字节流</returns>
|
/// <returns>格式化后的字节流</returns>
|
||||||
public abstract byte[] Format(IInputStruct message);
|
public abstract TParamIn Format(IInputStruct message);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从对象的参数数组格式化
|
/// 从对象的参数数组格式化
|
||||||
@@ -35,7 +43,7 @@ namespace Modbus.Net
|
|||||||
/// <param name="messageBytes">返回数据的字节流</param>
|
/// <param name="messageBytes">返回数据的字节流</param>
|
||||||
/// <param name="pos">转换标记位</param>
|
/// <param name="pos">转换标记位</param>
|
||||||
/// <returns>结构化的输出数据</returns>
|
/// <returns>结构化的输出数据</returns>
|
||||||
public abstract IOutputStruct Unformat(byte[] messageBytes, ref int pos);
|
public abstract IOutputStruct Unformat(TParamOut messageBytes, ref int pos);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 把仪器返回的内容填充到输出结构中
|
/// 把仪器返回的内容填充到输出结构中
|
||||||
@@ -44,7 +52,7 @@ namespace Modbus.Net
|
|||||||
/// <param name="pos">转换标记位</param>
|
/// <param name="pos">转换标记位</param>
|
||||||
/// <typeparam name="T">IOutputStruct的具体类型</typeparam>
|
/// <typeparam name="T">IOutputStruct的具体类型</typeparam>
|
||||||
/// <returns>结构化的输出数据</returns>
|
/// <returns>结构化的输出数据</returns>
|
||||||
public T Unformat<T>(byte[] messageBytes, ref int pos) where T : class, IOutputStruct
|
public T Unformat<T>(TParamOut messageBytes, ref int pos) where T : class, IOutputStruct
|
||||||
{
|
{
|
||||||
return Unformat(messageBytes, ref pos) as T;
|
return Unformat(messageBytes, ref pos) as T;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ namespace TripleAdd.Controllers
|
|||||||
new AddressUnit() {Id = "3", Area = "4X", Address = 3, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
new AddressUnit() {Id = "3", Area = "4X", Address = 3, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||||
new AddressUnit() {Id = "4", Area = "4X", Address = 4, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
new AddressUnit() {Id = "4", Area = "4X", Address = 4, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||||
}, 2, 0);
|
}, 2, 0);
|
||||||
machine.AddressCombiner = new AddressCombinerContinus(machine.AddressTranslator);
|
machine.AddressCombiner = new AddressCombinerContinus(machine.AddressTranslator, 100000);
|
||||||
machine.AddressCombinerSet = new AddressCombinerContinus(machine.AddressTranslator);
|
machine.AddressCombinerSet = new AddressCombinerContinus(machine.AddressTranslator, 100000);
|
||||||
}
|
}
|
||||||
var resultFormat = (await machine.GetDatasAsync(MachineGetDataType.CommunicationTag)).MapGetValuesToSetValues();
|
var resultFormat = (await machine.GetDatasAsync(MachineGetDataType.CommunicationTag)).MapGetValuesToSetValues();
|
||||||
return SetValue(new ushort[4] { (ushort)resultFormat["Add1"], (ushort)resultFormat["Add2"], (ushort)resultFormat["Add3"], (ushort)resultFormat["Ans"] });
|
return SetValue(new ushort[4] { (ushort)resultFormat["Add1"], (ushort)resultFormat["Add2"], (ushort)resultFormat["Add3"], (ushort)resultFormat["Ans"] });
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ namespace Modbus.Net.Tests
|
|||||||
public async Task InvokeUtility()
|
public async Task InvokeUtility()
|
||||||
{
|
{
|
||||||
BaseMachine<int, int> baseMachine = new ModbusMachine<int, int>(ModbusType.Tcp, "192.168.3.12", null, true, 2, 0);
|
BaseMachine<int, int> baseMachine = new ModbusMachine<int, int>(ModbusType.Tcp, "192.168.3.12", null, true, 2, 0);
|
||||||
var success = await baseMachine.InvokeUtilityMethod<IUtilityTime, Task<bool>>("SetTimeAsync", DateTime.Now);
|
var success = await baseMachine.BaseUtility.InvokeUtilityMethod<IUtilityTime, Task<bool>>("SetTimeAsync", DateTime.Now);
|
||||||
Assert.AreEqual(success, true);
|
Assert.AreEqual(success, true);
|
||||||
var time = await baseMachine.InvokeUtilityMethod<IUtilityTime, Task<DateTime>>("GetTimeAsync");
|
var time = await baseMachine.BaseUtility.InvokeUtilityMethod<IUtilityTime, Task<DateTime>>("GetTimeAsync");
|
||||||
Assert.AreEqual((time.ToUniversalTime() - DateTime.Now.ToUniversalTime()).Seconds < 10, true);
|
Assert.AreEqual((time.ToUniversalTime() - DateTime.Now.ToUniversalTime()).Seconds < 10, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user