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目录目录............................... ...
随机推荐
- 初学Python——字符串相关操作
基本字符串操作 Pyhton中字符串的格式化输出在前面已经总结了,接下来介绍一些常用的字符串操作 先定义一个字符变量,以下的操作都以此为例: name=" my name is china ...
- lower_bound
头文件: #include<algorithm> 作用: 查找第一个大于或等于给定数的元素或位置 在从小到大的排列数组中 注意注意: 是排列好的, 一般都是从小到大, 但从大到小也可以, ...
- AJAX请求返回HTTP 400 错误 - 请求无效 (Bad request)
在ajax请求后台数据时有时会报HTTP400错误-请求无效(Badrequest);出现这个请求无效报错说明请求没有进入到后台服务里: 原因: 1)前端提交数据的字段名称或者是字段类型和后台的实体类 ...
- 初窥RabbitMQ消息中间及SpringBoot整合
一:RabbitMQ简介 RabbitMQ介绍 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. 消息中间件最主要的作用是解耦,中间件最标准 ...
- 【C#复习总结】细说表达式树
1 前言 系类1:细说委托 系类2:细说匿名方法 系列3:细说Lambda表达式 系列4:细说泛型委托 系列5:细说表达式树 系列6:细说事件 涛声依旧,再续前言,接着用大佬的文章作为开头. 表达式树 ...
- 五子棋(无AI winform gdi+)
之前无意间在博客园看到一篇用深度学习玩马里奥的文章,于是就想做这个小东西来测试人工智能算法(准备用PYTHON的库,对神经网络的梦已经做了好多年了,但是太难了,一直懒得动它),本来是想用WPF做UI, ...
- VMware vSphere 6 序列号
vSphere 6 Hypervisor HY0XH-D508H-081U8-JA2GH-CCUM2 4C4WK-8KH8L-H85J0-UHCNK-8CKQ8 NV09R-2W007-08D38-C ...
- H5 21-属性选择器下
21-属性选择器下 --> <!DOCTYPE html> <html lang="en"> <head> <meta charse ...
- Django admin参数配置
admin参数配置 一. admin 启动 admin: Django的后台数据管理的web版本 针对Food表,url: http://127.0.0.1:8000/admin/app02/food ...
- 解决sqoop连接mysq错误
一.问题描述 1.由于当前集群没有配置Zookeeper.hcatalog.accumlo,因此应该在sqoop的配置文件中注释掉判断Zookeeper.hcatalog.accumlo路径是否正确的 ...