DotNetty 实现 Modbus TCP 系列 (一) 报文类
本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议
Modbus TCP/IP 报文
- 报文最大长度为 260 byte (ADU = 7 byte MBAP Header + 253 byte PDU)
- Length = Unit Identifier 长度 + PDU 长度
MBAP Header
PDU
PDU 由两部分构成:Function Code(功能码) 和 Data 组成
Function Code
部分功能码:
报文类
ModbusHeader
public class ModbusHeader
{
public ushort TransactionIdentifier { get; set; }
public ushort ProtocolIdentifier { get; set; }
public ushort Length { get; set; }
public short UnitIdentifier { get; set; }
public ModbusHeader(IByteBuffer buffer)
{
TransactionIdentifier = buffer.ReadUnsignedShort();
ProtocolIdentifier = buffer.ReadUnsignedShort();
Length = buffer.ReadUnsignedShort();
UnitIdentifier = buffer.ReadByte();
}
public ModbusHeader(ushort transactionIdentifier, short unitIdentifier)
: this(transactionIdentifier, 0x0000, unitIdentifier) // for modbus protocol: Protocol Identifier = 0x00
{
}
private ModbusHeader(ushort transactionIdentifier, ushort protocolIdentifier, short unitIdentifier)
{
TransactionIdentifier = transactionIdentifier;
ProtocolIdentifier = protocolIdentifier;
UnitIdentifier = unitIdentifier;
}
public IByteBuffer Encode()
{
IByteBuffer buffer = Unpooled.Buffer();
buffer.WriteUnsignedShort(TransactionIdentifier);
buffer.WriteUnsignedShort(ProtocolIdentifier);
buffer.WriteUnsignedShort(Length);
buffer.WriteByte(UnitIdentifier);
return buffer;
}
}
ModbusHeader 对应 MBAP Header,包含两个构造函数:第一个构造函数用于从缓冲区解析消息头,第二个构造函数用来请求/响应时手动构造消息头。Encode 方法用于在传输前对消息头进行编码。
ModbusFunction
public abstract class ModbusFunction
{
protected short FunctionCode { get; }
protected ModbusFunction(short functionCode)
{
FunctionCode = functionCode;
}
/// <summary>
/// PDU length -1 (not include function code length)
/// </summary>
/// <returns></returns>
public abstract int CalculateLength();
public abstract void Decode(IByteBuffer buffer);
public abstract IByteBuffer Encode();
}
ModbusFunction 对应 PDU,该类为抽象类,所有的请求/相应的 PDU 均继承自该类。实际使用中根据 FunctionCode 实例化具体的子类对象。其中 CalculateLength 方法用来计算 Data 部分的长度,Decode 方法用于从缓冲区解析 Data,Encode 方法用于在传输前对 Data 编码。
ModbusFrame
public class ModbusFrame
{
public ModbusHeader Header { get; set; }
public ModbusFunction Function { get; set; }
public ModbusFrame(ModbusHeader header, ModbusFunction function)
{
Header = header;
Function = function;
}
public IByteBuffer Encode()
{
Header.Length = (ushort)(1 + 1 + Function.CalculateLength());// Unit Identifier + Function Code + data length
IByteBuffer buffer = Unpooled.Buffer();
buffer.WriteBytes(Header.Encode());
buffer.WriteBytes(Function.Encode());
return buffer;
}
}
ModbusFrame 对应 ADU。Encode 方法用于在传输前对 ADU 编码。
开源地址:modbus-tcp
DotNetty 实现 Modbus TCP 系列 (一) 报文类的更多相关文章
- DotNetty 实现 Modbus TCP 系列 (二) ModbusFunction 类图及继承举例
本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议 ModbusFunction 类图如下: 如前文所述,所有请求/相应的 PDU 均继承自 ModbusFunction, ...
- DotNetty 实现 Modbus TCP 系列 (三) Codecs & Handler
本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议 DotNetty 作为一个半成品,我们不需要关注细节的实现,只需要关注自己的业务即可,所以最主要的就是处理 Codecs ...
- DotNetty 实现 Modbus TCP 系列 (四) Client & Server
本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议 Client public class ModbusClient { public string Ip { get; } ...
- 开源 DotNetty 实现的 Modbus TCP/IP 协议
本项目的目的是为了学习 DotNetty 与 Modbus 协议,参考 modjn 实现功能 0x01: Read Coils (读取线圈/离散量输出状态) 0x02: Read Discrete I ...
- 【.NET6+Modbus】Modbus TCP协议解析、仿真环境以及基于.NET实现基础通信
前言:随着工业化的发展,目前越来越多的开发,从互联网走向传统行业.其中,工业领域也是其中之一,包括各大厂也都在陆陆续续加入工业4.0的进程当中. 工业领域,最核心的基础设施,应该是与下位硬件设备或程序 ...
- modbus tcp数据报文结构
modbus tcp数据报文结构 请求:00 00 00 00 00 06 09 03 00 00 00 01 响应:00 00 00 00 00 05 09 03 02 12 34 一次modbus ...
- Modbus TCP 示例报文
调试modbus tcp 整理百度文库文档如下 <modbus-tcp-报文举例分析> <MODBUSTCP通讯报文> Client request: 19 B2 00 00 ...
- C#ModBus Tcp 报文解析
上一篇博客已经完成 C#ModBus Tcp Master的实现 本篇主要对不同的功能码所发出的报文进行解析(包括请求报文及响应报文) 读操作 功能码 0x01 读一组线圈 读取站号为1 从地址12开 ...
- 开放型Modbus/TCP 规范
修订版 1.0,1999 年3 月29 日Andy SwalesSchneider 电气公司aswales@modicon.com目录目录............................... ...
随机推荐
- odoo8 和odoo10区别
V8 函数:'sale_order_count': fields.function(_sale_order_count, string='# of Sales Order', type='integ ...
- hibernate(*.hbm.xml)中新添加的字段被标记为红色(找不到)的解决方法
首先得是以这个方式生成的bean和xml,配置好了数据源(这样才能让hibernate中的配置和mysql进行交互) https://www.cnblogs.com/kinome/p/10549969 ...
- Java执行JavaScript脚本破解encodeInp()加密
一:背景 在模拟登录某网站时遇到了用户名和密码被JS进行加密提交的问题,如图: 二:解决方法 1.我们首先需要获得该JS加密函数,一般如下: conwork.js var keyStr = " ...
- 撒花!中文翻译仓库链接已加入 ML.NET 官方示例网站首页
从2018年12月02日决定开始做ML.NET 示例中文版https://github.com/feiyun0112/machinelearning-samples.zh-cn,然后以每天一篇的速度进 ...
- python 操作数据库
官方文档:https://www.python.org/dev/peps/pep-0249/ 1.创建connection,建立网络连接 MySQLdb.Connect(host,port,user, ...
- 容器互联(linking)
容器互联(linking)是一种让多个容器中的应用进行快速交互的方式. 它会在源和接受容器中间创建连接关系,接受容器可以通过容器名快速访问到源容器而不用指出具体的IP地址.
- 牛客国庆集训派对Day2
题目链接:https://www.nowcoder.com/acm/contest/202/A A 题意:给出最大4096*64和64*4096的矩阵,其中有一个矩阵只含有0和1,问你它们相乘所得到得 ...
- c++ 入门之对象指针
我们想 像使用基本数据类型一样使用类,自然,类自然也有指针,我们通过下面的代码来领教一下对象指针存在的意义: # include "iostream" # include &quo ...
- ElastichSearch漏洞
Ubuntu服务器被黑经历(ElastichSearch漏洞) 起因 最近我们的一台Ubuntu阿里云服务器一直提示有肉鸡行为,提示了好几天,开始并没有关注,然后连续几天后发现应该是个大问题啊.很可能 ...
- semantic-ui 标题
在semantic-ui中定义了5中标题样式,注意HTML中有h1-h6,而semantic-ui中只有h1-h5. 不过需要注意的是,semantic-ui的标题仍旧使用h1-h5来表示,但是在cl ...