2017-02-06 update 1 Add AddressHelper and comments, reformat code.

This commit is contained in:
parallelbgls
2017-02-06 17:15:54 +08:00
parent f2ed8ac72b
commit 0d19567038
55 changed files with 2190 additions and 1821 deletions

View File

@@ -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
{ {

View File

@@ -1,8 +1,5 @@
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
{ {
@@ -11,8 +8,8 @@ namespace Modbus.Net.Modbus
/// </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)
}; };
} }
@@ -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)
}; };
} }

View File

@@ -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);
} }

View File

@@ -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)
{
}
} }
} }

View File

@@ -7,7 +7,7 @@ namespace Modbus.Net.Modbus
internal enum ModbusProtocalVariableFunctionCode : byte internal enum ModbusProtocalVariableFunctionCode : byte
{ {
ReadVariable = 20, ReadVariable = 20,
WriteVariable = 21, WriteVariable = 21
} }
/// <summary> /// <summary>
@@ -16,7 +16,7 @@ namespace Modbus.Net.Modbus
public enum ModbusProtocalTimeFunctionCode : byte public enum ModbusProtocalTimeFunctionCode : byte
{ {
GetSystemTime = 3, GetSystemTime = 3,
SetSystemTime = 16, SetSystemTime = 16
} }
/// <summary> /// <summary>
@@ -27,7 +27,7 @@ namespace Modbus.Net.Modbus
ReadCoilStatus = 1, ReadCoilStatus = 1,
ReadInputStatus = 2, ReadInputStatus = 2,
ReadHoldRegister = 3, ReadHoldRegister = 3,
ReadInputRegister = 4, ReadInputRegister = 4
} }
/// <summary> /// <summary>
@@ -36,11 +36,15 @@ namespace Modbus.Net.Modbus
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; }
@@ -181,28 +186,28 @@ namespace Modbus.Net.Modbus
{ {
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; }
@@ -257,24 +263,24 @@ namespace Modbus.Net.Modbus
{ {
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; }
@@ -352,8 +359,8 @@ namespace Modbus.Net.Modbus
{ {
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,13 +368,14 @@ 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>
@@ -375,8 +383,7 @@ namespace Modbus.Net.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; }
} }
} }

View File

@@ -13,9 +13,9 @@ namespace Modbus.Net.Modbus
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();
} }
} }

View File

@@ -5,11 +5,13 @@
/// </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);
} }

View File

@@ -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)
{
}
} }
} }

View File

@@ -5,16 +5,18 @@
/// </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);
} }

View File

@@ -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)
{
}
} }
} }

View File

@@ -1,5 +1,4 @@
using System; using System.Threading.Tasks;
using System.Threading.Tasks;
namespace Modbus.Net.Modbus namespace Modbus.Net.Modbus
{ {
@@ -12,20 +11,38 @@ namespace Modbus.Net.Modbus
/// 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,8 +118,8 @@ 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;
@@ -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;

View File

@@ -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;
} }

View File

@@ -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
{ {

View File

@@ -7,7 +7,6 @@ using Opc.Da;
namespace Modbus.Net.OPC namespace Modbus.Net.OPC
{ {
/// <summary> /// <summary>
/// Read value full result /// Read value full result
/// </summary> /// </summary>
@@ -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,
@@ -46,16 +51,14 @@ namespace Modbus.Net.OPC
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));
} }
} }
} }

View File

@@ -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};
} }

View File

@@ -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
{ {

View File

@@ -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)
{ {

View File

@@ -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)

View File

@@ -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)
{ {
} }
@@ -29,7 +26,8 @@ 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)
@@ -45,7 +43,8 @@ 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)

View File

@@ -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)

View File

@@ -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
{ {

View File

@@ -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)
}; };
} }

View File

@@ -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,13 +38,13 @@ 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)],
@@ -54,15 +52,15 @@ namespace Modbus.Net.Siemens
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;
} }
} }
} }

View File

@@ -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)
{
}
} }
} }

View File

@@ -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; }
} }
} }

View File

@@ -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;
} }

View File

@@ -89,3 +89,4 @@
} }
} }
*/ */

View File

@@ -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)

View File

@@ -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)
{
}
} }
} }

View File

@@ -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();
} }

View File

@@ -22,68 +22,94 @@ namespace Modbus.Net
/// </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);
} }
} }
} }

View File

@@ -1,6 +1,4 @@
using System; namespace Modbus.Net
namespace Modbus.Net
{ {
/// <summary> /// <summary>
/// 地址编码器 /// 地址编码器
@@ -8,6 +6,7 @@ namespace Modbus.Net
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>

View 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];
}
}
}

View File

@@ -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; }
@@ -30,6 +35,11 @@ namespace Modbus.Net
/// <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);
} }
@@ -40,13 +50,13 @@ namespace Modbus.Net
{ {
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
}; };
} }
} }

View File

@@ -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;
@@ -21,9 +26,9 @@ namespace Modbus.Net
/// <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();
} }
@@ -34,8 +39,8 @@ namespace Modbus.Net
/// <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();
@@ -65,8 +70,8 @@ namespace Modbus.Net
/// </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()
{ {
@@ -113,7 +118,7 @@ namespace Modbus.Net
/// </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,14 +140,11 @@ namespace Modbus.Net
_currentCount--; _currentCount--;
return _completed; return _completed;
} }
else
{
var waiter = new TaskCompletionSource<bool>(); var waiter = new TaskCompletionSource<bool>();
_waiters.Enqueue(waiter); _waiters.Enqueue(waiter);
return waiter.Task; return waiter.Task;
} }
} }
}
public void Release() public void Release()
{ {

View File

@@ -1,51 +1,61 @@
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>

View File

@@ -14,6 +14,7 @@ namespace Modbus.Net
/// 地址 /// 地址
/// </summary> /// </summary>
Address, Address,
/// <summary> /// <summary>
/// 通讯标识 /// 通讯标识
/// </summary> /// </summary>
@@ -29,6 +30,7 @@ namespace Modbus.Net
/// 地址 /// 地址
/// </summary> /// </summary>
Address, Address,
/// <summary> /// <summary>
/// 通讯标识 /// 通讯标识
/// </summary> /// </summary>
@@ -37,87 +39,7 @@ namespace Modbus.Net
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>
/// 设备的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>
/// 构造器 /// 构造器
@@ -146,23 +68,105 @@ namespace Modbus.Net
/// <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>
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> /// </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>
@@ -171,7 +175,7 @@ namespace Modbus.Net
{ {
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[
@@ -204,12 +209,17 @@ namespace Modbus.Net
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
@@ -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 + //字节坐标地址
var byteCount =
AddressHelper.MapProtocalGetCountToAbstractByteCount(
addressUnit.Address - communicateAddress.Address +
addressUnit.SubAddress*0.125/ addressUnit.SubAddress*0.125/
AddressTranslator.GetAreaByteLength(communicateAddress.Area)) * AddressTranslator.GetAreaByteLength(communicateAddress.Area),
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:
@@ -492,22 +514,27 @@ namespace Modbus.Net
/// 区域 /// 区域
/// </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>
@@ -519,7 +546,6 @@ namespace Modbus.Net
/// </summary> /// </summary>
public class UnitExtend public class UnitExtend
{ {
} }
/// <summary> /// <summary>
@@ -531,6 +557,7 @@ namespace Modbus.Net
/// 返回的数据 /// 返回的数据
/// </summary> /// </summary>
public double? PlcValue { get; set; } public double? PlcValue { get; set; }
/// <summary> /// <summary>
/// 数据的扩展 /// 数据的扩展
/// </summary> /// </summary>
@@ -543,52 +570,66 @@ namespace Modbus.Net
/// 数据单元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)
@@ -611,14 +652,17 @@ namespace Modbus.Net
/// 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>

View File

@@ -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);
} }
} }
} }

View File

@@ -10,7 +10,17 @@ namespace Modbus.Net
/// </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>
@@ -18,16 +28,6 @@ namespace Modbus.Net
/// </summary> /// </summary>
public ProtocalLinker ProtocalLinker { get; protected set; } public ProtocalLinker ProtocalLinker { get; protected set; }
/// <summary>
/// 构造器
/// </summary>
protected BaseProtocal(byte belongAddress, byte masterAddress)
{
Protocals = new Dictionary<string, ProtocalUnit>();
BelongAddress = belongAddress;
MasterAddress = masterAddress;
}
/// <summary> /// <summary>
/// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议 /// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议
/// </summary> /// </summary>
@@ -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];
@@ -93,11 +93,8 @@ 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>
/// 发送协议,通过传入需要使用的协议内容和输入结构 /// 发送协议,通过传入需要使用的协议内容和输入结构
@@ -118,7 +115,7 @@ namespace Modbus.Net
/// <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)
{ {

View File

@@ -11,15 +11,27 @@ namespace Modbus.Net
/// 协议收发主体 /// 协议收发主体
/// </summary> /// </summary>
protected BaseProtocal Wrapper; protected BaseProtocal Wrapper;
/// <summary>
/// 构造器
/// </summary>
protected BaseUtility(byte slaveAddress, byte masterAddress)
{
SlaveAddress = slaveAddress;
MasterAddress = masterAddress;
AddressTranslator = new AddressTranslatorBase();
}
protected string ConnectionString { get; set; } protected string ConnectionString { get; set; }
public byte BelongAddress { get; set; } public byte SlaveAddress { get; set; }
public byte MasterAddress { get; set; } public byte MasterAddress { get; set; }
/// <summary> /// <summary>
/// 获取协议是否遵循小端格式 /// 获取协议是否遵循小端格式
/// </summary> /// </summary>
public abstract bool GetLittleEndian { get; } public abstract bool GetLittleEndian { get; }
/// <summary> /// <summary>
/// 设置协议是否遵循小端格式 /// 设置协议是否遵循小端格式
/// </summary> /// </summary>
@@ -40,16 +52,6 @@ namespace Modbus.Net
/// </summary> /// </summary>
public AddressTranslator AddressTranslator { get; set; } public AddressTranslator AddressTranslator { get; set; }
/// <summary>
/// 构造器
/// </summary>
protected BaseUtility(byte belongAddress, byte masterAddress)
{
BelongAddress = belongAddress;
MasterAddress = masterAddress;
AddressTranslator = new AddressTranslatorBase();
}
/// <summary> /// <summary>
/// 设置连接类型 /// 设置连接类型
/// </summary> /// </summary>
@@ -78,8 +80,6 @@ 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>
@@ -92,8 +92,6 @@ 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)
@@ -121,8 +119,6 @@ namespace Modbus.Net
/// 获取数据 /// 获取数据
/// </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>
@@ -136,8 +132,6 @@ namespace Modbus.Net
/// 获取数据 /// 获取数据
/// </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)
@@ -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);
@@ -258,6 +252,5 @@ namespace Modbus.Net
{ {
return Wrapper.Disconnect(); return Wrapper.Disconnect();
} }
} }
} }

View File

@@ -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)
@@ -30,33 +35,33 @@ namespace Modbus.Net
/// <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
@@ -70,19 +75,16 @@ namespace Modbus.Net
/// <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
@@ -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;
} }
} }

View File

@@ -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);
}
} }
} }

View File

@@ -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);
} }
} }
} }

View File

@@ -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" />

View File

@@ -1,5 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Modbus.Net namespace Modbus.Net
@@ -9,14 +8,14 @@ namespace Modbus.Net
/// </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>
/// 连接设备 /// 连接设备
@@ -24,7 +23,7 @@ namespace Modbus.Net
/// <returns>设备是否连接成功</returns> /// <returns>设备是否连接成功</returns>
public bool Connect() public bool Connect()
{ {
return _baseConnector.Connect(); return BaseConnector.Connect();
} }
/// <summary> /// <summary>
@@ -33,7 +32,7 @@ namespace Modbus.Net
/// <returns>设备是否连接成功</returns> /// <returns>设备是否连接成功</returns>
public async Task<bool> ConnectAsync() public async Task<bool> ConnectAsync()
{ {
return await _baseConnector.ConnectAsync(); return await BaseConnector.ConnectAsync();
} }
/// <summary> /// <summary>
@@ -42,7 +41,7 @@ namespace Modbus.Net
/// <returns>设备是否断开成功</returns> /// <returns>设备是否断开成功</returns>
public bool Disconnect() public bool Disconnect()
{ {
return _baseConnector.Disconnect(); return BaseConnector.Disconnect();
} }
/// <summary> /// <summary>
@@ -62,8 +61,8 @@ namespace Modbus.Net
/// <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);
} }
@@ -85,7 +84,7 @@ namespace Modbus.Net
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);
@@ -112,8 +111,8 @@ namespace Modbus.Net
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);
} }
@@ -126,8 +125,8 @@ namespace Modbus.Net
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);
} }

View File

@@ -1,6 +1,4 @@
using System; namespace Modbus.Net
namespace Modbus.Net
{ {
/// <summary> /// <summary>
/// 协议字节伸缩 /// 协议字节伸缩

View File

@@ -2,8 +2,14 @@
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>
@@ -45,6 +51,9 @@ namespace Modbus.Net
} }
} }
/// <summary>
/// 特殊协议单元继承这个类的协议不会执行BytesExtend和BytesDecact
/// </summary>
public abstract class SpecialProtocalUnit : ProtocalUnit public abstract class SpecialProtocalUnit : ProtocalUnit
{ {
} }
@@ -71,7 +80,6 @@ namespace Modbus.Net
public ProtocalErrorException(string message) public ProtocalErrorException(string message)
: base(message) : base(message)
{ {
} }
} }
} }

View File

@@ -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)

View File

@@ -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;
@@ -28,20 +42,22 @@ namespace Modbus.Net
/// <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> /// <summary>
/// The maximum concurrency level allowed by this scheduler. /// The maximum concurrency level allowed by this scheduler.
/// </summary> /// </summary>
private readonly int _maxDegreeOfParallelism; 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> /// <summary>
/// Whether the scheduler is currently processing work items. /// Whether the scheduler is currently processing work items.
/// </summary> /// </summary>
private int _delegatesQueuedOrRunning = 0; // protected by lock(_tasks) private int _delegatesQueuedOrRunning; // protected by lock(_tasks)
/// <summary> /// <summary>
/// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the /// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the
@@ -56,6 +72,14 @@ namespace Modbus.Net
_maxDegreeOfParallelism = maxDegreeOfParallelism; _maxDegreeOfParallelism = maxDegreeOfParallelism;
} }
/// <summary>
/// Gets the maximum concurrency level supported by this scheduler.
/// </summary>
public sealed override int MaximumConcurrencyLevel
{
get { return _maxDegreeOfParallelism; }
}
/// <summary> /// <summary>
/// Queues a task to the scheduler. /// Queues a task to the scheduler.
/// </summary> /// </summary>
@@ -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,7 +157,7 @@ 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>
@@ -147,11 +174,6 @@ namespace Modbus.Net
lock (_tasks) return _tasks.Remove(task); lock (_tasks) return _tasks.Remove(task);
} }
/// <summary>
/// Gets the maximum concurrency level supported by this scheduler.
/// </summary>
public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } }
/// <summary> /// <summary>
/// Gets an enumerable of the tasks currently scheduled on this scheduler. /// Gets an enumerable of the tasks currently scheduled on this scheduler.
/// </summary> /// </summary>
@@ -160,7 +182,7 @@ namespace Modbus.Net
/// </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);
@@ -176,32 +198,71 @@ namespace Modbus.Net
public class TaskManager public class TaskManager
{ {
/// <summary>
/// 返回数据代理
/// </summary>
/// <param name="returnValue"></param>
public delegate void ReturnValuesDelegate(TaskReturnDef returnValue);
/// <summary> /// <summary>
/// 正在运行的设备 /// 正在运行的设备
/// </summary> /// </summary>
private HashSet<BaseMachine> _machines; private readonly HashSet<BaseMachine> _machines;
/// <summary> /// <summary>
/// 不在运行的设备 /// 不在运行的设备
/// </summary> /// </summary>
private HashSet<BaseMachine> _unlinkedMachines; private readonly HashSet<BaseMachine> _unlinkedMachines;
private TaskFactory _tasks;
private TaskScheduler _scheduler;
private CancellationTokenSource _cts; private CancellationTokenSource _cts;
/// <summary>
/// 获取间隔
/// </summary>
private int _getCycle;
/// <summary>
/// 保持连接
/// </summary>
private bool _keepConnect;
/// <summary>
/// 任务调度
/// </summary>
private TaskScheduler _scheduler;
/// <summary>
/// 任务工厂
/// </summary>
private TaskFactory _tasks;
/// <summary> /// <summary>
/// 正常读取的计时器 /// 正常读取的计时器
/// </summary> /// </summary>
private Timer _timer; private Timer _timer;
/// <summary> /// <summary>
/// 重连计时器 /// 重连计时器
/// </summary> /// </summary>
private Timer _timer2; private Timer _timer2;
/// <summary> /// <summary>
/// 保持连接 /// 构造一个TaskManager
/// </summary> /// </summary>
private bool _keepConnect; /// <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>
/// 保持连接 /// 保持连接
@@ -223,22 +284,6 @@ namespace Modbus.Net
} }
} }
/// <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> /// </summary>
@@ -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);
} }
@@ -294,7 +339,7 @@ namespace Modbus.Net
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,21 +369,9 @@ 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>
/// 添加一台设备 /// 添加一台设备
@@ -404,15 +440,15 @@ namespace Modbus.Net
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);
} }
@@ -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,16 +529,16 @@ 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
} }
} }
@@ -515,23 +551,23 @@ 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
} }
} }
@@ -572,10 +608,7 @@ namespace Modbus.Net
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)
@@ -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

View File

@@ -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,8 +75,6 @@ namespace Modbus.Net
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
private bool m_disposed = false;
/// <summary> /// <summary>
/// 虚方法,可供子类重写 /// 虚方法,可供子类重写
/// </summary> /// </summary>
@@ -128,7 +127,7 @@ namespace Modbus.Net
try try
{ {
CancellationTokenSource cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cts.CancelAfter(TimeoutTime); cts.CancelAfter(TimeoutTime);
await _socketClient.ConnectAsync(_host, _port).WithCancellation(cts.Token); await _socketClient.ConnectAsync(_host, _port).WithCancellation(cts.Token);
} }
@@ -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)

View File

@@ -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));
} }
} }
} }

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -9,11 +8,10 @@ namespace Modbus.Net
{ {
/// <summary> /// <summary>
/// 值与字节数组之间转换的辅助类这是一个Singleton类 /// 值与字节数组之间转换的辅助类这是一个Singleton类
/// 作者罗圣Chris L.
/// </summary> /// </summary>
public class ValueHelper public class ValueHelper
{ {
public Dictionary<string, double> ByteLength = new Dictionary<string, double>() public Dictionary<string, double> ByteLength = new Dictionary<string, double>
{ {
{"System.Boolean", 0.125}, {"System.Boolean", 0.125},
{"System.Byte", 1}, {"System.Byte", 1},
@@ -36,25 +34,12 @@ namespace Modbus.Net
/// </summary> /// </summary>
public static bool LittleEndian => true; public static bool LittleEndian => true;
#region Factory
private static ValueHelper _instance;
protected virtual ValueHelper _Instance => _instance;
/// <summary>
/// ValueHelper单例的实例
/// </summary>
public static ValueHelper Instance => _instance ?? (_instance = new ValueHelper());
#endregion
/// <summary> /// <summary>
/// 将一个byte数字转换为一个byte元素的数组。 /// 将一个byte数字转换为一个byte元素的数组。
/// </summary> /// </summary>
/// <param name="value">byte数字</param> /// <param name="value">byte数字</param>
/// <returns>byte数组</returns> /// <returns>byte数组</returns>
public Byte[] GetBytes(byte value) public byte[] GetBytes(byte value)
{ {
return new[] {value}; return new[] {value};
} }
@@ -64,7 +49,7 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public virtual Byte[] GetBytes(short value) public virtual byte[] GetBytes(short value)
{ {
return BitConverter.GetBytes(value); return BitConverter.GetBytes(value);
} }
@@ -74,7 +59,7 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public virtual Byte[] GetBytes(int value) public virtual byte[] GetBytes(int value)
{ {
return BitConverter.GetBytes(value); return BitConverter.GetBytes(value);
} }
@@ -84,7 +69,7 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public virtual Byte[] GetBytes(long value) public virtual byte[] GetBytes(long value)
{ {
return BitConverter.GetBytes(value); return BitConverter.GetBytes(value);
} }
@@ -94,7 +79,7 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public virtual Byte[] GetBytes(ushort value) public virtual byte[] GetBytes(ushort value)
{ {
return BitConverter.GetBytes(value); return BitConverter.GetBytes(value);
} }
@@ -104,7 +89,7 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public virtual Byte[] GetBytes(uint value) public virtual byte[] GetBytes(uint value)
{ {
return BitConverter.GetBytes(value); return BitConverter.GetBytes(value);
} }
@@ -114,7 +99,7 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public virtual Byte[] GetBytes(ulong value) public virtual byte[] GetBytes(ulong value)
{ {
return BitConverter.GetBytes(value); return BitConverter.GetBytes(value);
} }
@@ -124,7 +109,7 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public virtual Byte[] GetBytes(float value) public virtual byte[] GetBytes(float value)
{ {
return BitConverter.GetBytes(value); return BitConverter.GetBytes(value);
} }
@@ -134,7 +119,7 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public virtual Byte[] GetBytes(double value) public virtual byte[] GetBytes(double value)
{ {
return BitConverter.GetBytes(value); return BitConverter.GetBytes(value);
} }
@@ -145,53 +130,53 @@ namespace Modbus.Net
/// <param name="value"></param> /// <param name="value"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <returns></returns> /// <returns></returns>
public virtual Byte[] GetBytes(object value, Type type) public virtual byte[] GetBytes(object value, Type type)
{ {
switch (type.FullName) switch (type.FullName)
{ {
case "System.Int16": case "System.Int16":
{ {
byte[] bytes = _Instance.GetBytes((short) value); var bytes = _Instance.GetBytes((short) value);
return bytes; return bytes;
} }
case "System.Int32": case "System.Int32":
{ {
byte[] bytes = _Instance.GetBytes((int) value); var bytes = _Instance.GetBytes((int) value);
return bytes; return bytes;
} }
case "System.Int64": case "System.Int64":
{ {
byte[] bytes = _Instance.GetBytes((long) value); var bytes = _Instance.GetBytes((long) value);
return bytes; return bytes;
} }
case "System.UInt16": case "System.UInt16":
{ {
byte[] bytes = _Instance.GetBytes((ushort) value); var bytes = _Instance.GetBytes((ushort) value);
return bytes; return bytes;
} }
case "System.UInt32": case "System.UInt32":
{ {
byte[] bytes = _Instance.GetBytes((uint) value); var bytes = _Instance.GetBytes((uint) value);
return bytes; return bytes;
} }
case "System.UInt64": case "System.UInt64":
{ {
byte[] bytes = _Instance.GetBytes((ulong) value); var bytes = _Instance.GetBytes((ulong) value);
return bytes; return bytes;
} }
case "System.Single": case "System.Single":
{ {
byte[] bytes = _Instance.GetBytes((float) value); var bytes = _Instance.GetBytes((float) value);
return bytes; return bytes;
} }
case "System.Double": case "System.Double":
{ {
byte[] bytes = _Instance.GetBytes((double) value); var bytes = _Instance.GetBytes((double) value);
return bytes; return bytes;
} }
case "System.Byte": case "System.Byte":
{ {
byte[] bytes = _Instance.GetBytes((byte) value); var bytes = _Instance.GetBytes((byte) value);
return bytes; return bytes;
} }
default: default:
@@ -215,52 +200,52 @@ namespace Modbus.Net
{ {
case "System.Int16": case "System.Int16":
{ {
short value = _Instance.GetShort(data, ref pos); var value = _Instance.GetShort(data, ref pos);
return value; return value;
} }
case "System.Int32": case "System.Int32":
{ {
int value = _Instance.GetInt(data, ref pos); var value = _Instance.GetInt(data, ref pos);
return value; return value;
} }
case "System.Int64": case "System.Int64":
{ {
long value = _Instance.GetLong(data, ref pos); var value = _Instance.GetLong(data, ref pos);
return value; return value;
} }
case "System.UInt16": case "System.UInt16":
{ {
ushort value = _Instance.GetUShort(data, ref pos); var value = _Instance.GetUShort(data, ref pos);
return value; return value;
} }
case "System.UInt32": case "System.UInt32":
{ {
uint value = _Instance.GetUInt(data, ref pos); var value = _Instance.GetUInt(data, ref pos);
return value; return value;
} }
case "System.UInt64": case "System.UInt64":
{ {
ulong value = _Instance.GetULong(data, ref pos); var value = _Instance.GetULong(data, ref pos);
return value; return value;
} }
case "System.Single": case "System.Single":
{ {
float value = _Instance.GetFloat(data, ref pos); var value = _Instance.GetFloat(data, ref pos);
return value; return value;
} }
case "System.Double": case "System.Double":
{ {
double value = _Instance.GetDouble(data, ref pos); var value = _Instance.GetDouble(data, ref pos);
return value; return value;
} }
case "System.Byte": case "System.Byte":
{ {
byte value = _Instance.GetByte(data, ref pos); var value = _Instance.GetByte(data, ref pos);
return value; return value;
} }
case "System.Boolean": case "System.Boolean":
{ {
bool value = _Instance.GetBit(data, ref pos, ref subPos); var value = _Instance.GetBit(data, ref pos, ref subPos);
return value; return value;
} }
default: default:
@@ -278,7 +263,7 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual byte GetByte(byte[] data, ref int pos) public virtual byte GetByte(byte[] data, ref int pos)
{ {
byte t = data[pos]; var t = data[pos];
pos += 1; pos += 1;
return t; return t;
} }
@@ -291,7 +276,7 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual short GetShort(byte[] data, ref int pos) public virtual short GetShort(byte[] data, ref int pos)
{ {
short t = BitConverter.ToInt16(data, pos); var t = BitConverter.ToInt16(data, pos);
pos += 2; pos += 2;
return t; return t;
} }
@@ -304,7 +289,7 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual int GetInt(byte[] data, ref int pos) public virtual int GetInt(byte[] data, ref int pos)
{ {
int t = BitConverter.ToInt32(data, pos); var t = BitConverter.ToInt32(data, pos);
pos += 4; pos += 4;
return t; return t;
} }
@@ -317,7 +302,7 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual long GetLong(byte[] data, ref int pos) public virtual long GetLong(byte[] data, ref int pos)
{ {
long t = BitConverter.ToInt64(data, pos); var t = BitConverter.ToInt64(data, pos);
pos += 8; pos += 8;
return t; return t;
} }
@@ -330,7 +315,7 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual ushort GetUShort(byte[] data, ref int pos) public virtual ushort GetUShort(byte[] data, ref int pos)
{ {
ushort t = BitConverter.ToUInt16(data, pos); var t = BitConverter.ToUInt16(data, pos);
pos += 2; pos += 2;
return t; return t;
} }
@@ -343,7 +328,7 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual uint GetUInt(byte[] data, ref int pos) public virtual uint GetUInt(byte[] data, ref int pos)
{ {
uint t = BitConverter.ToUInt32(data, pos); var t = BitConverter.ToUInt32(data, pos);
pos += 4; pos += 4;
return t; return t;
} }
@@ -356,7 +341,7 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual ulong GetULong(byte[] data, ref int pos) public virtual ulong GetULong(byte[] data, ref int pos)
{ {
ulong t = BitConverter.ToUInt64(data, pos); var t = BitConverter.ToUInt64(data, pos);
pos += 8; pos += 8;
return t; return t;
} }
@@ -369,7 +354,7 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual float GetFloat(byte[] data, ref int pos) public virtual float GetFloat(byte[] data, ref int pos)
{ {
float t = BitConverter.ToSingle(data, pos); var t = BitConverter.ToSingle(data, pos);
pos += 4; pos += 4;
return t; return t;
} }
@@ -382,7 +367,7 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual double GetDouble(byte[] data, ref int pos) public virtual double GetDouble(byte[] data, ref int pos)
{ {
double t = BitConverter.ToDouble(data, pos); var t = BitConverter.ToDouble(data, pos);
pos += 8; pos += 8;
return t; return t;
} }
@@ -397,7 +382,7 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual string GetString(byte[] data, int count, ref int pos, Encoding encoding) public virtual string GetString(byte[] data, int count, ref int pos, Encoding encoding)
{ {
string t = encoding.GetString(data, pos, count); var t = encoding.GetString(data, pos, count);
pos += count; pos += count;
return t; return t;
} }
@@ -410,11 +395,11 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual bool[] GetBits(byte[] data, ref int pos) public virtual bool[] GetBits(byte[] data, ref int pos)
{ {
bool[] t = new bool[8]; var t = new bool[8];
byte temp = data[pos]; var temp = data[pos];
for (int i = 0; i < 8; i++) for (var i = 0; i < 8; i++)
{ {
t[i] = temp % 2 > 0; t[i] = temp%2 > 0;
temp /= 2; temp /= 2;
} }
pos += 1; pos += 1;
@@ -431,11 +416,11 @@ namespace Modbus.Net
public bool GetBit(byte number, ref int pos, ref int subPos) public bool GetBit(byte number, ref int pos, ref int subPos)
{ {
if (subPos < 0 && subPos >= 8) throw new IndexOutOfRangeException(); if (subPos < 0 && subPos >= 8) throw new IndexOutOfRangeException();
int ans = number % 2; var ans = number%2;
int i = 0; var i = 0;
while (i <= subPos) while (i <= subPos)
{ {
ans = number % 2; ans = number%2;
number /= 2; number /= 2;
i++; i++;
} }
@@ -448,18 +433,30 @@ namespace Modbus.Net
return ans > 0; return ans > 0;
} }
/// <summary>
/// 获取一个字节数组中某个Bit位的数据
/// </summary>
/// <param name="number"></param>
/// <param name="pos"></param>
/// <param name="subPos"></param>
/// <returns></returns>
public virtual bool GetBit(byte[] number, ref int pos, ref int subPos) public virtual bool GetBit(byte[] number, ref int pos, ref int subPos)
{ {
return GetBit(number[pos], ref pos, ref subPos); return GetBit(number[pos], ref pos, ref subPos);
} }
/// <summary>
/// 反转一个字节的8个Bit位
/// </summary>
/// <param name="originalByte"></param>
/// <returns></returns>
public virtual byte ReverseByte(byte originalByte) public virtual byte ReverseByte(byte originalByte)
{ {
byte result = 0; byte result = 0;
for (int i = 0; i < 8; i++) for (var i = 0; i < 8; i++)
{ {
result <<= 1; result <<= 1;
result |= (byte)(originalByte & 1); result |= (byte) (originalByte & 1);
originalByte >>= 1; originalByte >>= 1;
} }
return result; return result;
@@ -472,17 +469,17 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public virtual byte[] ObjectArrayToByteArray(object[] contents) public virtual byte[] ObjectArrayToByteArray(object[] contents)
{ {
bool b = false; var b = false;
//先查找传入的结构中有没有数组,有的话将其打开 //先查找传入的结构中有没有数组,有的话将其打开
var newContentsList = new List<object>(); var newContentsList = new List<object>();
foreach (object content in contents) foreach (var content in contents)
{ {
string t = content.GetType().ToString(); var t = content.GetType().ToString();
if (t.Substring(t.Length - 2, 2) == "[]") if (t.Substring(t.Length - 2, 2) == "[]")
{ {
b = true; b = true;
//自动将目标数组中内含的子数组展开,是所有包含在子数组拼接为一个数组 //自动将目标数组中内含的子数组展开,是所有包含在子数组拼接为一个数组
IEnumerable<object> contentArray = var contentArray =
ArrayList.Adapter((Array) content).ToArray(typeof (object)).OfType<object>(); ArrayList.Adapter((Array) content).ToArray(typeof (object)).OfType<object>();
newContentsList.AddRange(contentArray); newContentsList.AddRange(contentArray);
} }
@@ -496,12 +493,12 @@ namespace Modbus.Net
//把参数一个一个翻译为相对应的字节,然后拼成一个队列 //把参数一个一个翻译为相对应的字节,然后拼成一个队列
var translateTarget = new List<byte>(); var translateTarget = new List<byte>();
//将bool类型拼装为byte类型时按照8个一组不满8个时补false为原则进行 //将bool类型拼装为byte类型时按照8个一组不满8个时补false为原则进行
bool lastIsBool = false; var lastIsBool = false;
byte boolToByteTemp = 0; byte boolToByteTemp = 0;
int boolToByteCount = 0; var boolToByteCount = 0;
foreach (object content in contents) foreach (var content in contents)
{ {
string t = content.GetType().ToString(); var t = content.GetType().ToString();
if (t == "System.Boolean") if (t == "System.Boolean")
{ {
if (boolToByteCount >= 8) if (boolToByteCount >= 8)
@@ -513,11 +510,11 @@ namespace Modbus.Net
lastIsBool = true; lastIsBool = true;
if (LittleEndian) if (LittleEndian)
{ {
boolToByteTemp = (byte)(boolToByteTemp * 2 + ((bool)content ? 1 : 0)); boolToByteTemp = (byte) (boolToByteTemp*2 + ((bool) content ? 1 : 0));
} }
else else
{ {
boolToByteTemp += (byte)((bool)content ? Math.Pow(2, boolToByteCount) : 0); boolToByteTemp += (byte) ((bool) content ? Math.Pow(2, boolToByteCount) : 0);
} }
boolToByteCount++; boolToByteCount++;
} }
@@ -534,47 +531,47 @@ namespace Modbus.Net
{ {
case "System.Int16": case "System.Int16":
{ {
translateTarget.AddRange(_Instance.GetBytes((short)content)); translateTarget.AddRange(_Instance.GetBytes((short) content));
break; break;
} }
case "System.Int32": case "System.Int32":
{ {
translateTarget.AddRange(_Instance.GetBytes((int)content)); translateTarget.AddRange(_Instance.GetBytes((int) content));
break; break;
} }
case "System.Int64": case "System.Int64":
{ {
translateTarget.AddRange(_Instance.GetBytes((long)content)); translateTarget.AddRange(_Instance.GetBytes((long) content));
break; break;
} }
case "System.UInt16": case "System.UInt16":
{ {
translateTarget.AddRange(_Instance.GetBytes((ushort)content)); translateTarget.AddRange(_Instance.GetBytes((ushort) content));
break; break;
} }
case "System.UInt32": case "System.UInt32":
{ {
translateTarget.AddRange(_Instance.GetBytes((uint)content)); translateTarget.AddRange(_Instance.GetBytes((uint) content));
break; break;
} }
case "System.UInt64": case "System.UInt64":
{ {
translateTarget.AddRange(_Instance.GetBytes((ulong)content)); translateTarget.AddRange(_Instance.GetBytes((ulong) content));
break; break;
} }
case "System.Single": case "System.Single":
{ {
translateTarget.AddRange(_Instance.GetBytes((float)content)); translateTarget.AddRange(_Instance.GetBytes((float) content));
break; break;
} }
case "System.Double": case "System.Double":
{ {
translateTarget.AddRange(_Instance.GetBytes((double)content)); translateTarget.AddRange(_Instance.GetBytes((double) content));
break; break;
} }
case "System.Byte": case "System.Byte":
{ {
translateTarget.AddRange(_Instance.GetBytes((byte)content)); translateTarget.AddRange(_Instance.GetBytes((byte) content));
break; break;
} }
default: default:
@@ -601,9 +598,16 @@ namespace Modbus.Net
/// <returns>object数组</returns> /// <returns>object数组</returns>
public virtual object[] ByteArrayToObjectArray(byte[] contents, KeyValuePair<Type, int> translateTypeAndCount) public virtual object[] ByteArrayToObjectArray(byte[] contents, KeyValuePair<Type, int> translateTypeAndCount)
{ {
return ByteArrayToObjectArray(contents, new List<KeyValuePair<Type, int>>() {translateTypeAndCount}); return ByteArrayToObjectArray(contents, new List<KeyValuePair<Type, int>> {translateTypeAndCount});
} }
/// <summary>
/// 将一个byte数组转换成用户指定类型的数组使用模板参数确定需要转换的类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="contents"></param>
/// <param name="getCount"></param>
/// <returns></returns>
public virtual T[] ByteArrayToDestinationArray<T>(byte[] contents, int getCount) public virtual T[] ByteArrayToDestinationArray<T>(byte[] contents, int getCount)
{ {
var objectArray = _Instance.ByteArrayToObjectArray(contents, var objectArray = _Instance.ByteArrayToObjectArray(contents,
@@ -615,16 +619,19 @@ namespace Modbus.Net
/// 将byte数组转换为用户指定类型的数组通过object数组的方式返回用户需要再把object转换为自己需要的类型或调用ObjectArrayToDestinationArray返回单一类型的目标数组。 /// 将byte数组转换为用户指定类型的数组通过object数组的方式返回用户需要再把object转换为自己需要的类型或调用ObjectArrayToDestinationArray返回单一类型的目标数组。
/// </summary> /// </summary>
/// <param name="contents">byte数组</param> /// <param name="contents">byte数组</param>
/// <param name="translateTypeAndCount">一连串类型和需要转换的个数的键值对该方法会依次转换每一个需要转的目标数据类型。比如typeof(int),5; typeof(short),3 会转换出8个元素当然前提是byte数组足够长的时候5个int和3个short然后全部变为object类型返回。</param> /// <param name="translateTypeAndCount">
/// 一连串类型和需要转换的个数的键值对该方法会依次转换每一个需要转的目标数据类型。比如typeof(int),5; typeof(short),3
/// 会转换出8个元素当然前提是byte数组足够长的时候5个int和3个short然后全部变为object类型返回。
/// </param>
/// <returns>object数组</returns> /// <returns>object数组</returns>
public virtual object[] ByteArrayToObjectArray(byte[] contents, public virtual object[] ByteArrayToObjectArray(byte[] contents,
IEnumerable<KeyValuePair<Type, int>> translateTypeAndCount) IEnumerable<KeyValuePair<Type, int>> translateTypeAndCount)
{ {
List<object> translation = new List<object>(); var translation = new List<object>();
int count = 0; var count = 0;
foreach (var translateUnit in translateTypeAndCount) foreach (var translateUnit in translateTypeAndCount)
{ {
for (int i = 0; i < translateUnit.Value; i++) for (var i = 0; i < translateUnit.Value; i++)
{ {
if (count >= contents.Length) break; if (count >= contents.Length) break;
try try
@@ -633,64 +640,63 @@ namespace Modbus.Net
{ {
case "System.Int16": case "System.Int16":
{ {
short value = _Instance.GetShort(contents, ref count); var value = _Instance.GetShort(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Int32": case "System.Int32":
{ {
int value = _Instance.GetInt(contents, ref count); var value = _Instance.GetInt(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Int64": case "System.Int64":
{ {
long value = _Instance.GetLong(contents, ref count); var value = _Instance.GetLong(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.UInt16": case "System.UInt16":
{ {
ushort value = _Instance.GetUShort(contents, ref count); var value = _Instance.GetUShort(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.UInt32": case "System.UInt32":
{ {
uint value = _Instance.GetUInt(contents, ref count); var value = _Instance.GetUInt(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.UInt64": case "System.UInt64":
{ {
ulong value = _Instance.GetULong(contents, ref count); var value = _Instance.GetULong(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Single": case "System.Single":
{ {
float value = _Instance.GetFloat(contents, ref count); var value = _Instance.GetFloat(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Double": case "System.Double":
{ {
double value = _Instance.GetDouble(contents, ref count); var value = _Instance.GetDouble(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Byte": case "System.Byte":
{ {
byte value = _Instance.GetByte(contents, ref count); var value = _Instance.GetByte(contents, ref count);
translation.Add(value); translation.Add(value);
break; break;
} }
case "System.Boolean": case "System.Boolean":
{ {
var value = _Instance.GetBits(contents, ref count);
bool[] value = _Instance.GetBits(contents, ref count); var k = translateUnit.Value - i < 8 ? translateUnit.Value - i : 8;
int k = translateUnit.Value - i < 8 ? translateUnit.Value - i : 8; for (var j = 0; j < k; j++)
for (int j = 0; j < k; j++)
{ {
translation.Add(value[j]); translation.Add(value[j]);
} }
@@ -720,8 +726,8 @@ namespace Modbus.Net
/// <returns>目标数组</returns> /// <returns>目标数组</returns>
public T[] ObjectArrayToDestinationArray<T>(object[] contents) public T[] ObjectArrayToDestinationArray<T>(object[] contents)
{ {
T[] array = new T[contents.Length]; var array = new T[contents.Length];
Array.Copy(contents,array,contents.Length); Array.Copy(contents, array, contents.Length);
return array; return array;
} }
@@ -733,52 +739,52 @@ namespace Modbus.Net
{ {
case "System.Int16": case "System.Int16":
{ {
bool success = _Instance.SetValue(contents, setPos, (short)setValue); var success = _Instance.SetValue(contents, setPos, (short) setValue);
return success; return success;
} }
case "System.Int32": case "System.Int32":
{ {
bool success = _Instance.SetValue(contents, setPos, (int) setValue); var success = _Instance.SetValue(contents, setPos, (int) setValue);
return success; return success;
} }
case "System.Int64": case "System.Int64":
{ {
bool success = _Instance.SetValue(contents, setPos, (long) setValue); var success = _Instance.SetValue(contents, setPos, (long) setValue);
return success; return success;
} }
case "System.UInt16": case "System.UInt16":
{ {
bool success = _Instance.SetValue(contents, setPos, (ushort) setValue); var success = _Instance.SetValue(contents, setPos, (ushort) setValue);
return success; return success;
} }
case "System.UInt32": case "System.UInt32":
{ {
bool success = _Instance.SetValue(contents, setPos, (uint) setValue); var success = _Instance.SetValue(contents, setPos, (uint) setValue);
return success; return success;
} }
case "System.UInt64": case "System.UInt64":
{ {
bool success = _Instance.SetValue(contents, setPos, (ulong) setValue); var success = _Instance.SetValue(contents, setPos, (ulong) setValue);
return success; return success;
} }
case "System.Single": case "System.Single":
{ {
bool success = _Instance.SetValue(contents, setPos, (float) setValue); var success = _Instance.SetValue(contents, setPos, (float) setValue);
return success; return success;
} }
case "System.Double": case "System.Double":
{ {
bool success = _Instance.SetValue(contents, setPos, (double) setValue); var success = _Instance.SetValue(contents, setPos, (double) setValue);
return success; return success;
} }
case "System.Byte": case "System.Byte":
{ {
bool success = _Instance.SetValue(contents, setPos, (byte) setValue); var success = _Instance.SetValue(contents, setPos, (byte) setValue);
return success; return success;
} }
case "System.Boolean": case "System.Boolean":
{ {
bool success = _Instance.SetBit(contents, setPos, subPos, (bool) setValue); var success = _Instance.SetBit(contents, setPos, subPos, (bool) setValue);
return success; return success;
} }
default: default:
@@ -799,7 +805,7 @@ namespace Modbus.Net
{ {
try try
{ {
byte[] datas = _Instance.GetBytes(setValue, setValue.GetType()); var datas = _Instance.GetBytes(setValue, setValue.GetType());
Array.Copy(datas, 0, contents, pos, datas.Length); Array.Copy(datas, 0, contents, pos, datas.Length);
return true; return true;
} }
@@ -818,25 +824,22 @@ namespace Modbus.Net
/// <returns></returns> /// <returns></returns>
public byte SetBit(byte number, int subPos, bool setBit) public byte SetBit(byte number, int subPos, bool setBit)
{ {
int creation = 0; var creation = 0;
if (setBit) if (setBit)
{ {
for (int i = 7; i >= 0; i--) for (var i = 7; i >= 0; i--)
{ {
creation *= 2; creation *= 2;
if (i == subPos) creation++; if (i == subPos) creation++;
} }
return (byte)(number | creation); return (byte) (number | creation);
} }
else for (var i = 7; i >= 0; i--)
{
for (int i = 7; i >= 0; i--)
{ {
creation *= 2; creation *= 2;
if (i != subPos) creation++; if (i != subPos) creation++;
} }
return (byte)(number & creation); return (byte) (number & creation);
}
} }
/// <summary> /// <summary>
@@ -859,59 +862,72 @@ namespace Modbus.Net
return false; return false;
} }
} }
#region Factory
private static ValueHelper _instance;
protected virtual ValueHelper _Instance => _instance;
/// <summary>
/// ValueHelper单例的实例
/// </summary>
public static ValueHelper Instance => _instance ?? (_instance = new ValueHelper());
#endregion
} }
public class BigEndianValueHelper : ValueHelper public class BigEndianValueHelper : ValueHelper
{ {
private static BigEndianValueHelper _bigEndianInstance; private static BigEndianValueHelper _bigEndianInstance;
protected override ValueHelper _Instance => _bigEndianInstance;
protected BigEndianValueHelper() protected BigEndianValueHelper()
{ {
} }
protected override ValueHelper _Instance => _bigEndianInstance;
protected new bool LittleEndian => false; protected new bool LittleEndian => false;
public new static BigEndianValueHelper Instance => _bigEndianInstance ?? (_bigEndianInstance = new BigEndianValueHelper()); public new static BigEndianValueHelper Instance
=> _bigEndianInstance ?? (_bigEndianInstance = new BigEndianValueHelper());
public override Byte[] GetBytes(short value) public override byte[] GetBytes(short value)
{ {
return Reverse(BitConverter.GetBytes(value)); return Reverse(BitConverter.GetBytes(value));
} }
public override Byte[] GetBytes(int value) public override byte[] GetBytes(int value)
{ {
return Reverse(BitConverter.GetBytes(value)); return Reverse(BitConverter.GetBytes(value));
} }
public override Byte[] GetBytes(long value) public override byte[] GetBytes(long value)
{ {
return Reverse(BitConverter.GetBytes(value)); return Reverse(BitConverter.GetBytes(value));
} }
public override Byte[] GetBytes(ushort value) public override byte[] GetBytes(ushort value)
{ {
return Reverse(BitConverter.GetBytes(value)); return Reverse(BitConverter.GetBytes(value));
} }
public override Byte[] GetBytes(uint value) public override byte[] GetBytes(uint value)
{ {
return Reverse(BitConverter.GetBytes(value)); return Reverse(BitConverter.GetBytes(value));
} }
public override Byte[] GetBytes(ulong value) public override byte[] GetBytes(ulong value)
{ {
return Reverse(BitConverter.GetBytes(value)); return Reverse(BitConverter.GetBytes(value));
} }
public override Byte[] GetBytes(float value) public override byte[] GetBytes(float value)
{ {
return Reverse(BitConverter.GetBytes(value)); return Reverse(BitConverter.GetBytes(value));
} }
public override Byte[] GetBytes(double value) public override byte[] GetBytes(double value)
{ {
return Reverse(BitConverter.GetBytes(value)); return Reverse(BitConverter.GetBytes(value));
} }
@@ -919,7 +935,7 @@ namespace Modbus.Net
public override short GetShort(byte[] data, ref int pos) public override short GetShort(byte[] data, ref int pos)
{ {
Array.Reverse(data, pos, 2); Array.Reverse(data, pos, 2);
short t = BitConverter.ToInt16(data, pos); var t = BitConverter.ToInt16(data, pos);
Array.Reverse(data, pos, 2); Array.Reverse(data, pos, 2);
pos += 2; pos += 2;
return t; return t;
@@ -928,7 +944,7 @@ namespace Modbus.Net
public override int GetInt(byte[] data, ref int pos) public override int GetInt(byte[] data, ref int pos)
{ {
Array.Reverse(data, pos, 4); Array.Reverse(data, pos, 4);
int t = BitConverter.ToInt32(data, pos); var t = BitConverter.ToInt32(data, pos);
Array.Reverse(data, pos, 4); Array.Reverse(data, pos, 4);
pos += 4; pos += 4;
return t; return t;
@@ -937,7 +953,7 @@ namespace Modbus.Net
public override long GetLong(byte[] data, ref int pos) public override long GetLong(byte[] data, ref int pos)
{ {
Array.Reverse(data, pos, 8); Array.Reverse(data, pos, 8);
long t = BitConverter.ToInt64(data, pos); var t = BitConverter.ToInt64(data, pos);
Array.Reverse(data, pos, 8); Array.Reverse(data, pos, 8);
pos += 8; pos += 8;
return t; return t;
@@ -946,7 +962,7 @@ namespace Modbus.Net
public override ushort GetUShort(byte[] data, ref int pos) public override ushort GetUShort(byte[] data, ref int pos)
{ {
Array.Reverse(data, pos, 2); Array.Reverse(data, pos, 2);
ushort t = BitConverter.ToUInt16(data, pos); var t = BitConverter.ToUInt16(data, pos);
Array.Reverse(data, pos, 2); Array.Reverse(data, pos, 2);
pos += 2; pos += 2;
return t; return t;
@@ -955,7 +971,7 @@ namespace Modbus.Net
public override uint GetUInt(byte[] data, ref int pos) public override uint GetUInt(byte[] data, ref int pos)
{ {
Array.Reverse(data, pos, 4); Array.Reverse(data, pos, 4);
uint t = BitConverter.ToUInt32(data, pos); var t = BitConverter.ToUInt32(data, pos);
Array.Reverse(data, pos, 4); Array.Reverse(data, pos, 4);
pos += 4; pos += 4;
return t; return t;
@@ -964,7 +980,7 @@ namespace Modbus.Net
public override ulong GetULong(byte[] data, ref int pos) public override ulong GetULong(byte[] data, ref int pos)
{ {
Array.Reverse(data, pos, 8); Array.Reverse(data, pos, 8);
ulong t = BitConverter.ToUInt64(data, pos); var t = BitConverter.ToUInt64(data, pos);
Array.Reverse(data, pos, 8); Array.Reverse(data, pos, 8);
pos += 8; pos += 8;
return t; return t;
@@ -973,7 +989,7 @@ namespace Modbus.Net
public override float GetFloat(byte[] data, ref int pos) public override float GetFloat(byte[] data, ref int pos)
{ {
Array.Reverse(data, pos, 4); Array.Reverse(data, pos, 4);
float t = BitConverter.ToSingle(data, pos); var t = BitConverter.ToSingle(data, pos);
Array.Reverse(data, pos, 4); Array.Reverse(data, pos, 4);
pos += 4; pos += 4;
return t; return t;
@@ -982,7 +998,7 @@ namespace Modbus.Net
public override double GetDouble(byte[] data, ref int pos) public override double GetDouble(byte[] data, ref int pos)
{ {
Array.Reverse(data, pos, 8); Array.Reverse(data, pos, 8);
double t = BitConverter.ToDouble(data, pos); var t = BitConverter.ToDouble(data, pos);
Array.Reverse(data, pos, 8); Array.Reverse(data, pos, 8);
pos += 8; pos += 8;
return t; return t;
@@ -1005,11 +1021,11 @@ namespace Modbus.Net
public override bool[] GetBits(byte[] data, ref int pos) public override bool[] GetBits(byte[] data, ref int pos)
{ {
bool[] t = new bool[8]; var t = new bool[8];
byte temp = data[pos]; var temp = data[pos];
for (int i = 0; i < 8; i++) for (var i = 0; i < 8; i++)
{ {
t[7 - i] = temp % 2 > 0; t[7 - i] = temp%2 > 0;
temp /= 2; temp /= 2;
} }
pos += 1; pos += 1;
@@ -1021,7 +1037,7 @@ namespace Modbus.Net
return base.SetBit(number, pos, 7 - subPos, setBit); return base.SetBit(number, pos, 7 - subPos, setBit);
} }
private Byte[] Reverse(Byte[] data) private byte[] Reverse(byte[] data)
{ {
Array.Reverse(data); Array.Reverse(data);
return data; return data;