2014-10-09 update 3

This commit is contained in:
parallelbgls@outlook.com
2014-10-09 16:54:00 +08:00
parent c31a38d99a
commit 1a89292867
15 changed files with 275 additions and 45 deletions

View File

@@ -76,6 +76,9 @@ namespace ModBus.Net
}
}
/// <summary>
/// 基本的单元转换器
/// </summary>
public class AddressTranslatorBase : AddressTranslator
{
public override ushort AddressTranslate(string address)

View File

@@ -8,9 +8,27 @@ namespace ModBus.Net
{
public abstract class BaseConnector
{
/// <summary>
/// 连接PLC
/// </summary>
/// <returns></returns>
public abstract bool Connect();
/// <summary>
/// 断开PLC
/// </summary>
/// <returns></returns>
public abstract bool Disconnect();
/// <summary>
/// 无返回发送数据
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public abstract bool SendMsgWithoutReturn(byte[] message);
/// <summary>
/// 带返回发送数据
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public abstract byte[] SendMsg(byte[] message);
}
}

View File

@@ -8,9 +8,37 @@ namespace ModBus.Net
{
public abstract class BaseUtility
{
/// <summary>
/// 协议收发主体
/// </summary>
protected BaseProtocal Wrapper;
/// <summary>
/// 设置连接字符串
/// </summary>
/// <param name="connectionString">连接字符串</param>
public abstract void SetConnectionString(string connectionString);
/// <summary>
/// 设置连接类型
/// </summary>
/// <param name="connectionType">连接类型</param>
public abstract void SetConnectionType(int connectionType);
/// <summary>
/// 获取数据
/// </summary>
/// <param name="belongAddress">从站地址</param>
/// <param name="functionCode">功能码</param>
/// <param name="startAddress">开始地址</param>
/// <param name="getCount">接收个数</param>
/// <returns>接收到的byte数据</returns>
public abstract byte[] GetDatas(byte belongAddress, byte functionCode, string startAddress, ushort getCount);
/// <summary>
/// 设置数据
/// </summary>
/// <param name="belongAddress">从站地址</param>
/// <param name="functionCode">功能码</param>
/// <param name="startAddress">开始地址</param>
/// <param name="setContents">设置个数</param>
/// <returns>是否设置成功</returns>
public abstract bool SetDatas(byte belongAddress, byte functionCode, string startAddress, object[] setContents);
}
}

View File

@@ -6,15 +6,15 @@ using System.Threading.Tasks;
namespace ModBus.Net
{
public abstract class RtuProtocalLinker : ProtocalLinker
public abstract class ComProtocalLinker : ProtocalLinker
{
protected RtuProtocalLinker()
protected ComProtocalLinker()
{
//初始化连对象
_baseConnector = new ComConnector(ConfigurationManager.COM);
}
protected RtuProtocalLinker(string com)
protected ComProtocalLinker(string com)
{
_baseConnector = new ComConnector(com);
}

View File

@@ -46,7 +46,7 @@
<Compile Include="BaseUtility.cs" />
<Compile Include="ComConnector.cs" />
<Compile Include="ModbusUtility.cs" />
<Compile Include="RtuProtocalLinker.cs" />
<Compile Include="ComProtocalLinker.cs" />
<Compile Include="ConfigurationManager.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>

View File

@@ -2,18 +2,19 @@
using System.Collections.Generic;
using System.Runtime.Remoting.Messaging;
public enum ModbusProtocalFunctionCode
{
}
internal enum ModbusProtocalTimeFunctionCode
/// <summary>
/// 跟时间有关的功能码
/// </summary>
internal enum ModbusProtocalTimeFunctionCode : byte
{
GetSystemTime = 3,
SetSystemTime = 16,
};
public enum ModbusProtocalReadDataFunctionCode
/// <summary>
/// 跟读数据有关的功能码
/// </summary>
public enum ModbusProtocalReadDataFunctionCode : byte
{
ReadCoilStatus = 1,
ReadInputStatus = 2,
@@ -21,11 +22,15 @@ public enum ModbusProtocalReadDataFunctionCode
ReadInputRegister = 4,
}
public enum ModbusProtocalWriteDataFunctionCode
/// <summary>
/// 跟写数据有关的功能码
/// </summary>
public enum ModbusProtocalWriteDataFunctionCode : byte
{
WriteMultiCoil = 15,
WriteMultiRegister = 16,
}
namespace ModBus.Net
{
public abstract class ModbusProtocal : BaseProtocal
@@ -33,6 +38,7 @@ namespace ModBus.Net
}
#region PLC数据
public class ReadDataInputStruct : InputStruct
{
public ReadDataInputStruct(byte belongAddress, ModbusProtocalReadDataFunctionCode functionCode, string startAddress, ushort getCount)
@@ -92,6 +98,9 @@ namespace ModBus.Net
}
}
#endregion
#region PLC数据
public class WriteDataInputStruct : InputStruct
{
public WriteDataInputStruct(byte belongAddress, ModbusProtocalWriteDataFunctionCode functionCode, string startAddress, object[] writeValue)
@@ -162,6 +171,9 @@ namespace ModBus.Net
}
}
#endregion
#region PLC时间
public class GetSystemTimeInputStruct : InputStruct
{
public GetSystemTimeInputStruct(byte belongAddress)
@@ -231,6 +243,9 @@ namespace ModBus.Net
}
}
#endregion
#region PLC时间
public class SetSystemTimeInputStruct : InputStruct
{
public SetSystemTimeInputStruct(byte belongAddress, DateTime time)
@@ -317,16 +332,11 @@ namespace ModBus.Net
return new SetSystemTimeOutputStruct(belongAddress, functionCode, startAddress, writeCount);
}
}
#endregion
public class ProtocalErrorException : Exception
{
public ProtocalErrorException(string message)
: base(message)
{
}
}
/// <summary>
/// Modbus协议错误表
/// </summary>
public class ModbusProtocalErrorException : ProtocalErrorException
{
public int ErrorMessageNumber { get; private set; }

View File

@@ -6,6 +6,9 @@ using System.Threading.Tasks;
namespace ModBus.Net
{
/// <summary>
/// Modbus/Rtu协议
/// </summary>
public class ModbusRtuProtocal : ModbusProtocal
{
public ModbusRtuProtocal()

View File

@@ -6,14 +6,16 @@ using System.Threading.Tasks;
namespace ModBus.Net
{
class ModbusRtuProtocalLinker : RtuProtocalLinker
class ModbusRtuProtocalLinker : ComProtocalLinker
{
public override bool CheckRight(byte[] content)
{
//CRC校验失败
if (!Crc16.GetInstance().CrcEfficacy(content))
{
throw new ModbusProtocalErrorException(501);
}
//Modbus协议错误
if (content[1] > 127)
{
throw new ModbusProtocalErrorException(content[2]);
@@ -21,7 +23,7 @@ namespace ModBus.Net
return true;
}
public ModbusRtuProtocalLinker() : base()
public ModbusRtuProtocalLinker() : this(ConfigurationManager.COM)
{
}

View File

@@ -7,7 +7,6 @@ namespace ModBus.Net
/// </summary>
public class ModbusTcpProtocal : ModbusProtocal
{
//将连接器设置为Tcp连接器
public ModbusTcpProtocal()
{
_protocalLinker = new ModbusTcpProtocalLinker();

View File

@@ -10,10 +10,12 @@ namespace ModBus.Net
{
public override bool CheckRight(byte[] content)
{
//长度校验失败
if (content[5] != content.Length - 6)
{
throw new ModbusProtocalErrorException(500);
}
//Modbus协议错误
if (content[7] > 127)
{
throw new ModbusProtocalErrorException(content[2]);
@@ -21,7 +23,7 @@ namespace ModBus.Net
return true;
}
public ModbusTcpProtocalLinker() : base()
public ModbusTcpProtocalLinker() : this(ConfigurationManager.IP)
{
}

View File

@@ -2,9 +2,18 @@
using System.Collections;
using System.Windows.Forms;
/// <summary>
/// Modbus连接类型
/// </summary>
public enum ModbusType
{
/// <summary>
/// Rtu连接
/// </summary>
Rtu = 0,
/// <summary>
/// Tcp连接
/// </summary>
Tcp = 1,
}
@@ -12,11 +21,7 @@ namespace ModBus.Net
{
public class ModbusUtility : BaseUtility
{
private BaseProtocal _wrapper;
private string _connectionString;
public string ConnectionString { get; set; }
protected string ConnectionString { get; set; }
private ModbusType _modbusType;
@@ -33,12 +38,12 @@ namespace ModBus.Net
{
case ModbusType.Rtu:
{
_wrapper = ConnectionString == null ? new ModbusRtuProtocal() : new ModbusRtuProtocal(ConnectionString);
Wrapper = ConnectionString == null ? new ModbusRtuProtocal() : new ModbusRtuProtocal(ConnectionString);
break;
}
case ModbusType.Tcp:
{
_wrapper = ConnectionString == null ? new ModbusTcpProtocal() : new ModbusTcpProtocal(ConnectionString);
Wrapper = ConnectionString == null ? new ModbusTcpProtocal() : new ModbusTcpProtocal(ConnectionString);
break;
}
}
@@ -73,7 +78,7 @@ namespace ModBus.Net
{
var inputStruct = new ReadDataInputStruct(belongAddress, (ModbusProtocalReadDataFunctionCode)functionCode, startAddress, getCount);
var outputStruct =
_wrapper.SendReceive(_wrapper["ReadDataModbusProtocal"], inputStruct) as ReadDataOutputStruct;
Wrapper.SendReceive(Wrapper["ReadDataModbusProtocal"], inputStruct) as ReadDataOutputStruct;
return outputStruct.DataValue;
}
catch
@@ -89,7 +94,7 @@ namespace ModBus.Net
var inputStruct = new WriteDataInputStruct(belongAddress,
(ModbusProtocalWriteDataFunctionCode) functionCode, startAddress, setContents);
var outputStruct =
_wrapper.SendReceive(_wrapper["WriteDataModbusProtocal"], inputStruct) as
Wrapper.SendReceive(Wrapper["WriteDataModbusProtocal"], inputStruct) as
WriteDataOutputStruct;
if (outputStruct.WriteCount != setContents.Length) return false;
return true;

View File

@@ -57,7 +57,7 @@ namespace ModBus.Net
public override byte[] BytesExtend(byte[] content)
{
byte[] crc = new byte[2];
//Modbus/Tcp协议扩张增加CRC校验
//Modbus/Rtu协议扩张增加CRC校验
byte[] newFormat = new byte[content.Length + 2];
Crc16.GetInstance().GetCRC(content, ref crc);
Array.Copy(content, 0, newFormat, 0, content.Length);
@@ -67,7 +67,7 @@ namespace ModBus.Net
public override byte[] BytesDecact(byte[] content)
{
//Modbus/Com协议收缩抛弃后面1个字节的内容
//Modbus/Rtu协议收缩抛弃后面1个字节的内容
byte[] newContent = new byte[content.Length - 2];
Array.Copy(content, 0, newContent, 0, newContent.Length);
return newContent;

View File

@@ -64,4 +64,16 @@ namespace ModBus.Net
public class OutputStruct
{
}
/// <summary>
/// 协议错误
/// </summary>
public class ProtocalErrorException : Exception
{
public ProtocalErrorException(string message)
: base(message)
{
}
}
}

View File

@@ -4,11 +4,11 @@ using System.Linq;
namespace ModBus.Net
{
/// <summary>
/// Tcp连接对象
/// </summary>
public abstract class TcpProtocalLinker : ProtocalLinker
{
/// <summary>
/// 连接对象
/// </summary>
protected TcpProtocalLinker() : this(ConfigurationManager.IP)
{
@@ -18,6 +18,7 @@ namespace ModBus.Net
protected TcpProtocalLinker(string ip)
{
int port;
//是否启用ConfigurationManager里的Port参数
if (ConfigurationManager.ResourceManager.GetString("Port") != null && int.TryParse(ConfigurationManager.ResourceManager.GetString("Port"),out port))
{

View File

@@ -36,6 +36,9 @@ namespace ModBus.Net
protected static ValueHelper _Instance = null;
/// <summary>
/// ValueHelper单例的实例
/// </summary>
public static ValueHelper Instance
{
get
@@ -50,51 +53,102 @@ namespace ModBus.Net
#endregion
/// <summary>
/// 将一个byte数字转换为一个byte元素的数组。
/// </summary>
/// <param name="value">byte数字</param>
/// <returns>byte数组</returns>
public Byte[] GetBytes(byte value)
{
return new[] {value};
}
/// <summary>
/// 将short数字转换为byte数组
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual Byte[] GetBytes(short value)
{
return BitConverter.GetBytes(value);
}
/// <summary>
/// 将int数字转换为byte数组
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual Byte[] GetBytes(int value)
{
return BitConverter.GetBytes(value);
}
/// <summary>
/// 将long数字转换为byte数组
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual Byte[] GetBytes(long value)
{
return BitConverter.GetBytes(value);
}
/// <summary>
/// 将ushort数字转换为byte数组
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual Byte[] GetBytes(ushort value)
{
return BitConverter.GetBytes(value);
}
/// <summary>
/// 将uint数字转换为byte数组
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual Byte[] GetBytes(uint value)
{
return BitConverter.GetBytes(value);
}
/// <summary>
/// 将ulong数字转换为byte数组
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual Byte[] GetBytes(ulong value)
{
return BitConverter.GetBytes(value);
}
/// <summary>
/// 将float数字转换为byte数组
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual Byte[] GetBytes(float value)
{
return BitConverter.GetBytes(value);
}
/// <summary>
/// 将double数字转换为byte数组
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual Byte[] GetBytes(double value)
{
return BitConverter.GetBytes(value);
}
/// <summary>
/// 将byte数组中相应的位置转换为byte数字
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
/// <returns></returns>
public virtual byte GetByte(byte[] data, ref int pos)
{
byte t = data[pos];
@@ -102,6 +156,12 @@ namespace ModBus.Net
return t;
}
/// <summary>
/// 将byte数组中相应的位置转换为short数字
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
/// <returns></returns>
public virtual short GetShort(byte[] data, ref int pos)
{
short t = BitConverter.ToInt16(data, pos);
@@ -109,6 +169,12 @@ namespace ModBus.Net
return t;
}
/// <summary>
/// 将byte数组中相应的位置转换为int数字
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
/// <returns></returns>
public virtual int GetInt(byte[] data, ref int pos)
{
int t = BitConverter.ToInt32(data, pos);
@@ -116,6 +182,12 @@ namespace ModBus.Net
return t;
}
/// <summary>
/// 将byte数组中相应的位置转换为long数字
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
/// <returns></returns>
public virtual long GetLong(byte[] data, ref int pos)
{
long t = BitConverter.ToInt64(data, pos);
@@ -123,6 +195,12 @@ namespace ModBus.Net
return t;
}
/// <summary>
/// 将byte数组中相应的位置转换为ushort数字
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
/// <returns></returns>
public virtual ushort GetUShort(byte[] data, ref int pos)
{
ushort t = BitConverter.ToUInt16(data, pos);
@@ -130,6 +208,12 @@ namespace ModBus.Net
return t;
}
/// <summary>
/// 将byte数组中相应的位置转换为uint数字
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
/// <returns></returns>
public virtual uint GetUInt(byte[] data, ref int pos)
{
uint t = BitConverter.ToUInt32(data, pos);
@@ -137,6 +221,12 @@ namespace ModBus.Net
return t;
}
/// <summary>
/// 将byte数组中相应的位置转换为ulong数字
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
/// <returns></returns>
public virtual ulong GetULong(byte[] data, ref int pos)
{
ulong t = BitConverter.ToUInt64(data, pos);
@@ -144,6 +234,12 @@ namespace ModBus.Net
return t;
}
/// <summary>
/// 将byte数组中相应的位置转换为float数字
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
/// <returns></returns>
public virtual float GetFloat(byte[] data, ref int pos)
{
float t = BitConverter.ToSingle(data, pos);
@@ -151,6 +247,12 @@ namespace ModBus.Net
return t;
}
/// <summary>
/// 将byte数组中相应的位置转换为double数字
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
/// <returns></returns>
public virtual double GetDouble(byte[] data, ref int pos)
{
double t = BitConverter.ToDouble(data, pos);
@@ -158,6 +260,12 @@ namespace ModBus.Net
return t;
}
/// <summary>
/// 将byte数组中相应的位置转换为8个bit数字
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
/// <returns></returns>
public virtual bool[] GetBits(byte[] data, ref int pos)
{
bool[] t = new bool[8];
@@ -171,6 +279,11 @@ namespace ModBus.Net
return t;
}
/// <summary>
/// 将待转换的对象数组转换为需要发送的byte数组
/// </summary>
/// <param name="contents"></param>
/// <returns></returns>
public byte[] ObjectArrayToByteArray(object[] contents)
{
bool b = false;
@@ -182,6 +295,7 @@ namespace ModBus.Net
if (t.Substring(t.Length - 2, 2) == "[]")
{
b = true;
//自动将目标数组中内含的子数组展开,是所有包含在子数组拼接为一个数组
IEnumerable<object> contentArray =
ArrayList.Adapter((Array) content).ToArray(typeof (object)).OfType<object>();
newContentsList.AddRange(contentArray);
@@ -195,6 +309,7 @@ namespace ModBus.Net
if (b) return ObjectArrayToByteArray(newContentsList.ToArray());
//把参数一个一个翻译为相对应的字节,然后拼成一个队列
var translateTarget = new List<byte>();
//将bool类型拼装为byte类型时按照8个一组不满8个时补false为原则进行
bool lastIsBool = false;
byte boolToByteTemp = 0;
int boolToByteCount = 0;
@@ -283,19 +398,32 @@ namespace ModBus.Net
}
}
}
//最后把队列转换为数组
//最后是bool拼装时表示数字还没有添加把数字添加进返回数组中。
if (lastIsBool)
{
translateTarget.Add(boolToByteTemp);
}
//最后把队列转换为数组
return translateTarget.ToArray();
}
/// <summary>
/// 将byte数组转换为用户指定类型的数组通过object数组的方式返回用户需要再把object转换为自己需要的类型或调用ObjectArrayToDestinationArray返回单一类型的目标数组。
/// </summary>
/// <param name="contents">byte数组</param>
/// <param name="translateTypeAndCount">单一的类型和需要转换的个数的键值对</param>
/// <returns>object数组</returns>
public object[] ByteArrayToObjectArray(byte[] contents, KeyValuePair<Type, int> translateTypeAndCount)
{
return ByteArrayToObjectArray(contents, new List<KeyValuePair<Type, int>>() {translateTypeAndCount});
}
/// <summary>
/// 将byte数组转换为用户指定类型的数组通过object数组的方式返回用户需要再把object转换为自己需要的类型或调用ObjectArrayToDestinationArray返回单一类型的目标数组。
/// </summary>
/// <param name="contents">byte数组</param>
/// <param name="translateTypeAndCount">一连串类型和需要转换的个数的键值对该方法会依次转换每一个需要转的目标数据类型。比如typeof(int),5; typeof(short),3 会转换出8个元素当然前提是byte数组足够长的时候5个int和3个short然后全部变为object类型返回。</param>
/// <returns>object数组</returns>
public object[] ByteArrayToObjectArray(byte[] contents,
IEnumerable<KeyValuePair<Type, int>> translateTypeAndCount)
{
@@ -388,6 +516,12 @@ namespace ModBus.Net
return translation.ToArray();
}
/// <summary>
/// 将object数组转换为目标类型的单一数组
/// </summary>
/// <typeparam name="T">需要转换的目标类型</typeparam>
/// <param name="contents">object数组</param>
/// <returns>目标数组</returns>
public T[] ObjectArrayToDestinationArray<T>(object[] contents)
{
T[] array = new T[contents.Length];
@@ -395,6 +529,12 @@ namespace ModBus.Net
return array;
}
/// <summary>
/// 获取一个byte中相对应的bit数组展开中第n个位置中的bit元素。
/// </summary>
/// <param name="number">byte数字</param>
/// <param name="pos">bit数组中的对应位置</param>
/// <returns>对应位置的bit元素</returns>
public bool GetBit(byte number, ref int pos)
{
if (pos < 0 && pos > 8) throw new IndexOutOfRangeException();
@@ -410,26 +550,33 @@ namespace ModBus.Net
return ans > 0;
}
public ushort SetBit(ushort number, int pos, bool setBit)
/// <summary>
/// 设置对应数字中相应位置的bit的值
/// </summary>
/// <param name="number">byte数子</param>
/// <param name="pos">设置位置</param>
/// <param name="setBit">设置bit大小true为1false为0</param>
/// <returns></returns>
public byte SetBit(byte number, int pos, bool setBit)
{
int creation = 0;
if (setBit)
{
for (int i = 0; i < 16; i++)
for (int i = 0; i < 8; i++)
{
creation *= 2;
if (i == pos) creation++;
}
return (ushort) (number | creation);
return (byte) (number | creation);
}
else
{
for (int i = 0; i < 16; i++)
for (int i = 0; i < 8; i++)
{
creation *= 2;
if (i != pos) creation++;
}
return (ushort) (number & creation);
return (byte) (number & creation);
}
}
}