2017-06-14 update 1 add modbus single write and change invoke method to get methods.
This commit is contained in:
@@ -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>
|
||||||
@@ -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)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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'">
|
||||||
|
|||||||
@@ -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时间
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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'">
|
||||||
|
|||||||
@@ -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'">
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
/// 连接设备
|
/// 连接设备
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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>
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user