2017-02-06 update 1 Add AddressHelper and comments, reformat code.
This commit is contained in:
@@ -1,10 +1,4 @@
|
|||||||
using System;
|
namespace Modbus.Net.Modbus
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
|
||||||
{
|
{
|
||||||
public class AddressFormaterNA200H : AddressFormater
|
public class AddressFormaterNA200H : AddressFormater
|
||||||
{
|
{
|
||||||
@@ -28,7 +22,7 @@ namespace Modbus.Net.Modbus
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,15 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
namespace Modbus.Net.Modbus
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NA200H数据单元翻译器
|
/// NA200H数据单元翻译器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AddressTranslatorNA200H : AddressTranslator
|
public class AddressTranslatorNA200H : AddressTranslator
|
||||||
{
|
{
|
||||||
protected Dictionary<string, int> TransDictionary;
|
|
||||||
protected Dictionary<string, AreaOutputDef> ReadFunctionCodeDictionary;
|
protected Dictionary<string, AreaOutputDef> ReadFunctionCodeDictionary;
|
||||||
|
protected Dictionary<string, int> TransDictionary;
|
||||||
protected Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary;
|
protected Dictionary<string, AreaOutputDef> WriteFunctionCodeDictionary;
|
||||||
|
|
||||||
public AddressTranslatorNA200H()
|
public AddressTranslatorNA200H()
|
||||||
@@ -28,42 +25,134 @@ namespace Modbus.Net.Modbus
|
|||||||
{"SW", 5000},
|
{"SW", 5000},
|
||||||
{"MW", 0},
|
{"MW", 0},
|
||||||
{"QW", 20000},
|
{"QW", 20000},
|
||||||
{"NW", 21000},
|
{"NW", 21000}
|
||||||
};
|
};
|
||||||
ReadFunctionCodeDictionary = new Dictionary<string, AreaOutputDef>
|
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}},
|
"Q",
|
||||||
{"N", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadCoilStatus, AreaWidth = 0.125}},
|
new AreaOutputDef
|
||||||
{"I", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadInputStatus, AreaWidth = 0.125}},
|
{
|
||||||
{"S", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadInputStatus, AreaWidth = 0.125}},
|
Code = (int) ModbusProtocalReadDataFunctionCode.ReadCoilStatus,
|
||||||
{"IW", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadInputRegister, AreaWidth = 2}},
|
AreaWidth = 0.125
|
||||||
{"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}},
|
"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, AreaOutputDef>
|
WriteFunctionCodeDictionary = new Dictionary<string, AreaOutputDef>
|
||||||
{
|
{
|
||||||
{"Q", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, AreaWidth = 0.125}},
|
{
|
||||||
{"M", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, AreaWidth = 0.125}},
|
"Q",
|
||||||
{"N", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, AreaWidth = 0.125}},
|
new AreaOutputDef
|
||||||
{"MW", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, AreaWidth = 2}},
|
{
|
||||||
{"NW", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, AreaWidth = 2}},
|
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||||
{"QW", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, AreaWidth = 2}},
|
AreaWidth = 0.125
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"M",
|
||||||
|
new AreaOutputDef
|
||||||
|
{
|
||||||
|
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||||
|
AreaWidth = 0.125
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"N",
|
||||||
|
new AreaOutputDef
|
||||||
|
{
|
||||||
|
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||||
|
AreaWidth = 0.125
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MW",
|
||||||
|
new AreaOutputDef
|
||||||
|
{
|
||||||
|
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
|
||||||
|
AreaWidth = 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NW",
|
||||||
|
new AreaOutputDef
|
||||||
|
{
|
||||||
|
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
|
||||||
|
AreaWidth = 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"QW",
|
||||||
|
new AreaOutputDef
|
||||||
|
{
|
||||||
|
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
|
||||||
|
AreaWidth = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override AddressDef AddressTranslate(string address, bool isRead)
|
public override AddressDef AddressTranslate(string address, bool isRead)
|
||||||
{
|
{
|
||||||
address = address.ToUpper();
|
address = address.ToUpper();
|
||||||
string[] splitString = address.Split(' ');
|
var splitString = address.Split(' ');
|
||||||
string head = splitString[0];
|
var head = splitString[0];
|
||||||
string tail = splitString[1];
|
var tail = splitString[1];
|
||||||
string sub;
|
string sub;
|
||||||
if (tail.Contains('.'))
|
if (tail.Contains('.'))
|
||||||
{
|
{
|
||||||
string[] splitString2 = tail.Split('.');
|
var splitString2 = tail.Split('.');
|
||||||
sub = splitString2[1];
|
sub = splitString2[1];
|
||||||
tail = splitString2[0];
|
tail = splitString2[0];
|
||||||
}
|
}
|
||||||
@@ -72,19 +161,19 @@ namespace Modbus.Net.Modbus
|
|||||||
sub = "0";
|
sub = "0";
|
||||||
}
|
}
|
||||||
return isRead
|
return isRead
|
||||||
? new AddressDef()
|
? new AddressDef
|
||||||
{
|
{
|
||||||
AreaString = head,
|
AreaString = head,
|
||||||
Area = ReadFunctionCodeDictionary[head].Code,
|
Area = ReadFunctionCodeDictionary[head].Code,
|
||||||
Address = TransDictionary[head] + int.Parse(tail) - 1,
|
Address = TransDictionary[head] + int.Parse(tail) - 1,
|
||||||
SubAddress = int.Parse(sub),
|
SubAddress = int.Parse(sub)
|
||||||
}
|
}
|
||||||
: new AddressDef()
|
: new AddressDef
|
||||||
{
|
{
|
||||||
AreaString = head,
|
AreaString = head,
|
||||||
Area = WriteFunctionCodeDictionary[head].Code,
|
Area = WriteFunctionCodeDictionary[head].Code,
|
||||||
Address = TransDictionary[head] + int.Parse(tail) - 1,
|
Address = TransDictionary[head] + int.Parse(tail) - 1,
|
||||||
SubAddress = int.Parse(sub),
|
SubAddress = int.Parse(sub)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +184,7 @@ namespace Modbus.Net.Modbus
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus数据单元翻译器
|
/// Modbus数据单元翻译器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AddressTranslatorModbus : AddressTranslator
|
public class AddressTranslatorModbus : AddressTranslator
|
||||||
{
|
{
|
||||||
@@ -106,28 +195,62 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
ReadFunctionCodeDictionary = new Dictionary<string, AreaOutputDef>
|
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}},
|
"0X",
|
||||||
{"3X", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadInputRegister, AreaWidth = 2}},
|
new AreaOutputDef
|
||||||
{"4X", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}},
|
{
|
||||||
|
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, AreaOutputDef>
|
WriteFunctionCodeDictionary = new Dictionary<string, AreaOutputDef>
|
||||||
{
|
{
|
||||||
{"0X", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, AreaWidth = 0.125}},
|
{
|
||||||
{"4X", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, AreaWidth = 2}},
|
"0X",
|
||||||
|
new AreaOutputDef
|
||||||
|
{
|
||||||
|
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiCoil,
|
||||||
|
AreaWidth = 0.125
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"4X",
|
||||||
|
new AreaOutputDef
|
||||||
|
{
|
||||||
|
Code = (int) ModbusProtocalWriteDataFunctionCode.WriteMultiRegister,
|
||||||
|
AreaWidth = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override AddressDef AddressTranslate(string address, bool isRead)
|
public override AddressDef AddressTranslate(string address, bool isRead)
|
||||||
{
|
{
|
||||||
address = address.ToUpper();
|
address = address.ToUpper();
|
||||||
string[] splitString = address.Split(' ');
|
var splitString = address.Split(' ');
|
||||||
string head = splitString[0];
|
var head = splitString[0];
|
||||||
string tail = splitString[1];
|
var tail = splitString[1];
|
||||||
string sub;
|
string sub;
|
||||||
if (tail.Contains('.'))
|
if (tail.Contains('.'))
|
||||||
{
|
{
|
||||||
string[] splitString2 = tail.Split('.');
|
var splitString2 = tail.Split('.');
|
||||||
sub = splitString2[1];
|
sub = splitString2[1];
|
||||||
tail = splitString2[0];
|
tail = splitString2[0];
|
||||||
}
|
}
|
||||||
@@ -136,19 +259,19 @@ namespace Modbus.Net.Modbus
|
|||||||
sub = "0";
|
sub = "0";
|
||||||
}
|
}
|
||||||
return isRead
|
return isRead
|
||||||
? new AddressDef()
|
? new AddressDef
|
||||||
{
|
{
|
||||||
AreaString = head,
|
AreaString = head,
|
||||||
Area = ReadFunctionCodeDictionary[head].Code,
|
Area = ReadFunctionCodeDictionary[head].Code,
|
||||||
Address = int.Parse(tail) - 1,
|
Address = int.Parse(tail) - 1,
|
||||||
SubAddress = int.Parse(sub),
|
SubAddress = int.Parse(sub)
|
||||||
}
|
}
|
||||||
: new AddressDef()
|
: new AddressDef
|
||||||
{
|
{
|
||||||
AreaString = head,
|
AreaString = head,
|
||||||
Area = WriteFunctionCodeDictionary[head].Code,
|
Area = WriteFunctionCodeDictionary[head].Code,
|
||||||
Address = int.Parse(tail) - 1,
|
Address = int.Parse(tail) - 1,
|
||||||
SubAddress = int.Parse(sub),
|
SubAddress = int.Parse(sub)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
using System;
|
namespace Modbus.Net.Modbus
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus/Rtu协议
|
/// Modbus/Rtu协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ModbusAsciiProtocal : ModbusProtocal
|
public class ModbusAsciiProtocal : ModbusProtocal
|
||||||
{
|
{
|
||||||
public ModbusAsciiProtocal(byte belongAddress, byte masterAddress) : this(ConfigurationManager.COM, belongAddress, masterAddress)
|
public ModbusAsciiProtocal(byte slaveAddress, byte masterAddress)
|
||||||
|
: this(ConfigurationManager.COM, slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModbusAsciiProtocal(string com, byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
public ModbusAsciiProtocal(string com, byte slaveAddress, byte masterAddress)
|
||||||
|
: base(slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
ProtocalLinker = new ModbusAsciiProtocalLinker(com);
|
ProtocalLinker = new ModbusAsciiProtocalLinker(com);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
using System;
|
using System.IO.Ports;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO.Ports;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
namespace Modbus.Net.Modbus
|
||||||
{
|
{
|
||||||
public class ModbusAsciiProtocalLinker : ComProtocalLinker
|
public class ModbusAsciiProtocalLinker : ComProtocalLinker
|
||||||
{
|
{
|
||||||
|
public ModbusAsciiProtocalLinker(string com) : base(com, 9600, Parity.None, StopBits.One, 8)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
//CRC校验失败
|
//CRC校验失败
|
||||||
string contentString = Encoding.ASCII.GetString(content);
|
var contentString = Encoding.ASCII.GetString(content);
|
||||||
if (!Crc16.GetInstance().LrcEfficacy(contentString))
|
if (!Crc16.GetInstance().LrcEfficacy(contentString))
|
||||||
{
|
{
|
||||||
throw new ModbusProtocalErrorException(501);
|
throw new ModbusProtocalErrorException(501);
|
||||||
@@ -25,9 +25,5 @@ namespace Modbus.Net.Modbus
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModbusAsciiProtocalLinker(string com) : base(com, 9600, Parity.None, StopBits.One, 8)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,40 +7,44 @@ namespace Modbus.Net.Modbus
|
|||||||
internal enum ModbusProtocalVariableFunctionCode : byte
|
internal enum ModbusProtocalVariableFunctionCode : byte
|
||||||
{
|
{
|
||||||
ReadVariable = 20,
|
ReadVariable = 20,
|
||||||
WriteVariable = 21,
|
WriteVariable = 21
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 跟时间有关的功能码
|
/// 跟时间有关的功能码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum ModbusProtocalTimeFunctionCode : byte
|
public enum ModbusProtocalTimeFunctionCode : byte
|
||||||
{
|
{
|
||||||
GetSystemTime = 3,
|
GetSystemTime = 3,
|
||||||
SetSystemTime = 16,
|
SetSystemTime = 16
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 跟读数据有关的功能码
|
/// 跟读数据有关的功能码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum ModbusProtocalReadDataFunctionCode : byte
|
public enum ModbusProtocalReadDataFunctionCode : byte
|
||||||
{
|
{
|
||||||
ReadCoilStatus = 1,
|
ReadCoilStatus = 1,
|
||||||
ReadInputStatus = 2,
|
ReadInputStatus = 2,
|
||||||
ReadHoldRegister = 3,
|
ReadHoldRegister = 3,
|
||||||
ReadInputRegister = 4,
|
ReadInputRegister = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 跟写数据有关的功能码
|
/// 跟写数据有关的功能码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal enum ModbusProtocalWriteDataFunctionCode : byte
|
internal enum ModbusProtocalWriteDataFunctionCode : byte
|
||||||
{
|
{
|
||||||
WriteMultiCoil = 15,
|
WriteMultiCoil = 15,
|
||||||
WriteMultiRegister = 16,
|
WriteMultiRegister = 16
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class ModbusProtocal : BaseProtocal
|
public abstract class ModbusProtocal : BaseProtocal
|
||||||
{
|
{
|
||||||
|
protected ModbusProtocal(byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public override bool Connect()
|
public override bool Connect()
|
||||||
{
|
{
|
||||||
return ProtocalLinker.Connect();
|
return ProtocalLinker.Connect();
|
||||||
@@ -50,45 +54,43 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
return await ProtocalLinker.ConnectAsync();
|
return await ProtocalLinker.ConnectAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ModbusProtocal(byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 读PLC数据
|
#region 读PLC数据
|
||||||
|
|
||||||
public class ReadDataModbusInputStruct : InputStruct
|
public class ReadDataModbusInputStruct : InputStruct
|
||||||
{
|
{
|
||||||
public ReadDataModbusInputStruct(byte belongAddress, string startAddress, ushort getCount, AddressTranslator addressTranslator)
|
public ReadDataModbusInputStruct(byte slaveAddress, string startAddress, ushort getCount,
|
||||||
|
AddressTranslator addressTranslator)
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
var translateAddress = addressTranslator.AddressTranslate(startAddress, true);
|
var translateAddress = addressTranslator.AddressTranslate(startAddress, true);
|
||||||
FunctionCode = (byte)translateAddress.Area;
|
FunctionCode = (byte) translateAddress.Area;
|
||||||
StartAddress = (ushort)translateAddress.Address;
|
StartAddress = (ushort) translateAddress.Address;
|
||||||
GetCount = (ushort)Math.Ceiling(getCount / addressTranslator.GetAreaByteLength(translateAddress.AreaString));
|
GetCount = (ushort) Math.Ceiling(getCount/addressTranslator.GetAreaByteLength(translateAddress.AreaString));
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BelongAddress { get; private set; }
|
public byte SlaveAddress { get; }
|
||||||
|
|
||||||
public byte FunctionCode { get; private set; }
|
public byte FunctionCode { get; }
|
||||||
|
|
||||||
public ushort StartAddress { get; private set; }
|
public ushort StartAddress { get; }
|
||||||
|
|
||||||
public ushort GetCount { get; private set; }
|
public ushort GetCount { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReadDataModbusOutputStruct : OutputStruct
|
public class ReadDataModbusOutputStruct : OutputStruct
|
||||||
{
|
{
|
||||||
public ReadDataModbusOutputStruct(byte belongAddress, byte functionCode,
|
public ReadDataModbusOutputStruct(byte slaveAddress, byte functionCode,
|
||||||
int dataCount, byte[] dataValue)
|
int dataCount, byte[] dataValue)
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
FunctionCode = functionCode;
|
FunctionCode = functionCode;
|
||||||
DataCount = dataCount;
|
DataCount = dataCount;
|
||||||
DataValue = dataValue.Clone() as byte[];
|
DataValue = dataValue.Clone() as byte[];
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BelongAddress { get; private set; }
|
public byte SlaveAddress { get; private set; }
|
||||||
|
|
||||||
public byte FunctionCode { get; private set; }
|
public byte FunctionCode { get; private set; }
|
||||||
|
|
||||||
@@ -101,71 +103,74 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (ReadDataModbusInputStruct)message;
|
var r_message = (ReadDataModbusInputStruct) message;
|
||||||
return Format(r_message.BelongAddress, r_message.FunctionCode,
|
return Format(r_message.SlaveAddress, r_message.FunctionCode,
|
||||||
r_message.StartAddress, r_message.GetCount);
|
r_message.StartAddress, r_message.GetCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||||
{
|
{
|
||||||
byte belongAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var slaveAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
byte functionCode = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var functionCode = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
byte dataCount = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var dataCount = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
byte[] dataValue = new byte[dataCount];
|
var dataValue = new byte[dataCount];
|
||||||
Array.Copy(messageBytes, 3, dataValue, 0, dataCount);
|
Array.Copy(messageBytes, 3, dataValue, 0, dataCount);
|
||||||
if (functionCode == 1 || functionCode == 2)
|
if (functionCode == 1 || functionCode == 2)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < dataValue.Length; i++)
|
for (var i = 0; i < dataValue.Length; i++)
|
||||||
{
|
{
|
||||||
dataValue[i] = BigEndianValueHelper.Instance.ReverseByte(dataValue[i]);
|
dataValue[i] = BigEndianValueHelper.Instance.ReverseByte(dataValue[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new ReadDataModbusOutputStruct(belongAddress, functionCode, dataCount, dataValue);
|
return new ReadDataModbusOutputStruct(slaveAddress, functionCode, dataCount, dataValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 写PLC数据
|
#region 写PLC数据
|
||||||
|
|
||||||
public class WriteDataModbusInputStruct : InputStruct
|
public class WriteDataModbusInputStruct : InputStruct
|
||||||
{
|
{
|
||||||
public WriteDataModbusInputStruct(byte belongAddress, string startAddress, object[] writeValue, AddressTranslator addressTranslator)
|
public WriteDataModbusInputStruct(byte slaveAddress, string startAddress, object[] writeValue,
|
||||||
|
AddressTranslator addressTranslator)
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
var translateAddress = addressTranslator.AddressTranslate(startAddress, false);
|
var translateAddress = addressTranslator.AddressTranslate(startAddress, false);
|
||||||
FunctionCode = (byte)translateAddress.Area;
|
FunctionCode = (byte) translateAddress.Area;
|
||||||
StartAddress = (ushort)translateAddress.Address;
|
StartAddress = (ushort) translateAddress.Address;
|
||||||
var writeByteValue = BigEndianValueHelper.Instance.ObjectArrayToByteArray(writeValue);
|
var writeByteValue = BigEndianValueHelper.Instance.ObjectArrayToByteArray(writeValue);
|
||||||
WriteCount = (ushort)(writeByteValue.Length / addressTranslator.GetAreaByteLength(translateAddress.AreaString));
|
WriteCount =
|
||||||
WriteByteCount = (byte)writeByteValue.Length;
|
(ushort) (writeByteValue.Length/addressTranslator.GetAreaByteLength(translateAddress.AreaString));
|
||||||
|
WriteByteCount = (byte) writeByteValue.Length;
|
||||||
WriteValue = writeByteValue;
|
WriteValue = writeByteValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BelongAddress { get; private set; }
|
public byte SlaveAddress { get; }
|
||||||
|
|
||||||
public byte FunctionCode { get; private set; }
|
public byte FunctionCode { get; }
|
||||||
|
|
||||||
public ushort StartAddress { get; private set; }
|
public ushort StartAddress { get; }
|
||||||
|
|
||||||
public ushort WriteCount { get; private set; }
|
public ushort WriteCount { get; }
|
||||||
|
|
||||||
public byte WriteByteCount { get; private set; }
|
public byte WriteByteCount { get; }
|
||||||
|
|
||||||
public byte[] WriteValue { get; private set; }
|
public byte[] WriteValue { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WriteDataModbusOutputStruct : OutputStruct
|
public class WriteDataModbusOutputStruct : OutputStruct
|
||||||
{
|
{
|
||||||
public WriteDataModbusOutputStruct(byte belongAddress, byte functionCode,
|
public WriteDataModbusOutputStruct(byte slaveAddress, byte functionCode,
|
||||||
ushort startAddress, ushort writeCount)
|
ushort startAddress, ushort writeCount)
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
FunctionCode = functionCode;
|
FunctionCode = functionCode;
|
||||||
StartAddress = startAddress;
|
StartAddress = startAddress;
|
||||||
WriteCount = writeCount;
|
WriteCount = writeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BelongAddress { get; private set; }
|
public byte SlaveAddress { get; private set; }
|
||||||
|
|
||||||
public byte FunctionCode { get; private set; }
|
public byte FunctionCode { get; private set; }
|
||||||
|
|
||||||
@@ -175,34 +180,34 @@ namespace Modbus.Net.Modbus
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写多个寄存器状态
|
/// 写多个寄存器状态
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WriteDataModbusProtocal : ProtocalUnit
|
public class WriteDataModbusProtocal : ProtocalUnit
|
||||||
{
|
{
|
||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (WriteDataModbusInputStruct)message;
|
var r_message = (WriteDataModbusInputStruct) message;
|
||||||
var functionCode = r_message.FunctionCode;
|
var functionCode = r_message.FunctionCode;
|
||||||
byte[] dataValue = Format(r_message.WriteValue);
|
var dataValue = Format(r_message.WriteValue);
|
||||||
if (functionCode == 5 || functionCode == 15)
|
if (functionCode == 5 || functionCode == 15)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < dataValue.Length; i++)
|
for (var i = 0; i < dataValue.Length; i++)
|
||||||
{
|
{
|
||||||
dataValue[i] = BigEndianValueHelper.Instance.ReverseByte(dataValue[i]);
|
dataValue[i] = BigEndianValueHelper.Instance.ReverseByte(dataValue[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
byte[] formattingBytes = Format(r_message.BelongAddress, r_message.FunctionCode,
|
var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode,
|
||||||
r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, dataValue);
|
r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, dataValue);
|
||||||
return formattingBytes;
|
return formattingBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int flag)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int flag)
|
||||||
{
|
{
|
||||||
byte belongAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var slaveAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
byte functionCode = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var functionCode = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
ushort startAddress = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
var startAddress = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
||||||
ushort writeCount = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
var writeCount = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
||||||
return new WriteDataModbusOutputStruct(belongAddress, functionCode, startAddress,
|
return new WriteDataModbusOutputStruct(slaveAddress, functionCode, startAddress,
|
||||||
writeCount);
|
writeCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,38 +215,39 @@ namespace Modbus.Net.Modbus
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 读PLC时间
|
#region 读PLC时间
|
||||||
|
|
||||||
public class GetSystemTimeModbusInputStruct : InputStruct
|
public class GetSystemTimeModbusInputStruct : InputStruct
|
||||||
{
|
{
|
||||||
public GetSystemTimeModbusInputStruct(byte belongAddress)
|
public GetSystemTimeModbusInputStruct(byte slaveAddress)
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
FunctionCode = (byte)ModbusProtocalTimeFunctionCode.GetSystemTime;
|
FunctionCode = (byte) ModbusProtocalTimeFunctionCode.GetSystemTime;
|
||||||
StartAddress = 30000;
|
StartAddress = 30000;
|
||||||
GetCount = 5;
|
GetCount = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BelongAddress { get; private set; }
|
public byte SlaveAddress { get; }
|
||||||
|
|
||||||
public byte FunctionCode { get; private set; }
|
public byte FunctionCode { get; }
|
||||||
|
|
||||||
public ushort StartAddress { get; private set; }
|
public ushort StartAddress { get; }
|
||||||
|
|
||||||
public ushort GetCount { get; private set; }
|
public ushort GetCount { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GetSystemTimeModbusOutputStruct : OutputStruct
|
public class GetSystemTimeModbusOutputStruct : OutputStruct
|
||||||
{
|
{
|
||||||
public GetSystemTimeModbusOutputStruct(byte belongAddress, 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)
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
FunctionCode = functionCode;
|
FunctionCode = functionCode;
|
||||||
WriteByteCount = writeByteCount;
|
WriteByteCount = writeByteCount;
|
||||||
Time = new DateTime(year, month, day, hour, minute, second, millisecond);
|
Time = new DateTime(year, month, day, hour, minute, second, millisecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BelongAddress { get; private set; }
|
public byte SlaveAddress { get; private set; }
|
||||||
|
|
||||||
public byte FunctionCode { get; private set; }
|
public byte FunctionCode { get; private set; }
|
||||||
|
|
||||||
@@ -251,30 +257,30 @@ namespace Modbus.Net.Modbus
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 读系统时间
|
/// 读系统时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetSystemTimeModbusProtocal : ProtocalUnit
|
public class GetSystemTimeModbusProtocal : ProtocalUnit
|
||||||
{
|
{
|
||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (GetSystemTimeModbusInputStruct)message;
|
var r_message = (GetSystemTimeModbusInputStruct) message;
|
||||||
return Format(r_message.BelongAddress, r_message.FunctionCode,
|
return Format(r_message.SlaveAddress, r_message.FunctionCode,
|
||||||
r_message.StartAddress, r_message.GetCount);
|
r_message.StartAddress, r_message.GetCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int flag)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int flag)
|
||||||
{
|
{
|
||||||
byte belongAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var slaveAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
byte functionCode = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var functionCode = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
byte writeByteCount = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var writeByteCount = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
ushort year = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
var year = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
||||||
byte day = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var day = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
byte month = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var month = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
ushort hour = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
var hour = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
||||||
byte second = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var second = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
byte minute = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var minute = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
ushort millisecond = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
var millisecond = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
||||||
return new GetSystemTimeModbusOutputStruct(belongAddress, functionCode, writeByteCount, year, day,
|
return new GetSystemTimeModbusOutputStruct(slaveAddress, functionCode, writeByteCount, year, day,
|
||||||
month, hour, second, minute, millisecond);
|
month, hour, second, minute, millisecond);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,61 +288,62 @@ namespace Modbus.Net.Modbus
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 写PLC时间
|
#region 写PLC时间
|
||||||
|
|
||||||
public class SetSystemTimeModbusInputStruct : InputStruct
|
public class SetSystemTimeModbusInputStruct : InputStruct
|
||||||
{
|
{
|
||||||
public SetSystemTimeModbusInputStruct(byte belongAddress, DateTime time)
|
public SetSystemTimeModbusInputStruct(byte slaveAddress, DateTime time)
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
FunctionCode = (byte)ModbusProtocalTimeFunctionCode.SetSystemTime;
|
FunctionCode = (byte) ModbusProtocalTimeFunctionCode.SetSystemTime;
|
||||||
StartAddress = 30000;
|
StartAddress = 30000;
|
||||||
WriteCount = 5;
|
WriteCount = 5;
|
||||||
WriteByteCount = 10;
|
WriteByteCount = 10;
|
||||||
Year = (ushort)time.Year;
|
Year = (ushort) time.Year;
|
||||||
Day = (byte)time.Day;
|
Day = (byte) time.Day;
|
||||||
Month = (byte)time.Month;
|
Month = (byte) time.Month;
|
||||||
Hour = (ushort)time.Hour;
|
Hour = (ushort) time.Hour;
|
||||||
Second = (byte)time.Second;
|
Second = (byte) time.Second;
|
||||||
Minute = (byte)time.Minute;
|
Minute = (byte) time.Minute;
|
||||||
Millisecond = (ushort)time.Millisecond;
|
Millisecond = (ushort) time.Millisecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BelongAddress { get; private set; }
|
public byte SlaveAddress { get; }
|
||||||
|
|
||||||
public byte FunctionCode { get; private set; }
|
public byte FunctionCode { get; }
|
||||||
|
|
||||||
public ushort StartAddress { get; private set; }
|
public ushort StartAddress { get; }
|
||||||
|
|
||||||
public ushort WriteCount { get; private set; }
|
public ushort WriteCount { get; }
|
||||||
|
|
||||||
public byte WriteByteCount { get; private set; }
|
public byte WriteByteCount { get; }
|
||||||
|
|
||||||
public ushort Year { get; private set; }
|
public ushort Year { get; }
|
||||||
|
|
||||||
public byte Day { get; private set; }
|
public byte Day { get; }
|
||||||
|
|
||||||
public byte Month { get; private set; }
|
public byte Month { get; }
|
||||||
|
|
||||||
public ushort Hour { get; private set; }
|
public ushort Hour { get; }
|
||||||
|
|
||||||
public byte Second { get; private set; }
|
public byte Second { get; }
|
||||||
|
|
||||||
public byte Minute { get; private set; }
|
public byte Minute { get; }
|
||||||
|
|
||||||
public ushort Millisecond { get; private set; }
|
public ushort Millisecond { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SetSystemTimeModbusOutputStruct : OutputStruct
|
public class SetSystemTimeModbusOutputStruct : OutputStruct
|
||||||
{
|
{
|
||||||
public SetSystemTimeModbusOutputStruct(byte belongAddress, byte functionCode,
|
public SetSystemTimeModbusOutputStruct(byte slaveAddress, byte functionCode,
|
||||||
ushort startAddress, ushort writeCount)
|
ushort startAddress, ushort writeCount)
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
FunctionCode = functionCode;
|
FunctionCode = functionCode;
|
||||||
StartAddress = startAddress;
|
StartAddress = startAddress;
|
||||||
WriteCount = writeCount;
|
WriteCount = writeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BelongAddress { get; private set; }
|
public byte SlaveAddress { get; private set; }
|
||||||
|
|
||||||
public byte FunctionCode { get; private set; }
|
public byte FunctionCode { get; private set; }
|
||||||
|
|
||||||
@@ -346,14 +353,14 @@ namespace Modbus.Net.Modbus
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写系统时间
|
/// 写系统时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SetSystemTimeModbusProtocal : ProtocalUnit
|
public class SetSystemTimeModbusProtocal : ProtocalUnit
|
||||||
{
|
{
|
||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (SetSystemTimeModbusInputStruct)message;
|
var r_message = (SetSystemTimeModbusInputStruct) message;
|
||||||
return Format(r_message.BelongAddress, r_message.FunctionCode,
|
return Format(r_message.SlaveAddress, r_message.FunctionCode,
|
||||||
r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, r_message.Year,
|
r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, r_message.Year,
|
||||||
r_message.Day,
|
r_message.Day,
|
||||||
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);
|
||||||
@@ -361,22 +368,22 @@ namespace Modbus.Net.Modbus
|
|||||||
|
|
||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int flag)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int flag)
|
||||||
{
|
{
|
||||||
byte belongAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var slaveAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
byte functionCode = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
var functionCode = BigEndianValueHelper.Instance.GetByte(messageBytes, ref flag);
|
||||||
ushort startAddress = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
var startAddress = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
||||||
ushort writeCount = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
var writeCount = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref flag);
|
||||||
return new SetSystemTimeModbusOutputStruct(belongAddress, functionCode, startAddress, writeCount);
|
return new SetSystemTimeModbusOutputStruct(slaveAddress, functionCode, startAddress, writeCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus协议错误表
|
/// Modbus协议错误表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ModbusProtocalErrorException : ProtocalErrorException
|
public class ModbusProtocalErrorException : ProtocalErrorException
|
||||||
{
|
{
|
||||||
public int ErrorMessageNumber { get; private set; }
|
private static readonly Dictionary<int, string> ProtocalErrorDictionary = new Dictionary<int, string>
|
||||||
private static readonly Dictionary<int, string> ProtocalErrorDictionary = new Dictionary<int, string>()
|
|
||||||
{
|
{
|
||||||
{1, "ILLEGAL_FUNCTION"},
|
{1, "ILLEGAL_FUNCTION"},
|
||||||
{2, "ILLEGAL_DATA_ACCESS"},
|
{2, "ILLEGAL_DATA_ACCESS"},
|
||||||
@@ -385,7 +392,7 @@ namespace Modbus.Net.Modbus
|
|||||||
{5, "ACKNOWLWDGE"},
|
{5, "ACKNOWLWDGE"},
|
||||||
{6, "SLAVE_DEVICE_BUSY"},
|
{6, "SLAVE_DEVICE_BUSY"},
|
||||||
{500, "TCP_ILLEGAL_LENGTH"},
|
{500, "TCP_ILLEGAL_LENGTH"},
|
||||||
{501, "RTU_ILLEGAL_CRC"},
|
{501, "RTU_ILLEGAL_CRC"}
|
||||||
};
|
};
|
||||||
|
|
||||||
public ModbusProtocalErrorException(int messageNumber)
|
public ModbusProtocalErrorException(int messageNumber)
|
||||||
@@ -393,5 +400,7 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
ErrorMessageNumber = messageNumber;
|
ErrorMessageNumber = messageNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int ErrorMessageNumber { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,16 +6,16 @@ using System.Text;
|
|||||||
namespace Modbus.Net.Modbus
|
namespace Modbus.Net.Modbus
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tcp协议字节伸缩
|
/// Tcp协议字节伸缩
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ModbusTcpProtocalLinkerBytesExtend : ProtocalLinkerBytesExtend
|
public class ModbusTcpProtocalLinkerBytesExtend : ProtocalLinkerBytesExtend
|
||||||
{
|
{
|
||||||
public override byte[] BytesExtend(byte[] content)
|
public override byte[] BytesExtend(byte[] content)
|
||||||
{
|
{
|
||||||
//Modbus/Tcp协议扩张,前面加6个字节,前面4个为0,后面两个为协议整体内容的长度
|
//Modbus/Tcp协议扩张,前面加6个字节,前面4个为0,后面两个为协议整体内容的长度
|
||||||
byte[] newFormat = new byte[6 + content.Length];
|
var newFormat = new byte[6 + content.Length];
|
||||||
int tag = 0;
|
var tag = 0;
|
||||||
ushort leng = (ushort)content.Length;
|
var leng = (ushort) content.Length;
|
||||||
Array.Copy(BigEndianValueHelper.Instance.GetBytes(tag), 0, newFormat, 0, 4);
|
Array.Copy(BigEndianValueHelper.Instance.GetBytes(tag), 0, newFormat, 0, 4);
|
||||||
Array.Copy(BigEndianValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2);
|
Array.Copy(BigEndianValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2);
|
||||||
Array.Copy(content, 0, newFormat, 6, content.Length);
|
Array.Copy(content, 0, newFormat, 6, content.Length);
|
||||||
@@ -25,7 +25,7 @@ namespace Modbus.Net.Modbus
|
|||||||
public override byte[] BytesDecact(byte[] content)
|
public override byte[] BytesDecact(byte[] content)
|
||||||
{
|
{
|
||||||
//Modbus/Tcp协议收缩,抛弃前面6个字节的内容
|
//Modbus/Tcp协议收缩,抛弃前面6个字节的内容
|
||||||
byte[] newContent = new byte[content.Length - 6];
|
var newContent = new byte[content.Length - 6];
|
||||||
Array.Copy(content, 6, newContent, 0, newContent.Length);
|
Array.Copy(content, 6, newContent, 0, newContent.Length);
|
||||||
return newContent;
|
return newContent;
|
||||||
}
|
}
|
||||||
@@ -35,9 +35,9 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
public override byte[] BytesExtend(byte[] content)
|
public override byte[] BytesExtend(byte[] content)
|
||||||
{
|
{
|
||||||
byte[] crc = new byte[2];
|
var crc = new byte[2];
|
||||||
//Modbus/Rtu协议扩张,增加CRC校验
|
//Modbus/Rtu协议扩张,增加CRC校验
|
||||||
byte[] newFormat = new byte[content.Length + 2];
|
var newFormat = new byte[content.Length + 2];
|
||||||
Crc16.GetInstance().GetCRC(content, ref crc);
|
Crc16.GetInstance().GetCRC(content, ref crc);
|
||||||
Array.Copy(content, 0, newFormat, 0, content.Length);
|
Array.Copy(content, 0, newFormat, 0, content.Length);
|
||||||
Array.Copy(crc, 0, newFormat, newFormat.Length - 2, crc.Length);
|
Array.Copy(crc, 0, newFormat, newFormat.Length - 2, crc.Length);
|
||||||
@@ -47,7 +47,7 @@ namespace Modbus.Net.Modbus
|
|||||||
public override byte[] BytesDecact(byte[] content)
|
public override byte[] BytesDecact(byte[] content)
|
||||||
{
|
{
|
||||||
//Modbus/Rtu协议收缩,抛弃后面2个字节的内容
|
//Modbus/Rtu协议收缩,抛弃后面2个字节的内容
|
||||||
byte[] newContent = new byte[content.Length - 2];
|
var newContent = new byte[content.Length - 2];
|
||||||
Array.Copy(content, 0, newContent, 0, newContent.Length);
|
Array.Copy(content, 0, newContent, 0, newContent.Length);
|
||||||
return newContent;
|
return newContent;
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
public override byte[] BytesExtend(byte[] content)
|
public override byte[] BytesExtend(byte[] content)
|
||||||
{
|
{
|
||||||
List<byte> newContent = new List<byte>();
|
var newContent = new List<byte>();
|
||||||
newContent.AddRange(Encoding.ASCII.GetBytes(":"));
|
newContent.AddRange(Encoding.ASCII.GetBytes(":"));
|
||||||
foreach (var number in content)
|
foreach (var number in content)
|
||||||
{
|
{
|
||||||
@@ -71,16 +71,16 @@ namespace Modbus.Net.Modbus
|
|||||||
|
|
||||||
public override byte[] BytesDecact(byte[] content)
|
public override byte[] BytesDecact(byte[] content)
|
||||||
{
|
{
|
||||||
List<byte> newContent = new List<byte>();
|
var newContent = new List<byte>();
|
||||||
string ans = Encoding.ASCII.GetString(content);
|
var ans = Encoding.ASCII.GetString(content);
|
||||||
var index = ans.IndexOf(Environment.NewLine);
|
var index = ans.IndexOf(Environment.NewLine);
|
||||||
ans = ans.Substring(1, index - 1);
|
ans = ans.Substring(1, index - 1);
|
||||||
for (int i = 0; i < ans.Length; i += 2)
|
for (var i = 0; i < ans.Length; i += 2)
|
||||||
{
|
{
|
||||||
var number = byte.Parse(ans.Substring(i, 2), NumberStyles.HexNumber);
|
var number = byte.Parse(ans.Substring(i, 2), NumberStyles.HexNumber);
|
||||||
newContent.Add(number);
|
newContent.Add(number);
|
||||||
}
|
}
|
||||||
newContent.RemoveAt(newContent.Count-1);
|
newContent.RemoveAt(newContent.Count - 1);
|
||||||
return newContent.ToArray();
|
return newContent.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
namespace Modbus.Net.Modbus
|
namespace Modbus.Net.Modbus
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus/Rtu协议
|
/// Modbus/Rtu协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ModbusRtuProtocal : ModbusProtocal
|
public class ModbusRtuProtocal : ModbusProtocal
|
||||||
{
|
{
|
||||||
public ModbusRtuProtocal(byte belongAddress, byte masterAddress) : this(ConfigurationManager.COM, belongAddress, masterAddress)
|
public ModbusRtuProtocal(byte slaveAddress, byte masterAddress)
|
||||||
|
: this(ConfigurationManager.COM, slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModbusRtuProtocal(string com, byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
public ModbusRtuProtocal(string com, byte slaveAddress, byte masterAddress)
|
||||||
|
: base(slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
ProtocalLinker = new ModbusRtuProtocalLinker(com);
|
ProtocalLinker = new ModbusRtuProtocalLinker(com);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,12 @@
|
|||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
namespace Modbus.Net.Modbus
|
||||||
{
|
{
|
||||||
class ModbusRtuProtocalLinker : ComProtocalLinker
|
public class ModbusRtuProtocalLinker : ComProtocalLinker
|
||||||
{
|
{
|
||||||
|
public ModbusRtuProtocalLinker(string com) : base(com, 9600, Parity.None, StopBits.One, 8)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@@ -19,10 +23,5 @@ namespace Modbus.Net.Modbus
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModbusRtuProtocalLinker(string com) : base(com, 9600, Parity.None, StopBits.One, 8)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,22 @@
|
|||||||
namespace Modbus.Net.Modbus
|
namespace Modbus.Net.Modbus
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus/Tcp协议
|
/// Modbus/Tcp协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ModbusTcpProtocal : ModbusProtocal
|
public class ModbusTcpProtocal : ModbusProtocal
|
||||||
{
|
{
|
||||||
public ModbusTcpProtocal(byte belongAddress, byte masterAddress) : this(ConfigurationManager.IP, belongAddress, masterAddress)
|
public ModbusTcpProtocal(byte slaveAddress, byte masterAddress)
|
||||||
|
: this(ConfigurationManager.IP, slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModbusTcpProtocal(string ip, byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
public ModbusTcpProtocal(string ip, byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
ProtocalLinker = new ModbusTcpProtocalLinker(ip);
|
ProtocalLinker = new ModbusTcpProtocalLinker(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModbusTcpProtocal(string ip, int port, byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
public ModbusTcpProtocal(string ip, int port, byte slaveAddress, byte masterAddress)
|
||||||
|
: base(slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
ProtocalLinker = new ModbusTcpProtocalLinker(ip, port);
|
ProtocalLinker = new ModbusTcpProtocalLinker(ip, port);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,14 @@
|
|||||||
{
|
{
|
||||||
public class ModbusTcpProtocalLinker : TcpProtocalLinker
|
public class ModbusTcpProtocalLinker : TcpProtocalLinker
|
||||||
{
|
{
|
||||||
|
public ModbusTcpProtocalLinker(string ip) : base(ip, int.Parse(ConfigurationManager.ModbusPort))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModbusTcpProtocalLinker(string ip, int port) : base(ip, port)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@@ -17,15 +25,5 @@
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModbusTcpProtocalLinker(string ip) : base(ip, int.Parse(ConfigurationManager.ModbusPort))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModbusTcpProtocalLinker(string ip, int port) : base(ip, port)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,31 +1,48 @@
|
|||||||
using System;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.Modbus
|
namespace Modbus.Net.Modbus
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Modbus连接类型
|
/// Modbus连接类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum ModbusType
|
public enum ModbusType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rtu连接
|
/// Rtu连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Rtu = 0,
|
Rtu = 0,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tcp连接
|
/// Tcp连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Tcp = 1,
|
Tcp = 1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ascii连接
|
/// Ascii连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Ascii = 2,
|
Ascii = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ModbusUtility : BaseUtility
|
public class ModbusUtility : BaseUtility
|
||||||
{
|
{
|
||||||
private ModbusType _modbusType;
|
private ModbusType _modbusType;
|
||||||
|
|
||||||
|
public ModbusUtility(int connectionType, byte slaveAddress, byte masterAddress)
|
||||||
|
: base(slaveAddress, masterAddress)
|
||||||
|
{
|
||||||
|
ConnectionString = null;
|
||||||
|
ModbusType = (ModbusType) connectionType;
|
||||||
|
AddressTranslator = new AddressTranslatorModbus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModbusUtility(ModbusType connectionType, string connectionString, byte slaveAddress, byte masterAddress)
|
||||||
|
: base(slaveAddress, masterAddress)
|
||||||
|
{
|
||||||
|
ConnectionString = connectionString;
|
||||||
|
ModbusType = connectionType;
|
||||||
|
AddressTranslator = new AddressTranslatorModbus();
|
||||||
|
}
|
||||||
|
|
||||||
public override bool GetLittleEndian => Wrapper[typeof (ReadDataModbusProtocal)].IsLittleEndian;
|
public override bool GetLittleEndian => Wrapper[typeof (ReadDataModbusProtocal)].IsLittleEndian;
|
||||||
public override bool SetLittleEndian => Wrapper[typeof (WriteDataModbusProtocal)].IsLittleEndian;
|
public override bool SetLittleEndian => Wrapper[typeof (WriteDataModbusProtocal)].IsLittleEndian;
|
||||||
|
|
||||||
@@ -47,22 +64,18 @@ namespace Modbus.Net.Modbus
|
|||||||
var connectionStringSplit = ConnectionString.Split(':');
|
var connectionStringSplit = ConnectionString.Split(':');
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return connectionStringSplit.Length < 2 ? (int?)null : int.Parse(connectionStringSplit[1]);
|
return connectionStringSplit.Length < 2 ? (int?) null : int.Parse(connectionStringSplit[1]);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModbusType ModbusType
|
public ModbusType ModbusType
|
||||||
{
|
{
|
||||||
get
|
get { return _modbusType; }
|
||||||
{
|
|
||||||
return _modbusType;
|
|
||||||
}
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_modbusType = value;
|
_modbusType = value;
|
||||||
@@ -70,37 +83,32 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
case ModbusType.Rtu:
|
case ModbusType.Rtu:
|
||||||
{
|
{
|
||||||
Wrapper = ConnectionString == null ? new ModbusRtuProtocal(BelongAddress, MasterAddress) : new ModbusRtuProtocal(ConnectionString, BelongAddress, MasterAddress);
|
Wrapper = ConnectionString == null
|
||||||
|
? new ModbusRtuProtocal(SlaveAddress, MasterAddress)
|
||||||
|
: new ModbusRtuProtocal(ConnectionString, SlaveAddress, MasterAddress);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ModbusType.Tcp:
|
case ModbusType.Tcp:
|
||||||
{
|
{
|
||||||
Wrapper = ConnectionString == null ? new ModbusTcpProtocal(BelongAddress, MasterAddress) : (ConnectionStringPort == null ? new ModbusTcpProtocal(ConnectionString, BelongAddress, MasterAddress) : new ModbusTcpProtocal(ConnectionStringIp,ConnectionStringPort.Value, BelongAddress, MasterAddress));
|
Wrapper = ConnectionString == null
|
||||||
|
? new ModbusTcpProtocal(SlaveAddress, MasterAddress)
|
||||||
|
: (ConnectionStringPort == null
|
||||||
|
? new ModbusTcpProtocal(ConnectionString, SlaveAddress, MasterAddress)
|
||||||
|
: new ModbusTcpProtocal(ConnectionStringIp, ConnectionStringPort.Value, SlaveAddress,
|
||||||
|
MasterAddress));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ModbusType.Ascii:
|
case ModbusType.Ascii:
|
||||||
{
|
{
|
||||||
Wrapper = ConnectionString == null ? new ModbusAsciiProtocal(BelongAddress, MasterAddress) : new ModbusAsciiProtocal(ConnectionString, BelongAddress, MasterAddress);
|
Wrapper = ConnectionString == null
|
||||||
|
? new ModbusAsciiProtocal(SlaveAddress, MasterAddress)
|
||||||
|
: new ModbusAsciiProtocal(ConnectionString, SlaveAddress, MasterAddress);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModbusUtility(int connectionType, byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
|
||||||
{
|
|
||||||
ConnectionString = null;
|
|
||||||
ModbusType = (ModbusType)connectionType;
|
|
||||||
AddressTranslator = new AddressTranslatorModbus();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModbusUtility(ModbusType connectionType, string connectionString, byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
|
||||||
{
|
|
||||||
ConnectionString = connectionString;
|
|
||||||
ModbusType = connectionType;
|
|
||||||
AddressTranslator = new AddressTranslatorModbus();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetConnectionType(int connectionType)
|
public override void SetConnectionType(int connectionType)
|
||||||
{
|
{
|
||||||
ModbusType = (ModbusType) connectionType;
|
ModbusType = (ModbusType) connectionType;
|
||||||
@@ -110,12 +118,12 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var inputStruct = new ReadDataModbusInputStruct(BelongAddress, startAddress,
|
var inputStruct = new ReadDataModbusInputStruct(SlaveAddress, startAddress,
|
||||||
(ushort)getByteCount, AddressTranslator);
|
(ushort) getByteCount, AddressTranslator);
|
||||||
var outputStruct = await
|
var outputStruct = await
|
||||||
Wrapper.SendReceiveAsync(Wrapper[typeof (ReadDataModbusProtocal)], inputStruct) as
|
Wrapper.SendReceiveAsync(Wrapper[typeof (ReadDataModbusProtocal)], inputStruct) as
|
||||||
ReadDataModbusOutputStruct;
|
ReadDataModbusOutputStruct;
|
||||||
return outputStruct?.DataValue;
|
return outputStruct?.DataValue;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -127,7 +135,7 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var inputStruct = new WriteDataModbusInputStruct(BelongAddress, startAddress, setContents,
|
var inputStruct = new WriteDataModbusInputStruct(SlaveAddress, startAddress, setContents,
|
||||||
AddressTranslator);
|
AddressTranslator);
|
||||||
var outputStruct = await
|
var outputStruct = await
|
||||||
Wrapper.SendReceiveAsync(Wrapper[typeof (WriteDataModbusProtocal)], inputStruct) as
|
Wrapper.SendReceiveAsync(Wrapper[typeof (WriteDataModbusProtocal)], inputStruct) as
|
||||||
@@ -145,7 +153,7 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var inputStruct = new GetSystemTimeModbusInputStruct(BelongAddress);
|
var inputStruct = new GetSystemTimeModbusInputStruct(SlaveAddress);
|
||||||
var outputStruct =
|
var outputStruct =
|
||||||
Wrapper.SendReceive(Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct) as
|
Wrapper.SendReceive(Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct) as
|
||||||
GetSystemTimeModbusOutputStruct;
|
GetSystemTimeModbusOutputStruct;
|
||||||
@@ -161,7 +169,7 @@ namespace Modbus.Net.Modbus
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var inputStruct = new SetSystemTimeModbusInputStruct(BelongAddress, setTime);
|
var inputStruct = new SetSystemTimeModbusInputStruct(SlaveAddress, setTime);
|
||||||
var outputStruct =
|
var outputStruct =
|
||||||
Wrapper.SendReceive(Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct) as
|
Wrapper.SendReceive(Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct) as
|
||||||
SetSystemTimeModbusOutputStruct;
|
SetSystemTimeModbusOutputStruct;
|
||||||
|
|||||||
@@ -1,33 +1,31 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
public class AddressFormaterOpc : AddressFormater
|
public class AddressFormaterOpc : AddressFormater
|
||||||
{
|
{
|
||||||
public BaseMachine Machine { get; set; }
|
public AddressFormaterOpc(Func<BaseMachine, AddressUnit, string[]> tagGeter, BaseMachine machine,
|
||||||
|
char seperator = '/')
|
||||||
protected Func<BaseMachine, AddressUnit, string[]> TagGeter { get; set; }
|
|
||||||
|
|
||||||
protected char Seperator { get; set; }
|
|
||||||
|
|
||||||
public AddressFormaterOpc(Func<BaseMachine, AddressUnit, string[]> tagGeter, BaseMachine machine, char seperator = '/')
|
|
||||||
{
|
{
|
||||||
Machine = machine;
|
Machine = machine;
|
||||||
TagGeter = tagGeter;
|
TagGeter = tagGeter;
|
||||||
Seperator = seperator;
|
Seperator = seperator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BaseMachine Machine { get; set; }
|
||||||
|
|
||||||
|
protected Func<BaseMachine, AddressUnit, string[]> TagGeter { get; set; }
|
||||||
|
|
||||||
|
protected char Seperator { get; set; }
|
||||||
|
|
||||||
public override string FormatAddress(string area, int address)
|
public override string FormatAddress(string area, int address)
|
||||||
{
|
{
|
||||||
var findAddress = Machine?.GetAddresses.FirstOrDefault(p => p.Area == area && p.Address == address);
|
var findAddress = Machine?.GetAddresses.FirstOrDefault(p => p.Area == area && p.Address == address);
|
||||||
if (findAddress == null) return null;
|
if (findAddress == null) return null;
|
||||||
var strings = TagGeter(Machine, findAddress);
|
var strings = TagGeter(Machine, findAddress);
|
||||||
var ans = "";
|
var ans = "";
|
||||||
for (int i = 0; i < strings.Length; i++)
|
for (var i = 0; i < strings.Length; i++)
|
||||||
{
|
{
|
||||||
ans += strings[i].Trim().Replace(" ", "") + Seperator;
|
ans += strings[i].Trim().Replace(" ", "") + Seperator;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ using Opc.Da;
|
|||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read value full result
|
/// Read value full result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OpcValueResult
|
public class OpcValueResult
|
||||||
{
|
{
|
||||||
@@ -20,17 +19,23 @@ namespace Modbus.Net.OPC
|
|||||||
|
|
||||||
public class MyDaClient : DaClient
|
public class MyDaClient : DaClient
|
||||||
{
|
{
|
||||||
|
public MyDaClient(Uri serverUrl) : base(serverUrl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Write a value on the specified opc tag
|
/// Write a value on the specified opc tag
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tag">The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name.
|
/// <param name="tag">
|
||||||
/// E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo`</param>
|
/// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name.
|
||||||
|
/// E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo`
|
||||||
|
/// </param>
|
||||||
public OpcValueResult Read(string tag)
|
public OpcValueResult Read(string tag)
|
||||||
{
|
{
|
||||||
var item = new Item { ItemName = tag };
|
var item = new Item {ItemName = tag};
|
||||||
var result = Server.Read(new[] { item })[0];
|
var result = Server.Read(new[] {item})[0];
|
||||||
CheckResult(result, tag);
|
CheckResult(result, tag);
|
||||||
return new OpcValueResult()
|
return new OpcValueResult
|
||||||
{
|
{
|
||||||
Value = result.Value,
|
Value = result.Value,
|
||||||
Timestamp = result.Timestamp,
|
Timestamp = result.Timestamp,
|
||||||
@@ -39,23 +44,21 @@ namespace Modbus.Net.OPC
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read a tag asynchronusly
|
/// Read a tag asynchronusly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Task<OpcValueResult> ReadAsync(string tag)
|
public Task<OpcValueResult> ReadAsync(string tag)
|
||||||
{
|
{
|
||||||
return Task.Run(() => Read(tag));
|
return Task.Run(() => Read(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MyDaClient(Uri serverUrl) : base(serverUrl)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CheckResult(IResult result, string tag)
|
private static void CheckResult(IResult result, string tag)
|
||||||
{
|
{
|
||||||
if (result == null)
|
if (result == null)
|
||||||
throw new OpcException("The server replied with an empty response");
|
throw new OpcException("The server replied with an empty response");
|
||||||
if (result.ResultID.ToString() != "S_OK")
|
if (result.ResultID.ToString() != "S_OK")
|
||||||
throw new OpcException(string.Format("Invalid response from the server. (Response Status: {0}, Opc Tag: {1})", result.ResultID, tag));
|
throw new OpcException(
|
||||||
|
string.Format("Invalid response from the server. (Response Status: {0}, Opc Tag: {1})",
|
||||||
|
result.ResultID, tag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.Eventing.Reader;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Hylasoft.Opc.Common;
|
|
||||||
using Hylasoft.Opc.Da;
|
|
||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
public class OpcDaConnector : BaseConnector
|
public class OpcDaConnector : BaseConnector
|
||||||
{
|
{
|
||||||
public override string ConnectionToken { get; }
|
protected static Dictionary<string, OpcDaConnector> _instances = new Dictionary<string, OpcDaConnector>();
|
||||||
|
|
||||||
protected bool _connect;
|
protected bool _connect;
|
||||||
public override bool IsConnected => _connect;
|
|
||||||
|
|
||||||
protected static Dictionary<string, OpcDaConnector> _instances = new Dictionary<string, OpcDaConnector>();
|
|
||||||
protected MyDaClient _daClient;
|
protected MyDaClient _daClient;
|
||||||
|
|
||||||
protected OpcDaConnector(string host)
|
protected OpcDaConnector(string host)
|
||||||
@@ -24,6 +17,9 @@ namespace Modbus.Net.OPC
|
|||||||
ConnectionToken = host;
|
ConnectionToken = host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ConnectionToken { get; }
|
||||||
|
public override bool IsConnected => _connect;
|
||||||
|
|
||||||
public static OpcDaConnector Instance(string host)
|
public static OpcDaConnector Instance(string host)
|
||||||
{
|
{
|
||||||
if (!_instances.ContainsKey(host))
|
if (!_instances.ContainsKey(host))
|
||||||
@@ -99,23 +95,20 @@ namespace Modbus.Net.OPC
|
|||||||
var protocal = BigEndianValueHelper.Instance.GetByte(message, ref pos);
|
var protocal = BigEndianValueHelper.Instance.GetByte(message, ref pos);
|
||||||
if (protocal == 0)
|
if (protocal == 0)
|
||||||
{
|
{
|
||||||
byte[] tagBytes = new byte[message.Length - 1];
|
var tagBytes = new byte[message.Length - 1];
|
||||||
Array.Copy(message, 1, tagBytes, 0, tagBytes.Length);
|
Array.Copy(message, 1, tagBytes, 0, tagBytes.Length);
|
||||||
string tag = Encoding.UTF8.GetString(tagBytes);
|
var tag = Encoding.UTF8.GetString(tagBytes);
|
||||||
var result = await _daClient.ReadAsync(tag);
|
var result = await _daClient.ReadAsync(tag);
|
||||||
if (result.QualityGood)
|
if (result.QualityGood)
|
||||||
{
|
{
|
||||||
return BigEndianValueHelper.Instance.GetBytes(result.Value, result.Value.GetType());
|
return BigEndianValueHelper.Instance.GetBytes(result.Value, result.Value.GetType());
|
||||||
}
|
}
|
||||||
else
|
return Encoding.ASCII.GetBytes("NoData");
|
||||||
{
|
|
||||||
return Encoding.ASCII.GetBytes("NoData");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int index = 0;
|
var index = 0;
|
||||||
for (int i = 1; i < message.Length - 3; i++)
|
for (var i = 1; i < message.Length - 3; i++)
|
||||||
{
|
{
|
||||||
if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff &&
|
if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff &&
|
||||||
message[i + 3] == 0x00)
|
message[i + 3] == 0x00)
|
||||||
@@ -125,8 +118,8 @@ namespace Modbus.Net.OPC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int index2 = 0;
|
var index2 = 0;
|
||||||
for (int i = index + 4; i < message.Length - 3; i++)
|
for (var i = index + 4; i < message.Length - 3; i++)
|
||||||
{
|
{
|
||||||
if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff &&
|
if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff &&
|
||||||
message[i + 3] == 0x00)
|
message[i + 3] == 0x00)
|
||||||
@@ -135,16 +128,16 @@ namespace Modbus.Net.OPC
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
byte[] tagBytes = new byte[index - 1];
|
var tagBytes = new byte[index - 1];
|
||||||
Array.Copy(message, 1, tagBytes, 0, tagBytes.Length);
|
Array.Copy(message, 1, tagBytes, 0, tagBytes.Length);
|
||||||
string tag = Encoding.UTF8.GetString(tagBytes);
|
var tag = Encoding.UTF8.GetString(tagBytes);
|
||||||
byte[] typeBytes = new byte[index2 - index - 4];
|
var typeBytes = new byte[index2 - index - 4];
|
||||||
Array.Copy(message, index + 4, typeBytes, 0, typeBytes.Length);
|
Array.Copy(message, index + 4, typeBytes, 0, typeBytes.Length);
|
||||||
Type type = Type.GetType(Encoding.UTF8.GetString(typeBytes));
|
var type = Type.GetType(Encoding.UTF8.GetString(typeBytes));
|
||||||
byte[] valueBytes = new byte[message.Length - index2 - 4];
|
var valueBytes = new byte[message.Length - index2 - 4];
|
||||||
Array.Copy(message, index2 + 4, valueBytes, 0, valueBytes.Length);
|
Array.Copy(message, index2 + 4, valueBytes, 0, valueBytes.Length);
|
||||||
int mainpos = 0, subpos = 0;
|
int mainpos = 0, subpos = 0;
|
||||||
object value = BigEndianValueHelper.Instance.GetValue(valueBytes, ref mainpos, ref subpos, type);
|
var value = BigEndianValueHelper.Instance.GetValue(valueBytes, ref mainpos, ref subpos, type);
|
||||||
await _daClient.WriteAsync(tag, value);
|
await _daClient.WriteAsync(tag, value);
|
||||||
return new byte[] {1};
|
return new byte[] {1};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
using System;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
public class OpcDaProtocal : OpcProtocal
|
public class OpcDaProtocal : OpcProtocal
|
||||||
{
|
{
|
||||||
private int _connectTryCount;
|
|
||||||
|
|
||||||
private readonly string _host;
|
private readonly string _host;
|
||||||
|
private int _connectTryCount;
|
||||||
|
|
||||||
public OpcDaProtocal(string host)
|
public OpcDaProtocal(string host)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System.Text;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
@@ -10,12 +6,11 @@ namespace Modbus.Net.OPC
|
|||||||
{
|
{
|
||||||
public OpcDaProtocalLinker() : this(ConfigurationManager.OpcDaHost)
|
public OpcDaProtocalLinker() : this(ConfigurationManager.OpcDaHost)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpcDaProtocalLinker(string host)
|
public OpcDaProtocalLinker(string host)
|
||||||
{
|
{
|
||||||
_baseConnector = OpcDaConnector.Instance(host);
|
BaseConnector = OpcDaConnector.Instance(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool? CheckRight(byte[] content)
|
public override bool? CheckRight(byte[] content)
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
public class OpcDaUtility : BaseUtility
|
public class OpcDaUtility : BaseUtility
|
||||||
{
|
{
|
||||||
public override bool GetLittleEndian => Wrapper[typeof (ReadRequestOpcProtocal)].IsLittleEndian;
|
public OpcDaUtility(string connectionString) : base(0, 0)
|
||||||
public override bool SetLittleEndian => Wrapper[typeof (WriteRequestOpcProtocal)].IsLittleEndian;
|
|
||||||
|
|
||||||
public OpcDaUtility(string connectionString) : base(0,0)
|
|
||||||
{
|
{
|
||||||
ConnectionString = connectionString;
|
ConnectionString = connectionString;
|
||||||
AddressTranslator = new AddressTranslatorOpc();
|
AddressTranslator = new AddressTranslatorOpc();
|
||||||
Wrapper = new OpcDaProtocal(ConnectionString);
|
Wrapper = new OpcDaProtocal(ConnectionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool GetLittleEndian => Wrapper[typeof (ReadRequestOpcProtocal)].IsLittleEndian;
|
||||||
|
public override bool SetLittleEndian => Wrapper[typeof (WriteRequestOpcProtocal)].IsLittleEndian;
|
||||||
|
|
||||||
public override void SetConnectionType(int connectionType)
|
public override void SetConnectionType(int connectionType)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -28,8 +25,9 @@ namespace Modbus.Net.OPC
|
|||||||
{
|
{
|
||||||
var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress);
|
var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress);
|
||||||
var readRequestOpcOutputStruct =
|
var readRequestOpcOutputStruct =
|
||||||
await
|
await
|
||||||
Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestOpcProtocal)], readRequestOpcInputStruct) as ReadRequestOpcOutputStruct;
|
Wrapper.SendReceiveAsync(Wrapper[typeof (ReadRequestOpcProtocal)], readRequestOpcInputStruct) as
|
||||||
|
ReadRequestOpcOutputStruct;
|
||||||
return readRequestOpcOutputStruct?.GetValue;
|
return readRequestOpcOutputStruct?.GetValue;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -44,8 +42,9 @@ namespace Modbus.Net.OPC
|
|||||||
{
|
{
|
||||||
var writeRequestOpcInputStruct = new WriteRequestOpcInputStruct(startAddress, setContents[0]);
|
var writeRequestOpcInputStruct = new WriteRequestOpcInputStruct(startAddress, setContents[0]);
|
||||||
var writeRequestOpcOutputStruct =
|
var writeRequestOpcOutputStruct =
|
||||||
await
|
await
|
||||||
Wrapper.SendReceiveAsync(Wrapper[typeof(WriteRequestOpcProtocal)], writeRequestOpcInputStruct) as WriteRequestOpcOutputStruct;
|
Wrapper.SendReceiveAsync(Wrapper[typeof (WriteRequestOpcProtocal)], writeRequestOpcInputStruct)
|
||||||
|
as WriteRequestOpcOutputStruct;
|
||||||
return writeRequestOpcOutputStruct?.WriteResult == true;
|
return writeRequestOpcOutputStruct?.WriteResult == true;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System.Text;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.OPC
|
namespace Modbus.Net.OPC
|
||||||
{
|
{
|
||||||
@@ -20,7 +16,7 @@ namespace Modbus.Net.OPC
|
|||||||
Tag = tag;
|
Tag = tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Tag { get; private set; }
|
public string Tag { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReadRequestOpcOutputStruct : OutputStruct
|
public class ReadRequestOpcOutputStruct : OutputStruct
|
||||||
@@ -38,7 +34,7 @@ namespace Modbus.Net.OPC
|
|||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (ReadRequestOpcInputStruct) message;
|
var r_message = (ReadRequestOpcInputStruct) message;
|
||||||
return Format((byte)0x00, Encoding.UTF8.GetBytes(r_message.Tag));
|
return Format((byte) 0x00, Encoding.UTF8.GetBytes(r_message.Tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||||
@@ -55,8 +51,8 @@ namespace Modbus.Net.OPC
|
|||||||
SetValue = setValue;
|
SetValue = setValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Tag { get; private set; }
|
public string Tag { get; }
|
||||||
public object SetValue { get; private set; }
|
public object SetValue { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WriteRequestOpcOutputStruct : OutputStruct
|
public class WriteRequestOpcOutputStruct : OutputStruct
|
||||||
@@ -67,17 +63,16 @@ namespace Modbus.Net.OPC
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bool WriteResult { get; private set; }
|
public bool WriteResult { get; private set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WriteRequestOpcProtocal : SpecialProtocalUnit
|
public class WriteRequestOpcProtocal : SpecialProtocalUnit
|
||||||
{
|
{
|
||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (WriteRequestOpcInputStruct)message;
|
var r_message = (WriteRequestOpcInputStruct) message;
|
||||||
byte[] tag = Encoding.UTF8.GetBytes(r_message.Tag);
|
var tag = Encoding.UTF8.GetBytes(r_message.Tag);
|
||||||
byte[] fullName = Encoding.UTF8.GetBytes(r_message.SetValue.GetType().FullName);
|
var fullName = Encoding.UTF8.GetBytes(r_message.SetValue.GetType().FullName);
|
||||||
return Format((byte)0x01, tag, (int)0x00ffff00, fullName, (int)0x00ffff00, r_message.SetValue);
|
return Format((byte) 0x01, tag, 0x00ffff00, fullName, 0x00ffff00, r_message.SetValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
using System;
|
namespace Modbus.Net.Siemens
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.Siemens
|
|
||||||
{
|
{
|
||||||
public class AddressFormaterSiemens : AddressFormater
|
public class AddressFormaterSiemens : AddressFormater
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Modbus.Net.Siemens
|
namespace Modbus.Net.Siemens
|
||||||
@@ -23,20 +22,20 @@ namespace Modbus.Net.Siemens
|
|||||||
{"Q", 0x82},
|
{"Q", 0x82},
|
||||||
{"M", 0x83},
|
{"M", 0x83},
|
||||||
{"DB", 0x84},
|
{"DB", 0x84},
|
||||||
{"V", 0x184},
|
{"V", 0x184}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override AddressDef AddressTranslate(string address, bool isRead)
|
public override AddressDef AddressTranslate(string address, bool isRead)
|
||||||
{
|
{
|
||||||
address = address.ToUpper();
|
address = address.ToUpper();
|
||||||
string[] splitString = address.Split(' ');
|
var splitString = address.Split(' ');
|
||||||
string head = splitString[0];
|
var head = splitString[0];
|
||||||
string tail = splitString[1];
|
var tail = splitString[1];
|
||||||
string sub;
|
string sub;
|
||||||
if (tail.Contains('.'))
|
if (tail.Contains('.'))
|
||||||
{
|
{
|
||||||
string[] splitString2 = tail.Split('.');
|
var splitString2 = tail.Split('.');
|
||||||
sub = splitString2[1];
|
sub = splitString2[1];
|
||||||
tail = splitString2[0];
|
tail = splitString2[0];
|
||||||
}
|
}
|
||||||
@@ -47,21 +46,21 @@ namespace Modbus.Net.Siemens
|
|||||||
if (head.Length > 1 && head.Substring(0, 2) == "DB")
|
if (head.Length > 1 && head.Substring(0, 2) == "DB")
|
||||||
{
|
{
|
||||||
head = head.Substring(2);
|
head = head.Substring(2);
|
||||||
return new AddressDef()
|
return new AddressDef
|
||||||
{
|
{
|
||||||
AreaString = "DB"+head,
|
AreaString = "DB" + head,
|
||||||
Area = int.Parse(head)*256 + AreaCodeDictionary["DB"],
|
Area = int.Parse(head)*256 + AreaCodeDictionary["DB"],
|
||||||
Address = int.Parse(tail),
|
Address = int.Parse(tail),
|
||||||
SubAddress = int.Parse(sub),
|
SubAddress = int.Parse(sub)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
new AddressDef()
|
new AddressDef
|
||||||
{
|
{
|
||||||
AreaString = head,
|
AreaString = head,
|
||||||
Area = AreaCodeDictionary[head],
|
Area = AreaCodeDictionary[head],
|
||||||
Address = int.Parse(tail),
|
Address = int.Parse(tail),
|
||||||
SubAddress = int.Parse(sub),
|
SubAddress = int.Parse(sub)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net.Siemens
|
namespace Modbus.Net.Siemens
|
||||||
{
|
{
|
||||||
@@ -10,11 +6,13 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
private readonly string _com;
|
private readonly string _com;
|
||||||
|
|
||||||
public SiemensPpiProtocal(byte belongAddress, byte masterAddress) : this( ConfigurationManager.COM, belongAddress, masterAddress)
|
public SiemensPpiProtocal(byte slaveAddress, byte masterAddress)
|
||||||
|
: this(ConfigurationManager.COM, slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public SiemensPpiProtocal(string com, byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
public SiemensPpiProtocal(string com, byte slaveAddress, byte masterAddress)
|
||||||
|
: base(slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
_com = com;
|
_com = com;
|
||||||
}
|
}
|
||||||
@@ -40,29 +38,29 @@ namespace Modbus.Net.Siemens
|
|||||||
|
|
||||||
public override bool Connect()
|
public override bool Connect()
|
||||||
{
|
{
|
||||||
return AsyncHelper.RunSync(()=>ConnectAsync());
|
return AsyncHelper.RunSync(() => ConnectAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<bool> ConnectAsync()
|
public override async Task<bool> ConnectAsync()
|
||||||
{
|
{
|
||||||
ProtocalLinker = new SiemensPpiProtocalLinker(_com);
|
ProtocalLinker = new SiemensPpiProtocalLinker(_com);
|
||||||
var inputStruct = new ComCreateReferenceSiemensInputStruct(BelongAddress, MasterAddress);
|
var inputStruct = new ComCreateReferenceSiemensInputStruct(SlaveAddress, MasterAddress);
|
||||||
var outputStruct =
|
var outputStruct =
|
||||||
await await
|
await await
|
||||||
ForceSendReceiveAsync(this[typeof (ComCreateReferenceSiemensProtocal)],
|
ForceSendReceiveAsync(this[typeof (ComCreateReferenceSiemensProtocal)],
|
||||||
inputStruct).
|
inputStruct).
|
||||||
ContinueWith(async answer =>
|
ContinueWith(async answer =>
|
||||||
{
|
{
|
||||||
if (!ProtocalLinker.IsConnected) return false;
|
if (!ProtocalLinker.IsConnected) return false;
|
||||||
var inputStruct2 = new ComConfirmMessageSiemensInputStruct(BelongAddress, MasterAddress);
|
var inputStruct2 = new ComConfirmMessageSiemensInputStruct(SlaveAddress, MasterAddress);
|
||||||
var outputStruct2 =
|
var outputStruct2 =
|
||||||
(ComConfirmMessageSiemensOutputStruct)
|
(ComConfirmMessageSiemensOutputStruct)
|
||||||
await
|
await
|
||||||
ForceSendReceiveAsync(this[typeof(ComConfirmMessageSiemensProtocal)],
|
ForceSendReceiveAsync(this[typeof (ComConfirmMessageSiemensProtocal)],
|
||||||
inputStruct2);
|
inputStruct2);
|
||||||
return outputStruct2 != null;
|
return outputStruct2 != null;
|
||||||
});
|
});
|
||||||
return outputStruct != null;
|
return outputStruct;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
using System.IO.Ports;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO.Ports;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -11,9 +6,14 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
public class SiemensPpiProtocalLinker : ComProtocalLinker
|
public class SiemensPpiProtocalLinker : ComProtocalLinker
|
||||||
{
|
{
|
||||||
|
public SiemensPpiProtocalLinker(string com)
|
||||||
|
: base(com, 9600, Parity.Even, StopBits.One, 8)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public override async Task<byte[]> SendReceiveAsync(byte[] content)
|
public override async Task<byte[]> SendReceiveAsync(byte[] content)
|
||||||
{
|
{
|
||||||
byte[] extBytes = BytesExtend(content);
|
var extBytes = BytesExtend(content);
|
||||||
if (extBytes[6] == 0x7c)
|
if (extBytes[6] == 0x7c)
|
||||||
{
|
{
|
||||||
var inputStruct2 = new ComConfirmMessageSiemensInputStruct(content[4], content[5]);
|
var inputStruct2 = new ComConfirmMessageSiemensInputStruct(content[4], content[5]);
|
||||||
@@ -60,13 +60,13 @@ namespace Modbus.Net.Siemens
|
|||||||
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;
|
||||||
int fcsCheck = 0;
|
var fcsCheck = 0;
|
||||||
if (content.Length == 1 && content[0] == 0xe5)
|
if (content.Length == 1 && content[0] == 0xe5)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (content.Length == 6 && content[3] == 0) return true;
|
if (content.Length == 6 && content[3] == 0) return true;
|
||||||
for (int i = 4; i < content.Length - 2; i++)
|
for (var i = 4; i < content.Length - 2; i++)
|
||||||
{
|
{
|
||||||
fcsCheck += content[i];
|
fcsCheck += content[i];
|
||||||
}
|
}
|
||||||
@@ -76,10 +76,5 @@ namespace Modbus.Net.Siemens
|
|||||||
if (content[1] != content.Length - 6) return false;
|
if (content[1] != content.Length - 6) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SiemensPpiProtocalLinker(string com)
|
|
||||||
: base(com, 9600, Parity.Even, StopBits.One, 8)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,8 +12,8 @@ namespace Modbus.Net.Siemens
|
|||||||
DWord = 0x04,
|
DWord = 0x04,
|
||||||
C = 0x1E,
|
C = 0x1E,
|
||||||
T = 0x1F,
|
T = 0x1F,
|
||||||
HC = 0x20,
|
HC = 0x20
|
||||||
};
|
}
|
||||||
|
|
||||||
public enum SiemensAccessResult : byte
|
public enum SiemensAccessResult : byte
|
||||||
{
|
{
|
||||||
@@ -22,47 +22,47 @@ namespace Modbus.Net.Siemens
|
|||||||
IllegalObjectAccess = 0x03,
|
IllegalObjectAccess = 0x03,
|
||||||
InvalidAddress = 0x05,
|
InvalidAddress = 0x05,
|
||||||
DataTypeNotSupport = 0x06,
|
DataTypeNotSupport = 0x06,
|
||||||
ObjNotExistOrLengthError = 0x0A,
|
ObjNotExistOrLengthError = 0x0A
|
||||||
};
|
}
|
||||||
|
|
||||||
public enum SiemensDataType : byte
|
public enum SiemensDataType : byte
|
||||||
{
|
{
|
||||||
Error = 0x00,
|
Error = 0x00,
|
||||||
BitAccess = 0x03,
|
BitAccess = 0x03,
|
||||||
OtherAccess = 0x04
|
OtherAccess = 0x04
|
||||||
};
|
}
|
||||||
|
|
||||||
public abstract class SiemensProtocal : BaseProtocal
|
public abstract class SiemensProtocal : BaseProtocal
|
||||||
{
|
{
|
||||||
protected SiemensProtocal(byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
protected SiemensProtocal(byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ComCreateReferenceSiemensInputStruct : InputStruct
|
internal class ComCreateReferenceSiemensInputStruct : InputStruct
|
||||||
{
|
{
|
||||||
public byte BelongAddress { get; set; }
|
public ComCreateReferenceSiemensInputStruct(byte slaveAddress, byte masterAddress)
|
||||||
public byte MasterAddress { get; set; }
|
|
||||||
|
|
||||||
public ComCreateReferenceSiemensInputStruct(byte belongAddress, byte masterAddress)
|
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
MasterAddress = masterAddress;
|
MasterAddress = masterAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte SlaveAddress { get; set; }
|
||||||
|
public byte MasterAddress { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ComCreateReferenceSiemensOutputStruct : OutputStruct
|
internal class ComCreateReferenceSiemensOutputStruct : OutputStruct
|
||||||
{
|
{
|
||||||
public byte BelongAddress { get; set; }
|
public ComCreateReferenceSiemensOutputStruct(byte slaveAddress, byte masterAddress, byte confirmMessage)
|
||||||
public byte MasterAddress { get; set; }
|
|
||||||
public byte ConfirmMessage { get; set; }
|
|
||||||
|
|
||||||
public ComCreateReferenceSiemensOutputStruct(byte belongAddress, byte masterAddress, byte confirmMessage)
|
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
MasterAddress = masterAddress;
|
MasterAddress = masterAddress;
|
||||||
ConfirmMessage = confirmMessage;
|
ConfirmMessage = confirmMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte SlaveAddress { get; set; }
|
||||||
|
public byte MasterAddress { get; set; }
|
||||||
|
public byte ConfirmMessage { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ComCreateReferenceSiemensProtocal : SpecialProtocalUnit
|
internal class ComCreateReferenceSiemensProtocal : SpecialProtocalUnit
|
||||||
@@ -70,34 +70,35 @@ namespace Modbus.Net.Siemens
|
|||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (ComCreateReferenceSiemensInputStruct) message;
|
var r_message = (ComCreateReferenceSiemensInputStruct) message;
|
||||||
var crc = (r_message.BelongAddress + r_message.MasterAddress + 0x49)%256;
|
var crc = (r_message.SlaveAddress + r_message.MasterAddress + 0x49)%256;
|
||||||
return Format((byte)0x10, r_message.BelongAddress, r_message.MasterAddress, (byte)0x49, (byte)crc, (byte)0x16);
|
return Format((byte) 0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte) 0x49, (byte) crc,
|
||||||
|
(byte) 0x16);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||||
{
|
{
|
||||||
pos = 1;
|
pos = 1;
|
||||||
var masterAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var masterAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
var belongAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var slaveAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
var confirmMessage = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var confirmMessage = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
return new ComCreateReferenceSiemensOutputStruct(belongAddress, masterAddress, confirmMessage);
|
return new ComCreateReferenceSiemensOutputStruct(slaveAddress, masterAddress, confirmMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class CreateReferenceSiemensInputStruct : InputStruct
|
internal class CreateReferenceSiemensInputStruct : InputStruct
|
||||||
{
|
{
|
||||||
|
public byte TdpuSize;
|
||||||
|
|
||||||
|
public ushort TsapDst;
|
||||||
|
|
||||||
|
public ushort TsapSrc;
|
||||||
|
|
||||||
public CreateReferenceSiemensInputStruct(byte tdpuSize, ushort srcTsap, ushort dstTsap)
|
public CreateReferenceSiemensInputStruct(byte tdpuSize, ushort srcTsap, ushort dstTsap)
|
||||||
{
|
{
|
||||||
TdpuSize = tdpuSize;
|
TdpuSize = tdpuSize;
|
||||||
TsapSrc = srcTsap;
|
TsapSrc = srcTsap;
|
||||||
TsapDst = dstTsap;
|
TsapDst = dstTsap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte TdpuSize;
|
|
||||||
|
|
||||||
public ushort TsapSrc;
|
|
||||||
|
|
||||||
public ushort TsapDst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class CreateReferenceSiemensOutputStruct : OutputStruct
|
internal class CreateReferenceSiemensOutputStruct : OutputStruct
|
||||||
@@ -118,7 +119,7 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (CreateReferenceSiemensInputStruct)message;
|
var r_message = (CreateReferenceSiemensInputStruct) message;
|
||||||
const ushort head = 0x0300;
|
const ushort head = 0x0300;
|
||||||
const ushort len = 0x0016;
|
const ushort len = 0x0016;
|
||||||
const byte contentLen = 0x11;
|
const byte contentLen = 0x11;
|
||||||
@@ -127,11 +128,11 @@ namespace Modbus.Net.Siemens
|
|||||||
const ushort srcRef = 0x000c;
|
const ushort srcRef = 0x000c;
|
||||||
const byte reserved = 0x00;
|
const byte reserved = 0x00;
|
||||||
const ushort tdpuSizeCode = 0xc001;
|
const ushort tdpuSizeCode = 0xc001;
|
||||||
byte tdpuSizeContent = r_message.TdpuSize;
|
var tdpuSizeContent = r_message.TdpuSize;
|
||||||
const ushort srcTsapCode = 0xc102;
|
const ushort srcTsapCode = 0xc102;
|
||||||
ushort srcTsapContent = r_message.TsapSrc;
|
var srcTsapContent = r_message.TsapSrc;
|
||||||
const ushort dstTsapCode = 0xc202;
|
const ushort dstTsapCode = 0xc202;
|
||||||
ushort dstTsapContent = r_message.TsapDst;
|
var dstTsapContent = r_message.TsapDst;
|
||||||
return Format(head, len, contentLen, typeCode, dstRef, srcRef, reserved, tdpuSizeCode, tdpuSizeContent,
|
return Format(head, len, contentLen, typeCode, dstRef, srcRef, reserved, tdpuSizeCode, tdpuSizeContent,
|
||||||
srcTsapCode, srcTsapContent, dstTsapCode, dstTsapContent);
|
srcTsapCode, srcTsapContent, dstTsapCode, dstTsapContent);
|
||||||
}
|
}
|
||||||
@@ -168,14 +169,14 @@ namespace Modbus.Net.Siemens
|
|||||||
|
|
||||||
public class ComConfirmMessageSiemensInputStruct : InputStruct
|
public class ComConfirmMessageSiemensInputStruct : InputStruct
|
||||||
{
|
{
|
||||||
public byte BelongAddress { get; set; }
|
public ComConfirmMessageSiemensInputStruct(byte slaveAddress, byte masterAddress)
|
||||||
public byte MasterAddress { get; set; }
|
|
||||||
|
|
||||||
public ComConfirmMessageSiemensInputStruct(byte belongAddress, byte masterAddress)
|
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
MasterAddress = masterAddress;
|
MasterAddress = masterAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte SlaveAddress { get; set; }
|
||||||
|
public byte MasterAddress { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ComConfirmMessageSiemensOutputStruct : OutputStruct
|
public class ComConfirmMessageSiemensOutputStruct : OutputStruct
|
||||||
@@ -192,9 +193,10 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (ComConfirmMessageSiemensInputStruct)message;
|
var r_message = (ComConfirmMessageSiemensInputStruct) message;
|
||||||
var crc = r_message.BelongAddress + r_message.MasterAddress + 0x5c%256;
|
var crc = r_message.SlaveAddress + r_message.MasterAddress + 0x5c%256;
|
||||||
return Format((byte)0x10, r_message.BelongAddress, r_message.MasterAddress, (byte)0x5c, (byte)crc, (byte)0x16);
|
return Format((byte) 0x10, r_message.SlaveAddress, r_message.MasterAddress, (byte) 0x5c, (byte) crc,
|
||||||
|
(byte) 0x16);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||||
@@ -214,10 +216,10 @@ namespace Modbus.Net.Siemens
|
|||||||
MaxPdu = maxPdu;
|
MaxPdu = maxPdu;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ushort PduRef { get; private set; }
|
public ushort PduRef { get; }
|
||||||
public ushort MaxCalling { get; private set; }
|
public ushort MaxCalling { get; }
|
||||||
public ushort MaxCalled { get; private set; }
|
public ushort MaxCalled { get; }
|
||||||
public ushort MaxPdu { get; private set; }
|
public ushort MaxPdu { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class EstablishAssociationSiemensOutputStruct : OutputStruct
|
internal class EstablishAssociationSiemensOutputStruct : OutputStruct
|
||||||
@@ -244,14 +246,14 @@ namespace Modbus.Net.Siemens
|
|||||||
const byte protoId = 0x32;
|
const byte protoId = 0x32;
|
||||||
const byte rosctr = 0x01;
|
const byte rosctr = 0x01;
|
||||||
const ushort redId = 0x0000;
|
const ushort redId = 0x0000;
|
||||||
ushort pduRef = r_message.PduRef;
|
var pduRef = r_message.PduRef;
|
||||||
const ushort parLg = 0x0008;
|
const ushort parLg = 0x0008;
|
||||||
const ushort datLg = 0x0000;
|
const ushort datLg = 0x0000;
|
||||||
const byte serviceId = 0xf0;
|
const byte serviceId = 0xf0;
|
||||||
const byte reserved = 0x00;
|
const byte reserved = 0x00;
|
||||||
ushort maxCalling = r_message.MaxCalling;
|
var maxCalling = r_message.MaxCalling;
|
||||||
ushort maxCalled = r_message.MaxCalled;
|
var maxCalled = r_message.MaxCalled;
|
||||||
ushort maxPdu = r_message.MaxPdu;
|
var maxPdu = r_message.MaxPdu;
|
||||||
return Format(new byte[7], protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, reserved, maxCalling,
|
return Format(new byte[7], protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, reserved, maxCalling,
|
||||||
maxCalled, maxPdu);
|
maxCalled, maxPdu);
|
||||||
}
|
}
|
||||||
@@ -259,44 +261,46 @@ namespace Modbus.Net.Siemens
|
|||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||||
{
|
{
|
||||||
pos = 4;
|
pos = 4;
|
||||||
ushort pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
var pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
||||||
pos = 14;
|
pos = 14;
|
||||||
ushort maxCalling = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
var maxCalling = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
||||||
ushort maxCalled = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
var maxCalled = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
||||||
ushort maxPdu = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
var maxPdu = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
||||||
return new EstablishAssociationSiemensOutputStruct(pduRef,maxCalling,maxCalled,maxPdu);
|
return new EstablishAssociationSiemensOutputStruct(pduRef, maxCalling, maxCalled, maxPdu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReadRequestSiemensInputStruct : InputStruct
|
public class ReadRequestSiemensInputStruct : InputStruct
|
||||||
{
|
{
|
||||||
public ReadRequestSiemensInputStruct(byte belongAddress, byte masterAddress, ushort pduRef, SiemensTypeCode getType, string startAddress, ushort getCount, AddressTranslator addressTranslator)
|
public ReadRequestSiemensInputStruct(byte slaveAddress, byte masterAddress, ushort pduRef,
|
||||||
|
SiemensTypeCode getType, string startAddress, ushort getCount, AddressTranslator addressTranslator)
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
MasterAddress = masterAddress;
|
MasterAddress = masterAddress;
|
||||||
PduRef = pduRef;
|
PduRef = pduRef;
|
||||||
TypeCode = (byte) getType;
|
TypeCode = (byte) getType;
|
||||||
var address = addressTranslator.AddressTranslate(startAddress, true);
|
var address = addressTranslator.AddressTranslate(startAddress, true);
|
||||||
Offset = address.Address;
|
Offset = address.Address;
|
||||||
int area = address.Area;
|
var area = address.Area;
|
||||||
Area = (byte)(area%256);
|
Area = (byte) (area%256);
|
||||||
DbBlock = Area == 0x84 ? (ushort)(area/256) : (ushort)0;
|
DbBlock = Area == 0x84 ? (ushort) (area/256) : (ushort) 0;
|
||||||
NumberOfElements = getCount;
|
NumberOfElements = getCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BelongAddress { get; set; }
|
public byte SlaveAddress { get; set; }
|
||||||
public byte MasterAddress { get; set; }
|
public byte MasterAddress { get; set; }
|
||||||
public ushort PduRef { get; private set; }
|
public ushort PduRef { get; }
|
||||||
public byte TypeCode { get; private set; }
|
public byte TypeCode { get; }
|
||||||
public ushort NumberOfElements { get; private set; }
|
public ushort NumberOfElements { get; }
|
||||||
public ushort DbBlock { get; private set; }
|
public ushort DbBlock { get; }
|
||||||
public byte Area { get; private set; }
|
public byte Area { get; }
|
||||||
public int Offset { get; private set; }
|
public int Offset { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReadRequestSiemensOutputStruct : OutputStruct
|
public class ReadRequestSiemensOutputStruct : OutputStruct
|
||||||
{
|
{
|
||||||
public ReadRequestSiemensOutputStruct(ushort pduRef, SiemensAccessResult accessResult, SiemensDataType dataType, ushort getLength, byte[] value)
|
public ReadRequestSiemensOutputStruct(ushort pduRef, SiemensAccessResult accessResult, SiemensDataType dataType,
|
||||||
|
ushort getLength, byte[] value)
|
||||||
{
|
{
|
||||||
PduRef = pduRef;
|
PduRef = pduRef;
|
||||||
AccessResult = accessResult;
|
AccessResult = accessResult;
|
||||||
@@ -317,12 +321,12 @@ namespace Modbus.Net.Siemens
|
|||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (ReadRequestSiemensInputStruct) message;
|
var r_message = (ReadRequestSiemensInputStruct) message;
|
||||||
byte belongAddress = r_message.BelongAddress;
|
var slaveAddress = r_message.SlaveAddress;
|
||||||
byte masterAddress = r_message.MasterAddress;
|
var masterAddress = r_message.MasterAddress;
|
||||||
const byte protoId = 0x32;
|
const byte protoId = 0x32;
|
||||||
const byte rosctr = 0x01;
|
const byte rosctr = 0x01;
|
||||||
const ushort redId = 0x0000;
|
const ushort redId = 0x0000;
|
||||||
ushort pduRef = r_message.PduRef;
|
var pduRef = r_message.PduRef;
|
||||||
const ushort parLg = 14; // 参数字节数(2+12的倍数),目前仅为14
|
const ushort parLg = 14; // 参数字节数(2+12的倍数),目前仅为14
|
||||||
const ushort datLg = 0; // 数据字节数
|
const ushort datLg = 0; // 数据字节数
|
||||||
const byte serviceId = 0x04;
|
const byte serviceId = 0x04;
|
||||||
@@ -330,13 +334,14 @@ namespace Modbus.Net.Siemens
|
|||||||
const byte variableSpec = 0x12;
|
const byte variableSpec = 0x12;
|
||||||
const byte vAddrLg = 0x0A;
|
const byte vAddrLg = 0x0A;
|
||||||
const byte syntaxId = 0x10;
|
const byte syntaxId = 0x10;
|
||||||
byte type = r_message.TypeCode;
|
var type = r_message.TypeCode;
|
||||||
ushort numberOfElements = r_message.NumberOfElements;
|
var numberOfElements = r_message.NumberOfElements;
|
||||||
ushort dbBlock = r_message.DbBlock;
|
var dbBlock = r_message.DbBlock;
|
||||||
byte area = r_message.Area;
|
var area = r_message.Area;
|
||||||
int offsetBit = r_message.Offset*8;
|
var offsetBit = r_message.Offset*8;
|
||||||
byte[] offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit);
|
var offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit);
|
||||||
return Format(new byte[4], belongAddress, masterAddress, (byte)0x6c, protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, numberOfVariables
|
return Format(new byte[4], slaveAddress, masterAddress, (byte) 0x6c, protoId, rosctr, redId, pduRef, parLg,
|
||||||
|
datLg, serviceId, numberOfVariables
|
||||||
, variableSpec, vAddrLg, syntaxId, type, numberOfElements, dbBlock, area,
|
, variableSpec, vAddrLg, syntaxId, type, numberOfElements, dbBlock, area,
|
||||||
offsetBitBytes.Skip(1).ToArray());
|
offsetBitBytes.Skip(1).ToArray());
|
||||||
}
|
}
|
||||||
@@ -344,13 +349,13 @@ namespace Modbus.Net.Siemens
|
|||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||||
{
|
{
|
||||||
pos = 4;
|
pos = 4;
|
||||||
ushort pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
var pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
||||||
pos = 14;
|
pos = 14;
|
||||||
byte accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
byte dataType = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var dataType = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
ushort length = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
var length = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
||||||
int byteLength = length/8;
|
var byteLength = length/8;
|
||||||
var values = new Byte[byteLength];
|
var values = new byte[byteLength];
|
||||||
Array.Copy(messageBytes, pos, values, 0, byteLength);
|
Array.Copy(messageBytes, pos, values, 0, byteLength);
|
||||||
return new ReadRequestSiemensOutputStruct(pduRef, (SiemensAccessResult) accessResult,
|
return new ReadRequestSiemensOutputStruct(pduRef, (SiemensAccessResult) accessResult,
|
||||||
(SiemensDataType) dataType, length, values);
|
(SiemensDataType) dataType, length, values);
|
||||||
@@ -359,26 +364,27 @@ namespace Modbus.Net.Siemens
|
|||||||
|
|
||||||
public class WriteRequestSiemensInputStruct : InputStruct
|
public class WriteRequestSiemensInputStruct : InputStruct
|
||||||
{
|
{
|
||||||
public WriteRequestSiemensInputStruct(byte belongAddress, byte masterAddress, ushort pduRef, string startAddress, object[] writeValue, AddressTranslator addressTranslator)
|
public WriteRequestSiemensInputStruct(byte slaveAddress, byte masterAddress, ushort pduRef, string startAddress,
|
||||||
|
object[] writeValue, AddressTranslator addressTranslator)
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
MasterAddress = masterAddress;
|
MasterAddress = masterAddress;
|
||||||
PduRef = pduRef;
|
PduRef = pduRef;
|
||||||
var address = addressTranslator.AddressTranslate(startAddress, true);
|
var address = addressTranslator.AddressTranslate(startAddress, true);
|
||||||
Offset = address.Address;
|
Offset = address.Address;
|
||||||
int area = address.Area;
|
var area = address.Area;
|
||||||
Area = (byte)(area % 256);
|
Area = (byte) (area%256);
|
||||||
DbBlock = Area == 0x84 ? (ushort)(area / 256) : (ushort)0;
|
DbBlock = Area == 0x84 ? (ushort) (area/256) : (ushort) 0;
|
||||||
WriteValue = writeValue;
|
WriteValue = writeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BelongAddress { get; set; }
|
public byte SlaveAddress { get; set; }
|
||||||
public byte MasterAddress { get; set; }
|
public byte MasterAddress { get; set; }
|
||||||
public ushort PduRef { get; private set; }
|
public ushort PduRef { get; }
|
||||||
public ushort DbBlock { get; private set; }
|
public ushort DbBlock { get; }
|
||||||
public byte Area { get; private set; }
|
public byte Area { get; }
|
||||||
public int Offset { get; private set; }
|
public int Offset { get; }
|
||||||
public object[] WriteValue { get; private set; }
|
public object[] WriteValue { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WriteRequestSiemensOutputStruct : OutputStruct
|
public class WriteRequestSiemensOutputStruct : OutputStruct
|
||||||
@@ -390,8 +396,7 @@ namespace Modbus.Net.Siemens
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ushort PduRef { get; private set; }
|
public ushort PduRef { get; private set; }
|
||||||
public SiemensAccessResult AccessResult {get; private set; }
|
public SiemensAccessResult AccessResult { get; private set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WriteRequestSiemensProtocal : ProtocalUnit
|
public class WriteRequestSiemensProtocal : ProtocalUnit
|
||||||
@@ -399,30 +404,31 @@ namespace Modbus.Net.Siemens
|
|||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (WriteRequestSiemensInputStruct) message;
|
var r_message = (WriteRequestSiemensInputStruct) message;
|
||||||
byte[] valueBytes = BigEndianValueHelper.Instance.ObjectArrayToByteArray(r_message.WriteValue);
|
var valueBytes = BigEndianValueHelper.Instance.ObjectArrayToByteArray(r_message.WriteValue);
|
||||||
byte belongAddress = r_message.BelongAddress;
|
var slaveAddress = r_message.SlaveAddress;
|
||||||
byte masterAddress = r_message.MasterAddress;
|
var masterAddress = r_message.MasterAddress;
|
||||||
const byte protoId = 0x32;
|
const byte protoId = 0x32;
|
||||||
const byte rosctr = 0x01;
|
const byte rosctr = 0x01;
|
||||||
const ushort redId = 0x0000;
|
const ushort redId = 0x0000;
|
||||||
ushort pduRef = r_message.PduRef;
|
var pduRef = r_message.PduRef;
|
||||||
const ushort parLg = 14; // 参数字节数(2+12的倍数),目前仅为14
|
const ushort parLg = 14; // 参数字节数(2+12的倍数),目前仅为14
|
||||||
ushort datLg = (ushort)(4+valueBytes.Length); // 数据字节数
|
var datLg = (ushort) (4 + valueBytes.Length); // 数据字节数
|
||||||
const byte serviceId = 0x05;
|
const byte serviceId = 0x05;
|
||||||
const byte numberOfVariables = 1;
|
const byte numberOfVariables = 1;
|
||||||
const byte variableSpec = 0x12;
|
const byte variableSpec = 0x12;
|
||||||
const byte vAddrLg = 0x0A;
|
const byte vAddrLg = 0x0A;
|
||||||
const byte syntaxId = 0x10;
|
const byte syntaxId = 0x10;
|
||||||
const byte typeR = (byte)SiemensTypeCode.Byte;
|
const byte typeR = (byte) SiemensTypeCode.Byte;
|
||||||
ushort numberOfElements = (ushort)valueBytes.Length;
|
var numberOfElements = (ushort) valueBytes.Length;
|
||||||
ushort dbBlock = r_message.DbBlock;
|
var dbBlock = r_message.DbBlock;
|
||||||
byte area = r_message.Area;
|
var area = r_message.Area;
|
||||||
int offsetBit = r_message.Offset * 8;
|
var offsetBit = r_message.Offset*8;
|
||||||
byte[] offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit);
|
var offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit);
|
||||||
const byte reserved = 0x00;
|
const byte reserved = 0x00;
|
||||||
const byte type = (byte)SiemensDataType.OtherAccess;
|
const byte type = (byte) SiemensDataType.OtherAccess;
|
||||||
ushort numberOfWriteBits = (ushort)(valueBytes.Length*8);
|
var numberOfWriteBits = (ushort) (valueBytes.Length*8);
|
||||||
return Format(new byte[4], belongAddress, masterAddress, (byte)0x7c, protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, numberOfVariables
|
return Format(new byte[4], slaveAddress, masterAddress, (byte) 0x7c, protoId, rosctr, redId, pduRef, parLg,
|
||||||
|
datLg, serviceId, numberOfVariables
|
||||||
, variableSpec, vAddrLg, syntaxId, typeR, numberOfElements, dbBlock, area,
|
, variableSpec, vAddrLg, syntaxId, typeR, numberOfElements, dbBlock, area,
|
||||||
offsetBitBytes.Skip(1).ToArray(), reserved, type, numberOfWriteBits, valueBytes);
|
offsetBitBytes.Skip(1).ToArray(), reserved, type, numberOfWriteBits, valueBytes);
|
||||||
}
|
}
|
||||||
@@ -431,16 +437,17 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
if (messageBytes.Length == 1)
|
if (messageBytes.Length == 1)
|
||||||
{
|
{
|
||||||
byte accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
return new WriteRequestSiemensOutputStruct(0, accessResult == 0xe5 ? SiemensAccessResult.NoError : SiemensAccessResult.InvalidAddress);
|
return new WriteRequestSiemensOutputStruct(0,
|
||||||
|
accessResult == 0xe5 ? SiemensAccessResult.NoError : SiemensAccessResult.InvalidAddress);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pos = 4;
|
pos = 4;
|
||||||
ushort pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
var pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
||||||
pos = 14;
|
pos = 14;
|
||||||
byte accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
var accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
return new WriteRequestSiemensOutputStruct(pduRef, (SiemensAccessResult)accessResult);
|
return new WriteRequestSiemensOutputStruct(pduRef, (SiemensAccessResult) accessResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -525,9 +532,7 @@ namespace Modbus.Net.Siemens
|
|||||||
|
|
||||||
public class SiemensProtocalErrorException : ProtocalErrorException
|
public class SiemensProtocalErrorException : ProtocalErrorException
|
||||||
{
|
{
|
||||||
public int ErrorClass { get; private set; }
|
private static readonly Dictionary<int, string> ProtocalErrorDictionary = new Dictionary<int, string>
|
||||||
public int ErrorCode { get; private set; }
|
|
||||||
private static readonly Dictionary<int, string> ProtocalErrorDictionary = new Dictionary<int, string>()
|
|
||||||
{
|
{
|
||||||
{0x00, "No Error"},
|
{0x00, "No Error"},
|
||||||
{0x81, "Error in the application Id of the request"},
|
{0x81, "Error in the application Id of the request"},
|
||||||
@@ -540,7 +545,7 @@ namespace Modbus.Net.Siemens
|
|||||||
{0xD4, "Diagnostic error"},
|
{0xD4, "Diagnostic error"},
|
||||||
{0xD6, "Protection system error"},
|
{0xD6, "Protection system error"},
|
||||||
{0xD8, "BuB error"},
|
{0xD8, "BuB error"},
|
||||||
{0xEF, "Layer 2 specific error"},
|
{0xEF, "Layer 2 specific error"}
|
||||||
};
|
};
|
||||||
|
|
||||||
public SiemensProtocalErrorException(int errCls, int errCod)
|
public SiemensProtocalErrorException(int errCls, int errCod)
|
||||||
@@ -549,5 +554,8 @@ namespace Modbus.Net.Siemens
|
|||||||
ErrorClass = errCls;
|
ErrorClass = errCls;
|
||||||
ErrorCode = errCod;
|
ErrorCode = errCod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int ErrorClass { get; private set; }
|
||||||
|
public int ErrorCode { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,14 +6,14 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
public override byte[] BytesExtend(byte[] content)
|
public override 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);
|
||||||
Array.Copy(BigEndianValueHelper.Instance.GetBytes((ushort)content.Length), 0, content, 2, 2);
|
Array.Copy(BigEndianValueHelper.Instance.GetBytes((ushort) content.Length), 0, content, 2, 2);
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] BytesDecact(byte[] content)
|
public override byte[] BytesDecact(byte[] content)
|
||||||
{
|
{
|
||||||
byte[] newContent = new byte[content.Length - 7];
|
var newContent = new byte[content.Length - 7];
|
||||||
Array.Copy(content, 7, newContent, 0, newContent.Length);
|
Array.Copy(content, 7, newContent, 0, newContent.Length);
|
||||||
return newContent;
|
return newContent;
|
||||||
}
|
}
|
||||||
@@ -23,11 +23,12 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
public override byte[] BytesExtend(byte[] content)
|
public override byte[] BytesExtend(byte[] content)
|
||||||
{
|
{
|
||||||
byte[] newContent = new byte[content.Length + 2];
|
var newContent = new byte[content.Length + 2];
|
||||||
Array.Copy(content, 0, newContent, 0, content.Length);
|
Array.Copy(content, 0, newContent, 0, content.Length);
|
||||||
Array.Copy(new byte[] { 0x68, (byte)(content.Length - 4), (byte)(content.Length - 4), 0x68 }, 0, newContent, 0, 4);
|
Array.Copy(new byte[] {0x68, (byte) (content.Length - 4), (byte) (content.Length - 4), 0x68}, 0, newContent,
|
||||||
int check = 0;
|
0, 4);
|
||||||
for (int i = 4; i < newContent.Length - 2; i++)
|
var check = 0;
|
||||||
|
for (var i = 4; i < newContent.Length - 2; i++)
|
||||||
{
|
{
|
||||||
check += newContent[i];
|
check += newContent[i];
|
||||||
}
|
}
|
||||||
@@ -39,7 +40,7 @@ namespace Modbus.Net.Siemens
|
|||||||
|
|
||||||
public override byte[] BytesDecact(byte[] content)
|
public override byte[] BytesDecact(byte[] content)
|
||||||
{
|
{
|
||||||
byte[] newContent = new byte[content.Length - 9];
|
var newContent = new byte[content.Length - 9];
|
||||||
Array.Copy(content, 7, newContent, 0, newContent.Length);
|
Array.Copy(content, 7, newContent, 0, newContent.Length);
|
||||||
return newContent;
|
return newContent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,3 +89,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -15,17 +15,18 @@ namespace Modbus.Net.Siemens
|
|||||||
private readonly int _port;
|
private readonly int _port;
|
||||||
private int _connectTryCount;
|
private int _connectTryCount;
|
||||||
|
|
||||||
public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled, ushort maxPdu) : this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ConfigurationManager.IP)
|
public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled,
|
||||||
|
ushort maxPdu) : this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ConfigurationManager.IP)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
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) : this (tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ip, 0)
|
ushort maxPdu, string ip) : this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ip, 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled, ushort maxPdu, string ip, int port) : base (0, 0)
|
public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled,
|
||||||
|
ushort maxPdu, string ip, int port) : base(0, 0)
|
||||||
{
|
{
|
||||||
_taspSrc = tsapSrc;
|
_taspSrc = tsapSrc;
|
||||||
_tsapDst = tsapDst;
|
_tsapDst = tsapDst;
|
||||||
@@ -61,7 +62,11 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
if (ProtocalLinker != null && ProtocalLinker.IsConnected) return await base.SendReceiveAsync(unit, content);
|
if (ProtocalLinker != null && ProtocalLinker.IsConnected) return await base.SendReceiveAsync(unit, content);
|
||||||
if (_connectTryCount > 10) return null;
|
if (_connectTryCount > 10) return null;
|
||||||
return await await ConnectAsync().ContinueWith(answer => answer.Result ? base.SendReceiveAsync(unit, content) : null);
|
return
|
||||||
|
await
|
||||||
|
await
|
||||||
|
ConnectAsync()
|
||||||
|
.ContinueWith(answer => answer.Result ? base.SendReceiveAsync(unit, content) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<OutputStruct> ForceSendReceiveAsync(ProtocalUnit unit, InputStruct content)
|
private async Task<OutputStruct> ForceSendReceiveAsync(ProtocalUnit unit, InputStruct content)
|
||||||
|
|||||||
@@ -4,6 +4,16 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
public class SiemensTcpProtocalLinker : TcpProtocalLinker
|
public class SiemensTcpProtocalLinker : TcpProtocalLinker
|
||||||
{
|
{
|
||||||
|
public SiemensTcpProtocalLinker(string ip)
|
||||||
|
: base(ip, int.Parse(ConfigurationManager.SiemensPort))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SiemensTcpProtocalLinker(string ip, int port)
|
||||||
|
: base(ip, port)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@@ -17,27 +27,15 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
case 0x03:
|
case 0x03:
|
||||||
if (content[17] == 0x00 && content[18] == 0x00) return true;
|
if (content[17] == 0x00 && content[18] == 0x00) return true;
|
||||||
throw new SiemensProtocalErrorException(content[17],content[18]);
|
throw new SiemensProtocalErrorException(content[17], content[18]);
|
||||||
case 0x07:
|
case 0x07:
|
||||||
if (content[27] == 0x00 && content[28] == 0x00) return true;
|
if (content[27] == 0x00 && content[28] == 0x00) return true;
|
||||||
throw new SiemensProtocalErrorException(content[27],content[28]);
|
throw new SiemensProtocalErrorException(content[27], content[28]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SiemensTcpProtocalLinker(string ip)
|
|
||||||
: base(ip, int.Parse(ConfigurationManager.SiemensPort))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public SiemensTcpProtocalLinker(string ip, int port)
|
|
||||||
: base(ip, port)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ namespace Modbus.Net.Siemens
|
|||||||
Ppi = 0,
|
Ppi = 0,
|
||||||
Mpi = 1,
|
Mpi = 1,
|
||||||
Tcp = 2
|
Tcp = 2
|
||||||
};
|
}
|
||||||
|
|
||||||
public enum SiemensMachineModel
|
public enum SiemensMachineModel
|
||||||
{
|
{
|
||||||
@@ -18,7 +18,7 @@ namespace Modbus.Net.Siemens
|
|||||||
S7_400 = 3,
|
S7_400 = 3,
|
||||||
S7_1200 = 4,
|
S7_1200 = 4,
|
||||||
S7_1500 = 5
|
S7_1500 = 5
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
public class SiemensUtility : BaseUtility
|
public class SiemensUtility : BaseUtility
|
||||||
@@ -30,69 +30,10 @@ namespace Modbus.Net.Siemens
|
|||||||
private readonly ushort _maxCalled;
|
private readonly ushort _maxCalled;
|
||||||
private readonly ushort _maxPdu;
|
private readonly ushort _maxPdu;
|
||||||
|
|
||||||
public override bool GetLittleEndian => Wrapper[typeof (ReadRequestSiemensProtocal)].IsLittleEndian;
|
|
||||||
public override bool SetLittleEndian => Wrapper[typeof (WriteRequestSiemensProtocal)].IsLittleEndian;
|
|
||||||
|
|
||||||
protected string ConnectionStringIp
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (ConnectionString == null) return null;
|
|
||||||
return ConnectionString.Contains(":") ? ConnectionString.Split(':')[0] : ConnectionString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SiemensType _siemensType;
|
private SiemensType _siemensType;
|
||||||
|
|
||||||
public SiemensType ConnectionType
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _siemensType;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_siemensType = value;
|
|
||||||
switch (_siemensType)
|
|
||||||
{
|
|
||||||
case SiemensType.Ppi:
|
|
||||||
{
|
|
||||||
Wrapper = ConnectionString == null ? new SiemensPpiProtocal(BelongAddress, MasterAddress) : new SiemensPpiProtocal(ConnectionString, BelongAddress, MasterAddress);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//case SiemensType.Mpi:
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
case SiemensType.Tcp:
|
|
||||||
{
|
|
||||||
Wrapper = ConnectionString == null ? new SiemensTcpProtocal(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu) : (ConnectionStringPort == null ? new SiemensTcpProtocal(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu, ConnectionString) : new SiemensTcpProtocal(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu, ConnectionStringIp, ConnectionStringPort.Value));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SiemensUtility(SiemensType connectionType, string connectionString, SiemensMachineModel model,
|
public SiemensUtility(SiemensType connectionType, string connectionString, SiemensMachineModel model,
|
||||||
byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
ConnectionString = connectionString;
|
ConnectionString = connectionString;
|
||||||
switch (model)
|
switch (model)
|
||||||
@@ -148,6 +89,70 @@ namespace Modbus.Net.Siemens
|
|||||||
AddressTranslator = new AddressTranslatorSiemens();
|
AddressTranslator = new AddressTranslatorSiemens();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool GetLittleEndian => Wrapper[typeof (ReadRequestSiemensProtocal)].IsLittleEndian;
|
||||||
|
public override bool SetLittleEndian => Wrapper[typeof (WriteRequestSiemensProtocal)].IsLittleEndian;
|
||||||
|
|
||||||
|
protected string ConnectionStringIp
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (ConnectionString == null) return null;
|
||||||
|
return ConnectionString.Contains(":") ? ConnectionString.Split(':')[0] : ConnectionString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SiemensType ConnectionType
|
||||||
|
{
|
||||||
|
get { return _siemensType; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_siemensType = value;
|
||||||
|
switch (_siemensType)
|
||||||
|
{
|
||||||
|
case SiemensType.Ppi:
|
||||||
|
{
|
||||||
|
Wrapper = ConnectionString == null
|
||||||
|
? new SiemensPpiProtocal(SlaveAddress, MasterAddress)
|
||||||
|
: new SiemensPpiProtocal(ConnectionString, SlaveAddress, MasterAddress);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//case SiemensType.Mpi:
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
case SiemensType.Tcp:
|
||||||
|
{
|
||||||
|
Wrapper = ConnectionString == null
|
||||||
|
? new SiemensTcpProtocal(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu)
|
||||||
|
: (ConnectionStringPort == null
|
||||||
|
? new SiemensTcpProtocal(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu,
|
||||||
|
ConnectionString)
|
||||||
|
: new SiemensTcpProtocal(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu,
|
||||||
|
ConnectionStringIp, ConnectionStringPort.Value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetConnectionType(int connectionType)
|
public override void SetConnectionType(int connectionType)
|
||||||
{
|
{
|
||||||
ConnectionType = (SiemensType) connectionType;
|
ConnectionType = (SiemensType) connectionType;
|
||||||
@@ -157,7 +162,8 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var readRequestSiemensInputStruct = new ReadRequestSiemensInputStruct(BelongAddress, MasterAddress, 0xd3c7, SiemensTypeCode.Byte, startAddress, (ushort)getByteCount, AddressTranslator);
|
var readRequestSiemensInputStruct = new ReadRequestSiemensInputStruct(SlaveAddress, MasterAddress,
|
||||||
|
0xd3c7, SiemensTypeCode.Byte, startAddress, (ushort) getByteCount, AddressTranslator);
|
||||||
var readRequestSiemensOutputStruct =
|
var readRequestSiemensOutputStruct =
|
||||||
await
|
await
|
||||||
Wrapper.SendReceiveAsync(Wrapper[typeof (ReadRequestSiemensProtocal)],
|
Wrapper.SendReceiveAsync(Wrapper[typeof (ReadRequestSiemensProtocal)],
|
||||||
@@ -174,7 +180,8 @@ namespace Modbus.Net.Siemens
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var writeRequestSiemensInputStruct = new WriteRequestSiemensInputStruct(BelongAddress, MasterAddress, 0xd3c8, startAddress, setContents, AddressTranslator);
|
var writeRequestSiemensInputStruct = new WriteRequestSiemensInputStruct(SlaveAddress, MasterAddress,
|
||||||
|
0xd3c8, startAddress, setContents, AddressTranslator);
|
||||||
var writeRequestSiemensOutputStruct =
|
var writeRequestSiemensOutputStruct =
|
||||||
await
|
await
|
||||||
Wrapper.SendReceiveAsync(Wrapper[typeof (WriteRequestSiemensProtocal)],
|
Wrapper.SendReceiveAsync(Wrapper[typeof (WriteRequestSiemensProtocal)],
|
||||||
@@ -188,12 +195,12 @@ namespace Modbus.Net.Siemens
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public override DateTime GetTime(byte belongAddress)
|
public override DateTime GetTime(byte slaveAddress)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool SetTime(byte belongAddress, DateTime setTime)
|
public override bool SetTime(byte slaveAddress, DateTime setTime)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ using System.Linq;
|
|||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址组合器,组合后的每一组地址将只需一次向设备进行通讯
|
/// 地址组合器,组合后的每一组地址将只需一次向设备进行通讯
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class AddressCombiner
|
public abstract class AddressCombiner
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 组合地址
|
/// 组合地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="addresses">需要进行组合的地址</param>
|
/// <param name="addresses">需要进行组合的地址</param>
|
||||||
/// <returns>组合完成后与设备通讯的地址</returns>
|
/// <returns>组合完成后与设备通讯的地址</returns>
|
||||||
@@ -18,72 +18,98 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 连续的地址将组合成一组,向设备进行通讯
|
/// 连续的地址将组合成一组,向设备进行通讯
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AddressCombinerContinus : AddressCombiner
|
public class AddressCombinerContinus : AddressCombiner
|
||||||
{
|
{
|
||||||
|
public AddressCombinerContinus(AddressTranslator addressTranslator)
|
||||||
|
{
|
||||||
|
AddressTranslator = addressTranslator;
|
||||||
|
}
|
||||||
|
|
||||||
protected AddressTranslator AddressTranslator { get; set; }
|
protected AddressTranslator AddressTranslator { get; set; }
|
||||||
|
|
||||||
public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses)
|
public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses)
|
||||||
{
|
{
|
||||||
|
//按从小到大的顺序对地址进行排序
|
||||||
var groupedAddresses = from address in addresses
|
var groupedAddresses = from address in addresses
|
||||||
orderby address.Address + address.SubAddress * (0.125 / AddressTranslator.GetAreaByteLength(address.Area))
|
orderby
|
||||||
|
AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress,
|
||||||
|
AddressTranslator.GetAreaByteLength(address.Area))
|
||||||
group address by address.Area
|
group address by address.Area
|
||||||
into grouped
|
into grouped
|
||||||
select grouped;
|
select grouped;
|
||||||
var ans = new List<CommunicationUnit>();
|
var ans = new List<CommunicationUnit>();
|
||||||
foreach (var groupedAddress in groupedAddresses)
|
foreach (var groupedAddress in groupedAddresses)
|
||||||
{
|
{
|
||||||
string area = groupedAddress.Key;
|
var area = groupedAddress.Key;
|
||||||
|
//初始地址
|
||||||
double initNum = -1;
|
double initNum = -1;
|
||||||
|
//上一个地址
|
||||||
double preNum = -1;
|
double preNum = -1;
|
||||||
|
//上一个地址类型
|
||||||
Type preType = null;
|
Type preType = null;
|
||||||
List<AddressUnit> originalAddresses = new List<AddressUnit>();
|
//记录一个地址组合当中的所有原始地址
|
||||||
|
var originalAddresses = new List<AddressUnit>();
|
||||||
|
//对组合内地址从小到大进行排序
|
||||||
var orderedAddresses =
|
var orderedAddresses =
|
||||||
groupedAddress.OrderBy(
|
groupedAddress.OrderBy(
|
||||||
address =>
|
address =>
|
||||||
address.Address +
|
AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress,
|
||||||
address.SubAddress*(0.125/AddressTranslator.GetAreaByteLength(address.Area)));
|
AddressTranslator.GetAreaByteLength(address.Area)));
|
||||||
foreach (var address in orderedAddresses)
|
foreach (var address in orderedAddresses)
|
||||||
{
|
{
|
||||||
|
//第一次进入时直接压入地址
|
||||||
if (initNum < 0)
|
if (initNum < 0)
|
||||||
{
|
{
|
||||||
initNum = address.Address + address.SubAddress * (0.125 / AddressTranslator.GetAreaByteLength(address.Area));
|
initNum = AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress,
|
||||||
|
AddressTranslator.GetAreaByteLength(address.Area));
|
||||||
originalAddresses.Add(address);
|
originalAddresses.Add(address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (address.Address +
|
//如果当前地址小于已经记录的地址域,表示这个地址的开始已经记录过了
|
||||||
address.SubAddress*(0.125/AddressTranslator.GetAreaByteLength(address.Area)) <
|
if (AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress,
|
||||||
preNum +
|
AddressTranslator.GetAreaByteLength(address.Area)) <
|
||||||
BigEndianValueHelper.Instance.ByteLength[preType.FullName]/
|
AddressHelper.GetProtocalCoordinateNextPosition(preNum,
|
||||||
AddressTranslator.GetAreaByteLength(address.Area))
|
preType,
|
||||||
|
AddressTranslator.GetAreaByteLength(address.Area)))
|
||||||
{
|
{
|
||||||
originalAddresses.Add(address);
|
originalAddresses.Add(address);
|
||||||
if (address.Address +
|
//如果当前地址的末尾被记录,表示地址被记录的地址域覆盖,这个地址没有记录的必要
|
||||||
address.SubAddress*(0.125/AddressTranslator.GetAreaByteLength(address.Area)) +
|
if (AddressHelper.GetProtocalCoordinateNextPosition(
|
||||||
BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]/
|
AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress,
|
||||||
AddressTranslator.GetAreaByteLength(address.Area) <=
|
AddressTranslator.GetAreaByteLength(address.Area)),
|
||||||
preNum +
|
address.DataType,
|
||||||
BigEndianValueHelper.Instance.ByteLength[preType.FullName]/
|
AddressTranslator.GetAreaByteLength(address.Area)) <=
|
||||||
AddressTranslator.GetAreaByteLength(address.Area))
|
AddressHelper.GetProtocalCoordinateNextPosition(preNum,
|
||||||
|
preType,
|
||||||
|
AddressTranslator.GetAreaByteLength(address.Area)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (address.Address +
|
//如果当前地址大于记录的地址域的开头,则表示地址已经不连续了
|
||||||
address.SubAddress*(0.125/AddressTranslator.GetAreaByteLength(address.Area)) >
|
else if (AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress,
|
||||||
preNum +
|
AddressTranslator.GetAreaByteLength(address.Area)) >
|
||||||
BigEndianValueHelper.Instance.ByteLength[preType.FullName]/
|
AddressHelper.GetProtocalCoordinateNextPosition(preNum,
|
||||||
AddressTranslator.GetAreaByteLength(address.Area))
|
preType,
|
||||||
|
AddressTranslator.GetAreaByteLength(address.Area)))
|
||||||
{
|
{
|
||||||
ans.Add(new CommunicationUnit()
|
//上一个地址域压入返回结果,并把当前记录的结果清空。
|
||||||
|
ans.Add(new CommunicationUnit
|
||||||
{
|
{
|
||||||
Area = area,
|
Area = area,
|
||||||
Address = (int) Math.Floor(initNum),
|
Address = (int) Math.Floor(initNum),
|
||||||
GetCount = (int)Math.Ceiling((preNum - (int)Math.Floor(initNum)) * AddressTranslator.GetAreaByteLength(address.Area) + BigEndianValueHelper.Instance.ByteLength[preType.FullName]),
|
GetCount =
|
||||||
|
(int)
|
||||||
|
Math.Ceiling(
|
||||||
|
AddressHelper.MapProtocalGetCountToAbstractByteCount(
|
||||||
|
preNum - (int) Math.Floor(initNum),
|
||||||
|
AddressTranslator.GetAreaByteLength(address.Area),
|
||||||
|
BigEndianValueHelper.Instance.ByteLength[preType.FullName])),
|
||||||
DataType = typeof (byte),
|
DataType = typeof (byte),
|
||||||
OriginalAddresses = originalAddresses.ToList(),
|
OriginalAddresses = originalAddresses.ToList()
|
||||||
});
|
});
|
||||||
initNum = address.Address;
|
initNum = address.Address;
|
||||||
originalAddresses.Clear();
|
originalAddresses.Clear();
|
||||||
@@ -91,30 +117,37 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//地址连续,压入当前记录的结果
|
||||||
originalAddresses.Add(address);
|
originalAddresses.Add(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
preNum = address.Address + address.SubAddress * (0.125 / AddressTranslator.GetAreaByteLength(address.Area));
|
//把当前地址变为上一个地址
|
||||||
|
preNum = AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress,
|
||||||
|
AddressTranslator.GetAreaByteLength(address.Area));
|
||||||
preType = address.DataType;
|
preType = address.DataType;
|
||||||
}
|
}
|
||||||
ans.Add(new CommunicationUnit()
|
//最后一个地址域压入返回结果
|
||||||
|
ans.Add(new CommunicationUnit
|
||||||
{
|
{
|
||||||
Area = area,
|
Area = area,
|
||||||
Address = (int)Math.Floor(initNum),
|
Address = (int) Math.Floor(initNum),
|
||||||
GetCount = (int)Math.Ceiling((preNum - (int)Math.Floor(initNum)) * AddressTranslator.GetAreaByteLength(area) + BigEndianValueHelper.Instance.ByteLength[preType.FullName]),
|
GetCount =
|
||||||
|
(int)
|
||||||
|
Math.Ceiling(
|
||||||
|
AddressHelper.MapProtocalGetCountToAbstractByteCount(
|
||||||
|
preNum - (int) Math.Floor(initNum), AddressTranslator.GetAreaByteLength(area),
|
||||||
|
BigEndianValueHelper.Instance.ByteLength[preType.FullName])),
|
||||||
DataType = typeof (byte),
|
DataType = typeof (byte),
|
||||||
OriginalAddresses = originalAddresses.ToList()
|
OriginalAddresses = originalAddresses.ToList()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AddressCombinerContinus(AddressTranslator addressTranslator)
|
|
||||||
{
|
|
||||||
AddressTranslator = addressTranslator;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单个地址变为一组,每一个地址都进行一次查询
|
||||||
|
/// </summary>
|
||||||
public class AddressCombinerSingle : AddressCombiner
|
public class AddressCombinerSingle : AddressCombiner
|
||||||
{
|
{
|
||||||
public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses)
|
public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses)
|
||||||
@@ -122,37 +155,44 @@ namespace Modbus.Net
|
|||||||
return
|
return
|
||||||
addresses.Select(
|
addresses.Select(
|
||||||
address =>
|
address =>
|
||||||
new CommunicationUnit()
|
new CommunicationUnit
|
||||||
{
|
{
|
||||||
Area = address.Area,
|
Area = address.Area,
|
||||||
Address = address.Address,
|
Address = address.Address,
|
||||||
SubAddress = address.SubAddress,
|
SubAddress = address.SubAddress,
|
||||||
DataType = address.DataType,
|
DataType = address.DataType,
|
||||||
GetCount = 1,
|
GetCount = 1,
|
||||||
OriginalAddresses = new List<AddressUnit>() {address}
|
OriginalAddresses = new List<AddressUnit> {address}
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CommunicationUnitGap
|
/// <summary>
|
||||||
|
/// 两个CommunicationUnit之间的间隔
|
||||||
|
/// </summary>
|
||||||
|
internal class CommunicationUnitGap
|
||||||
{
|
{
|
||||||
public CommunicationUnit EndUnit { get; set; }
|
public CommunicationUnit EndUnit { get; set; }
|
||||||
public int GapNumber { get; set; }
|
public int GapNumber { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可以调过多少数量的地址,把两个地址段变为一组通讯
|
||||||
|
/// </summary>
|
||||||
public class AddressCombinerNumericJump : AddressCombinerContinus
|
public class AddressCombinerNumericJump : AddressCombinerContinus
|
||||||
{
|
{
|
||||||
private int JumpNumber { get; }
|
public AddressCombinerNumericJump(int jumpByteCount, AddressTranslator addressTranslator)
|
||||||
|
: base(addressTranslator)
|
||||||
public AddressCombinerNumericJump(int jumpByteCount, AddressTranslator addressTranslator) : base(addressTranslator)
|
|
||||||
{
|
{
|
||||||
JumpNumber = jumpByteCount;
|
JumpNumber = jumpByteCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int JumpNumber { get; }
|
||||||
|
|
||||||
public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses)
|
public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses)
|
||||||
{
|
{
|
||||||
var continusAddresses = base.Combine(addresses).ToList();
|
var continusAddresses = base.Combine(addresses).ToList();
|
||||||
List<CommunicationUnitGap> addressesGaps = new List<CommunicationUnitGap>();
|
var addressesGaps = new List<CommunicationUnitGap>();
|
||||||
CommunicationUnit preCommunicationUnit = null;
|
CommunicationUnit preCommunicationUnit = null;
|
||||||
foreach (var continusAddress in continusAddresses)
|
foreach (var continusAddress in continusAddresses)
|
||||||
{
|
{
|
||||||
@@ -163,17 +203,26 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
if (continusAddress.Area == preCommunicationUnit.Area)
|
if (continusAddress.Area == preCommunicationUnit.Area)
|
||||||
{
|
{
|
||||||
var gap = new CommunicationUnitGap()
|
//计算间隔
|
||||||
|
var gap = new CommunicationUnitGap
|
||||||
{
|
{
|
||||||
EndUnit = continusAddress,
|
EndUnit = continusAddress,
|
||||||
GapNumber = (int)Math.Ceiling((continusAddress.Address - preCommunicationUnit.Address) * AddressTranslator.GetAreaByteLength(continusAddress.Area) - preCommunicationUnit.GetCount * BigEndianValueHelper.Instance.ByteLength[preCommunicationUnit.DataType.FullName])
|
GapNumber =
|
||||||
|
(int)
|
||||||
|
Math.Ceiling(AddressHelper.MapProtocalCoordinateToAbstractCoordinate(
|
||||||
|
continusAddress.Address, preCommunicationUnit.Address,
|
||||||
|
AddressTranslator.GetAreaByteLength(continusAddress.Area)) -
|
||||||
|
preCommunicationUnit.GetCount*
|
||||||
|
BigEndianValueHelper.Instance.ByteLength[
|
||||||
|
preCommunicationUnit.DataType.FullName])
|
||||||
};
|
};
|
||||||
addressesGaps.Add(gap);
|
addressesGaps.Add(gap);
|
||||||
}
|
}
|
||||||
preCommunicationUnit = continusAddress;
|
preCommunicationUnit = continusAddress;
|
||||||
}
|
}
|
||||||
|
//减去间隔
|
||||||
var orderedGaps = addressesGaps.OrderBy(p => p.GapNumber);
|
var orderedGaps = addressesGaps.OrderBy(p => p.GapNumber);
|
||||||
int jumpNumberInner = JumpNumber;
|
var jumpNumberInner = JumpNumber;
|
||||||
foreach (var orderedGap in orderedGaps)
|
foreach (var orderedGap in orderedGaps)
|
||||||
{
|
{
|
||||||
jumpNumberInner -= orderedGap.GapNumber;
|
jumpNumberInner -= orderedGap.GapNumber;
|
||||||
@@ -184,7 +233,8 @@ namespace Modbus.Net
|
|||||||
var preAddress = continusAddresses[index];
|
var preAddress = continusAddresses[index];
|
||||||
continusAddresses.RemoveAt(index);
|
continusAddresses.RemoveAt(index);
|
||||||
continusAddresses.RemoveAt(index);
|
continusAddresses.RemoveAt(index);
|
||||||
var newAddress = new CommunicationUnit()
|
//变为新的地址段
|
||||||
|
var newAddress = new CommunicationUnit
|
||||||
{
|
{
|
||||||
Area = nowAddress.Area,
|
Area = nowAddress.Area,
|
||||||
Address = preAddress.Address,
|
Address = preAddress.Address,
|
||||||
@@ -203,21 +253,26 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可以调过多少百分比的地址,把两个地址段变为一个
|
||||||
|
/// </summary>
|
||||||
public class AddressCombinerPercentageJump : AddressCombinerContinus
|
public class AddressCombinerPercentageJump : AddressCombinerContinus
|
||||||
{
|
{
|
||||||
private double Percentage { get; }
|
public AddressCombinerPercentageJump(double percentage, AddressTranslator addressTranslator)
|
||||||
|
: base(addressTranslator)
|
||||||
public AddressCombinerPercentageJump(double percentage, AddressTranslator addressTranslator) :base (addressTranslator)
|
|
||||||
{
|
{
|
||||||
if (percentage < 0) percentage = 0;
|
if (percentage < 0) percentage = 0;
|
||||||
Percentage = percentage;
|
Percentage = percentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double Percentage { get; }
|
||||||
|
|
||||||
public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses)
|
public override IEnumerable<CommunicationUnit> Combine(IEnumerable<AddressUnit> addresses)
|
||||||
{
|
{
|
||||||
var addressUnits = addresses as IList<AddressUnit> ?? addresses.ToList();
|
var addressUnits = addresses as IList<AddressUnit> ?? addresses.ToList();
|
||||||
double count = addressUnits.Sum(address => BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]);
|
var count = addressUnits.Sum(address => BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]);
|
||||||
return new AddressCombinerNumericJump((int)(count * Percentage / 100.0), AddressTranslator).Combine(addressUnits);
|
return
|
||||||
|
new AddressCombinerNumericJump((int) (count*Percentage/100.0), AddressTranslator).Combine(addressUnits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
using System;
|
namespace Modbus.Net
|
||||||
|
|
||||||
namespace Modbus.Net
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址编码器
|
/// 地址编码器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class AddressFormater
|
public abstract class AddressFormater
|
||||||
{
|
{
|
||||||
public abstract string FormatAddress(string area, int address);
|
public abstract string FormatAddress(string area, int address);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 编码地址
|
/// 编码地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="area">地址所在的数据区域</param>
|
/// <param name="area">地址所在的数据区域</param>
|
||||||
/// <param name="address">地址</param>
|
/// <param name="address">地址</param>
|
||||||
@@ -19,7 +18,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基本的地址编码器
|
/// 基本的地址编码器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AddressFormaterBase : AddressFormater
|
public class AddressFormaterBase : AddressFormater
|
||||||
{
|
{
|
||||||
|
|||||||
98
Modbus.Net/Modbus.Net/AddressHelper.cs
Normal file
98
Modbus.Net/Modbus.Net/AddressHelper.cs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Modbus.Net
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 地址辅助类
|
||||||
|
/// </summary>
|
||||||
|
public static class AddressHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 将字节坐标变为协议坐标
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="abstractAddress">字节坐标地址</param>
|
||||||
|
/// <param name="startAddress">起始地址</param>
|
||||||
|
/// <param name="byteLength">协议坐标单个地址的字节长度</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double MapAbstractCoordinateToProtocalCoordinate(double abstractAddress, int startAddress,
|
||||||
|
double byteLength)
|
||||||
|
{
|
||||||
|
return abstractAddress/byteLength + startAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将协议坐标变为字节坐标
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="protocalAddress">协议坐标地址</param>
|
||||||
|
/// <param name="startAddress">起始地址</param>
|
||||||
|
/// <param name="byteLength">协议坐标单个地址的字节长度</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double MapProtocalCoordinateToAbstractCoordinate(double protocalAddress, int startAddress,
|
||||||
|
double byteLength)
|
||||||
|
{
|
||||||
|
return (protocalAddress - startAddress)*byteLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将协议获取数变为字节获取数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="protocalGetCount">协议坐标获取个数</param>
|
||||||
|
/// <param name="areaLength">协议坐标区域与字节之间的防缩倍数</param>
|
||||||
|
/// <param name="byteLength">协议坐标单个地址的字节长度</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double MapProtocalGetCountToAbstractByteCount(double protocalGetCount, double areaLength,
|
||||||
|
double byteLength)
|
||||||
|
{
|
||||||
|
return protocalGetCount*areaLength + byteLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取协议坐标
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">主地址</param>
|
||||||
|
/// <param name="subAddress">子地址</param>
|
||||||
|
/// <param name="byteLength">协议坐标单个地址的字节长度</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double GetProtocalCoordinate(int address, int subAddress, double byteLength)
|
||||||
|
{
|
||||||
|
return address + subAddress*(0.125/byteLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取字节坐标
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">主地址</param>
|
||||||
|
/// <param name="subAddress">子地址</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double GetAbstractCoordinate(int address, int subAddress)
|
||||||
|
{
|
||||||
|
return address + subAddress*0.125;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取协议坐标下一个数据的位置
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="protocalAddress">协议坐标地址</param>
|
||||||
|
/// <param name="nextPositionBetweenType">间隔的数据类型</param>
|
||||||
|
/// <param name="byteLength">协议坐标单个地址的字节长度</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double GetProtocalCoordinateNextPosition(double protocalAddress, Type nextPositionBetweenType,
|
||||||
|
double byteLength)
|
||||||
|
{
|
||||||
|
return protocalAddress +
|
||||||
|
BigEndianValueHelper.Instance.ByteLength[nextPositionBetweenType.FullName]/byteLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取字节坐标下一个数据的位置
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="abstractAddress">字节坐标地址</param>
|
||||||
|
/// <param name="nextPositionBetweenType">间隔的数据类型</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double GetAbstractCoordinateNextPosition(double abstractAddress, Type nextPositionBetweenType)
|
||||||
|
{
|
||||||
|
return abstractAddress +
|
||||||
|
BigEndianValueHelper.Instance.ByteLength[nextPositionBetweenType.FullName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 地址定义类
|
||||||
|
/// </summary>
|
||||||
public class AddressDef
|
public class AddressDef
|
||||||
{
|
{
|
||||||
public string AreaString { get; set; }
|
public string AreaString { get; set; }
|
||||||
@@ -11,6 +13,9 @@ namespace Modbus.Net
|
|||||||
public int SubAddress { get; set; }
|
public int SubAddress { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 区域数据定义类
|
||||||
|
/// </summary>
|
||||||
public class AreaOutputDef
|
public class AreaOutputDef
|
||||||
{
|
{
|
||||||
public int Code { get; set; }
|
public int Code { get; set; }
|
||||||
@@ -18,35 +23,40 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址翻译器
|
/// 地址翻译器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class AddressTranslator
|
public abstract class AddressTranslator
|
||||||
{
|
{
|
||||||
/// <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>Key为转换后的地址,Value为辅助码</returns>
|
||||||
public abstract AddressDef AddressTranslate(string address, bool isRead);
|
public abstract AddressDef AddressTranslate(string address, bool isRead);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取区域中的单个地址占用的字节长度
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="area">区域名称</param>
|
||||||
|
/// <returns>字节长度</returns>
|
||||||
public abstract double GetAreaByteLength(string area);
|
public abstract double GetAreaByteLength(string area);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基本的地址翻译器
|
/// 基本的地址翻译器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AddressTranslatorBase : AddressTranslator
|
public class AddressTranslatorBase : AddressTranslator
|
||||||
{
|
{
|
||||||
public override AddressDef AddressTranslate(string address, bool isRead)
|
public override AddressDef AddressTranslate(string address, bool isRead)
|
||||||
{
|
{
|
||||||
int num1,num2,num3;
|
int num1, num2, num3;
|
||||||
string[] split = address.Split(':');
|
var split = address.Split(':');
|
||||||
if (split.Length == 2)
|
if (split.Length == 2)
|
||||||
{
|
{
|
||||||
if (int.TryParse(split[0], out num1) && int.TryParse(split[1], out num2))
|
if (int.TryParse(split[0], out num1) && int.TryParse(split[1], out num2))
|
||||||
{
|
{
|
||||||
return new AddressDef()
|
return new AddressDef
|
||||||
{
|
{
|
||||||
Area = num1,
|
Area = num1,
|
||||||
Address = num2
|
Address = num2
|
||||||
@@ -55,13 +65,14 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
else if (split.Length == 3)
|
else if (split.Length == 3)
|
||||||
{
|
{
|
||||||
if (int.TryParse(split[0], out num1) && int.TryParse(split[1], out num2) && int.TryParse(split[3], out num3))
|
if (int.TryParse(split[0], out num1) && int.TryParse(split[1], out num2) &&
|
||||||
|
int.TryParse(split[3], out num3))
|
||||||
{
|
{
|
||||||
return new AddressDef()
|
return new AddressDef
|
||||||
{
|
{
|
||||||
Area = num1,
|
Area = num1,
|
||||||
Address = num2,
|
Address = num2,
|
||||||
SubAddress = num3,
|
SubAddress = num3
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
using System;
|
/* AsyncHelper 注释
|
||||||
|
* -- AsyncHelper来自于AsyncEx,为了引用方便直接拷贝了代码。Modbus.Net的作者不保留对AsyncHeloper类的版权。
|
||||||
|
* -- AsyncHelper copied from AsyncEx. The author of "Modbus.Net" <b>donnot</b> obtain the copyright of AsyncHelper(Only).
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -8,41 +13,41 @@ namespace Modbus.Net
|
|||||||
public static class AsyncHelper
|
public static class AsyncHelper
|
||||||
{
|
{
|
||||||
private static readonly TaskFactory _myTaskFactory = new
|
private static readonly TaskFactory _myTaskFactory = new
|
||||||
TaskFactory(CancellationToken.None,
|
TaskFactory(CancellationToken.None,
|
||||||
TaskCreationOptions.None,
|
TaskCreationOptions.None,
|
||||||
TaskContinuationOptions.None,
|
TaskContinuationOptions.None,
|
||||||
TaskScheduler.Default);
|
TaskScheduler.Default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Run async method syncronized
|
/// Run async method syncronized
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TResult">Return type</typeparam>
|
/// <typeparam name="TResult">Return type</typeparam>
|
||||||
/// <param name="func">Async method with return</param>
|
/// <param name="func">Async method with return</param>
|
||||||
/// <returns>Return value</returns>
|
/// <returns>Return value</returns>
|
||||||
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
|
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
|
||||||
{
|
{
|
||||||
return AsyncHelper._myTaskFactory
|
return _myTaskFactory
|
||||||
.StartNew<Task<TResult>>(func)
|
.StartNew(func)
|
||||||
.Unwrap<TResult>()
|
.Unwrap()
|
||||||
.GetAwaiter()
|
.GetAwaiter()
|
||||||
.GetResult();
|
.GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Run async method syncronized.
|
/// Run async method syncronized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="func">Async method</param>
|
/// <param name="func">Async method</param>
|
||||||
public static void RunSync(Func<Task> func)
|
public static void RunSync(Func<Task> func)
|
||||||
{
|
{
|
||||||
AsyncHelper._myTaskFactory
|
_myTaskFactory
|
||||||
.StartNew<Task>(func)
|
.StartNew(func)
|
||||||
.Unwrap()
|
.Unwrap()
|
||||||
.GetAwaiter()
|
.GetAwaiter()
|
||||||
.GetResult();
|
.GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change async task to async task with cancellation token
|
/// Change async task to async task with cancellation token
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="task">Async task</param>
|
/// <param name="task">Async task</param>
|
||||||
/// <param name="token">Cancellation Token</param>
|
/// <param name="token">Cancellation Token</param>
|
||||||
@@ -61,12 +66,12 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// AsyncLock locks across one or several await calls.
|
/// AsyncLock locks across one or several await calls.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AsyncLock
|
public class AsyncLock
|
||||||
{
|
{
|
||||||
private readonly AsyncSemaphore _semaphore;
|
|
||||||
private readonly Task<Releaser> _releaser;
|
private readonly Task<Releaser> _releaser;
|
||||||
|
private readonly AsyncSemaphore _semaphore;
|
||||||
|
|
||||||
public AsyncLock()
|
public AsyncLock()
|
||||||
{
|
{
|
||||||
@@ -75,7 +80,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Lock the async method. Call like: using (await asynclock.LockAsync())
|
/// Lock the async method. Call like: using (await asynclock.LockAsync())
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<Releaser> LockAsync()
|
public Task<Releaser> LockAsync()
|
||||||
@@ -109,11 +114,11 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// AsyncSemaphore semaphore the multi run tasks.
|
/// AsyncSemaphore semaphore the multi run tasks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AsyncSemaphore
|
public class AsyncSemaphore
|
||||||
{
|
{
|
||||||
private readonly static Task _completed = Task.FromResult(true);
|
private static readonly Task _completed = Task.FromResult(true);
|
||||||
private readonly Queue<TaskCompletionSource<bool>> _waiters = new Queue<TaskCompletionSource<bool>>();
|
private readonly Queue<TaskCompletionSource<bool>> _waiters = new Queue<TaskCompletionSource<bool>>();
|
||||||
private int _currentCount;
|
private int _currentCount;
|
||||||
|
|
||||||
@@ -135,12 +140,9 @@ namespace Modbus.Net
|
|||||||
_currentCount--;
|
_currentCount--;
|
||||||
return _completed;
|
return _completed;
|
||||||
}
|
}
|
||||||
else
|
var waiter = new TaskCompletionSource<bool>();
|
||||||
{
|
_waiters.Enqueue(waiter);
|
||||||
var waiter = new TaskCompletionSource<bool>();
|
return waiter.Task;
|
||||||
_waiters.Enqueue(waiter);
|
|
||||||
return waiter.Task;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,53 +1,63 @@
|
|||||||
using System;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 基础的协议连接类
|
||||||
|
/// </summary>
|
||||||
public abstract class BaseConnector
|
public abstract class BaseConnector
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 标识Connector的连接关键字
|
/// 标识Connector的连接关键字
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract string ConnectionToken { get; }
|
public abstract string ConnectionToken { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否处于连接状态
|
/// 是否处于连接状态
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract bool IsConnected { get; }
|
public abstract bool IsConnected { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 连接PLC
|
/// 连接PLC
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>是否连接成功</returns>
|
/// <returns>是否连接成功</returns>
|
||||||
public abstract bool Connect();
|
public abstract bool Connect();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 连接PLC,异步
|
/// 连接PLC,异步
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>是否连接成功</returns>
|
/// <returns>是否连接成功</returns>
|
||||||
public abstract Task<bool> ConnectAsync();
|
public abstract Task<bool> ConnectAsync();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 断开PLC
|
/// 断开PLC
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>是否断开成功</returns>
|
/// <returns>是否断开成功</returns>
|
||||||
public abstract bool Disconnect();
|
public abstract bool Disconnect();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 无返回发送数据
|
/// 无返回发送数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">需要发送的数据</param>
|
/// <param name="message">需要发送的数据</param>
|
||||||
/// <returns>是否发送成功</returns>
|
/// <returns>是否发送成功</returns>
|
||||||
public abstract bool SendMsgWithoutReturn(byte[] message);
|
public abstract bool SendMsgWithoutReturn(byte[] message);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 无返回发送数据
|
/// 无返回发送数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">需要发送的数据</param>
|
/// <param name="message">需要发送的数据</param>
|
||||||
/// <returns>是否发送成功</returns>
|
/// <returns>是否发送成功</returns>
|
||||||
public abstract Task<bool> SendMsgWithoutReturnAsync(byte[] message);
|
public abstract Task<bool> SendMsgWithoutReturnAsync(byte[] message);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 带返回发送数据
|
/// 带返回发送数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">需要发送的数据</param>
|
/// <param name="message">需要发送的数据</param>
|
||||||
/// <returns>是否发送成功</returns>
|
/// <returns>是否发送成功</returns>
|
||||||
public abstract byte[] SendMsg(byte[] message);
|
public abstract byte[] SendMsg(byte[] message);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 带返回发送数据
|
/// 带返回发送数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">需要发送的数据</param>
|
/// <param name="message">需要发送的数据</param>
|
||||||
/// <returns>是否发送成功</returns>
|
/// <returns>是否发送成功</returns>
|
||||||
|
|||||||
@@ -6,121 +6,43 @@ using System.Threading.Tasks;
|
|||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取设备值的方式
|
/// 获取设备值的方式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum MachineGetDataType
|
public enum MachineGetDataType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址
|
/// 地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Address,
|
Address,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通讯标识
|
/// 通讯标识
|
||||||
/// </summary>
|
/// </summary>
|
||||||
CommunicationTag
|
CommunicationTag
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 向设备设置值的方式
|
/// 向设备设置值的方式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum MachineSetDataType
|
public enum MachineSetDataType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址
|
/// 地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Address,
|
Address,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通讯标识
|
/// 通讯标识
|
||||||
/// </summary>
|
/// </summary>
|
||||||
CommunicationTag
|
CommunicationTag
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class BaseMachine : IMachineProperty
|
public abstract class BaseMachine : IMachineProperty
|
||||||
{
|
{
|
||||||
private int ErrorCount { get; set; } = 0;
|
private readonly int _maxErrorCount = 3;
|
||||||
private int _maxErrorCount = 3;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设备的Id
|
/// 构造器
|
||||||
/// </summary>
|
|
||||||
public string Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设备所在工程的名称
|
|
||||||
/// </summary>
|
|
||||||
public string ProjectName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设备的名称
|
|
||||||
/// </summary>
|
|
||||||
public string MachineName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否处于连接状态
|
|
||||||
/// </summary>
|
|
||||||
public bool IsConnected => BaseUtility.IsConnected;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标识设备的连接关键字
|
|
||||||
/// </summary>
|
|
||||||
public string ConnectionToken => BaseUtility.ConnectionToken;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 地址编码器
|
|
||||||
/// </summary>
|
|
||||||
public AddressFormater AddressFormater { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取地址组合器
|
|
||||||
/// </summary>
|
|
||||||
public AddressCombiner AddressCombiner { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入地址组合器
|
|
||||||
/// </summary>
|
|
||||||
public AddressCombiner AddressCombinerSet { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 地址转换器
|
|
||||||
/// </summary>
|
|
||||||
public AddressTranslator AddressTranslator
|
|
||||||
{
|
|
||||||
get { return BaseUtility.AddressTranslator; }
|
|
||||||
set { BaseUtility.AddressTranslator = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 与设备实际通讯的连续地址
|
|
||||||
/// </summary>
|
|
||||||
protected IEnumerable<CommunicationUnit> CommunicateAddresses => GetAddresses != null ? AddressCombiner.Combine(GetAddresses) : null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 描述需要与设备通讯的地址
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<AddressUnit> GetAddresses { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否保持连接
|
|
||||||
/// </summary>
|
|
||||||
public bool KeepConnect { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从站号
|
|
||||||
/// </summary>
|
|
||||||
public byte SlaveAddress { get; set; } = 2;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 主站号
|
|
||||||
/// </summary>
|
|
||||||
public byte MasterAddress { get; set; } = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设备的连接器
|
|
||||||
/// </summary>
|
|
||||||
protected BaseUtility BaseUtility { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造器
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="getAddresses">需要与设备通讯的地址</param>
|
/// <param name="getAddresses">需要与设备通讯的地址</param>
|
||||||
protected BaseMachine(IEnumerable<AddressUnit> getAddresses)
|
protected BaseMachine(IEnumerable<AddressUnit> getAddresses)
|
||||||
@@ -129,7 +51,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造器
|
/// 构造器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="getAddresses">需要与设备通讯的地址</param>
|
/// <param name="getAddresses">需要与设备通讯的地址</param>
|
||||||
/// <param name="keepConnect">是否保持连接</param>
|
/// <param name="keepConnect">是否保持连接</param>
|
||||||
@@ -140,38 +62,120 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造器
|
/// 构造器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="getAddresses">需要与设备通讯的地址</param>
|
/// <param name="getAddresses">需要与设备通讯的地址</param>
|
||||||
/// <param name="keepConnect">是否保持连接</param>
|
/// <param name="keepConnect">是否保持连接</param>
|
||||||
/// <param name="slaveAddress">从站地址</param>
|
/// <param name="slaveAddress">从站地址</param>
|
||||||
/// <param name="masterAddress">主站地址</param>
|
/// <param name="masterAddress">主站地址</param>
|
||||||
protected BaseMachine(IEnumerable<AddressUnit> getAddresses, bool keepConnect, byte slaveAddress, byte masterAddress) : this(getAddresses, keepConnect)
|
protected BaseMachine(IEnumerable<AddressUnit> getAddresses, bool keepConnect, byte slaveAddress,
|
||||||
|
byte masterAddress) : this(getAddresses, keepConnect)
|
||||||
{
|
{
|
||||||
SlaveAddress = slaveAddress;
|
SlaveAddress = slaveAddress;
|
||||||
MasterAddress = masterAddress;
|
MasterAddress = masterAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int ErrorCount { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 读取数据
|
/// 是否处于连接状态
|
||||||
|
/// </summary>
|
||||||
|
public bool IsConnected => BaseUtility.IsConnected;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 地址编码器
|
||||||
|
/// </summary>
|
||||||
|
public AddressFormater AddressFormater { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取地址组合器
|
||||||
|
/// </summary>
|
||||||
|
public AddressCombiner AddressCombiner { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写入地址组合器
|
||||||
|
/// </summary>
|
||||||
|
public AddressCombiner AddressCombinerSet { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 地址转换器
|
||||||
|
/// </summary>
|
||||||
|
public AddressTranslator AddressTranslator
|
||||||
|
{
|
||||||
|
get { return BaseUtility.AddressTranslator; }
|
||||||
|
set { BaseUtility.AddressTranslator = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 与设备实际通讯的连续地址
|
||||||
|
/// </summary>
|
||||||
|
protected IEnumerable<CommunicationUnit> CommunicateAddresses
|
||||||
|
=> GetAddresses != null ? AddressCombiner.Combine(GetAddresses) : null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 描述需要与设备通讯的地址
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<AddressUnit> GetAddresses { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否保持连接
|
||||||
|
/// </summary>
|
||||||
|
public bool KeepConnect { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从站号
|
||||||
|
/// </summary>
|
||||||
|
public byte SlaveAddress { get; set; } = 2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 主站号
|
||||||
|
/// </summary>
|
||||||
|
public byte MasterAddress { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备的连接器
|
||||||
|
/// </summary>
|
||||||
|
protected BaseUtility BaseUtility { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备的Id
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备所在工程的名称
|
||||||
|
/// </summary>
|
||||||
|
public string ProjectName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备的名称
|
||||||
|
/// </summary>
|
||||||
|
public string MachineName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标识设备的连接关键字
|
||||||
|
/// </summary>
|
||||||
|
public string ConnectionToken => BaseUtility.ConnectionToken;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>从设备读取的数据</returns>
|
/// <returns>从设备读取的数据</returns>
|
||||||
public Dictionary<string, ReturnUnit> GetDatas(MachineGetDataType getDataType)
|
public Dictionary<string, ReturnUnit> GetDatas(MachineGetDataType getDataType)
|
||||||
{
|
{
|
||||||
return AsyncHelper.RunSync(()=>GetDatasAsync(getDataType));
|
return AsyncHelper.RunSync(() => GetDatasAsync(getDataType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 读取数据
|
/// 读取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>从设备读取的数据</returns>
|
/// <returns>从设备读取的数据</returns>
|
||||||
public async Task<Dictionary<string, ReturnUnit>> GetDatasAsync(MachineGetDataType getDataType)
|
public async Task<Dictionary<string, ReturnUnit>> GetDatasAsync(MachineGetDataType getDataType)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Dictionary<string, ReturnUnit> ans = new Dictionary<string, ReturnUnit>();
|
var ans = new Dictionary<string, ReturnUnit>();
|
||||||
//检测并连接设备
|
//检测并连接设备
|
||||||
if (!BaseUtility.IsConnected)
|
if (!BaseUtility.IsConnected)
|
||||||
{
|
{
|
||||||
@@ -186,7 +190,8 @@ namespace Modbus.Net
|
|||||||
var datas =
|
var datas =
|
||||||
await
|
await
|
||||||
BaseUtility.GetDatasAsync(
|
BaseUtility.GetDatasAsync(
|
||||||
AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, communicateAddress.SubAddress),
|
AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address,
|
||||||
|
communicateAddress.SubAddress),
|
||||||
(int)
|
(int)
|
||||||
Math.Ceiling(communicateAddress.GetCount*
|
Math.Ceiling(communicateAddress.GetCount*
|
||||||
BigEndianValueHelper.Instance.ByteLength[
|
BigEndianValueHelper.Instance.ByteLength[
|
||||||
@@ -195,21 +200,26 @@ namespace Modbus.Net
|
|||||||
|
|
||||||
//如果没有数据,终止
|
//如果没有数据,终止
|
||||||
if (datas == null || (datas.Length != 0 && datas.Length <
|
if (datas == null || (datas.Length != 0 && datas.Length <
|
||||||
(int)
|
(int)
|
||||||
Math.Ceiling(communicateAddress.GetCount*
|
Math.Ceiling(communicateAddress.GetCount*
|
||||||
BigEndianValueHelper.Instance.ByteLength[
|
BigEndianValueHelper.Instance.ByteLength[
|
||||||
communicateAddress.DataType.FullName])))
|
communicateAddress.DataType.FullName])))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
||||||
foreach (var address in communicateAddress.OriginalAddresses)
|
foreach (var address in communicateAddress.OriginalAddresses)
|
||||||
{
|
{
|
||||||
var localPos = (address.Address - communicateAddress.Address)*
|
//字节坐标的位置
|
||||||
AddressTranslator.GetAreaByteLength(communicateAddress.Area) +
|
var localPos = AddressHelper.MapProtocalCoordinateToAbstractCoordinate(address.Address,
|
||||||
address.SubAddress/8.0;
|
communicateAddress.Address,
|
||||||
|
AddressTranslator.GetAreaByteLength(communicateAddress.Area)) +
|
||||||
|
address.SubAddress*0.125;
|
||||||
|
//字节坐标的主地址位置
|
||||||
var localMainPos = (int) localPos;
|
var localMainPos = (int) localPos;
|
||||||
|
//字节坐标的子地址位置
|
||||||
var localSubPos = (int) ((localPos - localMainPos)*8);
|
var localSubPos = (int) ((localPos - localMainPos)*8);
|
||||||
|
|
||||||
|
//根据类型选择返回结果的键是通讯标识还是地址
|
||||||
string key;
|
string key;
|
||||||
switch (getDataType)
|
switch (getDataType)
|
||||||
{
|
{
|
||||||
@@ -230,6 +240,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//如果没有数据返回空
|
||||||
if (datas.Length == 0)
|
if (datas.Length == 0)
|
||||||
{
|
{
|
||||||
ans.Add(key, new ReturnUnit
|
ans.Add(key, new ReturnUnit
|
||||||
@@ -281,7 +292,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写入数据
|
/// 写入数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="setDataType">写入类型</param>
|
/// <param name="setDataType">写入类型</param>
|
||||||
/// <param name="values">需要写入的数据字典,当写入类型为Address时,键为需要写入的地址,当写入类型为CommunicationTag时,键为需要写入的单元的描述</param>
|
/// <param name="values">需要写入的数据字典,当写入类型为Address时,键为需要写入的地址,当写入类型为CommunicationTag时,键为需要写入的单元的描述</param>
|
||||||
@@ -292,7 +303,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写入数据
|
/// 写入数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="setDataType">写入类型</param>
|
/// <param name="setDataType">写入类型</param>
|
||||||
/// <param name="values">需要写入的数据字典,当写入类型为Address时,键为需要写入的地址,当写入类型为CommunicationTag时,键为需要写入的单元的描述</param>
|
/// <param name="values">需要写入的数据字典,当写入类型为Address时,键为需要写入的地址,当写入类型为CommunicationTag时,键为需要写入的单元的描述</param>
|
||||||
@@ -308,7 +319,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
//如果设备无法连接,终止
|
//如果设备无法连接,终止
|
||||||
if (!BaseUtility.IsConnected) return false;
|
if (!BaseUtility.IsConnected) return false;
|
||||||
List<AddressUnit> addresses = new List<AddressUnit>();
|
var addresses = new List<AddressUnit>();
|
||||||
//遍历每个要设置的值
|
//遍历每个要设置的值
|
||||||
foreach (var value in values)
|
foreach (var value in values)
|
||||||
{
|
{
|
||||||
@@ -333,14 +344,17 @@ namespace Modbus.Net
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//地址为空报错
|
||||||
if (address == null)
|
if (address == null)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Machine {ConnectionToken} Address {value.Key} doesn't exist.");
|
Console.WriteLine($"Machine {ConnectionToken} Address {value.Key} doesn't exist.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
//不能写报错
|
||||||
if (!address.CanWrite)
|
if (!address.CanWrite)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Machine {ConnectionToken} Address {value.Key} cannot write.");
|
Console.WriteLine($"Machine {ConnectionToken} Address {value.Key} cannot write.");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
addresses.Add(address);
|
addresses.Add(address);
|
||||||
}
|
}
|
||||||
@@ -376,27 +390,35 @@ namespace Modbus.Net
|
|||||||
|
|
||||||
foreach (var addressUnit in communicateAddress.OriginalAddresses)
|
foreach (var addressUnit in communicateAddress.OriginalAddresses)
|
||||||
{
|
{
|
||||||
var byteCount = (addressUnit.Address - communicateAddress.Address +
|
//字节坐标地址
|
||||||
addressUnit.SubAddress*0.125/
|
var byteCount =
|
||||||
AddressTranslator.GetAreaByteLength(communicateAddress.Area)) *
|
AddressHelper.MapProtocalGetCountToAbstractByteCount(
|
||||||
AddressTranslator.GetAreaByteLength(communicateAddress.Area);
|
addressUnit.Address - communicateAddress.Address +
|
||||||
|
addressUnit.SubAddress*0.125/
|
||||||
|
AddressTranslator.GetAreaByteLength(communicateAddress.Area),
|
||||||
|
AddressTranslator.GetAreaByteLength(communicateAddress.Area), 0);
|
||||||
|
//字节坐标主地址
|
||||||
var mainByteCount = (int) byteCount;
|
var mainByteCount = (int) byteCount;
|
||||||
|
//字节坐标自地址
|
||||||
var localByteCount = (int) ((byteCount - (int) byteCount)*8);
|
var localByteCount = (int) ((byteCount - (int) byteCount)*8);
|
||||||
|
|
||||||
|
//协议坐标地址
|
||||||
var localPos = byteCount/AddressTranslator.GetAreaByteLength(communicateAddress.Area);
|
var localPos = byteCount/AddressTranslator.GetAreaByteLength(communicateAddress.Area);
|
||||||
//编码当前地址
|
//协议坐标子地址
|
||||||
var subPos =
|
var subPos =
|
||||||
(int)
|
(int)
|
||||||
((localPos - (int) localPos)/
|
((localPos - (int) localPos)/
|
||||||
(0.125/AddressTranslator.GetAreaByteLength(communicateAddress.Area)));
|
(0.125/AddressTranslator.GetAreaByteLength(communicateAddress.Area)));
|
||||||
|
//协议主地址字符串
|
||||||
var address = AddressFormater.FormatAddress(communicateAddress.Area,
|
var address = AddressFormater.FormatAddress(communicateAddress.Area,
|
||||||
communicateAddress.Address + (int) localPos, subPos);
|
communicateAddress.Address + (int) localPos, subPos);
|
||||||
|
//协议完整地址字符串
|
||||||
var address2 = subPos != 0
|
var address2 = subPos != 0
|
||||||
? null
|
? null
|
||||||
: AddressFormater.FormatAddress(communicateAddress.Area,
|
: AddressFormater.FormatAddress(communicateAddress.Area,
|
||||||
communicateAddress.Address + (int) localPos);
|
communicateAddress.Address + (int) localPos);
|
||||||
//获取写入类型
|
//获取写入类型
|
||||||
Type dataType = addressUnit.DataType;
|
var dataType = addressUnit.DataType;
|
||||||
switch (setDataType)
|
switch (setDataType)
|
||||||
{
|
{
|
||||||
case MachineSetDataType.Address:
|
case MachineSetDataType.Address:
|
||||||
@@ -443,7 +465,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 连接设备
|
/// 连接设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>是否连接成功</returns>
|
/// <returns>是否连接成功</returns>
|
||||||
public bool Connect()
|
public bool Connect()
|
||||||
@@ -452,7 +474,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 连接设备
|
/// 连接设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>是否连接成功</returns>
|
/// <returns>是否连接成功</returns>
|
||||||
public async Task<bool> ConnectAsync()
|
public async Task<bool> ConnectAsync()
|
||||||
@@ -461,7 +483,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 断开设备
|
/// 断开设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>是否断开成功</returns>
|
/// <returns>是否断开成功</returns>
|
||||||
public bool Disconnect()
|
public bool Disconnect()
|
||||||
@@ -484,55 +506,60 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通讯单元
|
/// 通讯单元
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CommunicationUnit
|
public class CommunicationUnit
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 区域
|
/// 区域
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Area { get; set; }
|
public string Area { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址
|
/// 地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Address { get; set; }
|
public int Address { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 子地址
|
/// 子地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int SubAddress { get; set; } = 0;
|
public int SubAddress { get; set; } = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取个数
|
/// 获取个数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int GetCount { get; set; }
|
public int GetCount { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据类型
|
/// 数据类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Type DataType { get; set; }
|
public Type DataType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 原始的地址
|
/// 原始的地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<AddressUnit> OriginalAddresses { get; set; }
|
public IEnumerable<AddressUnit> OriginalAddresses { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据单元扩展,返回数据时会同时将其返回
|
/// 数据单元扩展,返回数据时会同时将其返回
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UnitExtend
|
public class UnitExtend
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 返回的数据单元
|
/// 返回的数据单元
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ReturnUnit
|
public class ReturnUnit
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 返回的数据
|
/// 返回的数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double? PlcValue { get; set; }
|
public double? PlcValue { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据的扩展
|
/// 数据的扩展
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public UnitExtend UnitExtend { get; set; }
|
public UnitExtend UnitExtend { get; set; }
|
||||||
}
|
}
|
||||||
@@ -540,55 +567,69 @@ namespace Modbus.Net
|
|||||||
public class AddressUnit
|
public class AddressUnit
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据单元Id
|
/// 数据单元Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据所属的区域
|
/// 数据所属的区域
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Area { get; set; }
|
public string Area { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址
|
/// 地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Address { get; set; }
|
public int Address { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// bit位地址
|
/// bit位地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int SubAddress { get; set; } = 0;
|
public int SubAddress { get; set; } = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据类型
|
/// 数据类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Type DataType { get; set; }
|
public Type DataType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 放缩比例
|
/// 放缩比例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double Zoom { get; set; } = 1;
|
public double Zoom { get; set; } = 1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 小数位数
|
/// 小数位数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int DecimalPos { get; set; }
|
public int DecimalPos { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通讯标识名称
|
/// 通讯标识名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string CommunicationTag { get; set; }
|
public string CommunicationTag { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 名称
|
/// 名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 单位
|
/// 单位
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Unit { get; set; }
|
public string Unit { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否可写,默认可写
|
/// 是否可写,默认可写
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanWrite { get; set; } = true;
|
public bool CanWrite { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 扩展
|
/// 扩展
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public UnitExtend UnitExtend { get; set; }
|
public UnitExtend UnitExtend { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AddressUnit大小比较
|
||||||
|
/// </summary>
|
||||||
public struct AddressUnitEqualityComparer : IEqualityComparer<AddressUnit>
|
public struct AddressUnitEqualityComparer : IEqualityComparer<AddressUnit>
|
||||||
{
|
{
|
||||||
public bool Equals(AddressUnit x, AddressUnit y)
|
public bool Equals(AddressUnit x, AddressUnit y)
|
||||||
@@ -603,24 +644,27 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设备的抽象
|
/// 设备的抽象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMachineProperty
|
public interface IMachineProperty
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id
|
/// Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Id { get; set; }
|
string Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 工程名
|
/// 工程名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string ProjectName { get; set; }
|
string ProjectName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设备名
|
/// 设备名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string MachineName { get; set; }
|
string MachineName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 标识设备的连接关键字
|
/// 标识设备的连接关键字
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string ConnectionToken { get; }
|
string ConnectionToken { get; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// BaseMachine扩展类
|
||||||
|
/// </summary>
|
||||||
public static class BaseMachineExtend
|
public static class BaseMachineExtend
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 将获取的数据转换成可以向设备写入的数据格式
|
/// 将获取的数据转换成可以向设备写入的数据格式
|
||||||
|
/// 注意转换无法变更读写类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="getValues">获取的数据</param>
|
/// <param name="getValues">获取的数据</param>
|
||||||
/// <returns>写入的数据</returns>
|
/// <returns>应该写入的数据</returns>
|
||||||
public static Dictionary<string, double> MapGetValuesToSetValues(this Dictionary<string, ReturnUnit> getValues)
|
public static Dictionary<string, double> MapGetValuesToSetValues(this Dictionary<string, ReturnUnit> getValues)
|
||||||
{
|
{
|
||||||
if (getValues == null) return null;
|
if (getValues == null) return null;
|
||||||
return (from getValue in getValues
|
return (from getValue in getValues
|
||||||
where getValue.Value.PlcValue != null
|
where getValue.Value.PlcValue != null
|
||||||
select new KeyValuePair<string, double>(getValue.Key, getValue.Value.PlcValue.Value)).ToDictionary(p => p.Key, p => p.Value);
|
select new KeyValuePair<string, double>(getValue.Key, getValue.Value.PlcValue.Value)).ToDictionary(
|
||||||
|
p => p.Key, p => p.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,30 +6,30 @@ using System.Threading.Tasks;
|
|||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基本协议
|
/// 基本协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BaseProtocal
|
public abstract class BaseProtocal
|
||||||
{
|
{
|
||||||
public byte BelongAddress { get; set; }
|
/// <summary>
|
||||||
|
/// 构造器
|
||||||
|
/// </summary>
|
||||||
|
protected BaseProtocal(byte slaveAddress, byte masterAddress)
|
||||||
|
{
|
||||||
|
Protocals = new Dictionary<string, ProtocalUnit>();
|
||||||
|
SlaveAddress = slaveAddress;
|
||||||
|
MasterAddress = masterAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte SlaveAddress { get; set; }
|
||||||
public byte MasterAddress { get; set; }
|
public byte MasterAddress { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议的连接器
|
/// 协议的连接器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ProtocalLinker ProtocalLinker { get; protected set; }
|
public ProtocalLinker ProtocalLinker { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造器
|
/// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议
|
||||||
/// </summary>
|
|
||||||
protected BaseProtocal(byte belongAddress, byte masterAddress)
|
|
||||||
{
|
|
||||||
Protocals = new Dictionary<string, ProtocalUnit>();
|
|
||||||
BelongAddress = belongAddress;
|
|
||||||
MasterAddress = masterAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type">协议的类的GetType</param>
|
/// <param name="type">协议的类的GetType</param>
|
||||||
/// <returns>协议的实例</returns>
|
/// <returns>协议的实例</returns>
|
||||||
@@ -37,7 +37,7 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
string protocalName = type.FullName;
|
var protocalName = type.FullName;
|
||||||
if (Protocals.ContainsKey(protocalName))
|
if (Protocals.ContainsKey(protocalName))
|
||||||
{
|
{
|
||||||
return Protocals[protocalName];
|
return Protocals[protocalName];
|
||||||
@@ -52,12 +52,12 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议集合
|
/// 协议集合
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected Dictionary<string, ProtocalUnit> Protocals { get; }
|
protected Dictionary<string, ProtocalUnit> Protocals { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册一个协议
|
/// 注册一个协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="linkProtocal">需要注册的协议</param>
|
/// <param name="linkProtocal">需要注册的协议</param>
|
||||||
protected void Register(ProtocalUnit linkProtocal)
|
protected void Register(ProtocalUnit linkProtocal)
|
||||||
@@ -67,7 +67,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送协议内容并接收,一般方法
|
/// 发送协议内容并接收,一般方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="isLittleEndian">是否是小端格式</param>
|
/// <param name="isLittleEndian">是否是小端格式</param>
|
||||||
/// <param name="content">写入的内容,使用对象数组描述</param>
|
/// <param name="content">写入的内容,使用对象数组描述</param>
|
||||||
@@ -78,7 +78,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送协议内容并接收,一般方法
|
/// 发送协议内容并接收,一般方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="isLittleEndian">是否是小端格式</param>
|
/// <param name="isLittleEndian">是否是小端格式</param>
|
||||||
/// <param name="content">写入的内容,使用对象数组描述</param>
|
/// <param name="content">写入的内容,使用对象数组描述</param>
|
||||||
@@ -93,14 +93,11 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
return await ProtocalLinker.SendReceiveAsync(ProtocalUnit.TranslateContent(isLittleEndian, content));
|
return await ProtocalLinker.SendReceiveAsync(ProtocalUnit.TranslateContent(isLittleEndian, content));
|
||||||
}
|
}
|
||||||
else
|
return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送协议,通过传入需要使用的协议内容和输入结构
|
/// 发送协议,通过传入需要使用的协议内容和输入结构
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="unit">协议的实例</param>
|
/// <param name="unit">协议的实例</param>
|
||||||
/// <param name="content">输入信息的结构化描述</param>
|
/// <param name="content">输入信息的结构化描述</param>
|
||||||
@@ -111,14 +108,14 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送协议,通过传入需要使用的协议内容和输入结构
|
/// 发送协议,通过传入需要使用的协议内容和输入结构
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="unit">协议的实例</param>
|
/// <param name="unit">协议的实例</param>
|
||||||
/// <param name="content">输入信息的结构化描述</param>
|
/// <param name="content">输入信息的结构化描述</param>
|
||||||
/// <returns>输出信息的结构化描述</returns>
|
/// <returns>输出信息的结构化描述</returns>
|
||||||
public virtual async Task<OutputStruct> SendReceiveAsync(ProtocalUnit unit, InputStruct content)
|
public virtual async Task<OutputStruct> SendReceiveAsync(ProtocalUnit unit, InputStruct content)
|
||||||
{
|
{
|
||||||
int t = 0;
|
var t = 0;
|
||||||
var formatContent = unit.Format(content);
|
var formatContent = unit.Format(content);
|
||||||
if (formatContent != null)
|
if (formatContent != null)
|
||||||
{
|
{
|
||||||
@@ -141,19 +138,19 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议连接开始
|
/// 协议连接开始
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public abstract bool Connect();
|
public abstract bool Connect();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议连接开始(异步)
|
/// 协议连接开始(异步)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public abstract Task<bool> ConnectAsync();
|
public abstract Task<bool> ConnectAsync();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议连接断开
|
/// 协议连接断开
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual bool Disconnect()
|
public virtual bool Disconnect()
|
||||||
|
|||||||
@@ -8,56 +8,58 @@ namespace Modbus.Net
|
|||||||
public abstract class BaseUtility
|
public abstract class BaseUtility
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议收发主体
|
/// 协议收发主体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected BaseProtocal Wrapper;
|
protected BaseProtocal Wrapper;
|
||||||
protected string ConnectionString { get; set; }
|
|
||||||
|
|
||||||
public byte BelongAddress { get; set; }
|
|
||||||
public byte MasterAddress { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取协议是否遵循小端格式
|
/// 构造器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract bool GetLittleEndian { get; }
|
protected BaseUtility(byte slaveAddress, byte masterAddress)
|
||||||
/// <summary>
|
|
||||||
/// 设置协议是否遵循小端格式
|
|
||||||
/// </summary>
|
|
||||||
public abstract bool SetLittleEndian { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设备是否已经连接
|
|
||||||
/// </summary>
|
|
||||||
public bool IsConnected => Wrapper?.ProtocalLinker != null && Wrapper.ProtocalLinker.IsConnected;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标识设备的连接关键字
|
|
||||||
/// </summary>
|
|
||||||
public string ConnectionToken => Wrapper.ProtocalLinker.ConnectionToken;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 地址翻译器
|
|
||||||
/// </summary>
|
|
||||||
public AddressTranslator AddressTranslator { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造器
|
|
||||||
/// </summary>
|
|
||||||
protected BaseUtility(byte belongAddress, byte masterAddress)
|
|
||||||
{
|
{
|
||||||
BelongAddress = belongAddress;
|
SlaveAddress = slaveAddress;
|
||||||
MasterAddress = masterAddress;
|
MasterAddress = masterAddress;
|
||||||
AddressTranslator = new AddressTranslatorBase();
|
AddressTranslator = new AddressTranslatorBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected string ConnectionString { get; set; }
|
||||||
|
|
||||||
|
public byte SlaveAddress { get; set; }
|
||||||
|
public byte MasterAddress { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置连接类型
|
/// 获取协议是否遵循小端格式
|
||||||
|
/// </summary>
|
||||||
|
public abstract bool GetLittleEndian { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置协议是否遵循小端格式
|
||||||
|
/// </summary>
|
||||||
|
public abstract bool SetLittleEndian { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备是否已经连接
|
||||||
|
/// </summary>
|
||||||
|
public bool IsConnected => Wrapper?.ProtocalLinker != null && Wrapper.ProtocalLinker.IsConnected;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标识设备的连接关键字
|
||||||
|
/// </summary>
|
||||||
|
public string ConnectionToken => Wrapper.ProtocalLinker.ConnectionToken;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 地址翻译器
|
||||||
|
/// </summary>
|
||||||
|
public AddressTranslator AddressTranslator { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置连接类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connectionType">连接类型</param>
|
/// <param name="connectionType">连接类型</param>
|
||||||
public abstract void SetConnectionType(int connectionType);
|
public abstract void SetConnectionType(int connectionType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据
|
/// 获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="startAddress">开始地址</param>
|
/// <param name="startAddress">开始地址</param>
|
||||||
/// <param name="getByteCount">获取字节数个数</param>
|
/// <param name="getByteCount">获取字节数个数</param>
|
||||||
@@ -68,7 +70,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据
|
/// 获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="startAddress">开始地址</param>
|
/// <param name="startAddress">开始地址</param>
|
||||||
/// <param name="getByteCount">获取字节数个数</param>
|
/// <param name="getByteCount">获取字节数个数</param>
|
||||||
@@ -76,10 +78,8 @@ namespace Modbus.Net
|
|||||||
public abstract Task<byte[]> GetDatasAsync(string startAddress, int getByteCount);
|
public abstract Task<byte[]> GetDatasAsync(string startAddress, int getByteCount);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据
|
/// 获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="belongAddress">从站地址</param>
|
|
||||||
/// <param name="masterAddress">主站地址</param>
|
|
||||||
/// <param name="startAddress">开始地址</param>
|
/// <param name="startAddress">开始地址</param>
|
||||||
/// <param name="getTypeAndCount">获取类型和个数</param>
|
/// <param name="getTypeAndCount">获取类型和个数</param>
|
||||||
/// <returns>接收到的对应的类型和数据</returns>
|
/// <returns>接收到的对应的类型和数据</returns>
|
||||||
@@ -90,10 +90,8 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据
|
/// 获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="belongAddress">从站地址</param>
|
|
||||||
/// <param name="masterAddress">主站地址</param>
|
|
||||||
/// <param name="startAddress">开始地址</param>
|
/// <param name="startAddress">开始地址</param>
|
||||||
/// <param name="getTypeAndCount">获取类型和个数</param>
|
/// <param name="getTypeAndCount">获取类型和个数</param>
|
||||||
/// <returns>接收到的对应的类型和数据</returns>
|
/// <returns>接收到的对应的类型和数据</returns>
|
||||||
@@ -102,10 +100,10 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string typeName = getTypeAndCount.Key.FullName;
|
var typeName = getTypeAndCount.Key.FullName;
|
||||||
double bCount = BigEndianValueHelper.Instance.ByteLength[typeName];
|
var bCount = BigEndianValueHelper.Instance.ByteLength[typeName];
|
||||||
var getReturnValue = await GetDatasAsync(startAddress,
|
var getReturnValue = await GetDatasAsync(startAddress,
|
||||||
(int)Math.Ceiling(bCount * getTypeAndCount.Value));
|
(int) Math.Ceiling(bCount*getTypeAndCount.Value));
|
||||||
var getBytes = getReturnValue;
|
var getBytes = getReturnValue;
|
||||||
return GetLittleEndian
|
return GetLittleEndian
|
||||||
? ValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCount)
|
? ValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCount)
|
||||||
@@ -118,11 +116,9 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据
|
/// 获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">需要接收的类型</typeparam>
|
/// <typeparam name="T">需要接收的类型</typeparam>
|
||||||
/// <param name="belongAddress">从站地址</param>
|
|
||||||
/// <param name="masterAddress">主站地址</param>
|
|
||||||
/// <param name="startAddress">开始地址</param>
|
/// <param name="startAddress">开始地址</param>
|
||||||
/// <param name="getByteCount">获取字节数个数</param>
|
/// <param name="getByteCount">获取字节数个数</param>
|
||||||
/// <returns>接收到的对应的类型和数据</returns>
|
/// <returns>接收到的对应的类型和数据</returns>
|
||||||
@@ -133,11 +129,9 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据
|
/// 获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">需要接收的类型</typeparam>
|
/// <typeparam name="T">需要接收的类型</typeparam>
|
||||||
/// <param name="belongAddress">从站地址</param>
|
|
||||||
/// <param name="masterAddress">主站地址</param>
|
|
||||||
/// <param name="startAddress">开始地址</param>
|
/// <param name="startAddress">开始地址</param>
|
||||||
/// <param name="getByteCount">获取字节数个数</param>
|
/// <param name="getByteCount">获取字节数个数</param>
|
||||||
/// <returns>接收到的对应的类型和数据</returns>
|
/// <returns>接收到的对应的类型和数据</returns>
|
||||||
@@ -147,7 +141,7 @@ namespace Modbus.Net
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var getBytes = await GetDatasAsync(startAddress,
|
var getBytes = await GetDatasAsync(startAddress,
|
||||||
new KeyValuePair<Type, int>(typeof(T), getByteCount));
|
new KeyValuePair<Type, int>(typeof (T), getByteCount));
|
||||||
return BigEndianValueHelper.Instance.ObjectArrayToDestinationArray<T>(getBytes);
|
return BigEndianValueHelper.Instance.ObjectArrayToDestinationArray<T>(getBytes);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -157,7 +151,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据
|
/// 获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="startAddress">开始地址</param>
|
/// <param name="startAddress">开始地址</param>
|
||||||
/// <param name="getTypeAndCountList">获取类型和个数的队列</param>
|
/// <param name="getTypeAndCountList">获取类型和个数的队列</param>
|
||||||
@@ -170,7 +164,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据
|
/// 获取数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="startAddress">开始地址</param>
|
/// <param name="startAddress">开始地址</param>
|
||||||
/// <param name="getTypeAndCountList">获取类型和个数的队列</param>
|
/// <param name="getTypeAndCountList">获取类型和个数的队列</param>
|
||||||
@@ -181,13 +175,13 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
var translateTypeAndCount = getTypeAndCountList as IList<KeyValuePair<Type, int>> ??
|
var translateTypeAndCount = getTypeAndCountList as IList<KeyValuePair<Type, int>> ??
|
||||||
getTypeAndCountList.ToList();
|
getTypeAndCountList.ToList();
|
||||||
int bAllCount = (
|
var bAllCount = (
|
||||||
from getTypeAndCount in translateTypeAndCount
|
from getTypeAndCount in translateTypeAndCount
|
||||||
let typeName = getTypeAndCount.Key.FullName
|
let typeName = getTypeAndCount.Key.FullName
|
||||||
let bCount = BigEndianValueHelper.Instance.ByteLength[typeName]
|
let bCount = BigEndianValueHelper.Instance.ByteLength[typeName]
|
||||||
select (int) Math.Ceiling(bCount*getTypeAndCount.Value)).Sum();
|
select (int) Math.Ceiling(bCount*getTypeAndCount.Value)).Sum();
|
||||||
var getReturnValue = await GetDatasAsync(startAddress, bAllCount);
|
var getReturnValue = await GetDatasAsync(startAddress, bAllCount);
|
||||||
byte[] getBytes = getReturnValue;
|
var getBytes = getReturnValue;
|
||||||
return GetLittleEndian
|
return GetLittleEndian
|
||||||
? ValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount)
|
? ValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount)
|
||||||
: BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount);
|
: BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount);
|
||||||
@@ -199,7 +193,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置数据
|
/// 设置数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="startAddress">开始地址</param>
|
/// <param name="startAddress">开始地址</param>
|
||||||
/// <param name="setContents">设置数据</param>
|
/// <param name="setContents">设置数据</param>
|
||||||
@@ -210,7 +204,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置数据
|
/// 设置数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="startAddress">开始地址</param>
|
/// <param name="startAddress">开始地址</param>
|
||||||
/// <param name="setContents">设置数据</param>
|
/// <param name="setContents">设置数据</param>
|
||||||
@@ -233,7 +227,7 @@ namespace Modbus.Net
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 连接设备
|
/// 连接设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>设备是否连接成功</returns>
|
/// <returns>设备是否连接成功</returns>
|
||||||
public bool Connect()
|
public bool Connect()
|
||||||
@@ -242,7 +236,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 连接设备
|
/// 连接设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>设备是否连接成功</returns>
|
/// <returns>设备是否连接成功</returns>
|
||||||
public async Task<bool> ConnectAsync()
|
public async Task<bool> ConnectAsync()
|
||||||
@@ -251,13 +245,12 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 断开设备
|
/// 断开设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>设备是否断开成功</returns>
|
/// <returns>设备是否断开成功</returns>
|
||||||
public bool Disconnect()
|
public bool Disconnect()
|
||||||
{
|
{
|
||||||
return Wrapper.Disconnect();
|
return Wrapper.Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,21 @@
|
|||||||
using System;
|
/*
|
||||||
|
* Crc16来自于多个网络上的代码,Modbus.Net的作者不保留对Crc16类的版权。
|
||||||
|
* Crc16 class comes from mutiple websites, the author of "Modbus.Net" <b>donnot</b> obtain the copyright of Crc16(only).
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
public class Crc16
|
public class Crc16
|
||||||
{
|
{
|
||||||
|
private static Crc16 _crc16;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// CRC验证表
|
/// CRC验证表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[] crc_table = new byte[512];
|
public byte[] crc_table = new byte[512];
|
||||||
|
|
||||||
private static Crc16 _crc16 = null;
|
|
||||||
|
|
||||||
public static Crc16 GetInstance()
|
public static Crc16 GetInstance()
|
||||||
{
|
{
|
||||||
if (_crc16 == null)
|
if (_crc16 == null)
|
||||||
@@ -23,40 +28,40 @@ namespace Modbus.Net
|
|||||||
#region 生成CRC码
|
#region 生成CRC码
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成CRC码
|
/// 生成CRC码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">发送或返回的命令,CRC码除外</param>
|
/// <param name="message">发送或返回的命令,CRC码除外</param>
|
||||||
/// <param name="Rcvbuf">存储CRC码的字节的数组</param>
|
/// <param name="Rcvbuf">存储CRC码的字节的数组</param>
|
||||||
/// <param name="CRC">生成的CRC码</param>
|
/// <param name="CRC">生成的CRC码</param>
|
||||||
public short GetCRC(byte[] message, ref byte[] Rcvbuf)
|
public short GetCRC(byte[] message, ref byte[] Rcvbuf)
|
||||||
{
|
{
|
||||||
int IX,IY,CRC;
|
int IX, IY, CRC;
|
||||||
int Len = message.Length;
|
var Len = message.Length;
|
||||||
CRC=0xFFFF;
|
CRC = 0xFFFF;
|
||||||
//set all 1
|
//set all 1
|
||||||
if (Len<=0)
|
if (Len <= 0)
|
||||||
CRC = 0;
|
CRC = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Len--;
|
Len--;
|
||||||
for (IX=0;IX<=Len;IX++)
|
for (IX = 0; IX <= Len; IX++)
|
||||||
{
|
{
|
||||||
CRC=CRC^(message[IX]);
|
CRC = CRC ^ message[IX];
|
||||||
for(IY=0;IY<=7;IY++)
|
for (IY = 0; IY <= 7; IY++)
|
||||||
{
|
{
|
||||||
if ((CRC&1)!=0 )
|
if ((CRC & 1) != 0)
|
||||||
CRC=(CRC>>1)^0xA001;
|
CRC = (CRC >> 1) ^ 0xA001;
|
||||||
else
|
else
|
||||||
CRC=CRC>>1;
|
CRC = CRC >> 1;
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rcvbuf[1] = (byte)((CRC & 0xff00)>>8);//高位置
|
Rcvbuf[1] = (byte) ((CRC & 0xff00) >> 8); //高位置
|
||||||
Rcvbuf[0] = (byte)(CRC & 0x00ff); //低位置
|
Rcvbuf[0] = (byte) (CRC & 0x00ff); //低位置
|
||||||
CRC= Rcvbuf[0]<<8;
|
CRC = Rcvbuf[0] << 8;
|
||||||
CRC+= Rcvbuf[1];
|
CRC += Rcvbuf[1];
|
||||||
return (short)CRC;
|
return (short) CRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -64,31 +69,28 @@ namespace Modbus.Net
|
|||||||
#region CRC验证
|
#region CRC验证
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// CRC校验
|
/// CRC校验
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="src">ST开头,&&结尾</param>
|
/// <param name="src">ST开头,&&结尾</param>
|
||||||
/// <returns>十六进制数</returns>
|
/// <returns>十六进制数</returns>
|
||||||
public bool CrcEfficacy(byte[] byteframe)
|
public bool CrcEfficacy(byte[] byteframe)
|
||||||
{
|
{
|
||||||
byte[] recvbuff = new byte[2];
|
var recvbuff = new byte[2];
|
||||||
byte[] byteArr = new byte[byteframe.Length - 2];
|
var byteArr = new byte[byteframe.Length - 2];
|
||||||
Array.Copy(byteframe, 0, byteArr, 0, byteArr.Length);
|
Array.Copy(byteframe, 0, byteArr, 0, byteArr.Length);
|
||||||
GetCRC(byteArr, ref recvbuff);
|
GetCRC(byteArr, ref recvbuff);
|
||||||
if (recvbuff[0] == byteframe[byteframe.Length - 2] && recvbuff[1] == byteframe[byteframe.Length - 1])
|
if (recvbuff[0] == byteframe[byteframe.Length - 2] && recvbuff[1] == byteframe[byteframe.Length - 1])
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 取模FF(255)
|
/// 取模FF(255)
|
||||||
/// 取反+1
|
/// 取反+1
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="writeUncheck"></param>
|
/// <param name="writeUncheck"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@@ -97,25 +99,25 @@ namespace Modbus.Net
|
|||||||
var index = message.IndexOf(Environment.NewLine, StringComparison.InvariantCulture);
|
var index = message.IndexOf(Environment.NewLine, StringComparison.InvariantCulture);
|
||||||
var writeUncheck = message.Substring(1, index - 2);
|
var writeUncheck = message.Substring(1, index - 2);
|
||||||
var checkString = message.Substring(index - 2, 2);
|
var checkString = message.Substring(index - 2, 2);
|
||||||
char[] hexArray = new char[writeUncheck.Length];
|
var hexArray = new char[writeUncheck.Length];
|
||||||
hexArray = writeUncheck.ToCharArray();
|
hexArray = writeUncheck.ToCharArray();
|
||||||
int decNum = 0, decNumMSB = 0, decNumLSB = 0;
|
int decNum = 0, decNumMSB = 0, decNumLSB = 0;
|
||||||
int decByte, decByteTotal = 0;
|
int decByte, decByteTotal = 0;
|
||||||
|
|
||||||
bool msb = true;
|
var msb = true;
|
||||||
|
|
||||||
for (int t = 0; t <= hexArray.GetUpperBound(0); t++)
|
for (var t = 0; t <= hexArray.GetUpperBound(0); t++)
|
||||||
{
|
{
|
||||||
if ((hexArray[t] >= 48) && (hexArray[t] <= 57))
|
if ((hexArray[t] >= 48) && (hexArray[t] <= 57))
|
||||||
|
|
||||||
decNum = (hexArray[t] - 48);
|
decNum = hexArray[t] - 48;
|
||||||
|
|
||||||
else if ((hexArray[t] >= 65) & (hexArray[t] <= 70))
|
else if ((hexArray[t] >= 65) & (hexArray[t] <= 70))
|
||||||
decNum = 10 + (hexArray[t] - 65);
|
decNum = 10 + (hexArray[t] - 65);
|
||||||
|
|
||||||
if (msb)
|
if (msb)
|
||||||
{
|
{
|
||||||
decNumMSB = decNum * 16;
|
decNumMSB = decNum*16;
|
||||||
msb = false;
|
msb = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -130,7 +132,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
decByteTotal = (255 - decByteTotal) + 1;
|
decByteTotal = 255 - decByteTotal + 1;
|
||||||
decByteTotal = decByteTotal & 255;
|
decByteTotal = decByteTotal & 255;
|
||||||
|
|
||||||
int a, b = 0;
|
int a, b = 0;
|
||||||
@@ -141,7 +143,7 @@ namespace Modbus.Net
|
|||||||
for (i = 0; decByteTotal > 0; i++)
|
for (i = 0; decByteTotal > 0; i++)
|
||||||
{
|
{
|
||||||
//b = Convert.ToInt32(System.Math.Pow(16.0, i));
|
//b = Convert.ToInt32(System.Math.Pow(16.0, i));
|
||||||
a = decByteTotal % 16;
|
a = decByteTotal%16;
|
||||||
decByteTotal /= 16;
|
decByteTotal /= 16;
|
||||||
if (a <= 9)
|
if (a <= 9)
|
||||||
hexByte = a.ToString();
|
hexByte = a.ToString();
|
||||||
@@ -169,7 +171,7 @@ namespace Modbus.Net
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hexTotal = String.Concat(hexByte, hexTotal);
|
hexTotal = string.Concat(hexByte, hexTotal);
|
||||||
}
|
}
|
||||||
return hexTotal == checkString;
|
return hexTotal == checkString;
|
||||||
}
|
}
|
||||||
@@ -177,12 +179,12 @@ namespace Modbus.Net
|
|||||||
public string GetLRC(byte[] code)
|
public string GetLRC(byte[] code)
|
||||||
{
|
{
|
||||||
byte sum = 0;
|
byte sum = 0;
|
||||||
foreach (byte b in code)
|
foreach (var b in code)
|
||||||
{
|
{
|
||||||
sum += b;
|
sum += b;
|
||||||
}
|
}
|
||||||
sum = (byte)(~sum + 1);//取反+1
|
sum = (byte) (~sum + 1); //取反+1
|
||||||
string lrc = sum.ToString("X2");
|
var lrc = sum.ToString("X2");
|
||||||
return lrc;
|
return lrc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO.Ports;
|
using System.IO.Ports;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -6,12 +7,45 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 串口通讯类
|
||||||
|
/// </summary>
|
||||||
public class ComConnector : BaseConnector, IDisposable
|
public class ComConnector : BaseConnector, IDisposable
|
||||||
{
|
{
|
||||||
public override string ConnectionToken => _com;
|
public delegate byte[] GetDate(byte[] bts);
|
||||||
|
|
||||||
|
private readonly int _baudRate;
|
||||||
|
|
||||||
|
//private GetDate mygetDate;
|
||||||
|
private readonly string _com;
|
||||||
|
private readonly int _dataBits;
|
||||||
|
private readonly Parity _parity;
|
||||||
|
private readonly StopBits _stopBits;
|
||||||
|
private readonly int _timeoutTime;
|
||||||
|
|
||||||
private SerialPort _serialPort1;
|
private SerialPort _serialPort1;
|
||||||
|
|
||||||
|
private bool m_disposed = true;
|
||||||
|
|
||||||
|
public ComConnector(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits, int timeoutTime)
|
||||||
|
{
|
||||||
|
_com = com;
|
||||||
|
_timeoutTime = timeoutTime;
|
||||||
|
_baudRate = baudRate;
|
||||||
|
_parity = parity;
|
||||||
|
_stopBits = stopBits;
|
||||||
|
_dataBits = dataBits;
|
||||||
|
|
||||||
|
//端口号
|
||||||
|
//读超时
|
||||||
|
//比特率
|
||||||
|
//奇偶校验
|
||||||
|
//停止位
|
||||||
|
//数据位
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ConnectionToken => _com;
|
||||||
|
|
||||||
private SerialPort SerialPort1
|
private SerialPort SerialPort1
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -25,38 +59,222 @@ namespace Modbus.Net
|
|||||||
Parity = _parity,
|
Parity = _parity,
|
||||||
StopBits = _stopBits,
|
StopBits = _stopBits,
|
||||||
DataBits = _dataBits,
|
DataBits = _dataBits,
|
||||||
ReadTimeout = _timeoutTime,
|
ReadTimeout = _timeoutTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return _serialPort1;
|
return _serialPort1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public delegate byte[] GetDate(byte[] bts);
|
/// <summary>
|
||||||
|
/// 实现IDisposable接口
|
||||||
//private GetDate mygetDate;
|
/// </summary>
|
||||||
private readonly string _com;
|
public void Dispose()
|
||||||
private readonly int _timeoutTime;
|
|
||||||
private readonly int _baudRate;
|
|
||||||
private readonly Parity _parity;
|
|
||||||
private readonly StopBits _stopBits;
|
|
||||||
private readonly int _dataBits;
|
|
||||||
|
|
||||||
public ComConnector(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits, int timeoutTime)
|
|
||||||
{
|
{
|
||||||
_com = com;
|
Dispose(true);
|
||||||
_timeoutTime = timeoutTime;
|
//.NET Framework 类库
|
||||||
_baudRate = baudRate;
|
// GC..::.SuppressFinalize 方法
|
||||||
_parity = parity;
|
//请求系统不要调用指定对象的终结器。
|
||||||
_stopBits = stopBits;
|
GC.SuppressFinalize(this);
|
||||||
_dataBits = dataBits;
|
}
|
||||||
|
|
||||||
//端口号
|
/// <summary>
|
||||||
//比特率
|
/// 串口读(非阻塞方式读串口,直到串口缓冲区中没有数据
|
||||||
//奇偶校验
|
/// </summary>
|
||||||
//停止位
|
/// <param name="readBuf">串口数据缓冲 </param>
|
||||||
//读超时,即在1000内未读到数据就引起超时异常
|
/// <param name="bufRoom">串口数据缓冲空间大小 </param>
|
||||||
|
/// <param name="HowTime">设置串口读放弃时间 </param>
|
||||||
|
/// <param name="ByteTime">字节间隔最大时间 </param>
|
||||||
|
/// <returns>串口实际读入数据个数 </returns>
|
||||||
|
public int ReadComm(out byte[] readBuf, int bufRoom, int HowTime, int ByteTime)
|
||||||
|
{
|
||||||
|
//throw new System.NotImplementedException();
|
||||||
|
readBuf = new byte[1023];
|
||||||
|
Array.Clear(readBuf, 0, readBuf.Length);
|
||||||
|
|
||||||
|
int nReadLen, nBytelen;
|
||||||
|
if (SerialPort1.IsOpen == false)
|
||||||
|
return -1;
|
||||||
|
nBytelen = 0;
|
||||||
|
SerialPort1.ReadTimeout = HowTime;
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (SerialPort1.BytesToRead > 0)
|
||||||
|
{
|
||||||
|
readBuf[nBytelen] = (byte) SerialPort1.ReadByte();
|
||||||
|
var bTmp = new byte[bufRoom];
|
||||||
|
Array.Clear(bTmp, 0, bTmp.Length);
|
||||||
|
|
||||||
|
nReadLen = ReadBlock(bTmp, bufRoom, ByteTime);
|
||||||
|
|
||||||
|
if (nReadLen > 0)
|
||||||
|
{
|
||||||
|
Array.Copy(bTmp, 0, readBuf, nBytelen + 1, nReadLen);
|
||||||
|
nBytelen += 1 + nReadLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (nReadLen == 0)
|
||||||
|
nBytelen += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nBytelen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 串口同步读(阻塞方式读串口,直到串口缓冲区中没有数据,靠字符间间隔超时确定没有数据)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ReadBuf">串口数据缓冲 </param>
|
||||||
|
/// <param name="ReadRoom">串口数据缓冲空间大小 </param>
|
||||||
|
/// <param name="ByteTime">字节间隔最大时间 </param>
|
||||||
|
/// <returns>从串口实际读入的字节个数 </returns>
|
||||||
|
public int ReadBlock(byte[] ReadBuf, int ReadRoom, int ByteTime)
|
||||||
|
{
|
||||||
|
sbyte nBytelen;
|
||||||
|
//long nByteRead;
|
||||||
|
|
||||||
|
if (SerialPort1.IsOpen == false)
|
||||||
|
return 0;
|
||||||
|
nBytelen = 0;
|
||||||
|
SerialPort1.ReadTimeout = ByteTime;
|
||||||
|
|
||||||
|
while (nBytelen < ReadRoom - 1 && SerialPort1.BytesToRead > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ReadBuf[nBytelen] = (byte) SerialPort1.ReadByte();
|
||||||
|
nBytelen++; // add one
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReadBuf[nBytelen] = 0x00;
|
||||||
|
return nBytelen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 字符数组转字符串16进制
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="InBytes"> 二进制字节 </param>
|
||||||
|
/// <returns>类似"01 02 0F" </returns>
|
||||||
|
public static string ByteToString(byte[] InBytes)
|
||||||
|
{
|
||||||
|
var StringOut = "";
|
||||||
|
foreach (var InByte in InBytes)
|
||||||
|
{
|
||||||
|
StringOut = StringOut + string.Format("{0:X2}", InByte) + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringOut.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// strhex 转字节数组
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="InString">类似"01 02 0F" 用空格分开的 </param>
|
||||||
|
/// <returns> </returns>
|
||||||
|
public static byte[] StringToByte(string InString)
|
||||||
|
{
|
||||||
|
string[] ByteStrings;
|
||||||
|
ByteStrings = InString.Split(" ".ToCharArray());
|
||||||
|
byte[] ByteOut;
|
||||||
|
ByteOut = new byte[ByteStrings.Length];
|
||||||
|
for (var i = 0; i <= ByteStrings.Length - 1; i++)
|
||||||
|
{
|
||||||
|
ByteOut[i] = byte.Parse(ByteStrings[i], NumberStyles.HexNumber);
|
||||||
|
}
|
||||||
|
return ByteOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// strhex 转字节数组
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="InString">类似"01 02 0F" 中间无空格 </param>
|
||||||
|
/// <returns> </returns>
|
||||||
|
public static byte[] StringToByte_2(string InString)
|
||||||
|
{
|
||||||
|
byte[] ByteOut;
|
||||||
|
InString = InString.Replace(" ", "");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var ByteStrings = new string[InString.Length/2];
|
||||||
|
var j = 0;
|
||||||
|
for (var i = 0; i < ByteStrings.Length; i++)
|
||||||
|
{
|
||||||
|
ByteStrings[i] = InString.Substring(j, 2);
|
||||||
|
j += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteOut = new byte[ByteStrings.Length];
|
||||||
|
for (var i = 0; i <= ByteStrings.Length - 1; i++)
|
||||||
|
{
|
||||||
|
ByteOut[i] = byte.Parse(ByteStrings[i], NumberStyles.HexNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ByteOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 字符串 转16进制字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="InString">unico </param>
|
||||||
|
/// <returns>类似“01 0f” </returns>
|
||||||
|
public static string Str_To_0X(string InString)
|
||||||
|
{
|
||||||
|
return ByteToString(Encoding.Default.GetBytes(InString));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 虚方法,可供子类重写
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing"></param>
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!m_disposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
// Release managed resources
|
||||||
|
}
|
||||||
|
// Release unmanaged resources
|
||||||
|
if (_serialPort1 != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_serialPort1.Close();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
_serialPort1.Dispose();
|
||||||
|
_serialPort1 = null;
|
||||||
|
}
|
||||||
|
m_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 析构函数
|
||||||
|
/// 当客户端没有显示调用Dispose()时由GC完成资源回收功能
|
||||||
|
/// </summary>
|
||||||
|
~ComConnector()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 发送接收数据
|
#region 发送接收数据
|
||||||
@@ -111,10 +329,9 @@ namespace Modbus.Net
|
|||||||
|
|
||||||
public void SendMsg(string senStr)
|
public void SendMsg(string senStr)
|
||||||
{
|
{
|
||||||
byte[] myByte = StringToByte_2(senStr);
|
var myByte = StringToByte_2(senStr);
|
||||||
|
|
||||||
SendMsg(myByte);
|
SendMsg(myByte);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task<bool> SendMsgWithoutReturnAsync(byte[] message)
|
public override Task<bool> SendMsgWithoutReturnAsync(byte[] message)
|
||||||
@@ -164,18 +381,16 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ReadMsgStr()
|
public string ReadMsgStr()
|
||||||
{
|
{
|
||||||
string rd = "";
|
var rd = "";
|
||||||
|
|
||||||
byte[] data = ReadMsg();
|
var data = ReadMsg();
|
||||||
|
|
||||||
rd = ByteToString(data);
|
rd = ByteToString(data);
|
||||||
return rd;
|
return rd;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ReadMsg()
|
public byte[] ReadMsg()
|
||||||
@@ -189,8 +404,8 @@ namespace Modbus.Net
|
|||||||
|
|
||||||
byte[] data;
|
byte[] data;
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
int i = ReadComm(out data, 10, 5000, 1000);
|
var i = ReadComm(out data, 10, 5000, 1000);
|
||||||
byte[] returndata = new byte[i];
|
var returndata = new byte[i];
|
||||||
Array.Copy(data, 0, returndata, 0, i);
|
Array.Copy(data, 0, returndata, 0, i);
|
||||||
return returndata;
|
return returndata;
|
||||||
}
|
}
|
||||||
@@ -202,221 +417,5 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 串口读(非阻塞方式读串口,直到串口缓冲区中没有数据
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="readBuf">串口数据缓冲 </param>
|
|
||||||
/// <param name="bufRoom">串口数据缓冲空间大小 </param>
|
|
||||||
/// <param name="HowTime">设置串口读放弃时间 </param>
|
|
||||||
/// <param name="ByteTime">字节间隔最大时间 </param>
|
|
||||||
/// <returns>串口实际读入数据个数 </returns>
|
|
||||||
public int ReadComm(out Byte[] readBuf, int bufRoom, int HowTime, int ByteTime)
|
|
||||||
{
|
|
||||||
//throw new System.NotImplementedException();
|
|
||||||
readBuf = new Byte[1023];
|
|
||||||
Array.Clear(readBuf, 0, readBuf.Length);
|
|
||||||
|
|
||||||
int nReadLen, nBytelen;
|
|
||||||
if (SerialPort1.IsOpen == false)
|
|
||||||
return -1;
|
|
||||||
nBytelen = 0;
|
|
||||||
SerialPort1.ReadTimeout = HowTime;
|
|
||||||
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (SerialPort1.BytesToRead > 0)
|
|
||||||
{
|
|
||||||
readBuf[nBytelen] = (byte) SerialPort1.ReadByte();
|
|
||||||
byte[] bTmp = new byte[bufRoom];
|
|
||||||
Array.Clear(bTmp, 0, bTmp.Length);
|
|
||||||
|
|
||||||
nReadLen = ReadBlock(bTmp, bufRoom, ByteTime);
|
|
||||||
|
|
||||||
if (nReadLen > 0)
|
|
||||||
{
|
|
||||||
Array.Copy(bTmp, 0, readBuf, nBytelen + 1, nReadLen);
|
|
||||||
nBytelen += 1 + nReadLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (nReadLen == 0)
|
|
||||||
nBytelen += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception(ex.Message);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return nBytelen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 串口同步读(阻塞方式读串口,直到串口缓冲区中没有数据,靠字符间间隔超时确定没有数据)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ReadBuf">串口数据缓冲 </param>
|
|
||||||
/// <param name="ReadRoom">串口数据缓冲空间大小 </param>
|
|
||||||
/// <param name="ByteTime">字节间隔最大时间 </param>
|
|
||||||
/// <returns>从串口实际读入的字节个数 </returns>
|
|
||||||
public int ReadBlock(byte[] ReadBuf, int ReadRoom, int ByteTime)
|
|
||||||
{
|
|
||||||
sbyte nBytelen;
|
|
||||||
//long nByteRead;
|
|
||||||
|
|
||||||
if (SerialPort1.IsOpen == false)
|
|
||||||
return 0;
|
|
||||||
nBytelen = 0;
|
|
||||||
SerialPort1.ReadTimeout = ByteTime;
|
|
||||||
|
|
||||||
while (nBytelen < ReadRoom - 1 && SerialPort1.BytesToRead > 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ReadBuf[nBytelen] = (byte) SerialPort1.ReadByte();
|
|
||||||
nBytelen++; // add one
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ReadBuf[nBytelen] = 0x00;
|
|
||||||
return nBytelen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 字符数组转字符串16进制
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="InBytes"> 二进制字节 </param>
|
|
||||||
/// <returns>类似"01 02 0F" </returns>
|
|
||||||
public static string ByteToString(byte[] InBytes)
|
|
||||||
{
|
|
||||||
string StringOut = "";
|
|
||||||
foreach (byte InByte in InBytes)
|
|
||||||
{
|
|
||||||
StringOut = StringOut + String.Format("{0:X2}", InByte) + " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
return StringOut.Trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// strhex 转字节数组
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="InString">类似"01 02 0F" 用空格分开的 </param>
|
|
||||||
/// <returns> </returns>
|
|
||||||
public static byte[] StringToByte(string InString)
|
|
||||||
{
|
|
||||||
string[] ByteStrings;
|
|
||||||
ByteStrings = InString.Split(" ".ToCharArray());
|
|
||||||
byte[] ByteOut;
|
|
||||||
ByteOut = new byte[ByteStrings.Length];
|
|
||||||
for (int i = 0; i <= ByteStrings.Length - 1; i++)
|
|
||||||
{
|
|
||||||
ByteOut[i] = byte.Parse(ByteStrings[i], System.Globalization.NumberStyles.HexNumber);
|
|
||||||
}
|
|
||||||
return ByteOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// strhex 转字节数组
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="InString">类似"01 02 0F" 中间无空格 </param>
|
|
||||||
/// <returns> </returns>
|
|
||||||
public static byte[] StringToByte_2(string InString)
|
|
||||||
{
|
|
||||||
byte[] ByteOut;
|
|
||||||
InString = InString.Replace(" ", "");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string[] ByteStrings = new string[InString.Length/2];
|
|
||||||
int j = 0;
|
|
||||||
for (int i = 0; i < ByteStrings.Length; i++)
|
|
||||||
{
|
|
||||||
|
|
||||||
ByteStrings[i] = InString.Substring(j, 2);
|
|
||||||
j += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteOut = new byte[ByteStrings.Length];
|
|
||||||
for (int i = 0; i <= ByteStrings.Length - 1; i++)
|
|
||||||
{
|
|
||||||
ByteOut[i] = byte.Parse(ByteStrings[i], System.Globalization.NumberStyles.HexNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
|
|
||||||
throw new Exception(ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ByteOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 字符串 转16进制字符串
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="InString">unico </param>
|
|
||||||
/// <returns>类似“01 0f” </returns>
|
|
||||||
public static string Str_To_0X(string InString)
|
|
||||||
{
|
|
||||||
return ByteToString(UnicodeEncoding.Default.GetBytes(InString));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 实现IDisposable接口
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
//.NET Framework 类库
|
|
||||||
// GC..::.SuppressFinalize 方法
|
|
||||||
//请求系统不要调用指定对象的终结器。
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool m_disposed = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 虚方法,可供子类重写
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing"></param>
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (!m_disposed)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
// Release managed resources
|
|
||||||
}
|
|
||||||
// Release unmanaged resources
|
|
||||||
if (_serialPort1 != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_serialPort1.Close();
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
//ignore
|
|
||||||
}
|
|
||||||
_serialPort1.Dispose();
|
|
||||||
_serialPort1 = null;
|
|
||||||
}
|
|
||||||
m_disposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 析构函数
|
|
||||||
/// 当客户端没有显示调用Dispose()时由GC完成资源回收功能
|
|
||||||
/// </summary>
|
|
||||||
~ComConnector()
|
|
||||||
{
|
|
||||||
Dispose(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,21 @@
|
|||||||
using System;
|
using System.IO.Ports;
|
||||||
using System.IO.Ports;
|
|
||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 串口连接对象
|
||||||
|
/// </summary>
|
||||||
public abstract class ComProtocalLinker : ProtocalLinker
|
public abstract class ComProtocalLinker : ProtocalLinker
|
||||||
{
|
{
|
||||||
protected ComProtocalLinker(int baudRate, Parity parity, StopBits stopBits, int dataBits) : this(ConfigurationManager.COM, baudRate, parity, stopBits, dataBits)
|
protected ComProtocalLinker(int baudRate, Parity parity, StopBits stopBits, int dataBits)
|
||||||
|
: this(ConfigurationManager.COM, baudRate, parity, stopBits, dataBits)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ComProtocalLinker(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits)
|
protected ComProtocalLinker(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits)
|
||||||
{
|
{
|
||||||
//初始化连对象
|
//初始化连对象
|
||||||
_baseConnector = new ComConnector(com, baudRate, parity, stopBits, dataBits, 30000);
|
BaseConnector = new ComConnector(com, baudRate, parity, stopBits, dataBits, 30000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,26 @@
|
|||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议转换的接口
|
/// 协议转换的接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IProtocalFormatting
|
public interface IProtocalFormatting
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从输入结构格式化
|
/// 从输入结构格式化
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">结构化的输入数据</param>
|
/// <param name="message">结构化的输入数据</param>
|
||||||
/// <returns>格式化后的字节流</returns>
|
/// <returns>格式化后的字节流</returns>
|
||||||
byte[] Format(InputStruct message);
|
byte[] Format(InputStruct message);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从对象的参数数组格式化
|
/// 从对象的参数数组格式化
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">非结构化的输入数据</param>
|
/// <param name="message">非结构化的输入数据</param>
|
||||||
/// <returns>格式化后的字节流</returns>
|
/// <returns>格式化后的字节流</returns>
|
||||||
byte[] Format(params object[] message);
|
byte[] Format(params object[] message);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 把仪器返回的内容填充到输出结构中
|
/// 把仪器返回的内容填充到输出结构中
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="messageBytes">返回数据的字节流</param>
|
/// <param name="messageBytes">返回数据的字节流</param>
|
||||||
/// <param name="pos">转换标记位</param>
|
/// <param name="pos">转换标记位</param>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
<Compile Include="AddressCombiner.cs" />
|
<Compile Include="AddressCombiner.cs" />
|
||||||
<Compile Include="AddressFormater.cs" />
|
<Compile Include="AddressFormater.cs" />
|
||||||
<Compile Include="AddressTranslator.cs" />
|
<Compile Include="AddressTranslator.cs" />
|
||||||
|
<Compile Include="AddressHelper.cs" />
|
||||||
<Compile Include="AsyncHelper.cs" />
|
<Compile Include="AsyncHelper.cs" />
|
||||||
<Compile Include="BaseMachineExtend.cs" />
|
<Compile Include="BaseMachineExtend.cs" />
|
||||||
<Compile Include="BaseProtocal.cs" />
|
<Compile Include="BaseProtocal.cs" />
|
||||||
|
|||||||
@@ -1,52 +1,51 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基本的协议连接器
|
/// 基本的协议连接器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ProtocalLinker
|
public abstract class ProtocalLinker
|
||||||
{
|
{
|
||||||
protected BaseConnector _baseConnector;
|
protected BaseConnector BaseConnector;
|
||||||
|
|
||||||
public string ConnectionToken => _baseConnector.ConnectionToken;
|
public string ConnectionToken => BaseConnector.ConnectionToken;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设备是否连接
|
/// 设备是否连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsConnected => _baseConnector != null && _baseConnector.IsConnected;
|
public bool IsConnected => BaseConnector != null && BaseConnector.IsConnected;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 连接设备
|
/// 连接设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>设备是否连接成功</returns>
|
/// <returns>设备是否连接成功</returns>
|
||||||
public bool Connect()
|
public bool Connect()
|
||||||
{
|
{
|
||||||
return _baseConnector.Connect();
|
return BaseConnector.Connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 连接设备
|
/// 连接设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>设备是否连接成功</returns>
|
/// <returns>设备是否连接成功</returns>
|
||||||
public async Task<bool> ConnectAsync()
|
public async Task<bool> ConnectAsync()
|
||||||
{
|
{
|
||||||
return await _baseConnector.ConnectAsync();
|
return await BaseConnector.ConnectAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 断开设备
|
/// 断开设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>设备是否断开成功</returns>
|
/// <returns>设备是否断开成功</returns>
|
||||||
public bool Disconnect()
|
public bool Disconnect()
|
||||||
{
|
{
|
||||||
return _baseConnector.Disconnect();
|
return BaseConnector.Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送并接收数据
|
/// 发送并接收数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">发送协议的内容</param>
|
/// <param name="content">发送协议的内容</param>
|
||||||
/// <returns>接收协议的内容</returns>
|
/// <returns>接收协议的内容</returns>
|
||||||
@@ -56,19 +55,19 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送并接收数据
|
/// 发送并接收数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">发送协议的内容</param>
|
/// <param name="content">发送协议的内容</param>
|
||||||
/// <returns>接收协议的内容</returns>
|
/// <returns>接收协议的内容</returns>
|
||||||
public virtual async Task<byte[]> SendReceiveAsync(byte[] content)
|
public virtual async Task<byte[]> SendReceiveAsync(byte[] content)
|
||||||
{
|
{
|
||||||
byte[] extBytes = BytesExtend(content);
|
var extBytes = BytesExtend(content);
|
||||||
byte[] receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes);
|
var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes);
|
||||||
return receiveBytes == null ? null : receiveBytes.Length == 0 ? receiveBytes : BytesDecact(receiveBytes);
|
return receiveBytes == null ? null : receiveBytes.Length == 0 ? receiveBytes : BytesDecact(receiveBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送并接收数据,不进行协议扩展和收缩,用于特殊协议
|
/// 发送并接收数据,不进行协议扩展和收缩,用于特殊协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">发送协议的内容</param>
|
/// <param name="content">发送协议的内容</param>
|
||||||
/// <returns>接收协议的内容</returns>
|
/// <returns>接收协议的内容</returns>
|
||||||
@@ -78,14 +77,14 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送并接收数据,不进行协议扩展和收缩,用于特殊协议
|
/// 发送并接收数据,不进行协议扩展和收缩,用于特殊协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">发送协议的内容</param>
|
/// <param name="content">发送协议的内容</param>
|
||||||
/// <returns>接收协议的内容</returns>
|
/// <returns>接收协议的内容</returns>
|
||||||
public virtual async Task<byte[]> SendReceiveWithoutExtAndDecAsync(byte[] content)
|
public virtual async Task<byte[]> SendReceiveWithoutExtAndDecAsync(byte[] content)
|
||||||
{
|
{
|
||||||
//发送数据
|
//发送数据
|
||||||
byte[] receiveBytes = await _baseConnector.SendMsgAsync(content);
|
var receiveBytes = await BaseConnector.SendMsgAsync(content);
|
||||||
//容错处理
|
//容错处理
|
||||||
var checkRight = CheckRight(receiveBytes);
|
var checkRight = CheckRight(receiveBytes);
|
||||||
return checkRight == null ? new byte[0] : (!checkRight.Value ? null : receiveBytes);
|
return checkRight == null ? new byte[0] : (!checkRight.Value ? null : receiveBytes);
|
||||||
@@ -93,7 +92,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检查接收的数据是否正确
|
/// 检查接收的数据是否正确
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">接收协议的内容</param>
|
/// <param name="content">接收协议的内容</param>
|
||||||
/// <returns>协议是否是正确的</returns>
|
/// <returns>协议是否是正确的</returns>
|
||||||
@@ -105,29 +104,29 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议内容扩展,发送时根据需要扩展
|
/// 协议内容扩展,发送时根据需要扩展
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">扩展前的基本协议内容</param>
|
/// <param name="content">扩展前的基本协议内容</param>
|
||||||
/// <returns>扩展后的协议内容</returns>
|
/// <returns>扩展后的协议内容</returns>
|
||||||
public byte[] BytesExtend(byte[] content)
|
public byte[] BytesExtend(byte[] content)
|
||||||
{
|
{
|
||||||
//自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
|
//自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
|
||||||
ProtocalLinkerBytesExtend bytesExtend =
|
var bytesExtend =
|
||||||
Assembly.Load(this.GetType().Assembly.FullName).CreateInstance(this.GetType().FullName + "BytesExtend") as
|
Assembly.Load(GetType().Assembly.FullName).CreateInstance(GetType().FullName + "BytesExtend") as
|
||||||
ProtocalLinkerBytesExtend;
|
ProtocalLinkerBytesExtend;
|
||||||
return bytesExtend?.BytesExtend(content);
|
return bytesExtend?.BytesExtend(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议内容缩减,接收时根据需要缩减
|
/// 协议内容缩减,接收时根据需要缩减
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">缩减前的完整协议内容</param>
|
/// <param name="content">缩减前的完整协议内容</param>
|
||||||
/// <returns>缩减后的协议内容</returns>
|
/// <returns>缩减后的协议内容</returns>
|
||||||
public byte[] BytesDecact(byte[] content)
|
public byte[] BytesDecact(byte[] content)
|
||||||
{
|
{
|
||||||
//自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
|
//自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
|
||||||
ProtocalLinkerBytesExtend bytesExtend =
|
var bytesExtend =
|
||||||
Assembly.Load(this.GetType().Assembly.GetName().Name).CreateInstance(this.GetType().FullName + "BytesExtend") as
|
Assembly.Load(GetType().Assembly.GetName().Name).CreateInstance(GetType().FullName + "BytesExtend") as
|
||||||
ProtocalLinkerBytesExtend;
|
ProtocalLinkerBytesExtend;
|
||||||
return bytesExtend?.BytesDecact(content);
|
return bytesExtend?.BytesDecact(content);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
using System;
|
namespace Modbus.Net
|
||||||
|
|
||||||
namespace Modbus.Net
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议字节伸缩
|
/// 协议字节伸缩
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ProtocalLinkerBytesExtend
|
public abstract class ProtocalLinkerBytesExtend
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议扩展,协议内容发送前调用
|
/// 协议扩展,协议内容发送前调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">扩展前的原始协议内容</param>
|
/// <param name="content">扩展前的原始协议内容</param>
|
||||||
/// <returns>扩展后的协议内容</returns>
|
/// <returns>扩展后的协议内容</returns>
|
||||||
public abstract byte[] BytesExtend(byte[] content);
|
public abstract byte[] BytesExtend(byte[] content);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议收缩,协议内容接收后调用
|
/// 协议收缩,协议内容接收后调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">收缩前的完整协议内容</param>
|
/// <param name="content">收缩前的完整协议内容</param>
|
||||||
/// <returns>收缩后的协议内容</returns>
|
/// <returns>收缩后的协议内容</returns>
|
||||||
|
|||||||
@@ -2,19 +2,25 @@
|
|||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 协议单元
|
||||||
|
/// </summary>
|
||||||
public abstract class ProtocalUnit : IProtocalFormatting
|
public abstract class ProtocalUnit : IProtocalFormatting
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 是否为小端格式
|
||||||
|
/// </summary>
|
||||||
public bool IsLittleEndian { get; protected set; } = false;
|
public bool IsLittleEndian { get; protected set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从输入结构格式化
|
/// 从输入结构格式化
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">结构化的输入数据</param>
|
/// <param name="message">结构化的输入数据</param>
|
||||||
/// <returns>格式化后的字节流</returns>
|
/// <returns>格式化后的字节流</returns>
|
||||||
public abstract byte[] Format(InputStruct message);
|
public abstract byte[] Format(InputStruct message);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从对象的参数数组格式化
|
/// 从对象的参数数组格式化
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">非结构化的输入数据</param>
|
/// <param name="message">非结构化的输入数据</param>
|
||||||
/// <returns>格式化后的字节流</returns>
|
/// <returns>格式化后的字节流</returns>
|
||||||
@@ -24,7 +30,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 把仪器返回的内容填充到输出结构中
|
/// 把仪器返回的内容填充到输出结构中
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="messageBytes">返回数据的字节流</param>
|
/// <param name="messageBytes">返回数据的字节流</param>
|
||||||
/// <param name="pos">转换标记位</param>
|
/// <param name="pos">转换标记位</param>
|
||||||
@@ -32,7 +38,7 @@ namespace Modbus.Net
|
|||||||
public abstract OutputStruct Unformat(byte[] messageBytes, ref int pos);
|
public abstract OutputStruct Unformat(byte[] messageBytes, ref int pos);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转换静态方法,把对象数组转换为字节数组。
|
/// 转换静态方法,把对象数组转换为字节数组。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="isLittleEndian">是否是小端格式</param>
|
/// <param name="isLittleEndian">是否是小端格式</param>
|
||||||
/// <param name="contents">对象数组</param>
|
/// <param name="contents">对象数组</param>
|
||||||
@@ -45,33 +51,35 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 特殊协议单元,继承这个类的协议不会执行BytesExtend和BytesDecact
|
||||||
|
/// </summary>
|
||||||
public abstract class SpecialProtocalUnit : ProtocalUnit
|
public abstract class SpecialProtocalUnit : ProtocalUnit
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 输入结构
|
/// 输入结构
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class InputStruct
|
public class InputStruct
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 输出结构
|
/// 输出结构
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OutputStruct
|
public class OutputStruct
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议错误
|
/// 协议错误
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ProtocalErrorException : Exception
|
public class ProtocalErrorException : Exception
|
||||||
{
|
{
|
||||||
public ProtocalErrorException(string message)
|
public ProtocalErrorException(string message)
|
||||||
: base(message)
|
: base(message)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,17 +380,17 @@ public class ReadDataModbusProtocal : ProtocalUnit
|
|||||||
public override byte[] Format(InputStruct message)
|
public override byte[] Format(InputStruct message)
|
||||||
{
|
{
|
||||||
var r_message = (ReadDataModbusInputStruct)message;
|
var r_message = (ReadDataModbusInputStruct)message;
|
||||||
return Format(r_message.BelongAddress, r_message.FunctionCode, r_message.StartAddress, r_message.GetCount);
|
return Format(r_message.SlaveAddress, r_message.FunctionCode, r_message.StartAddress, r_message.GetCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||||
{
|
{
|
||||||
byte belongAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
byte slaveAddress = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
byte functionCode = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
byte functionCode = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
byte dataCount = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
byte dataCount = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||||
byte[] dataValue = new byte[dataCount];
|
byte[] dataValue = new byte[dataCount];
|
||||||
Array.Copy(messageBytes, 3, dataValue, 0, dataCount);
|
Array.Copy(messageBytes, 3, dataValue, 0, dataCount);
|
||||||
return new ReadDataModbusOutputStruct(belongAddress, functionCode, dataCount, dataValue);
|
return new ReadDataModbusOutputStruct(slaveAddress, functionCode, dataCount, dataValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -453,14 +453,14 @@ Implement low level api for Modbus.
|
|||||||
You need to implement three functions.
|
You need to implement three functions.
|
||||||
```C#
|
```C#
|
||||||
public override void SetConnectionType(int connectionType)
|
public override void SetConnectionType(int connectionType)
|
||||||
protected override async Task<byte[]> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount)
|
protected override async Task<byte[]> GetDatasAsync(byte slaveAddress, byte masterAddress, string startAddress, int getByteCount)
|
||||||
public override async Task<bool> SetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, object[] setContents)
|
public override async Task<bool> SetDatasAsync(byte slaveAddress, byte masterAddress, string startAddress, object[] setContents)
|
||||||
public override bool GetLittleEndian
|
public override bool GetLittleEndian
|
||||||
public override bool SetLittleEndian
|
public override bool SetLittleEndian
|
||||||
```
|
```
|
||||||
And don't remember set default AddressTranslator, belongAddress, masterAddress and Protocal.
|
And don't remember set default AddressTranslator, slaveAddress, masterAddress and Protocal.
|
||||||
```C#
|
```C#
|
||||||
public ModbusUtility(int connectionType, byte belongAddress, byte masterAddress) : base(belongAddress, masterAddress)
|
public ModbusUtility(int connectionType, byte slaveAddress, byte masterAddress) : base(slaveAddress, masterAddress)
|
||||||
{
|
{
|
||||||
ConnectionString = null;
|
ConnectionString = null;
|
||||||
ModbusType = (ModbusType)connectionType;
|
ModbusType = (ModbusType)connectionType;
|
||||||
@@ -552,8 +552,8 @@ Remember subpos system cannot cross a byte in current version. If you want to cr
|
|||||||
|
|
||||||
###Version 1.2.2
|
###Version 1.2.2
|
||||||
* Address Utility (In Road)
|
* Address Utility (In Road)
|
||||||
* Move SlaveAddress parameter to GetData and SetData. (In Road)
|
* More functions in TaskManager (In Road)
|
||||||
* More functions in TaskManager. (In Road)
|
* More interfaces (In Road)
|
||||||
|
|
||||||
###Version 1.2.3
|
###Version 1.2.3
|
||||||
* OPC UA Support (In Road)
|
* OPC UA Support (In Road)
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
using System;
|
/*
|
||||||
|
* LimitedConcurrencyLevelTaskScheduler类来自于MSDN官方样例,Modbus.Net的作者不保留对这个类的版权。
|
||||||
|
* LimitedConcurrencyLevelTaskScheduler class comes from offical samples of MSDN, the author of "Modbus.Net" "donnot" obtain the copyright of LimitedConcurrencyLevelTaskScheduler(only).
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -6,18 +11,27 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Modbus.Net
|
namespace Modbus.Net
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 设备的读写方式
|
||||||
|
/// </summary>
|
||||||
public enum MachineDataType
|
public enum MachineDataType
|
||||||
{
|
{
|
||||||
Address,
|
Address,
|
||||||
CommunicationTag,
|
CommunicationTag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 返回结果的定义类
|
||||||
|
/// </summary>
|
||||||
public class TaskReturnDef
|
public class TaskReturnDef
|
||||||
{
|
{
|
||||||
public string MachineId { get; set; }
|
public string MachineId { get; set; }
|
||||||
public Dictionary<string, ReturnUnit> ReturnValues { get; set; }
|
public Dictionary<string, ReturnUnit> ReturnValues { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 时间定义
|
||||||
|
/// </summary>
|
||||||
public static class TimeRestore
|
public static class TimeRestore
|
||||||
{
|
{
|
||||||
public static int Restore = 0;
|
public static int Restore = 0;
|
||||||
@@ -26,29 +40,31 @@ namespace Modbus.Net
|
|||||||
public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
|
public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the current thread is processing work items.
|
/// Whether the current thread is processing work items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ThreadStatic]
|
[ThreadStatic] private static bool _currentThreadIsProcessingItems;
|
||||||
private static bool _currentThreadIsProcessingItems;
|
|
||||||
/// <summary>
|
|
||||||
/// The list of tasks to be executed.
|
|
||||||
/// </summary>
|
|
||||||
private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); // protected by lock(_tasks)
|
|
||||||
/// <summary>
|
|
||||||
/// The maximum concurrency level allowed by this scheduler.
|
|
||||||
/// </summary>
|
|
||||||
private readonly int _maxDegreeOfParallelism;
|
|
||||||
/// <summary>
|
|
||||||
/// Whether the scheduler is currently processing work items.
|
|
||||||
/// </summary>
|
|
||||||
private int _delegatesQueuedOrRunning = 0; // protected by lock(_tasks)
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the
|
/// The maximum concurrency level allowed by this scheduler.
|
||||||
/// specified degree of parallelism.
|
/// </summary>
|
||||||
|
private readonly int _maxDegreeOfParallelism;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of tasks to be executed.
|
||||||
|
/// </summary>
|
||||||
|
private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); // protected by lock(_tasks)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the scheduler is currently processing work items.
|
||||||
|
/// </summary>
|
||||||
|
private int _delegatesQueuedOrRunning; // protected by lock(_tasks)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the
|
||||||
|
/// specified degree of parallelism.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="maxDegreeOfParallelism">
|
/// <param name="maxDegreeOfParallelism">
|
||||||
/// The maximum degree of parallelism provided by this scheduler.
|
/// The maximum degree of parallelism provided by this scheduler.
|
||||||
/// </param>
|
/// </param>
|
||||||
public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
|
public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
|
||||||
{
|
{
|
||||||
@@ -57,10 +73,18 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queues a task to the scheduler.
|
/// Gets the maximum concurrency level supported by this scheduler.
|
||||||
|
/// </summary>
|
||||||
|
public sealed override int MaximumConcurrencyLevel
|
||||||
|
{
|
||||||
|
get { return _maxDegreeOfParallelism; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queues a task to the scheduler.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="task">
|
/// <param name="task">
|
||||||
/// The task to be queued.
|
/// The task to be queued.
|
||||||
/// </param>
|
/// </param>
|
||||||
protected sealed override void QueueTask(Task task)
|
protected sealed override void QueueTask(Task task)
|
||||||
{
|
{
|
||||||
@@ -78,7 +102,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Informs the ThreadPool that there's work to be executed for this scheduler.
|
/// Informs the ThreadPool that there's work to be executed for this scheduler.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void NotifyThreadPoolOfPendingWork()
|
private void NotifyThreadPoolOfPendingWork()
|
||||||
{
|
{
|
||||||
@@ -109,11 +133,14 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute the task we pulled out of the queue
|
// Execute the task we pulled out of the queue
|
||||||
base.TryExecuteTask(item);
|
TryExecuteTask(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We're done processing items on the current thread
|
// We're done processing items on the current thread
|
||||||
finally { _currentThreadIsProcessingItems = false; }
|
finally
|
||||||
|
{
|
||||||
|
_currentThreadIsProcessingItems = false;
|
||||||
|
}
|
||||||
}, null);
|
}, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,17 +157,17 @@ namespace Modbus.Net
|
|||||||
if (taskWasPreviouslyQueued) TryDequeue(task);
|
if (taskWasPreviouslyQueued) TryDequeue(task);
|
||||||
|
|
||||||
// Try to run the task.
|
// Try to run the task.
|
||||||
return base.TryExecuteTask(task);
|
return TryExecuteTask(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to remove a previously scheduled task from the scheduler.
|
/// Attempts to remove a previously scheduled task from the scheduler.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="task">
|
/// <param name="task">
|
||||||
/// The task to be removed.
|
/// The task to be removed.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// Whether the task could be found and removed.
|
/// Whether the task could be found and removed.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
protected sealed override bool TryDequeue(Task task)
|
protected sealed override bool TryDequeue(Task task)
|
||||||
{
|
{
|
||||||
@@ -148,19 +175,14 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the maximum concurrency level supported by this scheduler.
|
/// Gets an enumerable of the tasks currently scheduled on this scheduler.
|
||||||
/// </summary>
|
|
||||||
public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an enumerable of the tasks currently scheduled on this scheduler.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// An enumerable of the tasks currently scheduled.
|
/// An enumerable of the tasks currently scheduled.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
protected sealed override IEnumerable<Task> GetScheduledTasks()
|
protected sealed override IEnumerable<Task> GetScheduledTasks()
|
||||||
{
|
{
|
||||||
bool lockTaken = false;
|
var lockTaken = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Monitor.TryEnter(_tasks, ref lockTaken);
|
Monitor.TryEnter(_tasks, ref lockTaken);
|
||||||
@@ -177,34 +199,73 @@ namespace Modbus.Net
|
|||||||
public class TaskManager
|
public class TaskManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 正在运行的设备
|
/// 返回数据代理
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private HashSet<BaseMachine> _machines;
|
/// <param name="returnValue"></param>
|
||||||
/// <summary>
|
public delegate void ReturnValuesDelegate(TaskReturnDef returnValue);
|
||||||
/// 不在运行的设备
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
private HashSet<BaseMachine> _unlinkedMachines;
|
/// 正在运行的设备
|
||||||
|
/// </summary>
|
||||||
|
private readonly HashSet<BaseMachine> _machines;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 不在运行的设备
|
||||||
|
/// </summary>
|
||||||
|
private readonly HashSet<BaseMachine> _unlinkedMachines;
|
||||||
|
|
||||||
private TaskFactory _tasks;
|
|
||||||
private TaskScheduler _scheduler;
|
|
||||||
private CancellationTokenSource _cts;
|
private CancellationTokenSource _cts;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 正常读取的计时器
|
/// 获取间隔
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Timer _timer;
|
private int _getCycle;
|
||||||
/// <summary>
|
|
||||||
/// 重连计时器
|
|
||||||
/// </summary>
|
|
||||||
private Timer _timer2;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保持连接
|
/// 保持连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _keepConnect;
|
private bool _keepConnect;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保持连接
|
/// 任务调度
|
||||||
|
/// </summary>
|
||||||
|
private TaskScheduler _scheduler;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 任务工厂
|
||||||
|
/// </summary>
|
||||||
|
private TaskFactory _tasks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 正常读取的计时器
|
||||||
|
/// </summary>
|
||||||
|
private Timer _timer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重连计时器
|
||||||
|
/// </summary>
|
||||||
|
private Timer _timer2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造一个TaskManager
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="maxRunningTask">同时可以运行的任务数</param>
|
||||||
|
/// <param name="getCycle">读取数据的时间间隔(秒)</param>
|
||||||
|
/// <param name="keepConnect">读取数据后是否保持连接</param>
|
||||||
|
/// <param name="dataType">获取与设置数据的方式</param>
|
||||||
|
public TaskManager(int maxRunningTask, int getCycle, bool keepConnect,
|
||||||
|
MachineDataType dataType = MachineDataType.CommunicationTag)
|
||||||
|
{
|
||||||
|
_scheduler = new LimitedConcurrencyLevelTaskScheduler(maxRunningTask);
|
||||||
|
_machines = new HashSet<BaseMachine>(new BaseMachineEqualityComparer());
|
||||||
|
_unlinkedMachines = new HashSet<BaseMachine>(new BaseMachineEqualityComparer());
|
||||||
|
_getCycle = getCycle;
|
||||||
|
KeepConnect = keepConnect;
|
||||||
|
MachineDataType = dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保持连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool KeepConnect
|
public bool KeepConnect
|
||||||
{
|
{
|
||||||
@@ -224,23 +285,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 返回数据代理
|
/// 获取间隔,毫秒
|
||||||
/// </summary>
|
|
||||||
/// <param name="returnValue"></param>
|
|
||||||
public delegate void ReturnValuesDelegate(TaskReturnDef returnValue);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 返回数据事件
|
|
||||||
/// </summary>
|
|
||||||
public event ReturnValuesDelegate ReturnValues;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取间隔
|
|
||||||
/// </summary>
|
|
||||||
private int _getCycle;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取间隔,毫秒
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int GetCycle
|
public int GetCycle
|
||||||
{
|
{
|
||||||
@@ -278,7 +323,7 @@ namespace Modbus.Net
|
|||||||
_getCycle = value;
|
_getCycle = value;
|
||||||
}
|
}
|
||||||
_timer = new Timer(MaintainTasks, null, 0, _getCycle);
|
_timer = new Timer(MaintainTasks, null, 0, _getCycle);
|
||||||
_timer2 = new Timer(MaintainTasks2, null, _getCycle * 2, _getCycle * 2);
|
_timer2 = new Timer(MaintainTasks2, null, _getCycle*2, _getCycle*2);
|
||||||
//调试行,调试时请注释上面两行并取消下面一行的注释,每台设备只会执行一次数据获取。
|
//调试行,调试时请注释上面两行并取消下面一行的注释,每台设备只会执行一次数据获取。
|
||||||
//MaintainTasks(null);
|
//MaintainTasks(null);
|
||||||
}
|
}
|
||||||
@@ -291,10 +336,10 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
switch (value)
|
switch (value)
|
||||||
{
|
{
|
||||||
case MachineDataType.Address:
|
case MachineDataType.Address:
|
||||||
{
|
{
|
||||||
GetDataType = MachineGetDataType.Address;
|
GetDataType = MachineGetDataType.Address;
|
||||||
SetDataType=MachineSetDataType.Address;
|
SetDataType = MachineSetDataType.Address;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MachineDataType.CommunicationTag:
|
case MachineDataType.CommunicationTag:
|
||||||
@@ -310,6 +355,9 @@ namespace Modbus.Net
|
|||||||
public MachineGetDataType GetDataType { get; set; }
|
public MachineGetDataType GetDataType { get; set; }
|
||||||
public MachineSetDataType SetDataType { get; set; }
|
public MachineSetDataType SetDataType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大可执行任务数
|
||||||
|
/// </summary>
|
||||||
public int MaxRunningTasks
|
public int MaxRunningTasks
|
||||||
{
|
{
|
||||||
get { return _scheduler.MaximumConcurrencyLevel; }
|
get { return _scheduler.MaximumConcurrencyLevel; }
|
||||||
@@ -321,24 +369,12 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个TaskManager
|
/// 返回数据事件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="maxRunningTask">同时可以运行的任务数</param>
|
public event ReturnValuesDelegate ReturnValues;
|
||||||
/// <param name="getCycle">读取数据的时间间隔(秒)</param>
|
|
||||||
/// <param name="keepConnect">读取数据后是否保持连接</param>
|
|
||||||
/// <param name="dataType">获取与设置数据的方式</param>
|
|
||||||
public TaskManager(int maxRunningTask, int getCycle, bool keepConnect, MachineDataType dataType = MachineDataType.CommunicationTag)
|
|
||||||
{
|
|
||||||
_scheduler = new LimitedConcurrencyLevelTaskScheduler(maxRunningTask);
|
|
||||||
_machines = new HashSet<BaseMachine>(new BaseMachineEqualityComparer());
|
|
||||||
_unlinkedMachines = new HashSet<BaseMachine>(new BaseMachineEqualityComparer());
|
|
||||||
_getCycle = getCycle;
|
|
||||||
KeepConnect = keepConnect;
|
|
||||||
MachineDataType = dataType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加一台设备
|
/// 添加一台设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="machine">设备</param>
|
/// <param name="machine">设备</param>
|
||||||
public void AddMachine(BaseMachine machine)
|
public void AddMachine(BaseMachine machine)
|
||||||
@@ -351,7 +387,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加多台设备
|
/// 添加多台设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="machines">设备的列表</param>
|
/// <param name="machines">设备的列表</param>
|
||||||
public void AddMachines(IEnumerable<BaseMachine> machines)
|
public void AddMachines(IEnumerable<BaseMachine> machines)
|
||||||
@@ -366,7 +402,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据设备的连接地址移除设备
|
/// 根据设备的连接地址移除设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="machineToken">设备的连接地址</param>
|
/// <param name="machineToken">设备的连接地址</param>
|
||||||
public void RemoveMachineWithToken(string machineToken)
|
public void RemoveMachineWithToken(string machineToken)
|
||||||
@@ -382,7 +418,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据设备的id移除设备
|
/// 根据设备的id移除设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">设备的id</param>
|
/// <param name="id">设备的id</param>
|
||||||
public void RemoveMachineWithId(string id)
|
public void RemoveMachineWithId(string id)
|
||||||
@@ -398,21 +434,21 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 将设备指定为未连接
|
/// 将设备指定为未连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">设备的id</param>
|
/// <param name="id">设备的id</param>
|
||||||
public void MoveMachineToUnlinked(string id)
|
public void MoveMachineToUnlinked(string id)
|
||||||
{
|
{
|
||||||
IEnumerable<BaseMachine> machines;
|
IEnumerable<BaseMachine> machines;
|
||||||
lock(_machines)
|
lock (_machines)
|
||||||
{
|
{
|
||||||
machines = _machines.Where(c => c.Id == id).ToList();
|
machines = _machines.Where(c => c.Id == id).ToList();
|
||||||
if (!machines.Any()) return;
|
if (!machines.Any()) return;
|
||||||
_machines.RemoveWhere(p => p.Id == id);
|
_machines.RemoveWhere(p => p.Id == id);
|
||||||
}
|
}
|
||||||
lock(_unlinkedMachines)
|
lock (_unlinkedMachines)
|
||||||
{
|
{
|
||||||
foreach(var machine in machines)
|
foreach (var machine in machines)
|
||||||
{
|
{
|
||||||
_unlinkedMachines.Add(machine);
|
_unlinkedMachines.Add(machine);
|
||||||
}
|
}
|
||||||
@@ -420,7 +456,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 将设备指定为已连接
|
/// 将设备指定为已连接
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">设备的id</param>
|
/// <param name="id">设备的id</param>
|
||||||
public void MoveMachineToLinked(string id)
|
public void MoveMachineToLinked(string id)
|
||||||
@@ -442,7 +478,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 移除设备
|
/// 移除设备
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="machine">设备的实例</param>
|
/// <param name="machine">设备的实例</param>
|
||||||
public void RemoveMachine(BaseMachine machine)
|
public void RemoveMachine(BaseMachine machine)
|
||||||
@@ -458,7 +494,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已连接设备更新
|
/// 已连接设备更新
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender"></param>
|
/// <param name="sender"></param>
|
||||||
private void MaintainTasks(object sender)
|
private void MaintainTasks(object sender)
|
||||||
@@ -467,7 +503,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 未连接设备更新
|
/// 未连接设备更新
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender"></param>
|
/// <param name="sender"></param>
|
||||||
private void MaintainTasks2(object sender)
|
private void MaintainTasks2(object sender)
|
||||||
@@ -476,7 +512,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已连接设备更新
|
/// 已连接设备更新
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task MaintainTasksAsync()
|
private async Task MaintainTasksAsync()
|
||||||
@@ -484,7 +520,7 @@ namespace Modbus.Net
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tasks = new List<Task>();
|
var tasks = new List<Task>();
|
||||||
HashSet<BaseMachine> saveMachines = new HashSet<BaseMachine>();
|
var saveMachines = new HashSet<BaseMachine>();
|
||||||
IEnumerable<BaseMachine> saveMachinesEnum;
|
IEnumerable<BaseMachine> saveMachinesEnum;
|
||||||
lock (_machines)
|
lock (_machines)
|
||||||
{
|
{
|
||||||
@@ -493,21 +529,21 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
foreach (var machine in saveMachinesEnum)
|
foreach (var machine in saveMachinesEnum)
|
||||||
{
|
{
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
cts.CancelAfter(TimeSpan.FromSeconds(_getCycle * 10));
|
cts.CancelAfter(TimeSpan.FromSeconds(_getCycle*10));
|
||||||
var task = _tasks.StartNew(() => RunTask(machine).WithCancellation(cts.Token));
|
var task = _tasks.StartNew(() => RunTask(machine).WithCancellation(cts.Token));
|
||||||
tasks.Add(task);
|
tasks.Add(task);
|
||||||
}
|
}
|
||||||
await Task.WhenAll(tasks);
|
await Task.WhenAll(tasks);
|
||||||
}
|
}
|
||||||
catch
|
catch(Exception)
|
||||||
{
|
{
|
||||||
return;
|
//ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 未连接设备更新
|
/// 未连接设备更新
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task MaintainTasks2Async()
|
private async Task MaintainTasks2Async()
|
||||||
@@ -515,28 +551,28 @@ namespace Modbus.Net
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tasks = new List<Task>();
|
var tasks = new List<Task>();
|
||||||
HashSet<BaseMachine> saveMachines = new HashSet<BaseMachine>();
|
var saveMachines = new HashSet<BaseMachine>();
|
||||||
lock (_unlinkedMachines)
|
lock (_unlinkedMachines)
|
||||||
{
|
{
|
||||||
saveMachines.UnionWith(_unlinkedMachines);
|
saveMachines.UnionWith(_unlinkedMachines);
|
||||||
}
|
}
|
||||||
foreach (var machine in saveMachines)
|
foreach (var machine in saveMachines)
|
||||||
{
|
{
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
cts.CancelAfter(TimeSpan.FromSeconds(_getCycle * 10));
|
cts.CancelAfter(TimeSpan.FromSeconds(_getCycle*10));
|
||||||
var task = _tasks.StartNew(() => RunTask(machine).WithCancellation(cts.Token));
|
var task = _tasks.StartNew(() => RunTask(machine).WithCancellation(cts.Token));
|
||||||
tasks.Add(task);
|
tasks.Add(task);
|
||||||
}
|
}
|
||||||
await Task.WhenAll(tasks);
|
await Task.WhenAll(tasks);
|
||||||
}
|
}
|
||||||
catch
|
catch(Exception)
|
||||||
{
|
{
|
||||||
return;
|
//ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置数据
|
/// 设置数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connectionToken">设备的连接标识</param>
|
/// <param name="connectionToken">设备的连接标识</param>
|
||||||
/// <param name="values">需要设置的数据</param>
|
/// <param name="values">需要设置的数据</param>
|
||||||
@@ -554,7 +590,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 启动TaskManager
|
/// 启动TaskManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void TaskStart()
|
public void TaskStart()
|
||||||
{
|
{
|
||||||
@@ -565,17 +601,14 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 停止TaskManager
|
/// 停止TaskManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void TaskStop()
|
public void TaskStop()
|
||||||
{
|
{
|
||||||
lock (_machines)
|
lock (_machines)
|
||||||
{
|
{
|
||||||
GetCycle = Timeout.Infinite;
|
GetCycle = Timeout.Infinite;
|
||||||
if (_cts != null)
|
_cts?.Cancel();
|
||||||
{
|
|
||||||
_cts.Cancel();
|
|
||||||
}
|
|
||||||
if (_machines != null)
|
if (_machines != null)
|
||||||
{
|
{
|
||||||
foreach (var machine in _machines)
|
foreach (var machine in _machines)
|
||||||
@@ -588,7 +621,7 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行对具体设备的数据更新
|
/// 执行对具体设备的数据更新
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="machine">设备的实例</param>
|
/// <param name="machine">设备的实例</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@@ -599,7 +632,7 @@ namespace Modbus.Net
|
|||||||
//调试代码,调试时取消下面一下代码的注释,会同步调用获取数据。
|
//调试代码,调试时取消下面一下代码的注释,会同步调用获取数据。
|
||||||
//var ans = machine.GetDatas();
|
//var ans = machine.GetDatas();
|
||||||
//设置Cancellation Token
|
//设置Cancellation Token
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
//超时后取消任务
|
//超时后取消任务
|
||||||
cts.CancelAfter(TimeSpan.FromSeconds(_getCycle));
|
cts.CancelAfter(TimeSpan.FromSeconds(_getCycle));
|
||||||
//读取数据
|
//读取数据
|
||||||
@@ -612,7 +645,7 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
MoveMachineToLinked(machine.Id);
|
MoveMachineToLinked(machine.Id);
|
||||||
}
|
}
|
||||||
ReturnValues?.Invoke(new TaskReturnDef()
|
ReturnValues?.Invoke(new TaskReturnDef
|
||||||
{
|
{
|
||||||
MachineId = machine.Id,
|
MachineId = machine.Id,
|
||||||
ReturnValues = ans
|
ReturnValues = ans
|
||||||
@@ -624,7 +657,7 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
MoveMachineToUnlinked(machine.Id);
|
MoveMachineToUnlinked(machine.Id);
|
||||||
}
|
}
|
||||||
ReturnValues?.Invoke(new TaskReturnDef()
|
ReturnValues?.Invoke(new TaskReturnDef
|
||||||
{
|
{
|
||||||
MachineId = machine.Id,
|
MachineId = machine.Id,
|
||||||
ReturnValues = null
|
ReturnValues = null
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -25,21 +24,30 @@ namespace Modbus.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class TcpConnector : BaseConnector, IDisposable
|
public class TcpConnector : BaseConnector, IDisposable
|
||||||
{
|
{
|
||||||
public override string ConnectionToken => _host;
|
|
||||||
|
|
||||||
private readonly string _host;
|
private readonly string _host;
|
||||||
|
private readonly int _port;
|
||||||
private int _sendCount;
|
|
||||||
private int _receiveCount;
|
|
||||||
private int _errorCount;
|
|
||||||
|
|
||||||
// 2MB 的接收缓冲区,目的是一次接收完服务器发回的消息
|
// 2MB 的接收缓冲区,目的是一次接收完服务器发回的消息
|
||||||
private readonly byte[] _receiveBuffer = new byte[1024];
|
private readonly byte[] _receiveBuffer = new byte[1024];
|
||||||
private readonly int _port;
|
private int _errorCount;
|
||||||
|
private int _receiveCount;
|
||||||
|
|
||||||
|
private int _sendCount;
|
||||||
private TcpClient _socketClient;
|
private TcpClient _socketClient;
|
||||||
|
|
||||||
private int _timeoutTime;
|
private int _timeoutTime;
|
||||||
|
|
||||||
|
private bool m_disposed;
|
||||||
|
|
||||||
|
public TcpConnector(string ipaddress, int port, int timeoutTime)
|
||||||
|
{
|
||||||
|
_host = ipaddress;
|
||||||
|
_port = port;
|
||||||
|
TimeoutTime = timeoutTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ConnectionToken => _host;
|
||||||
|
|
||||||
public int TimeoutTime
|
public int TimeoutTime
|
||||||
{
|
{
|
||||||
get { return _timeoutTime; }
|
get { return _timeoutTime; }
|
||||||
@@ -53,18 +61,11 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TcpConnector(string ipaddress, int port, int timeoutTime)
|
|
||||||
{
|
|
||||||
_host = ipaddress;
|
|
||||||
_port = port;
|
|
||||||
TimeoutTime = timeoutTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsConnected => _socketClient?.Client != null && _socketClient.Connected;
|
public override bool IsConnected => _socketClient?.Client != null && _socketClient.Connected;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 实现IDisposable接口
|
/// 实现IDisposable接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
@@ -74,10 +75,8 @@ namespace Modbus.Net
|
|||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool m_disposed = false;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 虚方法,可供子类重写
|
/// 虚方法,可供子类重写
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="disposing"></param>
|
/// <param name="disposing"></param>
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
@@ -99,8 +98,8 @@ namespace Modbus.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 析构函数
|
/// 析构函数
|
||||||
/// 当客户端没有显示调用Dispose()时由GC完成资源回收功能
|
/// 当客户端没有显示调用Dispose()时由GC完成资源回收功能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
~TcpConnector()
|
~TcpConnector()
|
||||||
{
|
{
|
||||||
@@ -118,37 +117,37 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
Disconnect();
|
Disconnect();
|
||||||
}
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_socketClient = new TcpClient
|
||||||
|
{
|
||||||
|
SendTimeout = TimeoutTime,
|
||||||
|
ReceiveTimeout = TimeoutTime
|
||||||
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_socketClient = new TcpClient
|
var cts = new CancellationTokenSource();
|
||||||
{
|
cts.CancelAfter(TimeoutTime);
|
||||||
SendTimeout = TimeoutTime,
|
await _socketClient.ConnectAsync(_host, _port).WithCancellation(cts.Token);
|
||||||
ReceiveTimeout = TimeoutTime
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
|
||||||
cts.CancelAfter(TimeoutTime);
|
|
||||||
await _socketClient.ConnectAsync(_host, _port).WithCancellation(cts.Token);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
AddInfo("client connected exception: " + e.Message);
|
|
||||||
}
|
|
||||||
if (_socketClient.Connected)
|
|
||||||
{
|
|
||||||
AddInfo("client connected.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
AddInfo("connect failed.");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
catch (Exception err)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
AddInfo("client connect exception: " + err.Message);
|
AddInfo("client connected exception: " + e.Message);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
if (_socketClient.Connected)
|
||||||
|
{
|
||||||
|
AddInfo("client connected.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
AddInfo("connect failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
AddInfo("client connect exception: " + err.Message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Disconnect()
|
public override bool Disconnect()
|
||||||
@@ -192,7 +191,7 @@ namespace Modbus.Net
|
|||||||
/// <returns>是否发送成功</returns>
|
/// <returns>是否发送成功</returns>
|
||||||
public override async Task<bool> SendMsgWithoutReturnAsync(byte[] message)
|
public override async Task<bool> SendMsgWithoutReturnAsync(byte[] message)
|
||||||
{
|
{
|
||||||
byte[] datagram = message;
|
var datagram = message;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -228,7 +227,7 @@ namespace Modbus.Net
|
|||||||
/// <returns>是否发送成功</returns>
|
/// <returns>是否发送成功</returns>
|
||||||
public override async Task<byte[]> SendMsgAsync(byte[] message)
|
public override async Task<byte[]> SendMsgAsync(byte[] message)
|
||||||
{
|
{
|
||||||
byte[] datagram = message;
|
var datagram = message;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -257,7 +256,7 @@ namespace Modbus.Net
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int len = await stream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length);
|
var len = await stream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length);
|
||||||
stream.Flush();
|
stream.Flush();
|
||||||
// 异步接收回答
|
// 异步接收回答
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
using System;
|
namespace Modbus.Net
|
||||||
|
|
||||||
namespace Modbus.Net
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tcp连接对象
|
/// Tcp连接对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class TcpProtocalLinker : ProtocalLinker
|
public abstract class TcpProtocalLinker : ProtocalLinker
|
||||||
{
|
{
|
||||||
|
|
||||||
protected TcpProtocalLinker() : this(ConfigurationManager.IP, int.Parse(ConfigurationManager.ModbusPort))
|
protected TcpProtocalLinker() : this(ConfigurationManager.IP, int.Parse(ConfigurationManager.ModbusPort))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TcpProtocalLinker(string ip, int port)
|
protected TcpProtocalLinker(string ip, int port)
|
||||||
{
|
{
|
||||||
_baseConnector = new TcpConnector(ip, port, int.Parse(ConfigurationManager.IPConnectionTimeout));
|
//初始化连接对象
|
||||||
|
BaseConnector = new TcpConnector(ip, port, int.Parse(ConfigurationManager.IPConnectionTimeout));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user