2017-05-17 Update 3 Implement log system and add comments

This commit is contained in:
parallelbgls
2017-05-17 18:01:30 +08:00
parent 1be8555a98
commit 93a24e90eb
34 changed files with 987 additions and 82 deletions

View File

@@ -5,11 +5,24 @@
/// </summary> /// </summary>
public class AddressFormaterNA200H : AddressFormater public class AddressFormaterNA200H : AddressFormater
{ {
/// <summary>
/// 格式化地址
/// </summary>
/// <param name="area">地址区域</param>
/// <param name="address">地址</param>
/// <returns>格式化的地址字符串</returns>
public override string FormatAddress(string area, int address) public override string FormatAddress(string area, int address)
{ {
return area + " " + 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) public override string FormatAddress(string area, int address, int subAddress)
{ {
return area + " " + address + "." + subAddress; return area + " " + address + "." + subAddress;
@@ -21,11 +34,24 @@
/// </summary> /// </summary>
public class AddressFormaterModbus : AddressFormater public class AddressFormaterModbus : AddressFormater
{ {
/// <summary>
/// 格式化地址
/// </summary>
/// <param name="area">地址区域</param>
/// <param name="address">地址</param>
/// <returns>格式化的地址字符串</returns>
public override string FormatAddress(string area, int address) public override string FormatAddress(string area, int address)
{ {
return area + " " + 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) public override string FormatAddress(string area, int address, int subAddress)
{ {
return area + " " + address + "." + subAddress; return area + " " + address + "." + subAddress;

View File

@@ -23,6 +23,9 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
protected Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary; protected Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary;
/// <summary>
/// 构造器
/// </summary>
public AddressTranslatorNA200H() public AddressTranslatorNA200H()
{ {
TransDictionary = new Dictionary<string, int> TransDictionary = new Dictionary<string, int>
@@ -154,6 +157,12 @@ namespace Modbus.Net.Modbus
}; };
} }
/// <summary>
/// 地址转换
/// </summary>
/// <param name="address">格式化的地址</param>
/// <param name="isRead">是否为读取,是为读取,否为写入</param>
/// <returns>翻译后的地址</returns>
public override AddressDef AddressTranslate(string address, bool isRead) public override AddressDef AddressTranslate(string address, bool isRead)
{ {
address = address.ToUpper(); address = address.ToUpper();
@@ -188,6 +197,11 @@ namespace Modbus.Net.Modbus
}; };
} }
/// <summary>
/// 获取区域中的单个地址占用的字节长度
/// </summary>
/// <param name="area">区域名称</param>
/// <returns>字节长度</returns>
public override double GetAreaByteLength(string area) public override double GetAreaByteLength(string area)
{ {
return ReadFunctionCodeDictionary[area].AreaWidth; return ReadFunctionCodeDictionary[area].AreaWidth;
@@ -209,6 +223,9 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
protected Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary; protected Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary;
/// <summary>
/// 构造器
/// </summary>
public AddressTranslatorModbus() public AddressTranslatorModbus()
{ {
ReadFunctionCodeDictionary = new Dictionary<string, AreaOutputDef> ReadFunctionCodeDictionary = new Dictionary<string, AreaOutputDef>
@@ -259,6 +276,12 @@ namespace Modbus.Net.Modbus
}; };
} }
/// <summary>
/// 地址转换
/// </summary>
/// <param name="address">格式化的地址</param>
/// <param name="isRead">是否为读取,是为读取,否为写入</param>
/// <returns>翻译后的地址</returns>
public override AddressDef AddressTranslate(string address, bool isRead) public override AddressDef AddressTranslate(string address, bool isRead)
{ {
address = address.ToUpper(); address = address.ToUpper();
@@ -293,6 +316,11 @@ namespace Modbus.Net.Modbus
}; };
} }
/// <summary>
/// 获取区域中的单个地址占用的字节长度
/// </summary>
/// <param name="area">区域名称</param>
/// <returns>字节长度</returns>
public override double GetAreaByteLength(string area) public override double GetAreaByteLength(string area)
{ {
return ReadFunctionCodeDictionary[area].AreaWidth; return ReadFunctionCodeDictionary[area].AreaWidth;

View File

@@ -7,11 +7,24 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusAsciiProtocal : ModbusProtocal 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) public ModbusAsciiProtocal(byte slaveAddress, byte masterAddress, Endian endian)
: this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress, 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) public ModbusAsciiProtocal(string com, byte slaveAddress, byte masterAddress, Endian endian)
: base(slaveAddress, masterAddress, endian) : base(slaveAddress, masterAddress, endian)
{ {

View File

@@ -8,13 +8,24 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusAsciiProtocalLinker : ComProtocalLinker public class ModbusAsciiProtocalLinker : ComProtocalLinker
{ {
/// <summary>
/// 构造函数
/// </summary>
/// <param name="com">串口地址</param>
/// <param name="slaveAddress">从站号</param>
public ModbusAsciiProtocalLinker(string com, int slaveAddress) public ModbusAsciiProtocalLinker(string com, int slaveAddress)
: base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress)
{ {
} }
/// <summary>
/// 校验返回数据是否正确
/// </summary>
/// <param name="content">返回的数据</param>
/// <returns>校验是否正确</returns>
public override bool? CheckRight(byte[] content) public override bool? CheckRight(byte[] content)
{ {
//ProtocalLinker不会返回null
if (!base.CheckRight(content).Value) return false; if (!base.CheckRight(content).Value) return false;
//CRC校验失败 //CRC校验失败
var contentString = Encoding.ASCII.GetString(content); var contentString = Encoding.ASCII.GetString(content);

View File

@@ -9,6 +9,16 @@ namespace Modbus.Net.Modbus
public class ModbusMachine<TKey, TUnitKey> : BaseMachine<TKey, TUnitKey> where TKey : IEquatable<TKey> public class ModbusMachine<TKey, TUnitKey> : BaseMachine<TKey, TUnitKey> where TKey : IEquatable<TKey>
where TUnitKey : IEquatable<TUnitKey> 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, public ModbusMachine(ModbusType connectionType, string connectionString,
IEnumerable<AddressUnit<TUnitKey>> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress, IEnumerable<AddressUnit<TUnitKey>> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress,
Endian endian = Endian.BigEndianLsb) Endian endian = Endian.BigEndianLsb)
@@ -20,6 +30,15 @@ namespace Modbus.Net.Modbus
AddressCombinerSet = 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, public ModbusMachine(ModbusType connectionType, string connectionString,
IEnumerable<AddressUnit<TUnitKey>> getAddresses, byte slaveAddress, byte masterAddress, IEnumerable<AddressUnit<TUnitKey>> getAddresses, byte slaveAddress, byte masterAddress,
Endian endian = Endian.BigEndianLsb) Endian endian = Endian.BigEndianLsb)
@@ -33,6 +52,16 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusMachine : BaseMachine 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, public ModbusMachine(ModbusType connectionType, string connectionString,
IEnumerable<AddressUnit> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress, IEnumerable<AddressUnit> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress,
Endian endian = Endian.BigEndianLsb) Endian endian = Endian.BigEndianLsb)
@@ -44,6 +73,15 @@ namespace Modbus.Net.Modbus
AddressCombinerSet = 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, public ModbusMachine(ModbusType connectionType, string connectionString,
IEnumerable<AddressUnit> getAddresses, byte slaveAddress, byte masterAddress, IEnumerable<AddressUnit> getAddresses, byte slaveAddress, byte masterAddress,
Endian endian = Endian.BigEndianLsb) Endian endian = Endian.BigEndianLsb)

View File

@@ -9,7 +9,14 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
internal enum ModbusProtocalVariableFunctionCode : byte internal enum ModbusProtocalVariableFunctionCode : byte
{ {
/// <summary>
/// 读变量
/// </summary>
ReadVariable = 20, ReadVariable = 20,
/// <summary>
/// 写变量
/// </summary>
WriteVariable = 21 WriteVariable = 21
} }
@@ -18,7 +25,14 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public enum ModbusProtocalTimeFunctionCode : byte public enum ModbusProtocalTimeFunctionCode : byte
{ {
/// <summary>
/// 读时间
/// </summary>
GetSystemTime = 3, GetSystemTime = 3,
/// <summary>
/// 写时间
/// </summary>
SetSystemTime = 16 SetSystemTime = 16
} }
@@ -27,9 +41,24 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public enum ModbusProtocalReadDataFunctionCode : byte public enum ModbusProtocalReadDataFunctionCode : byte
{ {
/// <summary>
/// 读线圈
/// </summary>
ReadCoilStatus = 1, ReadCoilStatus = 1,
/// <summary>
/// 读输入线圈
/// </summary>
ReadInputStatus = 2, ReadInputStatus = 2,
/// <summary>
/// 读保持寄存器
/// </summary>
ReadHoldRegister = 3, ReadHoldRegister = 3,
/// <summary>
/// 读输入寄存器
/// </summary>
ReadInputRegister = 4 ReadInputRegister = 4
} }
@@ -38,7 +67,24 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
internal enum ModbusProtocalWriteDataFunctionCode : byte internal enum ModbusProtocalWriteDataFunctionCode : byte
{ {
/// <summary>
/// 写单个线圈
/// </summary>
WriteSingleCoil = 5,
/// <summary>
/// 写单个寄存器
/// </summary>
WriteSingleRegister = 6,
/// <summary>
/// 写多个线圈
/// </summary>
WriteMultiCoil = 15, WriteMultiCoil = 15,
/// <summary>
/// 写多个寄存器
/// </summary>
WriteMultiRegister = 16 WriteMultiRegister = 16
} }
@@ -47,16 +93,30 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public abstract class ModbusProtocal : BaseProtocal 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) protected ModbusProtocal(byte slaveAddress, byte masterAddress, Endian endian)
: base(slaveAddress, masterAddress, endian) : base(slaveAddress, masterAddress, endian)
{ {
} }
/// <summary>
/// 连接
/// </summary>
/// <returns>是否连接成功</returns>
public override bool Connect() public override bool Connect()
{ {
return ProtocalLinker.Connect(); return ProtocalLinker.Connect();
} }
/// <summary>
/// 连接
/// </summary>
/// <returns>是否连接成功</returns>
public override async Task<bool> ConnectAsync() public override async Task<bool> ConnectAsync()
{ {
return await ProtocalLinker.ConnectAsync(); return await ProtocalLinker.ConnectAsync();
@@ -65,8 +125,18 @@ namespace Modbus.Net.Modbus
#region PLC数据 #region PLC数据
/// <summary>
/// 读数据输入
/// </summary>
public class ReadDataModbusInputStruct : IInputStruct 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, public ReadDataModbusInputStruct(byte slaveAddress, string startAddress, ushort getCount,
AddressTranslator addressTranslator) AddressTranslator addressTranslator)
{ {
@@ -78,17 +148,39 @@ namespace Modbus.Net.Modbus
(ushort) Math.Ceiling(getCount / addressTranslator.GetAreaByteLength(translateAddress.AreaString)); (ushort) Math.Ceiling(getCount / addressTranslator.GetAreaByteLength(translateAddress.AreaString));
} }
/// <summary>
/// 从站地址
/// </summary>
public byte SlaveAddress { get; } public byte SlaveAddress { get; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; } public byte FunctionCode { get; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; } public ushort StartAddress { get; }
/// <summary>
/// 获取个数
/// </summary>
public ushort GetCount { get; } public ushort GetCount { get; }
} }
/// <summary>
/// 读数据输出
/// </summary>
public class ReadDataModbusOutputStruct : IOutputStruct 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, public ReadDataModbusOutputStruct(byte slaveAddress, byte functionCode,
int dataCount, byte[] dataValue) int dataCount, byte[] dataValue)
{ {
@@ -98,17 +190,37 @@ namespace Modbus.Net.Modbus
DataValue = dataValue.Clone() as byte[]; DataValue = dataValue.Clone() as byte[];
} }
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; private set; } public byte SlaveAddress { get; private set; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; private set; } public byte FunctionCode { get; private set; }
/// <summary>
/// 数据个数
/// </summary>
public int DataCount { get; private set; } public int DataCount { get; private set; }
/// <summary>
/// 数据值
/// </summary>
public byte[] DataValue { get; private set; } public byte[] DataValue { get; private set; }
} }
/// <summary>
/// 读数据协议
/// </summary>
public class ReadDataModbusProtocal : ProtocalUnit public class ReadDataModbusProtocal : ProtocalUnit
{ {
/// <summary>
/// 格式化
/// </summary>
/// <param name="message">读取参数</param>
/// <returns>读取数据的协议核心</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (ReadDataModbusInputStruct) message; var r_message = (ReadDataModbusInputStruct) message;
@@ -116,6 +228,12 @@ namespace Modbus.Net.Modbus
r_message.StartAddress, r_message.GetCount); 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) public override IOutputStruct Unformat(byte[] messageBytes, ref int pos)
{ {
var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref pos); var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref pos);
@@ -131,8 +249,19 @@ namespace Modbus.Net.Modbus
#region PLC数据 #region PLC数据
/// <summary>
/// 写数据输入
/// </summary>
public class WriteDataModbusInputStruct : IInputStruct 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, public WriteDataModbusInputStruct(byte slaveAddress, string startAddress, object[] writeValue,
AddressTranslator addressTranslator, Endian endian) AddressTranslator addressTranslator, Endian endian)
{ {
@@ -147,21 +276,49 @@ namespace Modbus.Net.Modbus
WriteValue = writeByteValue; WriteValue = writeByteValue;
} }
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; } public byte SlaveAddress { get; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; } public byte FunctionCode { get; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; } public ushort StartAddress { get; }
/// <summary>
/// 写入个数
/// </summary>
public ushort WriteCount { get; } public ushort WriteCount { get; }
/// <summary>
/// 写入字节个数
/// </summary>
public byte WriteByteCount { get; } public byte WriteByteCount { get; }
/// <summary>
/// 写入的数据
/// </summary>
public byte[] WriteValue { get; } public byte[] WriteValue { get; }
} }
/// <summary>
/// 写数据输出
/// </summary>
public class WriteDataModbusOutputStruct : IOutputStruct 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, public WriteDataModbusOutputStruct(byte slaveAddress, byte functionCode,
ushort startAddress, ushort writeCount) ushort startAddress, ushort writeCount)
{ {
@@ -171,20 +328,37 @@ namespace Modbus.Net.Modbus
WriteCount = writeCount; WriteCount = writeCount;
} }
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; private set; } public byte SlaveAddress { get; private set; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; private set; } public byte FunctionCode { get; private set; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; private set; } public ushort StartAddress { get; private set; }
/// <summary>
/// 写入个数
/// </summary>
public ushort WriteCount { get; private set; } public ushort WriteCount { get; private set; }
} }
/// <summary> /// <summary>
/// 写多个寄存器状态 /// 写多个寄存器协议
/// </summary> /// </summary>
public class WriteDataModbusProtocal : ProtocalUnit public class WriteDataModbusProtocal : ProtocalUnit
{ {
/// <summary>
/// 格式化
/// </summary>
/// <param name="message">写寄存器参数</param>
/// <returns>写寄存器协议核心</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (WriteDataModbusInputStruct) message; var r_message = (WriteDataModbusInputStruct) message;
@@ -194,6 +368,12 @@ namespace Modbus.Net.Modbus
return formattingBytes; return formattingBytes;
} }
/// <summary>
/// 反格式化
/// </summary>
/// <param name="messageBytes">设备返回的信息</param>
/// <param name="flag">当前反格式化的位置</param>
/// <returns>反格式化的信息</returns>
public override IOutputStruct Unformat(byte[] messageBytes, ref int flag) public override IOutputStruct Unformat(byte[] messageBytes, ref int flag)
{ {
var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag); var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
@@ -209,8 +389,15 @@ namespace Modbus.Net.Modbus
#region PLC时间 #region PLC时间
/// <summary>
/// 读时间输入
/// </summary>
public class GetSystemTimeModbusInputStruct : IInputStruct public class GetSystemTimeModbusInputStruct : IInputStruct
{ {
/// <summary>
/// 构造函数
/// </summary>
/// <param name="slaveAddress">从站号</param>
public GetSystemTimeModbusInputStruct(byte slaveAddress) public GetSystemTimeModbusInputStruct(byte slaveAddress)
{ {
SlaveAddress = slaveAddress; SlaveAddress = slaveAddress;
@@ -219,17 +406,45 @@ namespace Modbus.Net.Modbus
GetCount = 5; GetCount = 5;
} }
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; } public byte SlaveAddress { get; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; } public byte FunctionCode { get; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; } public ushort StartAddress { get; }
/// <summary>
/// 获取个数
/// </summary>
public ushort GetCount { get; } public ushort GetCount { get; }
} }
/// <summary>
/// 读时间输出
/// </summary>
public class GetSystemTimeModbusOutputStruct : IOutputStruct 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, public GetSystemTimeModbusOutputStruct(byte slaveAddress, byte functionCode,
byte writeByteCount, ushort year, byte day, byte month, ushort hour, byte second, byte minute, byte writeByteCount, ushort year, byte day, byte month, ushort hour, byte second, byte minute,
ushort millisecond) ushort millisecond)
@@ -240,20 +455,37 @@ namespace Modbus.Net.Modbus
Time = new DateTime(year, month, day, hour, minute, second, millisecond); Time = new DateTime(year, month, day, hour, minute, second, millisecond);
} }
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; private set; } public byte SlaveAddress { get; private set; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; private set; } public byte FunctionCode { get; private set; }
/// <summary>
/// 写入个数
/// </summary>
public byte WriteByteCount { get; private set; } public byte WriteByteCount { get; private set; }
/// <summary>
/// 时间
/// </summary>
public DateTime Time { get; private set; } public DateTime Time { get; private set; }
} }
/// <summary> /// <summary>
/// 读系统时间 /// 读系统时间协议
/// </summary> /// </summary>
public class GetSystemTimeModbusProtocal : ProtocalUnit public class GetSystemTimeModbusProtocal : ProtocalUnit
{ {
/// <summary>
/// 格式化
/// </summary>
/// <param name="message">写系统时间参数</param>
/// <returns>写系统时间的核心</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (GetSystemTimeModbusInputStruct) message; var r_message = (GetSystemTimeModbusInputStruct) message;
@@ -261,6 +493,12 @@ namespace Modbus.Net.Modbus
r_message.StartAddress, r_message.GetCount); 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) public override IOutputStruct Unformat(byte[] messageBytes, ref int flag)
{ {
var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag); var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
@@ -282,8 +520,16 @@ namespace Modbus.Net.Modbus
#region PLC时间 #region PLC时间
/// <summary>
/// 写时间输入
/// </summary>
public class SetSystemTimeModbusInputStruct : IInputStruct public class SetSystemTimeModbusInputStruct : IInputStruct
{ {
/// <summary>
/// 构造函数
/// </summary>
/// <param name="slaveAddress">从站号</param>
/// <param name="time">时间</param>
public SetSystemTimeModbusInputStruct(byte slaveAddress, DateTime time) public SetSystemTimeModbusInputStruct(byte slaveAddress, DateTime time)
{ {
SlaveAddress = slaveAddress; SlaveAddress = slaveAddress;
@@ -300,33 +546,79 @@ namespace Modbus.Net.Modbus
Millisecond = (ushort) time.Millisecond; Millisecond = (ushort) time.Millisecond;
} }
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; } public byte SlaveAddress { get; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; } public byte FunctionCode { get; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; } public ushort StartAddress { get; }
/// <summary>
/// 写入个数
/// </summary>
public ushort WriteCount { get; } public ushort WriteCount { get; }
/// <summary>
/// 写入字节个数
/// </summary>
public byte WriteByteCount { get; } public byte WriteByteCount { get; }
/// <summary>
/// 年
/// </summary>
public ushort Year { get; } public ushort Year { get; }
/// <summary>
/// 日
/// </summary>
public byte Day { get; } public byte Day { get; }
/// <summary>
/// 月
/// </summary>
public byte Month { get; } public byte Month { get; }
/// <summary>
/// 时
/// </summary>
public ushort Hour { get; } public ushort Hour { get; }
/// <summary>
/// 秒
/// </summary>
public byte Second { get; } public byte Second { get; }
/// <summary>
/// 分
/// </summary>
public byte Minute { get; } public byte Minute { get; }
/// <summary>
/// 毫秒
/// </summary>
public ushort Millisecond { get; } public ushort Millisecond { get; }
} }
/// <summary>
/// 写时间输出
/// </summary>
public class SetSystemTimeModbusOutputStruct : IOutputStruct 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, public SetSystemTimeModbusOutputStruct(byte slaveAddress, byte functionCode,
ushort startAddress, ushort writeCount) ushort startAddress, ushort writeCount)
{ {
@@ -336,20 +628,37 @@ namespace Modbus.Net.Modbus
WriteCount = writeCount; WriteCount = writeCount;
} }
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; private set; } public byte SlaveAddress { get; private set; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; private set; } public byte FunctionCode { get; private set; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; private set; } public ushort StartAddress { get; private set; }
/// <summary>
/// 写入个数
/// </summary>
public ushort WriteCount { get; private set; } public ushort WriteCount { get; private set; }
} }
/// <summary> /// <summary>
/// 写系统时间 /// 写系统时间协议
/// </summary> /// </summary>
public class SetSystemTimeModbusProtocal : ProtocalUnit public class SetSystemTimeModbusProtocal : ProtocalUnit
{ {
/// <summary>
/// 格式化
/// </summary>
/// <param name="message">写系统时间的参数</param>
/// <returns>写系统时间的核心</returns>
public override byte[] Format(IInputStruct message) public override byte[] Format(IInputStruct message)
{ {
var r_message = (SetSystemTimeModbusInputStruct) message; var r_message = (SetSystemTimeModbusInputStruct) message;
@@ -359,6 +668,12 @@ namespace Modbus.Net.Modbus
r_message.Month, r_message.Hour, r_message.Second, r_message.Minute, r_message.Millisecond); 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) public override IOutputStruct Unformat(byte[] messageBytes, ref int flag)
{ {
var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag); var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
@@ -388,12 +703,19 @@ namespace Modbus.Net.Modbus
{501, "RTU_ILLEGAL_CRC"} {501, "RTU_ILLEGAL_CRC"}
}; };
/// <summary>
/// Modbus错误
/// </summary>
/// <param name="messageNumber">Modbus错误号</param>
public ModbusProtocalErrorException(int messageNumber) public ModbusProtocalErrorException(int messageNumber)
: base(ProtocalErrorDictionary[messageNumber]) : base(ProtocalErrorDictionary[messageNumber])
{ {
ErrorMessageNumber = messageNumber; ErrorMessageNumber = messageNumber;
} }
/// <summary>
/// Modbus错误号
/// </summary>
public int ErrorMessageNumber { get; private set; } public int ErrorMessageNumber { get; private set; }
} }
} }

View File

@@ -10,6 +10,11 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusTcpProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend public class ModbusTcpProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend
{ {
/// <summary>
/// 协议扩展,协议内容发送前调用
/// </summary>
/// <param name="content">扩展前的原始协议内容</param>
/// <returns>扩展后的协议内容</returns>
public byte[] BytesExtend(byte[] content) public byte[] BytesExtend(byte[] content)
{ {
//Modbus/Tcp协议扩张前面加6个字节前面4个为0后面两个为协议整体内容的长度 //Modbus/Tcp协议扩张前面加6个字节前面4个为0后面两个为协议整体内容的长度
@@ -22,6 +27,11 @@ namespace Modbus.Net.Modbus
return newFormat; return newFormat;
} }
/// <summary>
/// 协议收缩,协议内容接收后调用
/// </summary>
/// <param name="content">收缩前的完整协议内容</param>
/// <returns>收缩后的协议内容</returns>
public byte[] BytesDecact(byte[] content) public byte[] BytesDecact(byte[] content)
{ {
//Modbus/Tcp协议收缩抛弃前面6个字节的内容 //Modbus/Tcp协议收缩抛弃前面6个字节的内容
@@ -31,8 +41,16 @@ namespace Modbus.Net.Modbus
} }
} }
/// <summary>
/// Rtu协议字节伸缩
/// </summary>
public class ModbusRtuProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend public class ModbusRtuProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend
{ {
/// <summary>
/// 协议扩展,协议内容发送前调用
/// </summary>
/// <param name="content">扩展前的原始协议内容</param>
/// <returns>扩展后的协议内容</returns>
public byte[] BytesExtend(byte[] content) public byte[] BytesExtend(byte[] content)
{ {
var crc = new byte[2]; var crc = new byte[2];
@@ -44,6 +62,11 @@ namespace Modbus.Net.Modbus
return newFormat; return newFormat;
} }
/// <summary>
/// 协议收缩,协议内容接收后调用
/// </summary>
/// <param name="content">收缩前的完整协议内容</param>
/// <returns>收缩后的协议内容</returns>
public byte[] BytesDecact(byte[] content) public byte[] BytesDecact(byte[] content)
{ {
//Modbus/Rtu协议收缩抛弃后面2个字节的内容 //Modbus/Rtu协议收缩抛弃后面2个字节的内容
@@ -53,8 +76,16 @@ namespace Modbus.Net.Modbus
} }
} }
/// <summary>
/// Ascii协议字节伸缩
/// </summary>
public class ModbusAsciiProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend public class ModbusAsciiProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend
{ {
/// <summary>
/// 协议扩展,协议内容发送前调用
/// </summary>
/// <param name="content">扩展前的原始协议内容</param>
/// <returns>扩展后的协议内容</returns>
public byte[] BytesExtend(byte[] content) public byte[] BytesExtend(byte[] content)
{ {
//Modbus/Ascii协议扩张前面增加:后面增加LRC校验和尾字符 //Modbus/Ascii协议扩张前面增加:后面增加LRC校验和尾字符
@@ -68,6 +99,11 @@ namespace Modbus.Net.Modbus
return newContent.ToArray(); return newContent.ToArray();
} }
/// <summary>
/// 协议收缩,协议内容接收后调用
/// </summary>
/// <param name="content">收缩前的完整协议内容</param>
/// <returns>收缩后的协议内容</returns>
public byte[] BytesDecact(byte[] content) public byte[] BytesDecact(byte[] content)
{ {
//Modbus/Ascii协议收缩抛弃头尾。 //Modbus/Ascii协议收缩抛弃头尾。

View File

@@ -7,11 +7,24 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusRtuProtocal : ModbusProtocal 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) public ModbusRtuProtocal(byte slaveAddress, byte masterAddress, Endian endian)
: this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress, 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) public ModbusRtuProtocal(string com, byte slaveAddress, byte masterAddress, Endian endian)
: base(slaveAddress, masterAddress, endian) : base(slaveAddress, masterAddress, endian)
{ {

View File

@@ -7,13 +7,24 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusRtuProtocalLinker : ComProtocalLinker public class ModbusRtuProtocalLinker : ComProtocalLinker
{ {
/// <summary>
/// 构造函数
/// </summary>
/// <param name="com">串口地址</param>
/// <param name="slaveAddress">从站号</param>
public ModbusRtuProtocalLinker(string com, int slaveAddress) public ModbusRtuProtocalLinker(string com, int slaveAddress)
: base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress) : base(com, 9600, Parity.None, StopBits.One, 8, slaveAddress)
{ {
} }
/// <summary>
/// 校验返回数据
/// </summary>
/// <param name="content">设备返回的数据</param>
/// <returns>数据是否正确</returns>
public override bool? CheckRight(byte[] content) public override bool? CheckRight(byte[] content)
{ {
//ProtocalLinker的CheckRight不会返回null
if (!base.CheckRight(content).Value) return false; if (!base.CheckRight(content).Value) return false;
//CRC校验失败 //CRC校验失败
if (!Crc16.GetInstance().CrcEfficacy(content)) if (!Crc16.GetInstance().CrcEfficacy(content))

View File

@@ -7,17 +7,38 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusTcpProtocal : ModbusProtocal 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) public ModbusTcpProtocal(byte slaveAddress, byte masterAddress, Endian endian)
: this(ConfigurationManager.AppSettings["IP"], slaveAddress, masterAddress, 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) public ModbusTcpProtocal(string ip, byte slaveAddress, byte masterAddress, Endian endian)
: base(slaveAddress, masterAddress, endian) : base(slaveAddress, masterAddress, endian)
{ {
ProtocalLinker = new ModbusTcpProtocalLinker(ip); 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) public ModbusTcpProtocal(string ip, int port, byte slaveAddress, byte masterAddress, Endian endian)
: base(slaveAddress, masterAddress, endian) : base(slaveAddress, masterAddress, endian)
{ {

View File

@@ -7,17 +7,32 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
public class ModbusTcpProtocalLinker : TcpProtocalLinker public class ModbusTcpProtocalLinker : TcpProtocalLinker
{ {
/// <summary>
/// 构造函数
/// </summary>
/// <param name="ip">IP地址</param>
public ModbusTcpProtocalLinker(string ip) public ModbusTcpProtocalLinker(string ip)
: base(ip, int.Parse(ConfigurationManager.AppSettings["ModbusPort"] ?? "502")) : 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) public ModbusTcpProtocalLinker(string ip, int port) : base(ip, port)
{ {
} }
/// <summary>
/// 校验返回数据
/// </summary>
/// <param name="content">设备返回的数据</param>
/// <returns>数据是否正确</returns>
public override bool? CheckRight(byte[] content) public override bool? CheckRight(byte[] content)
{ {
//ProtocalLinker的CheckRight不会返回null
if (!base.CheckRight(content).Value) return false; if (!base.CheckRight(content).Value) return false;
//长度校验失败 //长度校验失败
if (content[5] != content.Length - 6) if (content[5] != content.Length - 6)

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog;
namespace Modbus.Net.Modbus namespace Modbus.Net.Modbus
{ {
@@ -34,6 +35,13 @@ namespace Modbus.Net.Modbus
/// </summary> /// </summary>
private ModbusType _modbusType; 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, public ModbusUtility(int connectionType, byte slaveAddress, byte masterAddress,
Endian endian = Endian.BigEndianLsb) Endian endian = Endian.BigEndianLsb)
: base(slaveAddress, masterAddress) : base(slaveAddress, masterAddress)
@@ -44,6 +52,14 @@ namespace Modbus.Net.Modbus
AddressTranslator = new AddressTranslatorModbus(); 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, public ModbusUtility(ModbusType connectionType, string connectionString, byte slaveAddress, byte masterAddress,
Endian endian = Endian.BigEndianLsb) Endian endian = Endian.BigEndianLsb)
: base(slaveAddress, masterAddress) : base(slaveAddress, masterAddress)
@@ -54,8 +70,14 @@ namespace Modbus.Net.Modbus
AddressTranslator = new AddressTranslatorModbus(); AddressTranslator = new AddressTranslatorModbus();
} }
/// <summary>
/// 端格式
/// </summary>
public override Endian Endian { get; } public override Endian Endian { get; }
/// <summary>
/// Ip地址
/// </summary>
protected string ConnectionStringIp protected string ConnectionStringIp
{ {
get get
@@ -65,6 +87,9 @@ namespace Modbus.Net.Modbus
} }
} }
/// <summary>
/// 端口
/// </summary>
protected int? ConnectionStringPort protected int? ConnectionStringPort
{ {
get get
@@ -76,13 +101,17 @@ namespace Modbus.Net.Modbus
{ {
return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]); return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]);
} }
catch catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility: {ConnectionString} format error");
return null; return null;
} }
} }
} }
/// <summary>
/// 协议类型
/// </summary>
public ModbusType ModbusType public ModbusType ModbusType
{ {
get { return _modbusType; } get { return _modbusType; }
@@ -136,8 +165,9 @@ namespace Modbus.Net.Modbus
Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct); Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct);
return outputStruct?.Time ?? DateTime.MinValue; return outputStruct?.Time ?? DateTime.MinValue;
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> GetTime: {ConnectionString} error");
return DateTime.MinValue; return DateTime.MinValue;
} }
} }
@@ -157,12 +187,17 @@ namespace Modbus.Net.Modbus
Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct); Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct);
return outputStruct?.WriteCount > 0; return outputStruct?.WriteCount > 0;
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> SetTime: {ConnectionString} error");
return false; return false;
} }
} }
/// <summary>
/// 设置协议类型
/// </summary>
/// <param name="connectionType">协议类型</param>
public override void SetConnectionType(int connectionType) public override void SetConnectionType(int connectionType)
{ {
ModbusType = (ModbusType) connectionType; ModbusType = (ModbusType) connectionType;
@@ -185,8 +220,9 @@ namespace Modbus.Net.Modbus
inputStruct); inputStruct);
return outputStruct?.DataValue; return outputStruct?.DataValue;
} }
catch catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> GetDatas: {ConnectionString} error");
return null; return null;
} }
} }
@@ -208,8 +244,9 @@ namespace Modbus.Net.Modbus
inputStruct); inputStruct);
return outputStruct?.WriteCount == setContents.Length; return outputStruct?.WriteCount == setContents.Length;
} }
catch catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> SetDatas: {ConnectionString} error");
return false; return false;
} }
} }

View File

@@ -5,6 +5,7 @@ using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hylasoft.Opc.Common; using Hylasoft.Opc.Common;
using Serilog;
namespace Modbus.Net.OPC namespace Modbus.Net.OPC
{ {
@@ -28,12 +29,12 @@ namespace Modbus.Net.OPC
Client?.Dispose(); Client?.Dispose();
Client = null; Client = null;
_connect = false; _connect = false;
AddInfo("client disconnected successfully."); Log.Information("opc client {ConnectionToken} disconnected success", ConnectionToken);
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
{ {
AddInfo("client disconnected exception: " + ex.Message); Log.Error(ex, "opc client {ConnectionToken} disconnected error", ConnectionToken);
_connect = false; _connect = false;
return false; return false;
} }
@@ -125,7 +126,7 @@ namespace Modbus.Net.OPC
} }
catch (Exception e) catch (Exception e)
{ {
AddInfo("opc write exception:" + e.Message); Log.Error(e, "opc client {ConnectionToken} write exception", ConnectionToken);
return new OpcParamOut return new OpcParamOut
{ {
Success = false Success = false
@@ -144,7 +145,7 @@ namespace Modbus.Net.OPC
} }
catch (Exception e) catch (Exception e)
{ {
AddInfo("opc client exception:" + e.Message); Log.Error(e, "opc client {ConnectionToken} read exception", ConnectionToken);
return new OpcParamOut return new OpcParamOut
{ {
Success = false, Success = false,
@@ -180,13 +181,12 @@ namespace Modbus.Net.OPC
{ {
Client.Connect(); Client.Connect();
_connect = true; _connect = true;
AddInfo("client connected."); Log.Information("opc client {ConnectionToken} connect success", ConnectionToken);
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
{ {
AddInfo("client connected exception: " + ex.Message); Log.Error(ex, "opc client {ConnectionToken} connected failed", ConnectionToken);
AddInfo("connect failed.");
_connect = false; _connect = false;
return false; return false;
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog;
namespace Modbus.Net.OPC namespace Modbus.Net.OPC
{ {
@@ -34,8 +35,9 @@ namespace Modbus.Net.OPC
readRequestOpcInputStruct); readRequestOpcInputStruct);
return readRequestOpcOutputStruct?.GetValue; return readRequestOpcOutputStruct?.GetValue;
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, $"OpcUtility -> GetDatas: {ConnectionString} error");
return null; return null;
} }
} }
@@ -54,6 +56,7 @@ namespace Modbus.Net.OPC
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, $"OpcUtility -> SetDatas: {ConnectionString} error");
return false; return false;
} }
} }

View File

@@ -5,11 +5,24 @@
/// </summary> /// </summary>
public class AddressFormaterSiemens : AddressFormater public class AddressFormaterSiemens : AddressFormater
{ {
/// <summary>
/// 编码地址
/// </summary>
/// <param name="area">地址所在的数据区域</param>
/// <param name="address">地址</param>
/// <returns>编码后的地址</returns>
public override string FormatAddress(string area, int address) public override string FormatAddress(string area, int address)
{ {
return area + " " + 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) public override string FormatAddress(string area, int address, int subAddress)
{ {
return area + " " + address + "." + subAddress; return area + " " + address + "." + subAddress;
@@ -21,6 +34,12 @@
/// </summary> /// </summary>
public class AddressFormaterSimenseStandard : AddressFormater public class AddressFormaterSimenseStandard : AddressFormater
{ {
/// <summary>
/// 编码地址
/// </summary>
/// <param name="area">地址所在的数据区域</param>
/// <param name="address">地址</param>
/// <returns>编码后的地址</returns>
public override string FormatAddress(string area, int address) public override string FormatAddress(string area, int address)
{ {
if (area.Length > 1 && if (area.Length > 1 &&
@@ -29,6 +48,13 @@
return area.ToUpper() + address; return area.ToUpper() + 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) public override string FormatAddress(string area, int address, int subAddress)
{ {
if (area.Length > 1 && if (area.Length > 1 &&

View File

@@ -9,8 +9,14 @@ namespace Modbus.Net.Siemens
/// </summary> /// </summary>
public class AddressTranslatorSiemens : AddressTranslator public class AddressTranslatorSiemens : AddressTranslator
{ {
/// <summary>
/// 区域的翻译字典
/// </summary>
protected Dictionary<string, int> AreaCodeDictionary; protected Dictionary<string, int> AreaCodeDictionary;
/// <summary>
/// 构造函数
/// </summary>
public AddressTranslatorSiemens() public AddressTranslatorSiemens()
{ {
AreaCodeDictionary = new Dictionary<string, int> AreaCodeDictionary = new Dictionary<string, int>
@@ -30,6 +36,12 @@ namespace Modbus.Net.Siemens
}; };
} }
/// <summary>
/// 地址转换
/// </summary>
/// <param name="address">格式化的地址</param>
/// <param name="isRead">是否为读取,是为读取,否为写入</param>
/// <returns>翻译后的地址</returns>
public override AddressDef AddressTranslate(string address, bool isRead) public override AddressDef AddressTranslate(string address, bool isRead)
{ {
address = address.ToUpper(); address = address.ToUpper();
@@ -68,6 +80,11 @@ namespace Modbus.Net.Siemens
}; };
} }
/// <summary>
/// 获取区域中的单个地址占用的字节长度
/// </summary>
/// <param name="area">区域名称</param>
/// <returns>字节长度</returns>
public override double GetAreaByteLength(string area) public override double GetAreaByteLength(string area)
{ {
return 1; return 1;
@@ -79,8 +96,14 @@ namespace Modbus.Net.Siemens
/// </summary> /// </summary>
public class AddressTranslatorSimenseStandard : AddressTranslator public class AddressTranslatorSimenseStandard : AddressTranslator
{ {
/// <summary>
/// 区域的翻译字典
/// </summary>
protected Dictionary<string, int> AreaCodeDictionary; protected Dictionary<string, int> AreaCodeDictionary;
/// <summary>
/// 构造函数
/// </summary>
public AddressTranslatorSimenseStandard() public AddressTranslatorSimenseStandard()
{ {
AreaCodeDictionary = new Dictionary<string, int> AreaCodeDictionary = new Dictionary<string, int>
@@ -100,6 +123,12 @@ namespace Modbus.Net.Siemens
}; };
} }
/// <summary>
/// 地址转换
/// </summary>
/// <param name="address">格式化的地址</param>
/// <param name="isRead">是否为读取,是为读取,否为写入</param>
/// <returns>翻译后的地址</returns>
public override AddressDef AddressTranslate(string address, bool isRead) public override AddressDef AddressTranslate(string address, bool isRead)
{ {
address = address.ToUpper(); address = address.ToUpper();
@@ -134,6 +163,11 @@ namespace Modbus.Net.Siemens
}; };
} }
/// <summary>
/// 获取区域中的单个地址占用的字节长度
/// </summary>
/// <param name="area">区域名称</param>
/// <returns>字节长度</returns>
public override double GetAreaByteLength(string area) public override double GetAreaByteLength(string area)
{ {
return 1; return 1;

View File

@@ -9,6 +9,16 @@ namespace Modbus.Net.Siemens
public class SiemensMachine<TKey, TUnitKey> : BaseMachine<TKey, TUnitKey> where TKey : IEquatable<TKey> public class SiemensMachine<TKey, TUnitKey> : BaseMachine<TKey, TUnitKey> where TKey : IEquatable<TKey>
where TUnitKey : IEquatable<TUnitKey> where TUnitKey : IEquatable<TUnitKey>
{ {
/// <summary>
/// 构造函数
/// </summary>
/// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param>
/// <param name="model">设备类型</param>
/// <param name="getAddresses">读写的地址</param>
/// <param name="keepConnect">是否保持连接</param>
/// <param name="slaveAddress">从站号</param>
/// <param name="masterAddress">主站号</param>
public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model,
IEnumerable<AddressUnit<TUnitKey>> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress) IEnumerable<AddressUnit<TUnitKey>> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress)
: base(getAddresses, keepConnect, slaveAddress, masterAddress) : base(getAddresses, keepConnect, slaveAddress, masterAddress)
@@ -19,6 +29,15 @@ namespace Modbus.Net.Siemens
AddressCombinerSet = new AddressCombinerContinus<TUnitKey>(AddressTranslator, 100); AddressCombinerSet = new AddressCombinerContinus<TUnitKey>(AddressTranslator, 100);
} }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param>
/// <param name="model">设备类型</param>
/// <param name="getAddresses">读写的地址</param>
/// <param name="slaveAddress">从站号</param>
/// <param name="masterAddress">主站号</param>
public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model,
IEnumerable<AddressUnit<TUnitKey>> getAddresses, byte slaveAddress, byte masterAddress) IEnumerable<AddressUnit<TUnitKey>> getAddresses, byte slaveAddress, byte masterAddress)
: this(connectionType, connectionString, model, getAddresses, false, slaveAddress, masterAddress) : this(connectionType, connectionString, model, getAddresses, false, slaveAddress, masterAddress)
@@ -31,6 +50,16 @@ namespace Modbus.Net.Siemens
/// </summary> /// </summary>
public class SiemensMachine : BaseMachine public class SiemensMachine : BaseMachine
{ {
/// <summary>
/// 构造函数
/// </summary>
/// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param>
/// <param name="model">设备类型</param>
/// <param name="getAddresses">读写的地址</param>
/// <param name="keepConnect">是否保持连接</param>
/// <param name="slaveAddress">从站号</param>
/// <param name="masterAddress">主站号</param>
public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model,
IEnumerable<AddressUnit> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress) IEnumerable<AddressUnit> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress)
: base(getAddresses, keepConnect, slaveAddress, masterAddress) : base(getAddresses, keepConnect, slaveAddress, masterAddress)
@@ -41,6 +70,15 @@ namespace Modbus.Net.Siemens
AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100);
} }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接地址</param>
/// <param name="model">设备类型</param>
/// <param name="getAddresses">读写的地址</param>
/// <param name="slaveAddress">从站号</param>
/// <param name="masterAddress">主站号</param>
public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model,
IEnumerable<AddressUnit> getAddresses, byte slaveAddress, byte masterAddress) IEnumerable<AddressUnit> getAddresses, byte slaveAddress, byte masterAddress)
: this(connectionType, connectionString, model, getAddresses, false, slaveAddress, masterAddress) : this(connectionType, connectionString, model, getAddresses, false, slaveAddress, masterAddress)

View File

@@ -10,22 +10,43 @@ namespace Modbus.Net.Siemens
{ {
private readonly string _com; private readonly string _com;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="slaveAddress">从站号</param>
/// <param name="masterAddress">主站号</param>
public SiemensPpiProtocal(byte slaveAddress, byte masterAddress) public SiemensPpiProtocal(byte slaveAddress, byte masterAddress)
: this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress) : this(ConfigurationManager.AppSettings["COM"], slaveAddress, masterAddress)
{ {
} }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="com">串口地址</param>
/// <param name="slaveAddress">从站号</param>
/// <param name="masterAddress">主站号</param>
public SiemensPpiProtocal(string com, byte slaveAddress, byte masterAddress) public SiemensPpiProtocal(string com, byte slaveAddress, byte masterAddress)
: base(slaveAddress, masterAddress) : base(slaveAddress, masterAddress)
{ {
_com = com; _com = com;
} }
/// <summary>
/// 发送协议内容并接收,一般方法
/// </summary>
/// <param name="content">写入的内容,使用对象数组描述</param>
/// <returns>从设备获取的字节流</returns>
public override byte[] SendReceive(params object[] content) public override byte[] SendReceive(params object[] content)
{ {
return AsyncHelper.RunSync(() => SendReceiveAsync(Endian, content)); return AsyncHelper.RunSync(() => SendReceiveAsync(Endian, content));
} }
/// <summary>
/// 发送协议内容并接收,一般方法
/// </summary>
/// <param name="content">写入的内容,使用对象数组描述</param>
/// <returns>从设备获取的字节流</returns>
public override async Task<byte[]> SendReceiveAsync(params object[] content) public override async Task<byte[]> SendReceiveAsync(params object[] content)
{ {
if (ProtocalLinker == null || !ProtocalLinker.IsConnected) if (ProtocalLinker == null || !ProtocalLinker.IsConnected)
@@ -33,16 +54,30 @@ namespace Modbus.Net.Siemens
return await base.SendReceiveAsync(Endian, content); return await base.SendReceiveAsync(Endian, content);
} }
/// <summary>
/// 强行发送,不检测连接状态
/// </summary>
/// <param name="unit">协议核心</param>
/// <param name="content">协议的参数</param>
/// <returns>设备返回的信息</returns>
private async Task<IOutputStruct> ForceSendReceiveAsync(ProtocalUnit unit, IInputStruct content) private async Task<IOutputStruct> ForceSendReceiveAsync(ProtocalUnit unit, IInputStruct content)
{ {
return await base.SendReceiveAsync(unit, content); return await base.SendReceiveAsync(unit, content);
} }
/// <summary>
/// 连接设备
/// </summary>
/// <returns>是否连接成功</returns>
public override bool Connect() public override bool Connect()
{ {
return AsyncHelper.RunSync(() => ConnectAsync()); return AsyncHelper.RunSync(ConnectAsync);
} }
/// <summary>
/// 连接设备
/// </summary>
/// <returns>是否连接成功</returns>
public override async Task<bool> ConnectAsync() public override async Task<bool> ConnectAsync()
{ {
ProtocalLinker = new SiemensPpiProtocalLinker(_com, SlaveAddress); ProtocalLinker = new SiemensPpiProtocalLinker(_com, SlaveAddress);

View File

@@ -9,11 +9,21 @@ namespace Modbus.Net.Siemens
/// </summary> /// </summary>
public class SiemensPpiProtocalLinker : ComProtocalLinker public class SiemensPpiProtocalLinker : ComProtocalLinker
{ {
/// <summary>
/// 构造函数
/// </summary>
/// <param name="com">串口地址</param>
/// <param name="slaveAddress">从站号</param>
public SiemensPpiProtocalLinker(string com, int slaveAddress) public SiemensPpiProtocalLinker(string com, int slaveAddress)
: base(com, 9600, Parity.Even, StopBits.One, 8, slaveAddress) : base(com, 9600, Parity.Even, StopBits.One, 8, slaveAddress)
{ {
} }
/// <summary>
/// 发送协议内容并接收返回
/// </summary>
/// <param name="content">发送的报文</param>
/// <returns>接收的报文</returns>
public override async Task<byte[]> SendReceiveAsync(byte[] content) public override async Task<byte[]> SendReceiveAsync(byte[] content)
{ {
var extBytes = BytesExtend(content); var extBytes = BytesExtend(content);
@@ -36,6 +46,11 @@ namespace Modbus.Net.Siemens
return BytesDecact(receiveBytes); return BytesDecact(receiveBytes);
} }
/// <summary>
/// 发送协议内容并接收返回,不进行协议扩展和收缩
/// </summary>
/// <param name="content">发送的报文</param>
/// <returns>接收的报文</returns>
public override async Task<byte[]> SendReceiveWithoutExtAndDecAsync(byte[] content) public override async Task<byte[]> SendReceiveWithoutExtAndDecAsync(byte[] content)
{ {
var ans = await base.SendReceiveWithoutExtAndDecAsync(content); var ans = await base.SendReceiveWithoutExtAndDecAsync(content);
@@ -60,6 +75,11 @@ namespace Modbus.Net.Siemens
return ans; return ans;
} }
/// <summary>
/// 校验报文
/// </summary>
/// <param name="content">设备返回的信息</param>
/// <returns>报文是否正确</returns>
public override bool? CheckRight(byte[] content) public override bool? CheckRight(byte[] content)
{ {
if (!base.CheckRight(content).Value) return false; if (!base.CheckRight(content).Value) return false;

View File

@@ -7,6 +7,11 @@ namespace Modbus.Net.Siemens
/// </summary> /// </summary>
public class SiemensTcpProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend public class SiemensTcpProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend
{ {
/// <summary>
/// 协议扩展,协议内容发送前调用
/// </summary>
/// <param name="content">扩展前的原始协议内容</param>
/// <returns>扩展后的协议内容</returns>
public byte[] BytesExtend(byte[] content) public byte[] BytesExtend(byte[] content)
{ {
Array.Copy(new byte[] {0x03, 0x00, 0x00, 0x00, 0x02, 0xf0, 0x80}, 0, content, 0, 7); Array.Copy(new byte[] {0x03, 0x00, 0x00, 0x00, 0x02, 0xf0, 0x80}, 0, content, 0, 7);
@@ -14,6 +19,11 @@ namespace Modbus.Net.Siemens
return content; return content;
} }
/// <summary>
/// 协议收缩,协议内容接收后调用
/// </summary>
/// <param name="content">收缩前的完整协议内容</param>
/// <returns>收缩后的协议内容</returns>
public byte[] BytesDecact(byte[] content) public byte[] BytesDecact(byte[] content)
{ {
var newContent = new byte[content.Length - 7]; var newContent = new byte[content.Length - 7];
@@ -27,6 +37,11 @@ namespace Modbus.Net.Siemens
/// </summary> /// </summary>
public class SiemensPpiProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend public class SiemensPpiProtocalLinkerBytesExtend : IProtocalLinkerBytesExtend
{ {
/// <summary>
/// 协议扩展,协议内容发送前调用
/// </summary>
/// <param name="content">扩展前的原始协议内容</param>
/// <returns>扩展后的协议内容</returns>
public byte[] BytesExtend(byte[] content) public byte[] BytesExtend(byte[] content)
{ {
var newContent = new byte[content.Length + 2]; var newContent = new byte[content.Length + 2];
@@ -42,6 +57,11 @@ namespace Modbus.Net.Siemens
return newContent; return newContent;
} }
/// <summary>
/// 协议收缩,协议内容接收后调用
/// </summary>
/// <param name="content">收缩前的完整协议内容</param>
/// <returns>收缩后的协议内容</returns>
public byte[] BytesDecact(byte[] content) public byte[] BytesDecact(byte[] content)
{ {
var newContent = new byte[content.Length - 9]; var newContent = new byte[content.Length - 9];

View File

@@ -18,12 +18,31 @@ namespace Modbus.Net.Siemens
private readonly ushort _tsapDst; private readonly ushort _tsapDst;
private int _connectTryCount; private int _connectTryCount;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="tdpuSize"></param>
/// <param name="tsapSrc"></param>
/// <param name="tsapDst"></param>
/// <param name="maxCalling"></param>
/// <param name="maxCalled"></param>
/// <param name="maxPdu"></param>
public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled, public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled,
ushort maxPdu) ushort maxPdu)
: this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ConfigurationManager.AppSettings["IP"]) : this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ConfigurationManager.AppSettings["IP"])
{ {
} }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="tdpuSize"></param>
/// <param name="tsapSrc"></param>
/// <param name="tsapDst"></param>
/// <param name="maxCalling"></param>
/// <param name="maxCalled"></param>
/// <param name="maxPdu"></param>
/// <param name="ip">IP地址</param>
public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled, public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled,
ushort maxPdu, string ip) ushort maxPdu, string ip)
: this( : this(
@@ -32,6 +51,17 @@ namespace Modbus.Net.Siemens
{ {
} }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="tdpuSize"></param>
/// <param name="tsapSrc"></param>
/// <param name="tsapDst"></param>
/// <param name="maxCalling"></param>
/// <param name="maxCalled"></param>
/// <param name="maxPdu"></param>
/// <param name="ip">IP地址</param>
/// <param name="port">端口</param>
public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled, public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled,
ushort maxPdu, string ip, int port) : base(0, 0) ushort maxPdu, string ip, int port) : base(0, 0)
{ {
@@ -46,11 +76,21 @@ namespace Modbus.Net.Siemens
_connectTryCount = 0; _connectTryCount = 0;
} }
/// <summary>
/// 发送数据并接收
/// </summary>
/// <param name="content">发送的数据</param>
/// <returns>返回的数据</returns>
public override byte[] SendReceive(params object[] content) public override byte[] SendReceive(params object[] content)
{ {
return AsyncHelper.RunSync(() => SendReceiveAsync(Endian, content)); return AsyncHelper.RunSync(() => SendReceiveAsync(Endian, content));
} }
/// <summary>
/// 发送数据并接收
/// </summary>
/// <param name="content">发送的数据</param>
/// <returns>返回的数据</returns>
public override async Task<byte[]> SendReceiveAsync(params object[] content) public override async Task<byte[]> SendReceiveAsync(params object[] content)
{ {
if (ProtocalLinker == null || !ProtocalLinker.IsConnected) if (ProtocalLinker == null || !ProtocalLinker.IsConnected)
@@ -58,11 +98,23 @@ namespace Modbus.Net.Siemens
return await base.SendReceiveAsync(Endian, content); return await base.SendReceiveAsync(Endian, content);
} }
/// <summary>
/// 发送数据并接收
/// </summary>
/// <param name="unit">协议的核心</param>
/// <param name="content">协议的参数</param>
/// <returns>返回的数据</returns>
public override IOutputStruct SendReceive(ProtocalUnit unit, IInputStruct content) public override IOutputStruct SendReceive(ProtocalUnit unit, IInputStruct content)
{ {
return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content)); return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content));
} }
/// <summary>
/// 发送数据并接收
/// </summary>
/// <param name="unit">发送的数据</param>
/// <param name="content">协议的参数</param>
/// <returns>返回的数据</returns>
public override async Task<IOutputStruct> SendReceiveAsync(ProtocalUnit unit, IInputStruct content) public override async Task<IOutputStruct> SendReceiveAsync(ProtocalUnit unit, IInputStruct content)
{ {
if (ProtocalLinker != null && ProtocalLinker.IsConnected) return await base.SendReceiveAsync(unit, content); if (ProtocalLinker != null && ProtocalLinker.IsConnected) return await base.SendReceiveAsync(unit, content);
@@ -74,16 +126,30 @@ namespace Modbus.Net.Siemens
.ContinueWith(answer => answer.Result ? base.SendReceiveAsync(unit, content) : null); .ContinueWith(answer => answer.Result ? base.SendReceiveAsync(unit, content) : null);
} }
/// <summary>
/// 强制发送数据并接收
/// </summary>
/// <param name="unit">发送的数据</param>
/// <param name="content">协议的参数</param>
/// <returns>返回的数据</returns>
private async Task<IOutputStruct> ForceSendReceiveAsync(ProtocalUnit unit, IInputStruct content) private async Task<IOutputStruct> ForceSendReceiveAsync(ProtocalUnit unit, IInputStruct content)
{ {
return await base.SendReceiveAsync(unit, content); return await base.SendReceiveAsync(unit, content);
} }
/// <summary>
/// 连接设备
/// </summary>
/// <returns>设备是否连接成功</returns>
public override bool Connect() public override bool Connect()
{ {
return AsyncHelper.RunSync(ConnectAsync); return AsyncHelper.RunSync(ConnectAsync);
} }
/// <summary>
/// 连接设备
/// </summary>
/// <returns>设备是否连接成功</returns>
public override async Task<bool> ConnectAsync() public override async Task<bool> ConnectAsync()
{ {
_connectTryCount++; _connectTryCount++;

View File

@@ -8,16 +8,30 @@ namespace Modbus.Net.Siemens
/// </summary> /// </summary>
public class SiemensTcpProtocalLinker : TcpProtocalLinker public class SiemensTcpProtocalLinker : TcpProtocalLinker
{ {
/// <summary>
/// 构造函数
/// </summary>
/// <param name="ip">IP地址</param>
public SiemensTcpProtocalLinker(string ip) public SiemensTcpProtocalLinker(string ip)
: this(ip, int.Parse(ConfigurationManager.AppSettings["SiemensPort"] ?? "102")) : this(ip, int.Parse(ConfigurationManager.AppSettings["SiemensPort"] ?? "102"))
{ {
} }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="ip">IP地址</param>
/// <param name="port">端口</param>
public SiemensTcpProtocalLinker(string ip, int port) public SiemensTcpProtocalLinker(string ip, int port)
: base(ip, port) : base(ip, port)
{ {
} }
/// <summary>
/// 校验报文
/// </summary>
/// <param name="content">设备返回的信息</param>
/// <returns>报文是否正确</returns>
public override bool? CheckRight(byte[] content) public override bool? CheckRight(byte[] content)
{ {
if (!base.CheckRight(content).Value) return false; if (!base.CheckRight(content).Value) return false;

View File

@@ -1,22 +1,56 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog;
namespace Modbus.Net.Siemens namespace Modbus.Net.Siemens
{ {
/// <summary>
/// 西门子协议类型
/// </summary>
public enum SiemensType public enum SiemensType
{ {
/// <summary>
/// PPI
/// </summary>
Ppi = 0, Ppi = 0,
/// <summary>
/// MPI
/// </summary>
Mpi = 1, Mpi = 1,
/// <summary>
/// 以太网
/// </summary>
Tcp = 2 Tcp = 2
} }
/// <summary>
/// 西门子设备类型
/// </summary>
public enum SiemensMachineModel public enum SiemensMachineModel
{ {
/// <summary>
/// S7-200
/// </summary>
S7_200 = 0, S7_200 = 0,
/// <summary>
/// S7-200 Smart
/// </summary>
S7_200_Smart = 1, S7_200_Smart = 1,
/// <summary>
/// S7-300
/// </summary>
S7_300 = 2, S7_300 = 2,
/// <summary>
/// S7-400
/// </summary>
S7_400 = 3, S7_400 = 3,
/// <summary>
/// S7-1200
/// </summary>
S7_1200 = 4, S7_1200 = 4,
/// <summary>
/// S7-1500
/// </summary>
S7_1500 = 5 S7_1500 = 5
} }
@@ -34,6 +68,14 @@ namespace Modbus.Net.Siemens
private SiemensType _siemensType; private SiemensType _siemensType;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="connectionType">连接类型</param>
/// <param name="connectionString">连接字符串</param>
/// <param name="model">设备类型</param>
/// <param name="slaveAddress">从站地址</param>
/// <param name="masterAddress">主站地址</param>
public SiemensUtility(SiemensType connectionType, string connectionString, SiemensMachineModel model, public SiemensUtility(SiemensType connectionType, string connectionString, SiemensMachineModel model,
byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress) byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress)
{ {
@@ -84,15 +126,21 @@ namespace Modbus.Net.Siemens
} }
default: default:
{ {
throw new NotImplementedException("没有相应的西门子类型"); throw new NotImplementedException("Siemens PLC Model not Supported");
} }
} }
ConnectionType = connectionType; ConnectionType = connectionType;
AddressTranslator = new AddressTranslatorSiemens(); AddressTranslator = new AddressTranslatorSiemens();
} }
/// <summary>
/// 端格式
/// </summary>
public override Endian Endian => Endian.BigEndianLsb; public override Endian Endian => Endian.BigEndianLsb;
/// <summary>
/// IP地址
/// </summary>
protected string ConnectionStringIp protected string ConnectionStringIp
{ {
get get
@@ -102,6 +150,9 @@ namespace Modbus.Net.Siemens
} }
} }
/// <summary>
/// 端口
/// </summary>
protected int? ConnectionStringPort protected int? ConnectionStringPort
{ {
get get
@@ -113,8 +164,9 @@ namespace Modbus.Net.Siemens
{ {
return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]); return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]);
} }
catch catch (Exception e)
{ {
Log.Error(e, $"SiemensUtility: {ConnectionString} format error");
return null; return null;
} }
} }
@@ -188,8 +240,9 @@ namespace Modbus.Net.Siemens
readRequestSiemensInputStruct); readRequestSiemensInputStruct);
return readRequestSiemensOutputStruct?.GetValue; return readRequestSiemensOutputStruct?.GetValue;
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, $"SiemensUtility -> GetDatas: {ConnectionString} error");
return null; return null;
} }
} }
@@ -213,8 +266,9 @@ namespace Modbus.Net.Siemens
writeRequestSiemensInputStruct); writeRequestSiemensInputStruct);
return writeRequestSiemensOutputStruct?.AccessResult == SiemensAccessResult.NoError; return writeRequestSiemensOutputStruct?.AccessResult == SiemensAccessResult.NoError;
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> SetDatas: {ConnectionString} error");
return false; return false;
} }
} }

View File

@@ -61,15 +61,16 @@ namespace Modbus.Net
/// </summary> /// </summary>
private readonly int _timeoutTime; private readonly int _timeoutTime;
private int _errorCount;
private int _receiveCount;
private int _sendCount;
/// <summary> /// <summary>
/// Dispose是否执行 /// Dispose是否执行
/// </summary> /// </summary>
private bool m_disposed; private bool m_disposed;
private int _sendCount;
private int _receiveCount;
private int _errorCount;
/// <summary> /// <summary>
/// 构造器 /// 构造器
/// </summary> /// </summary>
@@ -283,7 +284,7 @@ namespace Modbus.Net
{ {
SerialPort.Close(); SerialPort.Close();
} }
catch (Exception) catch
{ {
//ignore //ignore
} }
@@ -308,6 +309,24 @@ namespace Modbus.Net
Dispose(false); Dispose(false);
} }
private void RefreshSendCount()
{
_sendCount++;
Log.Verbose("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount);
}
private void RefreshReceiveCount()
{
_receiveCount++;
Log.Verbose("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount);
}
private void RefreshErrorCount()
{
_errorCount++;
Log.Verbose("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount);
}
#region #region
/// <summary> /// <summary>
@@ -381,7 +400,8 @@ namespace Modbus.Net
Log.Error(e, "Com client {ConnectionToken} disconnect error", ConnectionToken); Log.Error(e, "Com client {ConnectionToken} disconnect error", ConnectionToken);
return false; return false;
} }
Log.Error(new Exception("Linkers or Connectors Dictionary not found"), "Com client {ConnectionToken} disconnect error", ConnectionToken); Log.Error(new Exception("Linkers or Connectors Dictionary not found"),
"Com client {ConnectionToken} disconnect error", ConnectionToken);
return false; return false;
} }
@@ -436,7 +456,8 @@ namespace Modbus.Net
{ {
try try
{ {
Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, sendbytes.Length); Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken,
sendbytes.Length);
Log.Verbose("Com client {ConnectionToken} send msg: {SendBytes}", ConnectionToken, sendbytes); Log.Verbose("Com client {ConnectionToken} send msg: {SendBytes}", ConnectionToken, sendbytes);
SerialPort.Write(sendbytes, 0, sendbytes.Length); SerialPort.Write(sendbytes, 0, sendbytes.Length);
} }
@@ -450,8 +471,10 @@ namespace Modbus.Net
try try
{ {
returnBytes = ReadMsg(); returnBytes = ReadMsg();
Log.Verbose("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken, returnBytes.Length); Log.Verbose("Com client {ConnectionToken} receive msg length: {Length}", ConnectionToken,
Log.Verbose("Com client {ConnectionToken} receive msg: {SendBytes}", ConnectionToken, returnBytes); returnBytes.Length);
Log.Verbose("Com client {ConnectionToken} receive msg: {SendBytes}", ConnectionToken,
returnBytes);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -504,7 +527,8 @@ namespace Modbus.Net
{ {
try try
{ {
Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken, sendbytes.Length); Log.Verbose("Com client {ConnectionToken} send msg length: {Length}", ConnectionToken,
sendbytes.Length);
Log.Verbose("Com client {ConnectionToken} send msg: {SendBytes}", ConnectionToken, sendbytes); Log.Verbose("Com client {ConnectionToken} send msg: {SendBytes}", ConnectionToken, sendbytes);
SerialPort.Write(sendbytes, 0, sendbytes.Length); SerialPort.Write(sendbytes, 0, sendbytes.Length);
} }
@@ -549,23 +573,5 @@ namespace Modbus.Net
} }
#endregion #endregion
private void RefreshSendCount()
{
_sendCount++;
Log.Verbose("Tcp client {ConnectionToken} send count: {SendCount}", ConnectionToken, _sendCount);
}
private void RefreshReceiveCount()
{
_receiveCount++;
Log.Verbose("Tcp client {ConnectionToken} receive count: {SendCount}", ConnectionToken, _receiveCount);
}
private void RefreshErrorCount()
{
_errorCount++;
Log.Verbose("Tcp client {ConnectionToken} error count: {ErrorCount}", ConnectionToken, _errorCount);
}
} }
} }

View File

@@ -52,9 +52,9 @@ namespace Modbus.Net
/// <summary> /// <summary>
/// 地址转换 /// 地址转换
/// </summary> /// </summary>
/// <param name="address">地址前地址</param> /// <param name="address">格式化的地址</param>
/// <param name="isRead">是否为读取,是为读取,否为写入</param> /// <param name="isRead">是否为读取,是为读取,否为写入</param>
/// <returns>Key为转换后的地址Value为辅助码</returns> /// <returns>翻译后的地址</returns>
public abstract AddressDef AddressTranslate(string address, bool isRead); public abstract AddressDef AddressTranslate(string address, bool isRead);
/// <summary> /// <summary>

View File

@@ -7,7 +7,6 @@ namespace Modbus.Net
/// </summary> /// </summary>
public abstract class BaseConnector : BaseConnector<byte[], byte[]> public abstract class BaseConnector : BaseConnector<byte[], byte[]>
{ {
} }
/// <summary> /// <summary>

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog;
namespace Modbus.Net namespace Modbus.Net
{ {
@@ -333,8 +334,9 @@ namespace Modbus.Net
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(ConnectionToken + " " + e.Message);
ErrorCount++; ErrorCount++;
Log.Error(e, $"BaseMachine -> GetDatas, Id:{Id} Connection:{ConnectionToken} error. ErrorCount {ErrorCount}.");
if (ErrorCount >= _maxErrorCount) if (ErrorCount >= _maxErrorCount)
Disconnect(); Disconnect();
return null; return null;
@@ -532,7 +534,11 @@ namespace Modbus.Net
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(ConnectionToken + " " + e.Message); ErrorCount++;
Log.Error(e, $"BaseMachine -> SetDatas, Id:{Id} Connection:{ConnectionToken} error. ErrorCount {ErrorCount}.");
if (ErrorCount >= _maxErrorCount)
Disconnect();
return false; return false;
} }
return true; return true;
@@ -591,7 +597,7 @@ namespace Modbus.Net
.Invoke(this, parameters); .Invoke(this, parameters);
return (TReturnType) returnValue; return (TReturnType) returnValue;
} }
throw new InvalidCastException($"Machine未实现{typeof(TMachineMethod).Name}的接口"); throw new InvalidCastException($"Machine interface {nameof(TMachineMethod)} not implemented");
} }
/// <summary> /// <summary>
@@ -641,9 +647,9 @@ namespace Modbus.Net
{ {
return GetAddresses.SingleOrDefault(p => p.Id.Equals(addressUnitId)); return GetAddresses.SingleOrDefault(p => p.Id.Equals(addressUnitId));
} }
catch (Exception) catch (Exception e)
{ {
Console.WriteLine("Id重复请检查"); Log.Error(e, $"BaseMachine -> GetAddressUnitById Id:{Id} ConnectionToken:{ConnectionToken} addressUnitId:{addressUnitId} Repeated");
return null; return null;
} }
} }

View File

@@ -85,7 +85,8 @@ namespace Modbus.Net
//自动寻找存在的协议并将其加载 //自动寻找存在的协议并将其加载
var protocalUnit = var protocalUnit =
Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit; Activator.CreateInstance(type.GetTypeInfo().Assembly.GetType(protocalName)) as TProtocalUnit;
if (protocalUnit == null) throw new InvalidCastException("没有相应的协议内容"); if (protocalUnit == null)
throw new InvalidCastException($"No ProtocalUnit {nameof(TProtocalUnit)} implemented");
protocalUnit.Endian = Endian; protocalUnit.Endian = Endian;
Register(protocalUnit); Register(protocalUnit);
return Protocals[protocalName]; return Protocals[protocalName];

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog;
/// <summary> /// <summary>
/// 端格式 /// 端格式
@@ -124,8 +125,9 @@ namespace Modbus.Net
var getBytes = getReturnValue; var getBytes = getReturnValue;
return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, getTypeAndCount); return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, getTypeAndCount);
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> GetDatas: {ConnectionString} error");
return null; return null;
} }
} }
@@ -159,8 +161,9 @@ namespace Modbus.Net
new KeyValuePair<Type, int>(typeof(T), getByteCount)); new KeyValuePair<Type, int>(typeof(T), getByteCount));
return ValueHelper.GetInstance(Endian).ObjectArrayToDestinationArray<T>(getBytes); return ValueHelper.GetInstance(Endian).ObjectArrayToDestinationArray<T>(getBytes);
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> GetDatas Generic: {ConnectionString} error");
return null; return null;
} }
} }
@@ -199,8 +202,9 @@ namespace Modbus.Net
var getBytes = getReturnValue; var getBytes = getReturnValue;
return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, translateTypeAndCount); return ValueHelper.GetInstance(Endian).ByteArrayToObjectArray(getBytes, translateTypeAndCount);
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, $"ModbusUtility -> GetDatas pair: {ConnectionString} error");
return null; return null;
} }
} }
@@ -290,7 +294,7 @@ namespace Modbus.Net
.Invoke(this, parameters); .Invoke(this, parameters);
return (TReturnType) returnValue; return (TReturnType) returnValue;
} }
throw new InvalidCastException($"Utility未实现{typeof(TUtilityMethod).Name}的接口"); throw new InvalidCastException($"Utility interface {nameof(TUtilityMethod)} not implemented");
} }
/// <summary> /// <summary>

View File

@@ -9,6 +9,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Nito.AsyncEx; using Nito.AsyncEx;
using Serilog;
namespace Modbus.Net namespace Modbus.Net
{ {
@@ -864,7 +865,7 @@ namespace Modbus.Net
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine($"设备返回错误 {e.Message}"); Log.Error(e, $"Device {id} return error");
return null; return null;
} }
} }
@@ -889,7 +890,7 @@ namespace Modbus.Net
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine($"设备返回错误 {e.Message}"); Log.Error(e, $"Device {connectionToken} return error");
return null; return null;
} }
} }

View File

@@ -40,9 +40,10 @@ namespace Modbus.Net
/// </summary> /// </summary>
private readonly byte[] _receiveBuffer = new byte[1024]; private readonly byte[] _receiveBuffer = new byte[1024];
private int _sendCount;
private int _receiveCount;
private int _errorCount; private int _errorCount;
private int _receiveCount;
private int _sendCount;
private TcpClient _socketClient; private TcpClient _socketClient;
@@ -73,7 +74,8 @@ namespace Modbus.Net
/// </summary> /// </summary>
public int TimeoutTime public int TimeoutTime
{ {
get => _timeoutTime; get =>
_timeoutTime;
set set
{ {
_timeoutTime = value; _timeoutTime = value;
@@ -286,7 +288,8 @@ namespace Modbus.Net
RefreshSendCount(); RefreshSendCount();
var receiveBytes = await ReceiveAsync(stream); var receiveBytes = await ReceiveAsync(stream);
Log.Verbose("Tcp client {ConnectionToken} receive text len = {Length}", ConnectionToken, receiveBytes.Length); Log.Verbose("Tcp client {ConnectionToken} receive text len = {Length}", ConnectionToken,
receiveBytes.Length);
Log.Verbose("Tcp client {ConnectionToken} receive: {Datagram}", ConnectionToken, receiveBytes); Log.Verbose("Tcp client {ConnectionToken} receive: {Datagram}", ConnectionToken, receiveBytes);
return receiveBytes; return receiveBytes;

View File

@@ -1,6 +1,6 @@
#if NET40||NET45||NET451||NET452||NET46||NET461||NET462||NET47
#if NET40||NET45||NET451||NET452||NET46||NET461||NET462||NET47
using System.Configuration; using System.Configuration;
#endif #endif
namespace Modbus.Net namespace Modbus.Net

View File

@@ -36,7 +36,7 @@ namespace Modbus.Net
throw new NullReferenceException("The type has not been specified."); throw new NullReferenceException("The type has not been specified.");
if (string.IsNullOrEmpty(methodName)) if (string.IsNullOrEmpty(methodName))
throw new ArgumentNullException("methodName", "The name of the method has not been specified."); throw new ArgumentNullException(nameof(methodName), "The name of the method has not been specified.");
var methods = var methods =

View File

@@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Serilog;
namespace Modbus.Net namespace Modbus.Net
{ {
@@ -707,12 +708,13 @@ namespace Modbus.Net
} }
default: default:
{ {
throw new NotImplementedException("没有实现除整数以外的其它转换方式"); throw new NotImplementedException("Number casting not implemented");
} }
} }
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, "ValueHelper -> ByteArrayToObjectArray error");
count = contents.Length; count = contents.Length;
} }
} }
@@ -798,7 +800,7 @@ namespace Modbus.Net
} }
default: default:
{ {
throw new NotImplementedException("没有实现除整数以外的其它转换方式"); throw new NotImplementedException("Number casting not implemented");
} }
} }
} }
@@ -818,8 +820,9 @@ namespace Modbus.Net
Array.Copy(datas, 0, contents, pos, datas.Length); Array.Copy(datas, 0, contents, pos, datas.Length);
return true; return true;
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, "ValueHelper -> SetValue set value failed");
return false; return false;
} }
} }
@@ -866,8 +869,9 @@ namespace Modbus.Net
contents[pos] = SetBit(contents[pos], subPos, setValue); contents[pos] = SetBit(contents[pos], subPos, setValue);
return true; return true;
} }
catch (Exception) catch (Exception e)
{ {
Log.Error(e, "ValueHelper -> SetBit set bit failed");
return false; return false;
} }
} }