2014-08-01 update 6 Add comment

This commit is contained in:
parallelbgls
2014-08-01 16:39:06 +08:00
parent 1e77c6c121
commit b2bf591661
14 changed files with 261 additions and 50 deletions

View File

@@ -2,6 +2,9 @@
namespace ModBus.Net
{
/// <summary>
/// 数据单元翻译器
/// </summary>
public abstract class AddressTranslator
{
protected static AddressTranslator _instance;
@@ -10,6 +13,9 @@ namespace ModBus.Net
public abstract ushort AddressTranslate(string address);
}
/// <summary>
/// NA200H数据单元翻译器
/// </summary>
public class AddressTranslatorNA200H : AddressTranslator
{
private AddressTranslatorNA200H()

View File

@@ -4,10 +4,13 @@ using System.Reflection;
namespace ModBus.Net
{
/// <summary>
/// 基本协议
/// </summary>
public abstract class BaseProtocal
{
/// <summary>
/// 发送数据
/// 发送数据
/// </summary>
/// <param name="content">需要发送的数据</param>
/// <returns>数据是否正确接收</returns>
@@ -18,6 +21,11 @@ namespace ModBus.Net
Protocals = new Dictionary<string, ProtocalUnit>();
}
/// <summary>
/// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议
/// </summary>
/// <param name="protocalName">协议的类的名称</param>
/// <returns></returns>
public ProtocalUnit this[string protocalName]
{
get
@@ -26,6 +34,7 @@ namespace ModBus.Net
{
return Protocals[protocalName];
}
//自动寻找存在的协议并将其加载
var protocalUnit =
Assembly.Load("ModBus.Net").CreateInstance("ModBus.Net." + protocalName) as ProtocalUnit;
if (protocalUnit == null) throw new InvalidCastException("没有相应的协议内容");
@@ -36,24 +45,29 @@ namespace ModBus.Net
protected Dictionary<string, ProtocalUnit> Protocals { get; private set; }
public void Register(ProtocalUnit linkProtocal)
protected void Register(ProtocalUnit linkProtocal)
{
if (linkProtocal == null) return;
Protocals.Add(linkProtocal.GetType().Name, linkProtocal);
}
/// <summary>
/// 发送协议内容并接收,一般方法
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
public virtual byte[] SendReceive(params object[] content)
{
int t;
return _protocalLinker.SendReceive(ProtocalUnit.TranslateContent(content));
}
public virtual OutputStruct SendReceive(ProtocalUnit unit, params object[] content)
{
int t = 0;
return unit.Unformat(_protocalLinker.SendReceive(unit.Format(content)), ref t);
}
/// <summary>
/// 发送协议,通过传入需要使用的协议内容和输入结构
/// </summary>
/// <param name="unit"></param>
/// <param name="content"></param>
/// <returns></returns>
public virtual OutputStruct SendReceive(ProtocalUnit unit, InputStruct content)
{
int t = 0;
@@ -61,14 +75,22 @@ namespace ModBus.Net
}
/// <summary>
/// 接收数据
/// 仅发送数据
/// </summary>
/// <returns>接收到的数据</returns>
/// <param name="unit"></param>
/// <param name="content"></param>
/// <returns></returns>
public virtual bool SendOnly(ProtocalUnit unit, params object[] content)
{
return _protocalLinker.SendOnly(unit.Format(content));
}
/// <summary>
/// 仅发送数据
/// </summary>
/// <param name="unit"></param>
/// <param name="content"></param>
/// <returns></returns>
public virtual bool SendOnly(ProtocalUnit unit, InputStruct content)
{
return _protocalLinker.SendOnly(unit.Format(content));

View File

@@ -1,11 +1,30 @@
namespace ModBus.Net
{
/// <summary>
/// 协议转换的接口
/// </summary>
public interface IProtocalFormatting
{
/// <summary>
/// 从输入结构格式化
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
byte[] Format(InputStruct message);
/// <summary>
/// 从对象的参数数组格式化
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
byte[] Format(params object[] message);
/// <summary>
/// 把仪器返回的内容填充到输出结构中
/// </summary>
/// <param name="messageBytes"></param>
/// <param name="pos"></param>
/// <returns></returns>
OutputStruct Unformat(byte[] messageBytes, ref int pos);
}
}

View File

@@ -49,7 +49,9 @@
<DependentUpon>ConfigurationManager.resx</DependentUpon>
</Compile>
<Compile Include="IProtocalFormatting.cs" />
<Compile Include="ModbusTcpProtocalLinker.cs" />
<Compile Include="ProtocalLinker.cs" />
<Compile Include="ProtocalLinkerBytesExtend.cs" />
<Compile Include="ProtocalUnit.cs" />
<Compile Include="ModbusProtocal.cs" />
<Compile Include="ModbusTCPProtocal.cs" />

View File

@@ -23,6 +23,9 @@ namespace ModBus.Net
}
/// <summary>
/// 读线圈状态
/// </summary>
public class ReadCoilStatusModbusProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)
@@ -91,6 +94,9 @@ namespace ModBus.Net
}
}
/// <summary>
/// 读输入状态协
/// </summary>
public class ReadInputStatusModbusProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)
@@ -161,6 +167,9 @@ namespace ModBus.Net
}
}
/// <summary>
/// 读保持型寄存器
/// </summary>
public class ReadHoldRegisterModbusProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)
@@ -224,6 +233,9 @@ namespace ModBus.Net
}
}
/// <summary>
/// 读输入型寄存器
/// </summary>
public class ReadInputRegisterModbusProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)
@@ -347,6 +359,9 @@ namespace ModBus.Net
}
}
/// <summary>
/// 读单个线圈状态
/// </summary>
public class WriteOneCoilModbusProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)
@@ -406,6 +421,9 @@ namespace ModBus.Net
}
}
/// <summary>
/// 写单个寄存器状态
/// </summary>
public class WriteOneRegisterModbusProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)
@@ -463,6 +481,9 @@ namespace ModBus.Net
}
}
/// <summary>
/// 写多个线圈状态
/// </summary>
public class WriteMultiCoilModbusProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)
@@ -537,6 +558,9 @@ namespace ModBus.Net
}
}
/// <summary>
/// 写多个寄存器状态
/// </summary>
public class WriteMultiRegisterModbusProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)
@@ -602,6 +626,9 @@ namespace ModBus.Net
}
}
/// <summary>
/// 读系统时间
/// </summary>
public class GetSystemTimeModbusProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)
@@ -668,6 +695,9 @@ namespace ModBus.Net
}
}
/// <summary>
/// 写系统时间
/// </summary>
public class SetSystemTimeModbusProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)

View File

@@ -2,11 +2,15 @@
namespace ModBus.Net
{
/// <summary>
/// Modbus/Tcp协议
/// </summary>
public class ModbusTcpProtocal : ModbusProtocal
{
//将连接器设置为Tcp连接器
public ModbusTcpProtocal()
{
_protocalLinker = new TcpProtocalLinker();
_protocalLinker = new ModbusTcpProtocalLinker();
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ModBus.Net
{
class ModbusTcpProtocalLinker : TcpProtocalLinker
{
public override bool CheckRight(byte[] content)
{
if (content[1] > 127)
{
throw new ModbusProtocalErrorException(content[2]);
}
return true;
}
}
}

View File

@@ -2,22 +2,54 @@
namespace ModBus.Net
{
/// <summary>
/// 基本的协议连接器
/// </summary>
public abstract class ProtocalLinker
{
/// <summary>
/// 发送并接收数据
/// </summary>
/// <param name="content">发送协议的内容</param>
/// <returns>接收协议的内容</returns>
public abstract byte[] SendReceive(byte[] content);
/// <summary>
/// 仅发送数据
/// </summary>
/// <param name="content">发送协议的内容</param>
/// <returns>协议是否正确发送</returns>
public abstract bool SendOnly(byte[] content);
/// <summary>
/// 检查接收的数据是否正确
/// </summary>
/// <param name="content">接收协议的内容</param>
/// <returns>协议是否是正确的</returns>
public abstract bool CheckRight(byte[] content);
/// <summary>
/// 协议内容扩展,发送时根据需要扩展
/// </summary>
/// <param name="content">扩展前的基本协议内容</param>
/// <returns>扩展后的协议内容</returns>
public byte[] BytesExtend(byte[] content)
{
//自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
ProtocalLinkerBytesExtend bytesExtend =
Assembly.Load("ModBus.Net").CreateInstance(this.GetType().FullName + "BytesExtend") as
ProtocalLinkerBytesExtend;
return bytesExtend.BytesExtend(content);
}
/// <summary>
/// 协议内容缩减,接收时根据需要缩减
/// </summary>
/// <param name="content">缩减前的完整协议内容</param>
/// <returns>缩减后的协议内容</returns>
public byte[] BytesDecact(byte[] content)
{
//自动查找相应的协议放缩类,命令规则为——当前的实际类名(注意是继承后的)+"BytesExtend"。
ProtocalLinkerBytesExtend bytesExtend =
Assembly.Load("ModBus.Net").CreateInstance(this.GetType().FullName + "BytesExtend") as
ProtocalLinkerBytesExtend;

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ModBus.Net
{
/// <summary>
/// 协议字节伸缩
/// </summary>
public abstract class ProtocalLinkerBytesExtend
{
/// <summary>
/// 协议扩展,协议内容发送前调用
/// </summary>
/// <param name="content">扩展前的原始协议内容</param>
/// <returns>扩展后的协议内容</returns>
public abstract byte[] BytesExtend(byte[] content);
/// <summary>
/// 协议收缩,协议内容接收后调用
/// </summary>
/// <param name="content">收缩前的完整协议内容</param>
/// <returns>收缩后的协议内容</returns>
public abstract byte[] BytesDecact(byte[] content);
}
/// <summary>
/// Tcp协议字节伸缩
/// </summary>
public class ModbusTcpProtocalLinkerBytesExtend : ProtocalLinkerBytesExtend
{
public override byte[] BytesExtend(byte[] content)
{
//Modbus/Tcp协议扩张前面加6个字节前面4个为0后面两个为协议整体内容的长度
byte[] newFormat = new byte[6 + content.Length];
int tag = 0;
ushort leng = (ushort)content.Length;
Array.Copy(ValueHelper.Instance.GetBytes(tag), 0, newFormat, 0, 4);
Array.Copy(ValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2);
Array.Copy(content, 0, newFormat, 6, content.Length);
return newFormat;
}
public override byte[] BytesDecact(byte[] content)
{
//Modbus/Tcp协议收缩抛弃前面6个字节的内容
byte[] newContent = new byte[content.Length - 6];
Array.Copy(content, 6, newContent, 0, newContent.Length);
return newContent;
}
}
}

View File

@@ -7,21 +7,40 @@ namespace ModBus.Net
{
public abstract class ProtocalUnit : IProtocalFormatting
{
/// <summary>
/// 格式化,将输入结构转换为字节数组
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public abstract byte[] Format(InputStruct message);
/// <summary>
/// 格式化,将对象数组转换为字节数组
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public virtual byte[] Format(params object[] message)
{
return TranslateContent(message);
}
public abstract OutputStruct Unformat(byte[] messageBytes, ref int pos);
/// <summary>
/// 结构化,将字节数组转换为输出结构。
/// </summary>
/// <param name="messageBytes"></param>
/// <param name="pos"></param>
/// <returns></returns>
public abstract OutputStruct Unformat(byte[] messageBytes, ref int pos);
/// <summary>
/// 转换静态方法,把对象数组转换为字节数组。
/// </summary>
/// <param name="contents"></param>
/// <returns></returns>
public static byte[] TranslateContent(params object[] contents)
{
bool b = false;
//先查找传入的结构中有没有数组,有的话将其打开
var newContentsList = new List<object>();
foreach (object content in contents)
{
@@ -38,7 +57,9 @@ namespace ModBus.Net
newContentsList.Add(content);
}
}
//重新调用一边这个函数,这个传入的参数中一定没有数组。
if (b) return TranslateContent(newContentsList.ToArray());
//把参数一个一个翻译为相对应的字节,然后拼成一个队列
var translateTarget = new List<byte>();
foreach (object content in contents)
{
@@ -96,14 +117,21 @@ namespace ModBus.Net
}
}
}
//最后把队列转换为数组
return translateTarget.ToArray();
}
}
/// <summary>
/// 输入结构
/// </summary>
public class InputStruct
{
}
/// <summary>
/// 输出结构
/// </summary>
public class OutputStruct
{
}

View File

@@ -4,61 +4,37 @@ using System.Linq;
namespace ModBus.Net
{
public class TcpProtocalLinker : ProtocalLinker
public abstract class TcpProtocalLinker : ProtocalLinker
{
/// <summary>
/// 连接对象
/// </summary>
private TcpSocket _socket;
public TcpProtocalLinker()
protected TcpProtocalLinker()
{
//初始化连对象
_socket = new TcpSocket(ConfigurationManager.IP, int.Parse(ConfigurationManager.Port), false);
}
public override byte[] SendReceive(byte[] content)
{
//接收数据
byte[] receiveBytes = BytesDecact(_socket.SendMsg(BytesExtend(content)));
if (receiveBytes[1] > 127)
{
string message;
throw new ModbusProtocalErrorException(receiveBytes[2]);
}
//容错处理
if (!CheckRight(content)) return null;
//返回数据
return receiveBytes;
}
public override bool SendOnly(byte[] content)
{
return _socket.SendMsgWithoutReturn(BytesExtend(content));
}
}
public abstract class ProtocalLinkerBytesExtend
{
public abstract byte[] BytesExtend(byte[] content);
public abstract byte[] BytesDecact(byte[] content);
}
public class TcpProtocalLinkerBytesExtend : ProtocalLinkerBytesExtend
{
public override byte[] BytesExtend(byte[] content)
{
byte[] newFormat = new byte[6 + content.Length];
int tag = 0;
ushort leng = (ushort)content.Length;
Array.Copy(ValueHelper.Instance.GetBytes(tag), 0, newFormat, 0, 4);
Array.Copy(ValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2);
Array.Copy(content, 0, newFormat, 6, content.Length);
return newFormat;
}
public override byte[] BytesDecact(byte[] content)
{
byte[] newContent = new byte[content.Length - 6];
Array.Copy(content, 6, newContent, 0, newContent.Length);
return newContent;
}
}
public class ProtocalErrorException : Exception
{

View File

@@ -31,7 +31,7 @@ namespace ModBus.Net
private readonly string host;
// 2MB 的接收缓冲区,目的是一次接收完服务器发回的消息
private readonly byte[] m_receiveBuffer = new byte[200000];
private readonly byte[] m_receiveBuffer = new byte[1024];
private readonly int port;
public int m_errorCount = 0;
public int m_receiveCount = 0;

View File

@@ -2,20 +2,29 @@
namespace ModBus.Net
{
/// <summary>
/// 值与字节数组之间转换的辅助类这是一个Singleton类
/// 作者罗圣Chris L.
/// </summary>
public class ValueHelper
{
protected static bool _littleEndian = false;
protected ValueHelper()
{
}
/// <summary>
/// 协议中的内容构造是否小端的,默认是大端构造协议。
/// </summary>
public static bool LittleEndian
{
get { return _littleEndian; }
set
{
_littleEndian = value;
//这里需要重点说明,因为.net默认是小端构造法所以目标协议是大端的话反而需要调用小端构造协议把小端反转为大端。
_Instance = LittleEndian ? new ValueHelper() : new LittleEndianValueHelper();
}
}