# 一、Modbus协议

参考:MODBUS-RTU协议

# 基于Netty实现

# 案例分析

系统服务采集智能水电表数据

本次水电表采用的协议是Modbus-RTU协议,而该协议只是头部携带了地址码,所以我疑惑部署在机房的服务器如何只通过地址码去跟设备建立建立,在查阅了相关资料后,我的理解如下: 串口通信不能接入网络,所以通过串口获取设备数据的服务应该在物理上跟设备是连接的,串口服务要接入网络,需要使用串口服务器,所以我们的系统要采集智能水电表的数据,需要通过TCP/IP跟串口服务器建立连接,然后再由串口服务器通过串口采集水电表设备信息。

下面例子是从01号从机读1个采集到的基本数据,采集的数据为总用水量(占用4个字节,如下面返回数据中的两个寄存器数据),下面的高字节和低字节指的是以一个字节大小为划分,用16进制的格式展示的数据内容,所以无论高低字节,本质都是一字节的大小。

image-20220828160538714

# 代码实现

水表对接的案例代码已经上传到github,进入上面地址并选择nettymodubus目录,各个类的解析

  • DataCacheMap:缓存采集的数据,避免每采集一个设备发送一次kafka,通过定时认为定时将缓存中的数据批量发送
  • ChannelMap:缓存连接的管道,避免创建大量连接
  • ServerDeviceMap:保存串口服务器对应的设备地址码
  • NettyClient:创建Netty Bootstrap,提供连接建立、请求发送的功能。
  • WaterMeterDecoder:Modbus协议解码器
  • WaterMeterEncoder:Modbus协议编码器
  • WaterMeterHandler:经过解码器后进入改处理器,提取采集的数据
  • WaterMeterNettyService:提供设备采集,数据同步至kafka的方法,由定时任务调用

# 问题

  1. 用了Netty和不用Netty有什么区别?

如果没有Netty,连接流程是这样的:通过BIO Socket跟设备建立连接,并且阻塞等待结果。而有了Netty后,连接不再阻塞,而是简历channel注入seletor多路复用器,客户端线程可以直接返回,由netty线程监听channel的IO事件。

  1. Netty接收层是几个实例的?可以横向扩展吗?

目前是一个,通过定时任务的方式扫描各个服务区串口服务器及对应的设备地址码,并将各个服务区的设备采集任务提交到线程池,开启多线程处理(为什么不细分到单个设备的采集开启一个线程?因为串口服务器一次只允许有一个消息在总线上传输)

  1. 从设备的机器码可能会重复吗?是一个服务区带一个串口服务器接入网络?

同个串口服务器上的从设备地址码不可重复,不同串口服务器上的设备地址码可以重复。

  1. Netty的pipeline是如何实现的?

pipeline本质是一个双端链表,自定义的handler分别实现了in,out接口,在编排的时候我们从上往下的顺序添加handler

  • 对于in接口:从前往后添加到链表
  • 对于out接口:从后往前添加到链表
Last Updated: 2022-9-6 3:18:49 ├F10: PM┤