物联网RTU(Modbus TCP协议)Java接口开发及Modbus Slave仿真使用
Posted 肖永威
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了物联网RTU(Modbus TCP协议)Java接口开发及Modbus Slave仿真使用相关的知识,希望对你有一定的参考价值。
在物联网体系中,经常用到RTU(远程终端单元),RTU是负责对现场信号、工业设备的监测和控制,通常由信号输入/出模块、微处理器、有线/无线通讯设备、电源及外壳等组成,由微处理器控制,并支持网络系统。
在物联网应用平台上,需要通过RTU与现场设备对接,采集现场数据、控制设备,通过网络与RTU连接,主要是采用Modbus TCP协议。
Modbus是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一种通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一个控制器请求访问其它设备的过程,如何回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。
物联网应用软件开发,需要与RTU接口,为了方便软件开发,降低对物联网设备的依赖,Modbus仿真软件也就出现,对此,物联网开发人员应该很熟悉,但是对于普通互联网开发人员,还是很陌生的,为此,此文介绍ModbusTCP仿真软件使用和基于Netty的RTU java接口开发。
1、ModbusTCP仿真
ModbusSlave(软件官方网站地址)是一个从站设备仿真软件,它用于接收主设备的命令包,并回送数据包;可用于测试和调试Modbus主站设备,便于观察Modbus通信过程中的各种报文。ModbusPoll及ModbusSlave支持ModbusRTU, ASCII,TCP/IP等协议。
首先,了解MODBUS支持的部分功能代码,以十进制表示,如下表所示。
代码 | 中文名称 | 英文名称 | 位操作/字操作 | 操作数量 |
---|---|---|---|---|
01 | 读线圈状态 | READ COIL STATUS | 位操作 | 单个或多个 |
02 | 读离散输入状态 | READ INPUT STATUS | 位操作 | 单个或多个 |
03 | 读保持寄存器 | READ HOLDING REGISTER | 字操作 | 单个或多个 |
04 | 读输入寄存器 | READ INPUT REGISTER | 字操作 | 单个或多个 |
05 | 写线圈状态 | WRITE SINGLE COIL | 位操作 | 单个 |
06 | 写单个保持寄存器 | WRITE SINGLE REGISTER | 字操作 | 单个 |
15 | 写多个线圈 | WRITE MULTIPLE COIL | 位操作 | 多个 |
16 | 写多个保持寄存器 | WRITE MULTIPLE REGISTER | 字操作 | 多个 |
参数设置:
点击菜单“Setup”中“Slave Definition.. F2”进行参数设置,会弹出如下图对话框
其中:
(1)Slave ID:设备ID;
(2)Function:对应上表所对应的Modbus功能,例如本文所选用的“03 Holding Register…”,与下文Java代码“见类ReadHoldingRegistersResponse ”所对应。
(3)Address:寄存器地址;
(4)Quantity:数量。
打开ModbusSlave软件,为方便起见,本文采用默认的地址(localhost,与下文第二段代码对应“见类ClientForTests ”),功能码,寄存器数量,单击Connection->connect,在弹出的窗口设置connection为TCP/IP,端口Port设置为30502,点击OK,如下图所示,从端配置完毕。
注意:
(1)本文连接Connection采用Modbus TCP/IP协议;
(2)网络地址为本地地址,127.0.0.1;
(3)端口与下文第二段代码“见类ClientForTests”中的地址和端口设置为“30502”;
(4)选择“Ignore Unit ID”,如果不选择,测试程序返回空值。
2、基于Netty实现RTU接口
本文Java代码,来源于modjn(https://github.com/klymenek/modjn),基于Netty 4.x实现Modbus TCP客户端和服务端(Modbus TCP client/server implementation in Java with Netty 4.x)。
package de.gandev.modjn.example;
import de.gandev.modjn.ModbusClient;
import de.gandev.modjn.entity.exception.ConnectionException;
import de.gandev.modjn.entity.exception.ErrorResponseException;
import de.gandev.modjn.entity.exception.NoResponseException;
import de.gandev.modjn.entity.func.response.ReadCoilsResponse;
import de.gandev.modjn.entity.func.response.ReadHoldingRegistersResponse;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author XiaoYW
*
*/
public class TestModbusSlave
public static void main(String[] args)
ModbusClient modbusClient = ClientForTests.getInstance().getModbusClient();
ReadCoilsResponse readCoils = null;
try
readCoils = modbusClient.readCoils(12321, 5);
catch (NoResponseException | ErrorResponseException | ConnectionException ex)
Logger.getLogger(Example.class.getName()).log(Level.SEVERE, ex.getLocalizedMessage());
System.out.println(readCoils);
ReadHoldingRegistersResponse readHolding = null;
try
readHolding = modbusClient.readHoldingRegisters(2200,10);
catch (NoResponseException | ErrorResponseException | ConnectionException ex)
Logger.getLogger(Example.class.getName()).log(Level.SEVERE, ex.getLocalizedMessage());
System.out.println(readHolding);
modbusClient.close();
客户端测试代码,如下文所示。
package de.gandev.modjn.example;
import de.gandev.modjn.ModbusClient;
import de.gandev.modjn.entity.exception.ConnectionException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author ares
*/
public class ClientForTests
private final ModbusClient modbusClient;
private ClientForTests()
modbusClient = new ModbusClient("localhost" /*
* "192.168.1.55"
*/, 30502); //ModbusConstants.MODBUS_DEFAULT_PORT);
try
modbusClient.setup();
catch (ConnectionException ex)
Logger.getLogger(ClientForTests.class.getName()).log(Level.SEVERE, null, ex);
public ModbusClient getModbusClient()
return modbusClient;
public static ClientForTests getInstance()
return ClientAndServerHolder.INSTANCE;
private static class ClientAndServerHolder
private static final ClientForTests INSTANCE = new ClientForTests();
以Java应用程序运行,运行结果:
ReadCoilsResponsebyteCount=1, coilStatus=0, 3
ReadHoldingRegistersResponsebyteCount=20,
inputRegisters=register_0=2, register_1=0, register_2=0, register_3=3, register_4=0, register_5=0, register_6=8, register_7=0, register_8=0, register_9=0
参考:
《谈谈基于Netty实现Restful搭建服务架构思路》 CSDN博客 肖永威 2018年7月
《Modbus学习总结》 CSDN博客 深之JohnChen的专栏 2017年9月
以上是关于物联网RTU(Modbus TCP协议)Java接口开发及Modbus Slave仿真使用的主要内容,如果未能解决你的问题,请参考以下文章