本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议

ModbusFunction 类图如下:

如前文所述,所有请求/相应的 PDU 均继承自 ModbusFunction,其子类传入对应的 Function Code 并实现三个方法:

  1. CalculateLength:Data 部分的长度(该方法也可以为属性,但属性没有强制性,怕漏掉故改为抽象方法)
  2. Decode:从缓冲区解析 Data
  3. Encode:在传输前对 Data 编码

实现举例

每个 Function Code 均对应 ModbusFunction 的两个子类:请求类和响应类,以 0x03(读取保持寄存器值)为例:

请求类

请求报文 Data 说明:

public class ReadHoldingRegistersRequest : ModbusFunction
{
public ushort StartingAddress { get; private set; }
public ushort Quantity { get; private set; } public ReadHoldingRegistersRequest()
: base((short)ModbusCommand.ReadHoldingRegisters)
{ } public ReadHoldingRegistersRequest(ushort startingAddress, ushort quantity)
: base((short)ModbusCommand.ReadHoldingRegisters)
{
StartingAddress = startingAddress;
Quantity = quantity;
} public override int CalculateLength()
{
return 2 + 2; // StartingAddress Length + Quantity Length
}
public override void Decode(IByteBuffer buffer)
{
StartingAddress = buffer.ReadUnsignedShort();
Quantity = buffer.ReadUnsignedShort();
}
public override IByteBuffer Encode()
{
IByteBuffer buffer = Unpooled.Buffer();
buffer.WriteByte(FunctionCode); buffer.WriteUnsignedShort(StartingAddress);
buffer.WriteUnsignedShort(Quantity); return buffer;
}
}

响应类

响应报文 Data 说明:

public class ReadHoldingRegistersResponse : ModbusFunction
{
private ushort byteCount;
public ushort[] Registers { get; private set; } public ReadHoldingRegistersResponse()
: base((short)ModbusCommand.ReadHoldingRegisters)
{ } public ReadHoldingRegistersResponse(ushort[] registers)
: base((short)ModbusCommand.ReadHoldingRegisters)
{
Registers = registers;
byteCount = (ushort)(registers.Length * 2);
} public override int CalculateLength()
{
return 1 + byteCount;
} public override void Decode(IByteBuffer buffer)
{
byteCount = buffer.ReadByte();
Registers = new ushort[byteCount / 2];
for (int i = 0; i < Registers.Length; i++)
{
Registers[i] = buffer.ReadUnsignedShort();
} } public override IByteBuffer Encode()
{
IByteBuffer buffer = Unpooled.Buffer();
buffer.WriteByte(FunctionCode);
buffer.WriteByte(byteCount); foreach (var register in Registers)
{
buffer.WriteUnsignedShort(register);
} return buffer;
}
}

其中 ModbusCommand 为 Function Code 的枚举:

enum ModbusCommand : short
{ ReadCoils = 0x01,
ReadDiscreteInputs = 0x02,
ReadHoldingRegisters = 0x03,
ReadInputRegisters = 0x04,
WriteSingleCoil = 0x05,
WriteSingleRegister = 0x06, WriteMultipleCoils = 0x0F,
WriteMultipleRegisters = 0x10, }

文中为方便理解请求类和响应类均直接继承 ModbusFunction,实际开发中请求类和响应类均没有直接继承 ModbusFunction,而是根据其他 Function Code 的 Data 进行再次抽象后继承。

开源地址:modbus-tcp

DotNetty 实现 Modbus TCP 系列 (二) ModbusFunction 类图及继承举例的更多相关文章

  1. DotNetty 实现 Modbus TCP 系列 (一) 报文类

    本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议 Modbus TCP/IP 报文 报文最大长度为 260 byte (ADU = 7 byte MBAP Header ...

  2. DotNetty 实现 Modbus TCP 系列 (三) Codecs & Handler

    本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议 DotNetty 作为一个半成品,我们不需要关注细节的实现,只需要关注自己的业务即可,所以最主要的就是处理 Codecs ...

  3. DotNetty 实现 Modbus TCP 系列 (四) Client & Server

    本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议 Client public class ModbusClient { public string Ip { get; } ...

  4. c/c++ 模板与STL小例子系列<二> 模板类与友元函数

    c/c++ 模板与STL小例子系列 模板类与友元函数 比如某个类是个模板类D,有个需求是需要重载D的operator<<函数,这时就需要用到友元. 实现这样的友元需要3个必要步骤 1,在模 ...

  5. UML学习(二)-----类图

    UML学习(二)-----类图 http://www.cnblogs.com/silent2012/archive/2011/09/07/2169946.html http://www.cnblogs ...

  6. 转载:UML学习(二)-----类图(silent)

    原文:http://www.cnblogs.com/huiy/p/8552607.html 1.什么是类图 类图(Class diagram)主要用于描述系统的结构化设计.类图也是最常用的UML图,用 ...

  7. UML类图关系(继承、泛化、实现、依赖、关联、聚合、组合)

    继承.实现.依赖.关联.聚合.组合的联系与区别 分别介绍这几种关系: 继承 指的是一个类(称为子类.子接口)继承另外的一个类(称为父类.父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者 ...

  8. UML类图关系--继承(泛化)、实现、关联、聚合、组合、依赖

    在UML类图中,常见的有以下几种关系:  泛化(Generalization),  实现(Realization),关联(Association),聚合(Aggregation),组合(Composi ...

  9. Java多线程系列二——Thread类的方法

    Thread实现Runnable接口并实现了大量实用的方法 public static native void yield(); 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机 ...

随机推荐

  1. <网络编程>基本TCP套接字编程

    tcp提供了可靠传输,当tcp向另一端发送数据的时候,要求对端返回一个确认.如果没有接收到确认,tcp就重传数据并且等待更长时间,数次重传失败后,tcp才放弃. 建立一个tcp连接会发生如下事情: 服 ...

  2. 工具篇-Json处理

    1. @JsonProperty和@SerializedName注解 使用场景 将一个json格式的字符串转换成某个java对象,或者将一个java对象转换成json格式的字符串时,如果json字符串 ...

  3. redis学习(一)——redis介绍及安装

    一.redis简介 redis是一个高性能的key-value非关系数据库,它可以存键(key)与5种不同类型的值(value)之间的映射(mapping),支持存储的value类型包括:String ...

  4. BZOJ3199 SDOI2013 逃考 半平面交、最短路

    传送门 如果我们对于每一个点能找到与其相邻的点(即不经过其他点监视范围能够直接到达其监视范围的点)和是否直接到达边界,就可以直接BFS求最短路求出答案. 所以当前最重要的问题是如何找到对于每一个点相邻 ...

  5. ML.NET 示例:回归之价格预测

    写在前面 准备近期将微软的machinelearning-samples翻译成中文,水平有限,如有错漏,请大家多多指正. 如果有朋友对此感兴趣,可以加入我:https://github.com/fei ...

  6. Linux 用户身份与进程权限

    在学习 Linux 系统权限相关的主题时,我们首先关注的基本都是文件的 ugo 权限.ugo 权限信息是文件的属性,它指明了用户与文件之间的关系.但是真正操作文件的却是进程,也就是说用户所拥有的文件访 ...

  7. JVM参数配置 java内存区域

    java内存区域 一些基本概念 http://www.importnew.com/18694.html https://www.cnblogs.com/wangyayun/p/6557851.html ...

  8. DSSM:深度语义匹配模型(及其变体CLSM、LSTM-DSSM)

    导语 在NLP领域,语义相似度的计算一直是个难题:搜索场景下Query和Doc的语义相似度.feeds场景下Doc和Doc的语义相似度.机器翻译场景下A句子和B句子的语义相似度等等.本文通过介绍DSS ...

  9. Python-Django下载与基本命令

    1.下载Django: pip3 install django 2.创建一个django project django-admin.py startproject mysite 当前目录下会生成mys ...

  10. Python入门-Hello Word

    1.python语言介绍 Python创始人:Guido Van Rossum 2.python是一种解释型.动态类型计算机程序设计语言. 解释型:程序无需编译成二进制代码,而是在执行时对语句一条一条 ...