2017-09-26 update 1 Update to .Net Standard 2.0
This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// 南大奥拓NA200H专用AddressFormater
|
||||
/// </summary>
|
||||
public class AddressFormaterNA200H : AddressFormater
|
||||
{
|
||||
/// <summary>
|
||||
/// 格式化地址
|
||||
/// </summary>
|
||||
/// <param name="area">地址区域</param>
|
||||
/// <param name="address">地址</param>
|
||||
/// <returns>格式化的地址字符串</returns>
|
||||
public override string FormatAddress(string area, int address)
|
||||
{
|
||||
return area + " " + address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化地址
|
||||
/// </summary>
|
||||
/// <param name="area">地址区域</param>
|
||||
/// <param name="address">地址</param>
|
||||
/// <param name="subAddress">比特位地址</param>
|
||||
/// <returns>格式化的地址字符串</returns>
|
||||
public override string FormatAddress(string area, int address, int subAddress)
|
||||
{
|
||||
return area + " " + address + "." + subAddress;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modbus标准AddressFormater
|
||||
/// </summary>
|
||||
public class AddressFormaterModbus : AddressFormater
|
||||
{
|
||||
/// <summary>
|
||||
/// 格式化地址
|
||||
/// </summary>
|
||||
/// <param name="area">地址区域</param>
|
||||
/// <param name="address">地址</param>
|
||||
/// <returns>格式化的地址字符串</returns>
|
||||
public override string FormatAddress(string area, int address)
|
||||
{
|
||||
return area + " " + address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化地址
|
||||
/// </summary>
|
||||
/// <param name="area">地址区域</param>
|
||||
/// <param name="address">地址</param>
|
||||
/// <param name="subAddress">比特位地址</param>
|
||||
/// <returns>格式化的地址字符串</returns>
|
||||
public override string FormatAddress(string area, int address, int subAddress)
|
||||
{
|
||||
return area + " " + address + "." + subAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,418 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
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 : ModbusTranslatorBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 读功能码
|
||||
/// </summary>
|
||||
protected Dictionary<string, AreaOutputDef> ReadFunctionCodeDictionary;
|
||||
|
||||
/// <summary>
|
||||
/// 功能码翻译至标准Modbus地址位置
|
||||
/// </summary>
|
||||
protected Dictionary<string, int> TransDictionary;
|
||||
|
||||
/// <summary>
|
||||
/// 写功能码
|
||||
/// </summary>
|
||||
protected Dictionary<(string, bool), AreaOutputDef> WriteFunctionCodeDictionary;
|
||||
|
||||
/// <summary>
|
||||
/// 构造器
|
||||
/// </summary>
|
||||
public AddressTranslatorNA200H()
|
||||
{
|
||||
TransDictionary = new Dictionary<string, int>
|
||||
{
|
||||
{"Q", 0},
|
||||
{"M", 10000},
|
||||
{"N", 30000},
|
||||
{"I", 0},
|
||||
{"S", 10000},
|
||||
{"IW", 0},
|
||||
{"SW", 5000},
|
||||
{"MW", 0},
|
||||
{"QW", 20000},
|
||||
{"NW", 21000}
|
||||
};
|
||||
ReadFunctionCodeDictionary = new Dictionary<string, AreaOutputDef>
|
||||
{
|
||||
{
|
||||
"Q",
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalReadDataFunctionCode.ReadCoilStatus,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
"M",
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalReadDataFunctionCode.ReadCoilStatus,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
"N",
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalReadDataFunctionCode.ReadCoilStatus,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
"I",
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalReadDataFunctionCode.ReadInputStatus,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
"S",
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalReadDataFunctionCode.ReadInputStatus,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
"IW",
|
||||
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadInputRegister, AreaWidth = 2}
|
||||
},
|
||||
{
|
||||
"SW",
|
||||
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadInputRegister, AreaWidth = 2}
|
||||
},
|
||||
{
|
||||
"MW",
|
||||
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}
|
||||
},
|
||||
{
|
||||
"NW",
|
||||
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}
|
||||
},
|
||||
{
|
||||
"QW",
|
||||
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}
|
||||
}
|
||||
};
|
||||
WriteFunctionCodeDictionary = new Dictionary<(string, bool), AreaOutputDef>
|
||||
{
|
||||
{
|
||||
("Q", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
("M", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
("N", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
("MW", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
|
||||
AreaWidth = 2
|
||||
}
|
||||
},
|
||||
{
|
||||
("NW", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
|
||||
AreaWidth = 2
|
||||
}
|
||||
},
|
||||
{
|
||||
("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
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 地址转换
|
||||
/// </summary>
|
||||
/// <param name="address">格式化的地址</param>
|
||||
/// <param name="isRead">是否为读取,是为读取,否为写入</param>
|
||||
/// <param name="isSingle">是否只写入一个数据</param>
|
||||
/// <returns>翻译后的地址</returns>
|
||||
public override AddressDef AddressTranslate(string address, bool isRead, bool isSingle)
|
||||
{
|
||||
address = address.ToUpper();
|
||||
var splitString = address.Split(' ');
|
||||
var head = splitString[0];
|
||||
var tail = splitString[1];
|
||||
string sub;
|
||||
if (tail.Contains('.'))
|
||||
{
|
||||
var splitString2 = tail.Split('.');
|
||||
sub = splitString2[1];
|
||||
tail = splitString2[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
sub = "0";
|
||||
}
|
||||
return isRead
|
||||
? new AddressDef
|
||||
{
|
||||
AreaString = head,
|
||||
Area = ReadFunctionCodeDictionary[head].Code,
|
||||
Address = TransDictionary[head] + int.Parse(tail) - 1,
|
||||
SubAddress = int.Parse(sub)
|
||||
}
|
||||
: new AddressDef
|
||||
{
|
||||
AreaString = head,
|
||||
Area = WriteFunctionCodeDictionary[(head, isSingle)].Code,
|
||||
Address = TransDictionary[head] + int.Parse(tail) - 1,
|
||||
SubAddress = int.Parse(sub)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取区域中的单个地址占用的字节长度
|
||||
/// </summary>
|
||||
/// <param name="area">区域名称</param>
|
||||
/// <returns>字节长度</returns>
|
||||
public override double GetAreaByteLength(string area)
|
||||
{
|
||||
return ReadFunctionCodeDictionary[area].AreaWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modbus数据单元翻译器
|
||||
/// </summary>
|
||||
public class AddressTranslatorModbus : ModbusTranslatorBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 读功能码
|
||||
/// </summary>
|
||||
protected Dictionary<string, AreaOutputDef> ReadFunctionCodeDictionary;
|
||||
|
||||
/// <summary>
|
||||
/// 写功能码
|
||||
/// </summary>
|
||||
protected Dictionary<(string, bool), AreaOutputDef> WriteFunctionCodeDictionary;
|
||||
|
||||
/// <summary>
|
||||
/// 构造器
|
||||
/// </summary>
|
||||
public AddressTranslatorModbus()
|
||||
{
|
||||
ReadFunctionCodeDictionary = new Dictionary<string, AreaOutputDef>
|
||||
{
|
||||
{
|
||||
"0X",
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalReadDataFunctionCode.ReadCoilStatus,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
"1X",
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalReadDataFunctionCode.ReadInputStatus,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
"3X",
|
||||
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadInputRegister, AreaWidth = 2}
|
||||
},
|
||||
{
|
||||
"4X",
|
||||
new AreaOutputDef {Code = (int) ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}
|
||||
}
|
||||
};
|
||||
WriteFunctionCodeDictionary = new Dictionary<(string, bool), AreaOutputDef>
|
||||
{
|
||||
{
|
||||
("0X", false),
|
||||
new AreaOutputDef
|
||||
{
|
||||
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||
AreaWidth = 0.125
|
||||
}
|
||||
},
|
||||
{
|
||||
("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
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 地址转换
|
||||
/// </summary>
|
||||
/// <param name="address">格式化的地址</param>
|
||||
/// <param name="isRead">是否为读取,是为读取,否为写入</param>
|
||||
/// <param name="isSingle">是否只写入一个数据</param>
|
||||
/// <returns>翻译后的地址</returns>
|
||||
public override AddressDef AddressTranslate(string address, bool isRead, bool isSingle)
|
||||
{
|
||||
address = address.ToUpper();
|
||||
var splitString = address.Split(' ');
|
||||
var head = splitString[0];
|
||||
var tail = splitString[1];
|
||||
string sub;
|
||||
if (tail.Contains('.'))
|
||||
{
|
||||
var splitString2 = tail.Split('.');
|
||||
sub = splitString2[1];
|
||||
tail = splitString2[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
sub = "0";
|
||||
}
|
||||
return isRead
|
||||
? new AddressDef
|
||||
{
|
||||
AreaString = head,
|
||||
Area = ReadFunctionCodeDictionary[head].Code,
|
||||
Address = int.Parse(tail) - 1,
|
||||
SubAddress = int.Parse(sub)
|
||||
}
|
||||
: new AddressDef
|
||||
{
|
||||
AreaString = head,
|
||||
Area = WriteFunctionCodeDictionary[(head, isSingle)].Code,
|
||||
Address = int.Parse(tail) - 1,
|
||||
SubAddress = int.Parse(sub)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取区域中的单个地址占用的字节长度
|
||||
/// </summary>
|
||||
/// <param name="area">区域名称</param>
|
||||
/// <returns>字节长度</returns>
|
||||
public override double GetAreaByteLength(string area)
|
||||
{
|
||||
return ReadFunctionCodeDictionary[area].AreaWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<AssemblyName>Modbus.Net.Modbus</AssemblyName>
|
||||
<RootNamespace>Modbus.Net.Modbus</RootNamespace>
|
||||
<PackageId>Modbus.Net.Modbus</PackageId>
|
||||
<Version>1.3.9</Version>
|
||||
<Version>1.3.10</Version>
|
||||
<Authors>Chris L.(Luo Sheng)</Authors>
|
||||
<Company>Hangzhou Delian IoT Science Technology Co.,Ltd.</Company>
|
||||
<Product>Modbus.Net.Modbus</Product>
|
||||
@@ -30,11 +30,30 @@
|
||||
<ProjectReference Include="..\Modbus.Net\Modbus.Net.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\src\Modbus.Common\AddressFormaterModbus.cs" Link="AddressFormaterModbus.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\AddressTranslatorModbus.cs" Link="AddressTranslatorModbus.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusAsciiProtocal.cs" Link="ModbusAsciiProtocal.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusAsciiProtocalLinker.cs" Link="ModbusAsciiProtocalLinker.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusAsciiInTcpProtocal.cs" Link="ModbusAsciiInTcpProtocal.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusAsciiInTcpProtocalLinker.cs" Link="ModbusAsciiInTcpProtocalLinker.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusMachine.cs" Link="ModbusMachine.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusProtocal.cs" Link="ModbusProtocal.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusProtocalLinkerBytesExtend.cs" Link="ModbusProtocalLinkerBytesExtend.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusRtuProtocal.cs" Link="ModbusRtuProtocal.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusRtuProtocalLinker.cs" Link="ModbusRtuProtocalLinker.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusRtuInTcpProtocal.cs" Link="ModbusRtuInTcpProtocal.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusRtuInTcpProtocalLinker.cs" Link="ModbusRtuInTcpProtocalLinker.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusTcpProtocal.cs" Link="ModbusTcpProtocal.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusTcpProtocalLinker.cs" Link="ModbusTcpProtocalLinker.cs" />
|
||||
<Compile Include="..\src\Modbus.Common\ModbusUtility.cs" Link="ModbusUtility.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Configuration" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.ValueTuple" Version="4.3.1" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.4.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,34 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus/Ascii码协议
|
||||
/// </summary>
|
||||
public class ModbusAsciiProtocal : ModbusProtocal
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusAsciiProtocal(byte slaveAddress, byte masterAddress, Endian endian)
|
||||
: this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress, endian)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="com">串口地址</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusAsciiProtocal(string com, byte slaveAddress, byte masterAddress, Endian endian)
|
||||
: base(slaveAddress, masterAddress, endian)
|
||||
{
|
||||
ProtocalLinker = new ModbusAsciiProtocalLinker(com, slaveAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System.IO.Ports;
|
||||
using System.Text;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus/Ascii码协议连接器
|
||||
/// </summary>
|
||||
public class ModbusAsciiProtocalLinker : ComProtocalLinker
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="com">串口地址</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
public ModbusAsciiProtocalLinker(string com, int slaveAddress)
|
||||
: base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验返回数据是否正确
|
||||
/// </summary>
|
||||
/// <param name="content">返回的数据</param>
|
||||
/// <returns>校验是否正确</returns>
|
||||
public override bool? CheckRight(byte[] content)
|
||||
{
|
||||
//ProtocalLinker不会返回null
|
||||
if (!base.CheckRight(content).Value) return false;
|
||||
//CRC校验失败
|
||||
var contentString = Encoding.ASCII.GetString(content);
|
||||
if (!Crc16.GetInstance().LrcEfficacy(contentString))
|
||||
throw new ModbusProtocalErrorException(501);
|
||||
//Modbus协议错误
|
||||
if (byte.Parse(contentString.Substring(3, 2)) > 127)
|
||||
throw new ModbusProtocalErrorException(byte.Parse(contentString.Substring(5, 2)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus设备
|
||||
/// </summary>
|
||||
public class ModbusMachine<TKey, TUnitKey> : BaseMachine<TKey, TUnitKey> where TKey : IEquatable<TKey>
|
||||
where TUnitKey : IEquatable<TUnitKey>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="connectionType">连接类型</param>
|
||||
/// <param name="connectionString">连接地址</param>
|
||||
/// <param name="getAddresses">读写的地址</param>
|
||||
/// <param name="keepConnect">是否保持连接</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusMachine(ModbusType connectionType, string connectionString,
|
||||
IEnumerable<AddressUnit<TUnitKey>> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress,
|
||||
Endian endian = Endian.BigEndianLsb)
|
||||
: base(getAddresses, keepConnect, slaveAddress, masterAddress)
|
||||
{
|
||||
BaseUtility = new ModbusUtility(connectionType, connectionString, slaveAddress, masterAddress, endian);
|
||||
AddressFormater = new AddressFormaterModbus();
|
||||
AddressCombiner = new AddressCombinerContinus<TUnitKey>(AddressTranslator, 100);
|
||||
AddressCombinerSet = new AddressCombinerContinus<TUnitKey>(AddressTranslator, 100);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="connectionType">连接类型</param>
|
||||
/// <param name="connectionString">连接地址</param>
|
||||
/// <param name="getAddresses">读写的地址</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusMachine(ModbusType connectionType, string connectionString,
|
||||
IEnumerable<AddressUnit<TUnitKey>> getAddresses, byte slaveAddress, byte masterAddress,
|
||||
Endian endian = Endian.BigEndianLsb)
|
||||
: this(connectionType, connectionString, getAddresses, false, slaveAddress, masterAddress, endian)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modbus设备
|
||||
/// </summary>
|
||||
public class ModbusMachine : BaseMachine
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="connectionType">连接类型</param>
|
||||
/// <param name="connectionString">连接地址</param>
|
||||
/// <param name="getAddresses">读写的地址</param>
|
||||
/// <param name="keepConnect">是否保持连接</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusMachine(ModbusType connectionType, string connectionString,
|
||||
IEnumerable<AddressUnit> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress,
|
||||
Endian endian = Endian.BigEndianLsb)
|
||||
: base(getAddresses, keepConnect, slaveAddress, masterAddress)
|
||||
{
|
||||
BaseUtility = new ModbusUtility(connectionType, connectionString, slaveAddress, masterAddress, endian);
|
||||
AddressFormater = new AddressFormaterModbus();
|
||||
AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100);
|
||||
AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="connectionType">连接类型</param>
|
||||
/// <param name="connectionString">连接地址</param>
|
||||
/// <param name="getAddresses">读写的地址</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusMachine(ModbusType connectionType, string connectionString,
|
||||
IEnumerable<AddressUnit> getAddresses, byte slaveAddress, byte masterAddress,
|
||||
Endian endian = Endian.BigEndianLsb)
|
||||
: this(connectionType, connectionString, getAddresses, false, slaveAddress, masterAddress, endian)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,853 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// 变量功能码
|
||||
/// </summary>
|
||||
internal enum ModbusProtocalVariableFunctionCode : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 读变量
|
||||
/// </summary>
|
||||
ReadVariable = 20,
|
||||
|
||||
/// <summary>
|
||||
/// 写变量
|
||||
/// </summary>
|
||||
WriteVariable = 21
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 跟时间有关的功能码
|
||||
/// </summary>
|
||||
public enum ModbusProtocalTimeFunctionCode : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 读时间
|
||||
/// </summary>
|
||||
GetSystemTime = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 写时间
|
||||
/// </summary>
|
||||
SetSystemTime = 16
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 跟读数据有关的功能码
|
||||
/// </summary>
|
||||
public enum ModbusProtocalReadDataFunctionCode : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 读线圈
|
||||
/// </summary>
|
||||
ReadCoilStatus = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 读输入线圈
|
||||
/// </summary>
|
||||
ReadInputStatus = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 读保持寄存器
|
||||
/// </summary>
|
||||
ReadHoldRegister = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 读输入寄存器
|
||||
/// </summary>
|
||||
ReadInputRegister = 4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 跟写数据有关的功能码
|
||||
/// </summary>
|
||||
internal enum ModbusProtocalWriteDataFunctionCode : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 写单个线圈
|
||||
/// </summary>
|
||||
WriteSingleCoil = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 写单个寄存器
|
||||
/// </summary>
|
||||
WriteSingleRegister = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 写多个线圈
|
||||
/// </summary>
|
||||
WriteMultiCoil = 15,
|
||||
|
||||
/// <summary>
|
||||
/// 写多个寄存器
|
||||
/// </summary>
|
||||
WriteMultiRegister = 16
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modbus协议
|
||||
/// </summary>
|
||||
public abstract class ModbusProtocal : BaseProtocal
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站地址</param>
|
||||
/// <param name="masterAddress">主站地址</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
protected ModbusProtocal(byte slaveAddress, byte masterAddress, Endian endian)
|
||||
: base(slaveAddress, masterAddress, endian)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接
|
||||
/// </summary>
|
||||
/// <returns>是否连接成功</returns>
|
||||
public override bool Connect()
|
||||
{
|
||||
return ProtocalLinker.Connect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接
|
||||
/// </summary>
|
||||
/// <returns>是否连接成功</returns>
|
||||
public override async Task<bool> ConnectAsync()
|
||||
{
|
||||
return await ProtocalLinker.ConnectAsync();
|
||||
}
|
||||
}
|
||||
|
||||
#region 读PLC数据
|
||||
|
||||
/// <summary>
|
||||
/// 读数据输入
|
||||
/// </summary>
|
||||
public class ReadDataModbusInputStruct : IInputStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站地址</param>
|
||||
/// <param name="startAddress">开始地址</param>
|
||||
/// <param name="getCount">读取个数</param>
|
||||
/// <param name="addressTranslator">地址翻译器</param>
|
||||
public ReadDataModbusInputStruct(byte slaveAddress, string startAddress, ushort getCount,
|
||||
AddressTranslator addressTranslator)
|
||||
{
|
||||
SlaveAddress = slaveAddress;
|
||||
var translateAddress = addressTranslator.AddressTranslate(startAddress, true);
|
||||
FunctionCode = (byte) translateAddress.Area;
|
||||
StartAddress = (ushort) translateAddress.Address;
|
||||
GetCount =
|
||||
(ushort) Math.Ceiling(getCount / addressTranslator.GetAreaByteLength(translateAddress.AreaString));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从站地址
|
||||
/// </summary>
|
||||
public byte SlaveAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 功能码
|
||||
/// </summary>
|
||||
public byte FunctionCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始地址
|
||||
/// </summary>
|
||||
public ushort StartAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取个数
|
||||
/// </summary>
|
||||
public ushort GetCount { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读数据输出
|
||||
/// </summary>
|
||||
public class ReadDataModbusOutputStruct : IOutputStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <param name="dataCount">数据个数</param>
|
||||
/// <param name="dataValue">读取的数据值</param>
|
||||
public ReadDataModbusOutputStruct(byte slaveAddress, byte functionCode,
|
||||
int dataCount, byte[] dataValue)
|
||||
{
|
||||
SlaveAddress = slaveAddress;
|
||||
FunctionCode = functionCode;
|
||||
DataCount = dataCount;
|
||||
DataValue = dataValue.Clone() as byte[];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从站号
|
||||
/// </summary>
|
||||
public byte SlaveAddress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 功能码
|
||||
/// </summary>
|
||||
public byte FunctionCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据个数
|
||||
/// </summary>
|
||||
public int DataCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据值
|
||||
/// </summary>
|
||||
public byte[] DataValue { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读数据协议
|
||||
/// </summary>
|
||||
public class ReadDataModbusProtocal : ProtocalUnit
|
||||
{
|
||||
/// <summary>
|
||||
/// 格式化
|
||||
/// </summary>
|
||||
/// <param name="message">读取参数</param>
|
||||
/// <returns>读取数据的协议核心</returns>
|
||||
public override byte[] Format(IInputStruct message)
|
||||
{
|
||||
var r_message = (ReadDataModbusInputStruct) message;
|
||||
return Format(r_message.SlaveAddress, r_message.FunctionCode,
|
||||
r_message.StartAddress, r_message.GetCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反格式化
|
||||
/// </summary>
|
||||
/// <param name="messageBytes">设备返回的信息</param>
|
||||
/// <param name="pos">当前反格式化的位置</param>
|
||||
/// <returns>反格式化的信息</returns>
|
||||
public override IOutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||
{
|
||||
var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref pos);
|
||||
var functionCode = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref pos);
|
||||
var dataCount = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref pos);
|
||||
var dataValue = new byte[dataCount];
|
||||
Array.Copy(messageBytes, 3, dataValue, 0, dataCount);
|
||||
return new ReadDataModbusOutputStruct(slaveAddress, functionCode, dataCount, dataValue);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 写PLC数据
|
||||
|
||||
/// <summary>
|
||||
/// 写数据输入
|
||||
/// </summary>
|
||||
public class WriteDataModbusInputStruct : IInputStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="startAddress">开始地址</param>
|
||||
/// <param name="writeValue">写入的数据</param>
|
||||
/// <param name="addressTranslator">地址翻译器</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public WriteDataModbusInputStruct(byte slaveAddress, string startAddress, object[] writeValue,
|
||||
AddressTranslator addressTranslator, Endian endian)
|
||||
{
|
||||
SlaveAddress = slaveAddress;
|
||||
var translateAddress = addressTranslator.AddressTranslate(startAddress, false);
|
||||
FunctionCode = (byte) translateAddress.Area;
|
||||
StartAddress = (ushort) translateAddress.Address;
|
||||
var writeByteValue = ValueHelper.GetInstance(endian).ObjectArrayToByteArray(writeValue);
|
||||
WriteCount =
|
||||
(ushort) (writeByteValue.Length / addressTranslator.GetAreaByteLength(translateAddress.AreaString));
|
||||
WriteByteCount = (byte) writeByteValue.Length;
|
||||
WriteValue = writeByteValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从站号
|
||||
/// </summary>
|
||||
public byte SlaveAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 功能码
|
||||
/// </summary>
|
||||
public byte FunctionCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始地址
|
||||
/// </summary>
|
||||
public ushort StartAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入个数
|
||||
/// </summary>
|
||||
public ushort WriteCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入字节个数
|
||||
/// </summary>
|
||||
public byte WriteByteCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入的数据
|
||||
/// </summary>
|
||||
public byte[] WriteValue { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写数据输出
|
||||
/// </summary>
|
||||
public class WriteDataModbusOutputStruct : IOutputStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <param name="startAddress">开始地址</param>
|
||||
/// <param name="writeCount">写入个数</param>
|
||||
public WriteDataModbusOutputStruct(byte slaveAddress, byte functionCode,
|
||||
ushort startAddress, ushort writeCount)
|
||||
{
|
||||
SlaveAddress = slaveAddress;
|
||||
FunctionCode = functionCode;
|
||||
StartAddress = startAddress;
|
||||
WriteCount = writeCount;
|
||||
}
|
||||
|
||||
/// <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 ushort WriteCount { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写多个寄存器协议
|
||||
/// </summary>
|
||||
public class WriteDataModbusProtocal : ProtocalUnit
|
||||
{
|
||||
/// <summary>
|
||||
/// 格式化
|
||||
/// </summary>
|
||||
/// <param name="message">写寄存器参数</param>
|
||||
/// <returns>写寄存器协议核心</returns>
|
||||
public override byte[] Format(IInputStruct message)
|
||||
{
|
||||
var r_message = (WriteDataModbusInputStruct) message;
|
||||
var dataValue = Format(r_message.WriteValue);
|
||||
var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode,
|
||||
r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, 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 writeCount = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
|
||||
return new WriteDataModbusOutputStruct(slaveAddress, functionCode, startAddress,
|
||||
writeCount);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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, 0x00})
|
||||
: 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时间
|
||||
|
||||
/// <summary>
|
||||
/// 读时间输入
|
||||
/// </summary>
|
||||
public class GetSystemTimeModbusInputStruct : IInputStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
public GetSystemTimeModbusInputStruct(byte slaveAddress)
|
||||
{
|
||||
SlaveAddress = slaveAddress;
|
||||
FunctionCode = (byte) ModbusProtocalTimeFunctionCode.GetSystemTime;
|
||||
StartAddress = 30000;
|
||||
GetCount = 5;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从站号
|
||||
/// </summary>
|
||||
public byte SlaveAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 功能码
|
||||
/// </summary>
|
||||
public byte FunctionCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始地址
|
||||
/// </summary>
|
||||
public ushort StartAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取个数
|
||||
/// </summary>
|
||||
public ushort GetCount { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读时间输出
|
||||
/// </summary>
|
||||
public class GetSystemTimeModbusOutputStruct : IOutputStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <param name="writeByteCount">写入个数</param>
|
||||
/// <param name="year">年</param>
|
||||
/// <param name="day">日</param>
|
||||
/// <param name="month">月</param>
|
||||
/// <param name="hour">时</param>
|
||||
/// <param name="second">秒</param>
|
||||
/// <param name="minute">分</param>
|
||||
/// <param name="millisecond">毫秒</param>
|
||||
public GetSystemTimeModbusOutputStruct(byte slaveAddress, byte functionCode,
|
||||
byte writeByteCount, ushort year, byte day, byte month, ushort hour, byte second, byte minute,
|
||||
ushort millisecond)
|
||||
{
|
||||
SlaveAddress = slaveAddress;
|
||||
FunctionCode = functionCode;
|
||||
WriteByteCount = writeByteCount;
|
||||
Time = new DateTime(year, month, day, hour, minute, second, millisecond);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从站号
|
||||
/// </summary>
|
||||
public byte SlaveAddress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 功能码
|
||||
/// </summary>
|
||||
public byte FunctionCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入个数
|
||||
/// </summary>
|
||||
public byte WriteByteCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时间
|
||||
/// </summary>
|
||||
public DateTime Time { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读系统时间协议
|
||||
/// </summary>
|
||||
public class GetSystemTimeModbusProtocal : ProtocalUnit
|
||||
{
|
||||
/// <summary>
|
||||
/// 格式化
|
||||
/// </summary>
|
||||
/// <param name="message">写系统时间参数</param>
|
||||
/// <returns>写系统时间的核心</returns>
|
||||
public override byte[] Format(IInputStruct message)
|
||||
{
|
||||
var r_message = (GetSystemTimeModbusInputStruct) message;
|
||||
return Format(r_message.SlaveAddress, r_message.FunctionCode,
|
||||
r_message.StartAddress, r_message.GetCount);
|
||||
}
|
||||
|
||||
/// <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 writeByteCount = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
|
||||
var year = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
|
||||
var day = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
|
||||
var month = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
|
||||
var hour = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
|
||||
var second = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
|
||||
var minute = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
|
||||
var millisecond = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
|
||||
return new GetSystemTimeModbusOutputStruct(slaveAddress, functionCode, writeByteCount, year, day,
|
||||
month, hour, second, minute, millisecond);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 写PLC时间
|
||||
|
||||
/// <summary>
|
||||
/// 写时间输入
|
||||
/// </summary>
|
||||
public class SetSystemTimeModbusInputStruct : IInputStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="time">时间</param>
|
||||
public SetSystemTimeModbusInputStruct(byte slaveAddress, DateTime time)
|
||||
{
|
||||
SlaveAddress = slaveAddress;
|
||||
FunctionCode = (byte) ModbusProtocalTimeFunctionCode.SetSystemTime;
|
||||
StartAddress = 30000;
|
||||
WriteCount = 5;
|
||||
WriteByteCount = 10;
|
||||
Year = (ushort) time.Year;
|
||||
Day = (byte) time.Day;
|
||||
Month = (byte) time.Month;
|
||||
Hour = (ushort) time.Hour;
|
||||
Second = (byte) time.Second;
|
||||
Minute = (byte) time.Minute;
|
||||
Millisecond = (ushort) time.Millisecond;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从站号
|
||||
/// </summary>
|
||||
public byte SlaveAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 功能码
|
||||
/// </summary>
|
||||
public byte FunctionCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始地址
|
||||
/// </summary>
|
||||
public ushort StartAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入个数
|
||||
/// </summary>
|
||||
public ushort WriteCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 写入字节个数
|
||||
/// </summary>
|
||||
public byte WriteByteCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 年
|
||||
/// </summary>
|
||||
public ushort Year { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 日
|
||||
/// </summary>
|
||||
public byte Day { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 月
|
||||
/// </summary>
|
||||
public byte Month { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 时
|
||||
/// </summary>
|
||||
public ushort Hour { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 秒
|
||||
/// </summary>
|
||||
public byte Second { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 分
|
||||
/// </summary>
|
||||
public byte Minute { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 毫秒
|
||||
/// </summary>
|
||||
public ushort Millisecond { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写时间输出
|
||||
/// </summary>
|
||||
public class SetSystemTimeModbusOutputStruct : IOutputStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <param name="startAddress">开始地址</param>
|
||||
/// <param name="writeCount">写入个数</param>
|
||||
public SetSystemTimeModbusOutputStruct(byte slaveAddress, byte functionCode,
|
||||
ushort startAddress, ushort writeCount)
|
||||
{
|
||||
SlaveAddress = slaveAddress;
|
||||
FunctionCode = functionCode;
|
||||
StartAddress = startAddress;
|
||||
WriteCount = writeCount;
|
||||
}
|
||||
|
||||
/// <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 ushort WriteCount { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写系统时间协议
|
||||
/// </summary>
|
||||
public class SetSystemTimeModbusProtocal : ProtocalUnit
|
||||
{
|
||||
/// <summary>
|
||||
/// 格式化
|
||||
/// </summary>
|
||||
/// <param name="message">写系统时间的参数</param>
|
||||
/// <returns>写系统时间的核心</returns>
|
||||
public override byte[] Format(IInputStruct message)
|
||||
{
|
||||
var r_message = (SetSystemTimeModbusInputStruct) message;
|
||||
return Format(r_message.SlaveAddress, r_message.FunctionCode,
|
||||
r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, r_message.Year,
|
||||
r_message.Day,
|
||||
r_message.Month, r_message.Hour, r_message.Second, r_message.Minute, r_message.Millisecond);
|
||||
}
|
||||
|
||||
/// <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 writeCount = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
|
||||
return new SetSystemTimeModbusOutputStruct(slaveAddress, functionCode, startAddress, writeCount);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Modbus协议错误表
|
||||
/// </summary>
|
||||
public class ModbusProtocalErrorException : ProtocalErrorException
|
||||
{
|
||||
private static readonly Dictionary<int, string> ProtocalErrorDictionary = new Dictionary<int, string>
|
||||
{
|
||||
{1, "ILLEGAL_FUNCTION"},
|
||||
{2, "ILLEGAL_DATA_ACCESS"},
|
||||
{3, "ILLEGAL_DATA_VALUE"},
|
||||
{4, "SLAVE_DEVICE_FAILURE"},
|
||||
{5, "ACKNOWLWDGE"},
|
||||
{6, "SLAVE_DEVICE_BUSY"},
|
||||
{500, "TCP_ILLEGAL_LENGTH"},
|
||||
{501, "RTU_ILLEGAL_CRC"}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Modbus错误
|
||||
/// </summary>
|
||||
/// <param name="messageNumber">Modbus错误号</param>
|
||||
public ModbusProtocalErrorException(int messageNumber)
|
||||
: base(ProtocalErrorDictionary[messageNumber])
|
||||
{
|
||||
ErrorMessageNumber = messageNumber;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modbus错误号
|
||||
/// </summary>
|
||||
public int ErrorMessageNumber { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Tcp协议字节伸缩
|
||||
/// </summary>
|
||||
public class ModbusTcpProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// 协议扩展,协议内容发送前调用
|
||||
/// </summary>
|
||||
/// <param name="content">扩展前的原始协议内容</param>
|
||||
/// <returns>扩展后的协议内容</returns>
|
||||
public byte[] BytesExtend(byte[] content)
|
||||
{
|
||||
//Modbus/Tcp协议扩张,前面加6个字节,前面4个为0,后面两个为协议整体内容的长度
|
||||
var newFormat = new byte[6 + content.Length];
|
||||
var tag = 0;
|
||||
var leng = (ushort) content.Length;
|
||||
Array.Copy(BigEndianValueHelper.Instance.GetBytes(tag), 0, newFormat, 0, 4);
|
||||
Array.Copy(BigEndianValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2);
|
||||
Array.Copy(content, 0, newFormat, 6, content.Length);
|
||||
return newFormat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 协议收缩,协议内容接收后调用
|
||||
/// </summary>
|
||||
/// <param name="content">收缩前的完整协议内容</param>
|
||||
/// <returns>收缩后的协议内容</returns>
|
||||
public byte[] BytesDecact(byte[] content)
|
||||
{
|
||||
//Modbus/Tcp协议收缩,抛弃前面6个字节的内容
|
||||
var newContent = new byte[content.Length - 6];
|
||||
Array.Copy(content, 6, newContent, 0, newContent.Length);
|
||||
return newContent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rtu协议字节伸缩
|
||||
/// </summary>
|
||||
public class ModbusRtuProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// 协议扩展,协议内容发送前调用
|
||||
/// </summary>
|
||||
/// <param name="content">扩展前的原始协议内容</param>
|
||||
/// <returns>扩展后的协议内容</returns>
|
||||
public byte[] BytesExtend(byte[] content)
|
||||
{
|
||||
var crc = new byte[2];
|
||||
//Modbus/Rtu协议扩张,增加CRC校验
|
||||
var newFormat = new byte[content.Length + 2];
|
||||
Crc16.GetInstance().GetCRC(content, ref crc);
|
||||
Array.Copy(content, 0, newFormat, 0, content.Length);
|
||||
Array.Copy(crc, 0, newFormat, newFormat.Length - 2, crc.Length);
|
||||
return newFormat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 协议收缩,协议内容接收后调用
|
||||
/// </summary>
|
||||
/// <param name="content">收缩前的完整协议内容</param>
|
||||
/// <returns>收缩后的协议内容</returns>
|
||||
public byte[] BytesDecact(byte[] content)
|
||||
{
|
||||
//Modbus/Rtu协议收缩,抛弃后面2个字节的内容
|
||||
var newContent = new byte[content.Length - 2];
|
||||
Array.Copy(content, 0, newContent, 0, newContent.Length);
|
||||
return newContent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ascii协议字节伸缩
|
||||
/// </summary>
|
||||
public class ModbusAsciiProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// 协议扩展,协议内容发送前调用
|
||||
/// </summary>
|
||||
/// <param name="content">扩展前的原始协议内容</param>
|
||||
/// <returns>扩展后的协议内容</returns>
|
||||
public byte[] BytesExtend(byte[] content)
|
||||
{
|
||||
//Modbus/Ascii协议扩张,前面增加:,后面增加LRC校验和尾字符
|
||||
var newContent = new List<byte>();
|
||||
newContent.AddRange(Encoding.ASCII.GetBytes(":"));
|
||||
foreach (var number in content)
|
||||
newContent.AddRange(Encoding.ASCII.GetBytes(number.ToString("X2")));
|
||||
newContent.AddRange(Encoding.ASCII.GetBytes(Crc16.GetInstance().GetLRC(content)));
|
||||
newContent.Add(0x0d);
|
||||
newContent.Add(0x0a);
|
||||
return newContent.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 协议收缩,协议内容接收后调用
|
||||
/// </summary>
|
||||
/// <param name="content">收缩前的完整协议内容</param>
|
||||
/// <returns>收缩后的协议内容</returns>
|
||||
public byte[] BytesDecact(byte[] content)
|
||||
{
|
||||
//Modbus/Ascii协议收缩,抛弃头尾。
|
||||
var newContent = new List<byte>();
|
||||
var ans = Encoding.ASCII.GetString(content);
|
||||
var index = ans.IndexOf(Environment.NewLine);
|
||||
ans = ans.Substring(1, index - 1);
|
||||
for (var i = 0; i < ans.Length; i += 2)
|
||||
{
|
||||
var number = byte.Parse(ans.Substring(i, 2), NumberStyles.HexNumber);
|
||||
newContent.Add(number);
|
||||
}
|
||||
newContent.RemoveAt(newContent.Count - 1);
|
||||
return newContent.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus/Rtu协议
|
||||
/// </summary>
|
||||
public class ModbusRtuProtocal : ModbusProtocal
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusRtuProtocal(byte slaveAddress, byte masterAddress, Endian endian)
|
||||
: this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress, endian)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="com">串口</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusRtuProtocal(string com, byte slaveAddress, byte masterAddress, Endian endian)
|
||||
: base(slaveAddress, masterAddress, endian)
|
||||
{
|
||||
ProtocalLinker = new ModbusRtuProtocalLinker(com, slaveAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus/Rtu协议连接器
|
||||
/// </summary>
|
||||
public class ModbusRtuProtocalLinker : ComProtocalLinker
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="com">串口地址</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
public ModbusRtuProtocalLinker(string com, int slaveAddress)
|
||||
: base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验返回数据
|
||||
/// </summary>
|
||||
/// <param name="content">设备返回的数据</param>
|
||||
/// <returns>数据是否正确</returns>
|
||||
public override bool? CheckRight(byte[] content)
|
||||
{
|
||||
//ProtocalLinker的CheckRight不会返回null
|
||||
if (!base.CheckRight(content).Value) return false;
|
||||
//CRC校验失败
|
||||
if (!Crc16.GetInstance().CrcEfficacy(content))
|
||||
throw new ModbusProtocalErrorException(501);
|
||||
//Modbus协议错误
|
||||
if (content[1] > 127)
|
||||
throw new ModbusProtocalErrorException(content[2]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus/Tcp协议
|
||||
/// </summary>
|
||||
public class ModbusTcpProtocal : ModbusProtocal
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusTcpProtocal(byte slaveAddress, byte masterAddress, Endian endian)
|
||||
: this(ConfigurationManager.AppSettings["IP"], slaveAddress, masterAddress, endian)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="ip">ip地址</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusTcpProtocal(string ip, byte slaveAddress, byte masterAddress, Endian endian)
|
||||
: base(slaveAddress, masterAddress, endian)
|
||||
{
|
||||
ProtocalLinker = new ModbusTcpProtocalLinker(ip);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="ip">ip地址</param>
|
||||
/// <param name="port">端口</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusTcpProtocal(string ip, int port, byte slaveAddress, byte masterAddress, Endian endian)
|
||||
: base(slaveAddress, masterAddress, endian)
|
||||
{
|
||||
ProtocalLinker = new ModbusTcpProtocalLinker(ip, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus/Tcp协议连接器
|
||||
/// </summary>
|
||||
public class ModbusTcpProtocalLinker : TcpProtocalLinker
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="ip">IP地址</param>
|
||||
public ModbusTcpProtocalLinker(string ip)
|
||||
: base(ip, int.Parse(ConfigurationManager.AppSettings["ModbusPort"] ?? "502"))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="ip">IP地址</param>
|
||||
/// <param name="port">端口</param>
|
||||
public ModbusTcpProtocalLinker(string ip, int port) : base(ip, port)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验返回数据
|
||||
/// </summary>
|
||||
/// <param name="content">设备返回的数据</param>
|
||||
/// <returns>数据是否正确</returns>
|
||||
public override bool? CheckRight(byte[] content)
|
||||
{
|
||||
//ProtocalLinker的CheckRight不会返回null
|
||||
if (!base.CheckRight(content).Value) return false;
|
||||
//长度校验失败
|
||||
if (content[5] != content.Length - 6)
|
||||
throw new ModbusProtocalErrorException(500);
|
||||
//Modbus协议错误
|
||||
if (content[7] > 127)
|
||||
throw new ModbusProtocalErrorException(content[2] > 0 ? content[2] : content[8]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,289 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus连接类型
|
||||
/// </summary>
|
||||
public enum ModbusType
|
||||
{
|
||||
/// <summary>
|
||||
/// Rtu连接
|
||||
/// </summary>
|
||||
Rtu = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Tcp连接
|
||||
/// </summary>
|
||||
Tcp = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Ascii连接
|
||||
/// </summary>
|
||||
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, IUtilityMethodWriteSingle
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus协议类型
|
||||
/// </summary>
|
||||
private ModbusType _modbusType;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="connectionType">协议类型</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusUtility(int connectionType, byte slaveAddress, byte masterAddress,
|
||||
Endian endian = Endian.BigEndianLsb)
|
||||
: base(slaveAddress, masterAddress)
|
||||
{
|
||||
Endian = endian;
|
||||
ConnectionString = null;
|
||||
ModbusType = (ModbusType) connectionType;
|
||||
AddressTranslator = new AddressTranslatorModbus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="connectionType">协议类型</param>
|
||||
/// <param name="connectionString">连接地址</param>
|
||||
/// <param name="slaveAddress">从站号</param>
|
||||
/// <param name="masterAddress">主站号</param>
|
||||
/// <param name="endian">端格式</param>
|
||||
public ModbusUtility(ModbusType connectionType, string connectionString, byte slaveAddress, byte masterAddress,
|
||||
Endian endian = Endian.BigEndianLsb)
|
||||
: base(slaveAddress, masterAddress)
|
||||
{
|
||||
Endian = endian;
|
||||
ConnectionString = connectionString;
|
||||
ModbusType = connectionType;
|
||||
AddressTranslator = new AddressTranslatorModbus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 端格式
|
||||
/// </summary>
|
||||
public override Endian Endian { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ip地址
|
||||
/// </summary>
|
||||
protected string ConnectionStringIp
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ConnectionString == null) return null;
|
||||
return ConnectionString.Contains(":") ? ConnectionString.Split(':')[0] : ConnectionString;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 端口
|
||||
/// </summary>
|
||||
protected int? ConnectionStringPort
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ConnectionString == null) return null;
|
||||
if (!ConnectionString.Contains(":")) return null;
|
||||
var connectionStringSplit = ConnectionString.Split(':');
|
||||
try
|
||||
{
|
||||
return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, $"ModbusUtility: {ConnectionString} format error");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 协议类型
|
||||
/// </summary>
|
||||
public ModbusType ModbusType
|
||||
{
|
||||
get { return _modbusType; }
|
||||
set
|
||||
{
|
||||
_modbusType = value;
|
||||
switch (_modbusType)
|
||||
{
|
||||
//Rtu协议
|
||||
case ModbusType.Rtu:
|
||||
{
|
||||
Wrapper = ConnectionString == null
|
||||
? new ModbusRtuProtocal(SlaveAddress, MasterAddress, Endian)
|
||||
: new ModbusRtuProtocal(ConnectionString, SlaveAddress, MasterAddress, Endian);
|
||||
break;
|
||||
}
|
||||
//Tcp协议
|
||||
case ModbusType.Tcp:
|
||||
{
|
||||
Wrapper = ConnectionString == null
|
||||
? new ModbusTcpProtocal(SlaveAddress, MasterAddress, Endian)
|
||||
: (ConnectionStringPort == null
|
||||
? new ModbusTcpProtocal(ConnectionString, SlaveAddress, MasterAddress, Endian)
|
||||
: new ModbusTcpProtocal(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress,
|
||||
MasterAddress, Endian));
|
||||
break;
|
||||
}
|
||||
//Ascii协议
|
||||
case ModbusType.Ascii:
|
||||
{
|
||||
Wrapper = ConnectionString == null
|
||||
? new ModbusAsciiProtocal(SlaveAddress, MasterAddress, Endian)
|
||||
: new ModbusAsciiProtocal(ConnectionString, SlaveAddress, MasterAddress, Endian);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读时间
|
||||
/// </summary>
|
||||
/// <returns>设备的时间</returns>
|
||||
public async Task<DateTime> GetTimeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var inputStruct = new GetSystemTimeModbusInputStruct(SlaveAddress);
|
||||
var outputStruct =
|
||||
await Wrapper.SendReceiveAsync<GetSystemTimeModbusOutputStruct>(
|
||||
Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct);
|
||||
return outputStruct?.Time ?? DateTime.MinValue;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, $"ModbusUtility -> GetTime: {ConnectionString} error");
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写时间
|
||||
/// </summary>
|
||||
/// <param name="setTime">需要写入的时间</param>
|
||||
/// <returns>写入是否成功</returns>
|
||||
public async Task<bool> SetTimeAsync(DateTime setTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
var inputStruct = new SetSystemTimeModbusInputStruct(SlaveAddress, setTime);
|
||||
var outputStruct =
|
||||
await Wrapper.SendReceiveAsync<SetSystemTimeModbusOutputStruct>(
|
||||
Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct);
|
||||
return outputStruct?.WriteCount > 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, $"ModbusUtility -> SetTime: {ConnectionString} error");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置协议类型
|
||||
/// </summary>
|
||||
/// <param name="connectionType">协议类型</param>
|
||||
public override void SetConnectionType(int connectionType)
|
||||
{
|
||||
ModbusType = (ModbusType) connectionType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读数据
|
||||
/// </summary>
|
||||
/// <param name="startAddress">起始地址</param>
|
||||
/// <param name="getByteCount">获取字节个数</param>
|
||||
/// <returns>获取的结果</returns>
|
||||
public override async Task<byte[]> GetDatasAsync(string startAddress, int getByteCount)
|
||||
{
|
||||
try
|
||||
{
|
||||
var inputStruct = new ReadDataModbusInputStruct(SlaveAddress, startAddress,
|
||||
(ushort) getByteCount, AddressTranslator);
|
||||
var outputStruct = await
|
||||
Wrapper.SendReceiveAsync<ReadDataModbusOutputStruct>(Wrapper[typeof(ReadDataModbusProtocal)],
|
||||
inputStruct);
|
||||
return outputStruct?.DataValue;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, $"ModbusUtility -> GetDatas: {ConnectionString} error");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写数据
|
||||
/// </summary>
|
||||
/// <param name="startAddress">起始地址</param>
|
||||
/// <param name="setContents">需要设置的数据</param>
|
||||
/// <returns>设置是否成功</returns>
|
||||
public override async Task<bool> SetDatasAsync(string startAddress, object[] setContents)
|
||||
{
|
||||
try
|
||||
{
|
||||
var inputStruct = new WriteDataModbusInputStruct(SlaveAddress, startAddress, setContents,
|
||||
AddressTranslator, Endian);
|
||||
var outputStruct = await
|
||||
Wrapper.SendReceiveAsync<WriteDataModbusOutputStruct>(Wrapper[typeof(WriteDataModbusProtocal)],
|
||||
inputStruct);
|
||||
return outputStruct?.WriteCount == setContents.Length;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, $"ModbusUtility -> SetDatas: {ConnectionString} error");
|
||||
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