2017-06-14 update 1 add modbus single write and change invoke method to get methods.
This commit is contained in:
@@ -3,10 +3,33 @@ using System.Linq;
|
||||
|
||||
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>
|
||||
/// 南大奥拓NA200H数据单元翻译器
|
||||
/// </summary>
|
||||
public class AddressTranslatorNA200H : AddressTranslator
|
||||
public class AddressTranslatorNA200H : ModbusTranslatorBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 读功能码
|
||||
@@ -21,7 +44,7 @@ namespace Modbus.Net.Modbus
|
||||
/// <summary>
|
||||
/// 写功能码
|
||||
/// </summary>
|
||||
protected Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary;
|
||||
protected Dictionary<(string, bool), AreaOutputDef> WriteFunctionCodeDictionary;
|
||||
|
||||
/// <summary>
|
||||
/// 构造器
|
||||
@@ -104,10 +127,10 @@ namespace Modbus.Net.Modbus
|
||||
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}
|
||||
}
|
||||
};
|
||||
WriteFunctionCodeDictionary = new Dictionary<string, AreaOutputDef>
|
||||
WriteFunctionCodeDictionary = new Dictionary<(string, bool), AreaOutputDef>
|
||||
{
|
||||
{
|
||||
"Q",
|
||||
("Q", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||
@@ -115,7 +138,7 @@ namespace Modbus.Net.Modbus
|
||||
}
|
||||
},
|
||||
{
|
||||
"M",
|
||||
("M", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||
@@ -123,7 +146,7 @@ namespace Modbus.Net.Modbus
|
||||
}
|
||||
},
|
||||
{
|
||||
"N",
|
||||
("N", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||
@@ -131,7 +154,7 @@ namespace Modbus.Net.Modbus
|
||||
}
|
||||
},
|
||||
{
|
||||
"MW",
|
||||
("MW", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
|
||||
@@ -139,7 +162,7 @@ namespace Modbus.Net.Modbus
|
||||
}
|
||||
},
|
||||
{
|
||||
"NW",
|
||||
("NW", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
|
||||
@@ -147,12 +170,60 @@ namespace Modbus.Net.Modbus
|
||||
}
|
||||
},
|
||||
{
|
||||
"QW",
|
||||
("QW", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
|
||||
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>
|
||||
/// <param name="address">格式化的地址</param>
|
||||
/// <param name="isRead">是否为读取,是为读取,否为写入</param>
|
||||
/// <param name="isSingle">是否只写入一个数据</param>
|
||||
/// <returns>翻译后的地址</returns>
|
||||
public override AddressDef AddressTranslate(string address, bool isRead)
|
||||
public override AddressDef AddressTranslate(string address, bool isRead, bool isSingle)
|
||||
{
|
||||
address = address.ToUpper();
|
||||
var splitString = address.Split(' ');
|
||||
@@ -191,7 +263,7 @@ namespace Modbus.Net.Modbus
|
||||
: new AddressDef
|
||||
{
|
||||
AreaString = head,
|
||||
Area = WriteFunctionCodeDictionary[head].Code,
|
||||
Area = WriteFunctionCodeDictionary[(head, isSingle)].Code,
|
||||
Address = TransDictionary[head] + int.Parse(tail) - 1,
|
||||
SubAddress = int.Parse(sub)
|
||||
};
|
||||
@@ -211,7 +283,7 @@ namespace Modbus.Net.Modbus
|
||||
/// <summary>
|
||||
/// Modbus数据单元翻译器
|
||||
/// </summary>
|
||||
public class AddressTranslatorModbus : AddressTranslator
|
||||
public class AddressTranslatorModbus : ModbusTranslatorBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 读功能码
|
||||
@@ -221,7 +293,7 @@ namespace Modbus.Net.Modbus
|
||||
/// <summary>
|
||||
/// 写功能码
|
||||
/// </summary>
|
||||
protected Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary;
|
||||
protected Dictionary<(string, bool), AreaOutputDef> WriteFunctionCodeDictionary;
|
||||
|
||||
/// <summary>
|
||||
/// 构造器
|
||||
@@ -255,10 +327,10 @@ namespace Modbus.Net.Modbus
|
||||
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}
|
||||
}
|
||||
};
|
||||
WriteFunctionCodeDictionary = new Dictionary<string, AreaOutputDef>
|
||||
WriteFunctionCodeDictionary = new Dictionary<(string, bool), AreaOutputDef>
|
||||
{
|
||||
{
|
||||
"0X",
|
||||
("0X", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||
@@ -266,12 +338,28 @@ namespace Modbus.Net.Modbus
|
||||
}
|
||||
},
|
||||
{
|
||||
"4X",
|
||||
("4X", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
|
||||
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>
|
||||
/// <param name="address">格式化的地址</param>
|
||||
/// <param name="isRead">是否为读取,是为读取,否为写入</param>
|
||||
/// <param name="isSingle">是否只写入一个数据</param>
|
||||
/// <returns>翻译后的地址</returns>
|
||||
public override AddressDef AddressTranslate(string address, bool isRead)
|
||||
public override AddressDef AddressTranslate(string address, bool isRead, bool isSingle)
|
||||
{
|
||||
address = address.ToUpper();
|
||||
var splitString = address.Split(' ');
|
||||
@@ -310,7 +399,7 @@ namespace Modbus.Net.Modbus
|
||||
: new AddressDef
|
||||
{
|
||||
AreaString = head,
|
||||
Area = WriteFunctionCodeDictionary[head].Code,
|
||||
Area = WriteFunctionCodeDictionary[(head, isSingle)].Code,
|
||||
Address = int.Parse(tail) - 1,
|
||||
SubAddress = int.Parse(sub)
|
||||
};
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
<RepositoryUrl>https://github.com/parallelbgls/Modbus.Net</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>hardware communicate protocal modbus Delian</PackageTags>
|
||||
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<IncludeSymbols>True</IncludeSymbols>
|
||||
<IncludeSource>True</IncludeSource>
|
||||
</PropertyGroup>
|
||||
|
||||
<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
|
||||
|
||||
#region 读PLC时间
|
||||
|
||||
@@ -25,10 +25,21 @@ namespace Modbus.Net.Modbus
|
||||
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>
|
||||
/// Modbus基础Api入口
|
||||
/// </summary>
|
||||
public class ModbusUtility : BaseUtility, IUtilityMethodTime
|
||||
public class ModbusUtility : BaseUtility, IUtilityMethodTime, IUtilityMethodWriteSingle
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus协议类型
|
||||
@@ -250,5 +261,29 @@ namespace Modbus.Net.Modbus
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user