2017-06-14 update 1 add modbus single write and change invoke method to get methods.

This commit is contained in:
parallelbgls
2017-06-14 12:17:40 +08:00
parent 6e01f0c1e6
commit d85aee17ee
12 changed files with 320 additions and 75 deletions

View File

@@ -18,6 +18,8 @@
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance> <PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<IncludeSymbols>True</IncludeSymbols>
<IncludeSource>True</IncludeSource>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -59,6 +61,7 @@
<PackageReference Include="Serilog" Version="2.4.0" /> <PackageReference Include="Serilog" Version="2.4.0" />
<PackageReference Include="System.Collections.NonGeneric" Version="4.3.0" /> <PackageReference Include="System.Collections.NonGeneric" Version="4.3.0" />
<PackageReference Include="System.Threading.ThreadPool" Version="4.3.0" /> <PackageReference Include="System.Threading.ThreadPool" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.3.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -3,10 +3,33 @@ using System.Linq;
namespace Modbus.Net.Modbus namespace Modbus.Net.Modbus
{ {
public abstract class ModbusTranslatorBase : AddressTranslator
{
/// <summary>
/// 地址转换
/// </summary>
/// <param name="address">格式化的地址</param>
/// <param name="isRead">是否为读取,是为读取,否为写入</param>
/// <param name="isSingle">是否只写入一个数据</param>
/// <returns>翻译后的地址</returns>
public abstract AddressDef AddressTranslate(string address, bool isRead, bool isSingle);
/// <summary>
/// 地址转换
/// </summary>
/// <param name="address">格式化的地址</param>
/// <param name="isRead">是否为读取,是为读取,否为写入</param>
/// <returns>翻译后的地址</returns>
public override AddressDef AddressTranslate(string address, bool isRead)
{
return AddressTranslate(address, isRead, false);
}
}
/// <summary> /// <summary>
/// 南大奥拓NA200H数据单元翻译器 /// 南大奥拓NA200H数据单元翻译器
/// </summary> /// </summary>
public class AddressTranslatorNA200H : AddressTranslator public class AddressTranslatorNA200H : ModbusTranslatorBase
{ {
/// <summary> /// <summary>
/// 读功能码 /// 读功能码
@@ -21,7 +44,7 @@ namespace Modbus.Net.Modbus
/// <summary> /// <summary>
/// 写功能码 /// 写功能码
/// </summary> /// </summary>
protected Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary; protected Dictionary<(string, bool), AreaOutputDef> WriteFunctionCodeDictionary;
/// <summary> /// <summary>
/// 构造器 /// 构造器
@@ -104,10 +127,10 @@ namespace Modbus.Net.Modbus
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2} new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}
} }
}; };
WriteFunctionCodeDictionary = new Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary = new Dictionary<(string, bool), AreaOutputDef>
{ {
{ {
"Q", ("Q", false),
new AreaOutputDef new AreaOutputDef
{ {
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
@@ -115,7 +138,7 @@ namespace Modbus.Net.Modbus
} }
}, },
{ {
"M", ("M", false),
new AreaOutputDef new AreaOutputDef
{ {
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
@@ -123,7 +146,7 @@ namespace Modbus.Net.Modbus
} }
}, },
{ {
"N", ("N", false),
new AreaOutputDef new AreaOutputDef
{ {
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
@@ -131,7 +154,7 @@ namespace Modbus.Net.Modbus
} }
}, },
{ {
"MW", ("MW", false),
new AreaOutputDef new AreaOutputDef
{ {
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
@@ -139,7 +162,7 @@ namespace Modbus.Net.Modbus
} }
}, },
{ {
"NW", ("NW", false),
new AreaOutputDef new AreaOutputDef
{ {
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
@@ -147,12 +170,60 @@ namespace Modbus.Net.Modbus
} }
}, },
{ {
"QW", ("QW", false),
new AreaOutputDef new AreaOutputDef
{ {
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
AreaWidth = 2 AreaWidth = 2
} }
},
{
("Q", true),
new AreaOutputDef
{
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil,
AreaWidth = 0.125
}
},
{
("M", true),
new AreaOutputDef
{
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil,
AreaWidth = 0.125
}
},
{
("N", true),
new AreaOutputDef
{
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil,
AreaWidth = 0.125
}
},
{
("MW", true),
new AreaOutputDef
{
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleRegister,
AreaWidth = 2
}
},
{
("NW", true),
new AreaOutputDef
{
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleRegister,
AreaWidth = 2
}
},
{
("QW", true),
new AreaOutputDef
{
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleRegister,
AreaWidth = 2
}
} }
}; };
} }
@@ -162,8 +233,9 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
/// <param name="address">格式化的地址</param> /// <param name="address">格式化的地址</param>
/// <param name="isRead">是否为读取,是为读取,否为写入</param> /// <param name="isRead">是否为读取,是为读取,否为写入</param>
/// <param name="isSingle">是否只写入一个数据</param>
/// <returns>翻译后的地址</returns> /// <returns>翻译后的地址</returns>
public override AddressDef AddressTranslate(string address, bool isRead) public override AddressDef AddressTranslate(string address, bool isRead, bool isSingle)
{ {
address = address.ToUpper(); address = address.ToUpper();
var splitString = address.Split(' '); var splitString = address.Split(' ');
@@ -191,7 +263,7 @@ namespace Modbus.Net.Modbus
: new AddressDef : new AddressDef
{ {
AreaString = head, AreaString = head,
Area = WriteFunctionCodeDictionary[head].Code, Area = WriteFunctionCodeDictionary[(head, isSingle)].Code,
Address = TransDictionary[head] + int.Parse(tail) - 1, Address = TransDictionary[head] + int.Parse(tail) - 1,
SubAddress = int.Parse(sub) SubAddress = int.Parse(sub)
}; };
@@ -211,7 +283,7 @@ namespace Modbus.Net.Modbus
/// <summary> /// <summary>
/// Modbus数据单元翻译器 /// Modbus数据单元翻译器
/// </summary> /// </summary>
public class AddressTranslatorModbus : AddressTranslator public class AddressTranslatorModbus : ModbusTranslatorBase
{ {
/// <summary> /// <summary>
/// 读功能码 /// 读功能码
@@ -221,7 +293,7 @@ namespace Modbus.Net.Modbus
/// <summary> /// <summary>
/// 写功能码 /// 写功能码
/// </summary> /// </summary>
protected Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary; protected Dictionary<(string, bool), AreaOutputDef> WriteFunctionCodeDictionary;
/// <summary> /// <summary>
/// 构造器 /// 构造器
@@ -255,10 +327,10 @@ namespace Modbus.Net.Modbus
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2} new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}
} }
}; };
WriteFunctionCodeDictionary = new Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary = new Dictionary<(string, bool), AreaOutputDef>
{ {
{ {
"0X", ("0X", false),
new AreaOutputDef new AreaOutputDef
{ {
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
@@ -266,12 +338,28 @@ namespace Modbus.Net.Modbus
} }
}, },
{ {
"4X", ("4X", false),
new AreaOutputDef new AreaOutputDef
{ {
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
AreaWidth = 2 AreaWidth = 2
} }
},
{
("0X", true),
new AreaOutputDef
{
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil,
AreaWidth = 0.125
}
},
{
("4X", true),
new AreaOutputDef
{
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteSingleRegister,
AreaWidth = 2
}
} }
}; };
} }
@@ -281,8 +369,9 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
/// <param name="address">格式化的地址</param> /// <param name="address">格式化的地址</param>
/// <param name="isRead">是否为读取,是为读取,否为写入</param> /// <param name="isRead">是否为读取,是为读取,否为写入</param>
/// <param name="isSingle">是否只写入一个数据</param>
/// <returns>翻译后的地址</returns> /// <returns>翻译后的地址</returns>
public override AddressDef AddressTranslate(string address, bool isRead) public override AddressDef AddressTranslate(string address, bool isRead, bool isSingle)
{ {
address = address.ToUpper(); address = address.ToUpper();
var splitString = address.Split(' '); var splitString = address.Split(' ');
@@ -310,7 +399,7 @@ namespace Modbus.Net.Modbus
: new AddressDef : new AddressDef
{ {
AreaString = head, AreaString = head,
Area = WriteFunctionCodeDictionary[head].Code, Area = WriteFunctionCodeDictionary[(head, isSingle)].Code,
Address = int.Parse(tail) - 1, Address = int.Parse(tail) - 1,
SubAddress = int.Parse(sub) SubAddress = int.Parse(sub)
}; };

View File

@@ -16,7 +16,10 @@
<RepositoryUrl>https://github.com/parallelbgls/Modbus.Net</RepositoryUrl> <RepositoryUrl>https://github.com/parallelbgls/Modbus.Net</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<PackageTags>hardware communicate protocal modbus Delian</PackageTags> <PackageTags>hardware communicate protocal modbus Delian</PackageTags>
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<IncludeSymbols>True</IncludeSymbols>
<IncludeSource>True</IncludeSource>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -385,6 +385,138 @@ namespace Modbus.Net.Modbus
} }
} }
/// <summary>
/// 写数据输入
/// </summary>
public class WriteSingleDataModbusInputStruct : IInputStruct
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="slaveAddress">从站号</param>
/// <param name="startAddress">开始地址</param>
/// <param name="writeValue">写入的数据</param>
/// <param name="addressTranslator">地址翻译器</param>
/// <param name="endian">端格式</param>
public WriteSingleDataModbusInputStruct(byte slaveAddress, string startAddress, object writeValue,
ModbusTranslatorBase addressTranslator, Endian endian)
{
SlaveAddress = slaveAddress;
var translateAddress = addressTranslator.AddressTranslate(startAddress, false, true);
FunctionCode = (byte) translateAddress.Area;
StartAddress = (ushort) translateAddress.Address;
int a = 0, b = 0;
var writeByteValue =
FunctionCode == (byte) ModbusProtocalWriteDataFunctionCode.WriteSingleCoil
? ((bool) writeValue
? new byte[] {0xFF, 0x00}
: new byte[] {0x00, 0xFF})
: ValueHelper.GetInstance(endian).GetBytes(ushort.Parse(writeValue.ToString()));
WriteValue = writeByteValue;
}
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; }
/// <summary>
/// 写入的数据
/// </summary>
public byte[] WriteValue { get; }
}
/// <summary>
/// 写数据输出
/// </summary>
public class WriteSingleDataModbusOutputStruct : IOutputStruct
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="slaveAddress">从站号</param>
/// <param name="functionCode">功能码</param>
/// <param name="startAddress">开始地址</param>
/// <param name="writeValue">写入的数据</param>
public WriteSingleDataModbusOutputStruct(byte slaveAddress, byte functionCode,
ushort startAddress, object writeValue)
{
SlaveAddress = slaveAddress;
FunctionCode = functionCode;
StartAddress = startAddress;
WriteValue = writeValue;
}
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; private set; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; private set; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; private set; }
/// <summary>
/// 写入的数据
/// </summary>
public object WriteValue { get; private set; }
}
/// <summary>
/// 写多个寄存器协议
/// </summary>
public class WriteSingleDataModbusProtocal : ProtocalUnit
{
/// <summary>
/// 格式化
/// </summary>
/// <param name="message">写寄存器参数</param>
/// <returns>写寄存器协议核心</returns>
public override byte[] Format(IInputStruct message)
{
var r_message = (WriteSingleDataModbusInputStruct) message;
var dataValue = Format(r_message.WriteValue);
var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode,
r_message.StartAddress, dataValue);
return formattingBytes;
}
/// <summary>
/// 反格式化
/// </summary>
/// <param name="messageBytes">设备返回的信息</param>
/// <param name="flag">当前反格式化的位置</param>
/// <returns>反格式化的信息</returns>
public override IOutputStruct Unformat(byte[] messageBytes, ref int flag)
{
var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var functionCode = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var startAddress = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
var writeValue = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
var returnValue = functionCode == (byte)ModbusProtocalWriteDataFunctionCode.WriteSingleCoil
? (object)(writeValue == 0xFF00) : writeValue;
return new WriteSingleDataModbusOutputStruct(slaveAddress, functionCode, startAddress,
returnValue);
}
}
#endregion #endregion
#region PLC时间 #region PLC时间

View File

@@ -25,10 +25,21 @@ namespace Modbus.Net.Modbus
Ascii = 2 Ascii = 2
} }
public interface IUtilityMethodWriteSingle : IUtilityMethod
{
/// <summary>
/// 写数据
/// </summary>
/// <param name="startAddress">起始地址</param>
/// <param name="setContent">需要设置的数据</param>
/// <returns>设置是否成功</returns>
Task<bool> SetSingleDataAsync(string startAddress, object setContent);
}
/// <summary> /// <summary>
/// Modbus基础Api入口 /// Modbus基础Api入口
/// </summary> /// </summary>
public class ModbusUtility : BaseUtility, IUtilityMethodTime public class ModbusUtility : BaseUtility, IUtilityMethodTime, IUtilityMethodWriteSingle
{ {
/// <summary> /// <summary>
/// Modbus协议类型 /// Modbus协议类型
@@ -250,5 +261,29 @@ namespace Modbus.Net.Modbus
return false; return false;
} }
} }
/// <summary>
/// 写数据
/// </summary>
/// <param name="startAddress">起始地址</param>
/// <param name="setContent">需要设置的数据</param>
/// <returns>设置是否成功</returns>
public async Task<bool> SetSingleDataAsync(string startAddress, object setContent)
{
try
{
var inputStruct = new WriteSingleDataModbusInputStruct(SlaveAddress, startAddress, setContent,
(ModbusTranslatorBase)AddressTranslator, Endian);
var outputStruct = await
Wrapper.SendReceiveAsync<WriteSingleDataModbusOutputStruct>(Wrapper[typeof(WriteSingleDataModbusProtocal)],
inputStruct);
return outputStruct?.WriteValue.ToString() == setContent.ToString();
}
catch (Exception e)
{
Log.Error(e, $"ModbusUtility -> SetSingleDatas: {ConnectionString} error");
return false;
}
}
} }
} }

View File

@@ -16,7 +16,10 @@
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<PackageTags>hardware communicate protocal OPC DA Delian</PackageTags> <PackageTags>hardware communicate protocal OPC DA Delian</PackageTags>
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance> <PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<IncludeSymbols>True</IncludeSymbols>
<IncludeSource>True</IncludeSource>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -15,7 +15,10 @@
<RepositoryUrl>https://github.com/parallelbgls/Modbus.Net</RepositoryUrl> <RepositoryUrl>https://github.com/parallelbgls/Modbus.Net</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<PackageTags>hardware communicate protocal Siemens profinet Delian</PackageTags> <PackageTags>hardware communicate protocal Siemens profinet Delian</PackageTags>
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<IncludeSymbols>True</IncludeSymbols>
<IncludeSource>True</IncludeSource>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -16,7 +16,10 @@
<Copyright>Copyright 2017 Hangzhou Delian IoT Science Technology Co.,Ltd.</Copyright> <Copyright>Copyright 2017 Hangzhou Delian IoT Science Technology Co.,Ltd.</Copyright>
<PackageTags>hardware communicate protocal Delian</PackageTags> <PackageTags>hardware communicate protocal Delian</PackageTags>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<IncludeSymbols>True</IncludeSymbols>
<IncludeSource>True</IncludeSource>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -54,6 +57,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Nito.AsyncEx" Version="4.0.1" /> <PackageReference Include="Nito.AsyncEx" Version="4.0.1" />
<PackageReference Include="Serilog" Version="2.4.0" /> <PackageReference Include="Serilog" Version="2.4.0" />
<PackageReference Include="System.ValueTuple" Version="4.3.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -243,7 +243,7 @@ namespace Modbus.Net
//获取数据 //获取数据
var datas = var datas =
await await
BaseUtility.InvokeUtilityMethod<IUtilityMethodData, Task<byte[]>>("GetDatasAsync", BaseUtility.GetUtilityMethods<IUtilityMethodData>().GetDatasAsync(
AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address,
communicateAddress.SubAddress), communicateAddress.SubAddress),
(int) (int)
@@ -446,7 +446,7 @@ namespace Modbus.Net
communicateAddress.Address); communicateAddress.Address);
var datasReturn = var datasReturn =
await BaseUtility.InvokeUtilityMethod<IUtilityMethodData, Task<byte[]>>("GetDatasAsync", await BaseUtility.GetUtilityMethods<IUtilityMethodData>().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 *
@@ -536,7 +536,7 @@ namespace Modbus.Net
} }
//写入数据 //写入数据
await await
BaseUtility.InvokeUtilityMethod<IUtilityMethodData, Task<bool>>("SetDatasAsync", addressStart, BaseUtility.GetUtilityMethods<IUtilityMethodData>().SetDatasAsync(addressStart,
valueHelper.ByteArrayToObjectArray(datas, valueHelper.ByteArrayToObjectArray(datas,
new KeyValuePair<Type, int>(communicateAddress.DataType, communicateAddress.GetCount))); new KeyValuePair<Type, int>(communicateAddress.DataType, communicateAddress.GetCount)));
} }
@@ -591,25 +591,13 @@ namespace Modbus.Net
/// </summary> /// </summary>
public string ConnectionToken => BaseUtility.ConnectionToken; public string ConnectionToken => BaseUtility.ConnectionToken;
/// <summary> public TMachineMethod GetMachineMethods<TMachineMethod>() where TMachineMethod : class, IMachineMethod
/// 调用Machine中的方法
/// </summary>
/// <typeparam name="TMachineMethod">Machine实现的接口名称</typeparam>
/// <typeparam name="TReturnType">返回值的类型</typeparam>
/// <param name="methodName">方法的名称</param>
/// <param name="parameters">方法的参数</param>
/// <returns></returns>
public TReturnType InvokeMachineMethod<TMachineMethod, TReturnType>(string methodName,
params object[] parameters) where TMachineMethod : IMachineMethod
{ {
if (this is TMachineMethod) if (this is TMachineMethod)
{ {
var t = typeof(TMachineMethod); return this as TMachineMethod;
var returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray())
.Invoke(this, parameters);
return (TReturnType) returnValue;
} }
throw new InvalidCastException($"Machine interface {nameof(TMachineMethod)} not implemented"); return null;
} }
/// <summary> /// <summary>
@@ -876,15 +864,11 @@ namespace Modbus.Net
IUtilityProperty BaseUtility { get; } IUtilityProperty BaseUtility { get; }
/// <summary> /// <summary>
/// 调用Machine中的方法 /// 获取设备的方法集合
/// </summary> /// </summary>
/// <typeparam name="TMachineMethod">Machine实现的接口名称</typeparam> /// <typeparam name="TMachineMethod">方法集合的类型</typeparam>
/// <typeparam name="TReturnType">返回值的类型</typeparam> /// <returns>设备的方法集合</returns>
/// <param name="methodName">方法的名称</param> TMachineMethod GetMachineMethods<TMachineMethod>() where TMachineMethod : class, IMachineMethod;
/// <param name="parameters">方法的参数</param>
/// <returns></returns>
TReturnType InvokeMachineMethod<TMachineMethod, TReturnType>(string methodName,
params object[] parameters) where TMachineMethod : IMachineMethod;
/// <summary> /// <summary>
/// 连接设备 /// 连接设备

View File

@@ -277,24 +277,17 @@ namespace Modbus.Net
} }
/// <summary> /// <summary>
/// 调用Utility的方法 /// 返回Utility的方法集合
/// </summary> /// </summary>
/// <typeparam name="TUtilityMethod">Utility实现的接口名称</typeparam> /// <typeparam name="TUtilityMethod">Utility方法集合类型</typeparam>
/// <typeparam name="TReturnType">返回值的类型</typeparam> /// <returns>Utility方法集合</returns>
/// <param name="methodName">方法的名称</param> public TUtilityMethod GetUtilityMethods<TUtilityMethod>() where TUtilityMethod : class, IUtilityMethod
/// <param name="parameters">方法的参数</param>
/// <returns></returns>
public TReturnType InvokeUtilityMethod<TUtilityMethod, TReturnType>(string methodName,
params object[] parameters) where TUtilityMethod : IUtilityMethod
{ {
if (this is TUtilityMethod) if (this is TUtilityMethod)
{ {
var t = typeof(TUtilityMethod); return this as TUtilityMethod;
var returnValue = t.GetRuntimeMethod(methodName, parameters.Select(p => p.GetType()).ToArray(), false)
.Invoke(this, parameters);
return (TReturnType) returnValue;
} }
throw new InvalidCastException($"Utility interface {nameof(TUtilityMethod)} not implemented"); return null;
} }
/// <summary> /// <summary>
@@ -348,14 +341,10 @@ namespace Modbus.Net
bool Disconnect(); bool Disconnect();
/// <summary> /// <summary>
/// 调用Utility的方法 /// 返回Utility的方法集合
/// </summary> /// </summary>
/// <typeparam name="TUtilityMethod">Utility实现的接口名称</typeparam> /// <typeparam name="TUtilityMethod">Utility方法集合类型</typeparam>
/// <typeparam name="TReturnType">返回值的类型</typeparam> /// <returns>Utility方法集合</returns>
/// <param name="methodName">方法的名称</param> TUtilityMethod GetUtilityMethods<TUtilityMethod>() where TUtilityMethod : class, IUtilityMethod;
/// <param name="parameters">方法的参数</param>
/// <returns></returns>
TReturnType InvokeUtilityMethod<TUtilityMethod, TReturnType>(string methodName,
params object[] parameters) where TUtilityMethod : IUtilityMethod;
} }
} }

View File

@@ -416,8 +416,8 @@ namespace Modbus.Net
cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime)); cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime));
var ans = var ans =
await tasks.StartNew( await tasks.StartNew(
async () => await machine.InvokeMachineMethod<IMachineMethodData, async () => await machine.GetMachineMethods<IMachineMethodData>()
Task<Dictionary<string, ReturnUnit>>>("GetDatasAsync", .GetDatasAsync(
getDataType).WithCancellation(cts.Token)).Unwrap(); getDataType).WithCancellation(cts.Token)).Unwrap();
return new DataReturnDef return new DataReturnDef
{ {
@@ -467,8 +467,8 @@ namespace Modbus.Net
cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime)); cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime));
var ans = var ans =
await tasks.StartNew( await tasks.StartNew(
async () => await machine.InvokeMachineMethod<IMachineMethodData, async () => await machine.GetMachineMethods<IMachineMethodData>().
Task<bool>>("SetDatasAsync", setDataType, parameters[0] SetDatasAsync(setDataType, (Dictionary<string, double>)parameters[0]
).WithCancellation(cts.Token)).Unwrap(); ).WithCancellation(cts.Token)).Unwrap();
return ans; return ans;
}; };

View File

@@ -26,9 +26,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.BaseUtility.InvokeUtilityMethod<IUtilityMethodTime, Task<bool>>("SetTimeAsync", DateTime.Now); var success = await baseMachine.BaseUtility.GetUtilityMethods<IUtilityMethodTime>().SetTimeAsync(DateTime.Now);
Assert.AreEqual(success, true); Assert.AreEqual(success, true);
var time = await baseMachine.BaseUtility.InvokeUtilityMethod<IUtilityMethodTime, Task<DateTime>>("GetTimeAsync"); var time = await baseMachine.BaseUtility.GetUtilityMethods<IUtilityMethodTime>().GetTimeAsync();
Assert.AreEqual((time.ToUniversalTime() - DateTime.Now.ToUniversalTime()).Seconds < 10, true); Assert.AreEqual((time.ToUniversalTime() - DateTime.Now.ToUniversalTime()).Seconds < 10, true);
baseMachine.Disconnect(); baseMachine.Disconnect();
} }
@@ -48,7 +48,7 @@ namespace Modbus.Net.Tests
DataType = typeof(bool) DataType = typeof(bool)
} }
}, true, 2, 0); }, true, 2, 0);
var success = await baseMachine.InvokeMachineMethod<IMachineMethodData, Task<bool>>("SetDatasAsync", var success = await baseMachine.GetMachineMethods<IMachineMethodData>().SetDatasAsync(
MachineSetDataType.Address, MachineSetDataType.Address,
new Dictionary<string, double> new Dictionary<string, double>
{ {
@@ -57,9 +57,9 @@ namespace Modbus.Net.Tests
} }
}); });
Assert.AreEqual(success, true); Assert.AreEqual(success, true);
var datas = await baseMachine.InvokeMachineMethod<IMachineMethodData, Task<Dictionary<string, ReturnUnit>>>("GetDatasAsync", MachineGetDataType.Address); var datas = await baseMachine.GetMachineMethods<IMachineMethodData>().GetDatasAsync(MachineGetDataType.Address);
Assert.AreEqual(datas["0X 1.0"].PlcValue, 1); Assert.AreEqual(datas["0X 1.0"].PlcValue, 1);
success = await baseMachine.InvokeMachineMethod<IMachineMethodData, Task<bool>>("SetDatasAsync", success = await baseMachine.GetMachineMethods<IMachineMethodData>().SetDatasAsync(
MachineSetDataType.Address, MachineSetDataType.Address,
new Dictionary<string, double> new Dictionary<string, double>
{ {