package com.modbus;
import java.nio.ByteBuffer;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.msg.ModbusRequest;
import com.serotonin.modbus4j.msg.ModbusResponse;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersResponse;
import com.serotonin.util.queue.ByteQueue;
/**
* modbus 处理类
* @author xuao
*
*/
public class ModbusHandler {
static ModbusFactory modbusFactory;
static {
if (modbusFactory == null) {
modbusFactory = new ModbusFactory();
}
}
/**
* 得到 WriteRegistersRequest
*
* @param ip
* @param port
* @param slaveId
* @param start
* @param values
*/
public static WriteRegistersRequest getWriteRegistersRequest(int slaveId,
int start, short[] values) {
WriteRegistersRequest request = null;
try {
request = new WriteRegistersRequest(slaveId, start, values);
} catch (ModbusTransportException e) {
e.printStackTrace();
}
return request;
}
/**
* 得到 WriteRegistersRequest
*
* @param ip
* @param port
* @param slaveId
* @param start
* @param values
*/
public static WriteRegistersResponse getWriteRegistersResponse(
ModbusMaster tcpMaster, WriteRegistersRequest request) {
WriteRegistersResponse response = null;
try {
response = (WriteRegistersResponse) tcpMaster.send(request);
} catch (ModbusTransportException e) {
e.printStackTrace();
}
return response;
}
/**
* 写入
*
* @param ip
* @param port
* @param slaveId
* @param start
* @param values
*/
public static int modbusWTCP(String ip, int port, int slaveId, int start,
short[] values) {
ModbusMaster tcpMaster = getTcpMaster(ip, port, slaveId);
if (tcpMaster == null) {System.out.println("tcpMaster is null ");return 0;}
tcpMaster = initTcpMaster(tcpMaster);
WriteRegistersRequest request = getWriteRegistersRequest(slaveId,start, values);
WriteRegistersResponse response = getWriteRegistersResponse(tcpMaster,request);
if (response.isException()) {
return 0;
} else {
return 1;
}
}
/**
* 初始化?tcpMaster
*
* @param tcpMaster
* @return
*/
public static ModbusMaster initTcpMaster(ModbusMaster tcpMaster) {
if (tcpMaster == null)return null;
try {
tcpMaster.init();
return tcpMaster;
} catch (ModbusInitException e) {
return null;
}
}
/**
* 得到 ModbusRequest
*
* @param salveId
* @param start
* @param readLenth
* @param tcpMaster
*/
public static ModbusRequest getRequest(int salveId, int start,
int readLenth, ModbusMaster tcpMaster) {
ModbusRequest modbusRequest = null;
try {
modbusRequest = new ReadHoldingRegistersRequest(salveId, start,readLenth);
return modbusRequest;
} catch (ModbusTransportException e) {
e.printStackTrace();
return null;
}
}
/**
* 得到 ModbusResponse
*
* @param salveId
* @param start
* @param readLenth
* @param tcpMaster
*/
public static ModbusResponse getModbusResponse(ModbusMaster tcpMaster,
ModbusRequest request) {
ModbusResponse modbusResponse = null;
try {
modbusResponse = tcpMaster.send(request);
return modbusResponse;
} catch (ModbusTransportException e) {
e.printStackTrace();
return null;
}
}
/**
* 获取 设备数据
* @param ip
* 信息机地址ip
* @param port
* 端口 默认 端口502
* @param salveId
* 从站地址
* @param start
* 数据报文 的 起始 位置
* @param readLenth
* 读取的长度
* @return 结果
*/
public static ByteQueue modbusRTCP(String ip, int port, int salveId,
int start, int readLenth) {
ModbusMaster tcpMaster = getTcpMaster(ip, port, salveId);// 得到tcpMaster
if (tcpMaster == null) {System.out.println("tcpMaster is null ");return null;
}
return modbusRTCP0(ip, port, salveId, start, readLenth, tcpMaster);
}
/**
* 获取 tcp master
*
* @param ip
* @param port
* @param salveId
*/
public static ModbusMaster getTcpMaster(String ip, int port, int salveId) {
IpParameters params = new IpParameters();
params.setHost(ip);// 设置ip
if (port == 0)params.setPort(502);// 设置端口,默认为502
else params.setPort(port);
ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, true);// 获取ModbusMaster对象
return tcpMaster;
}
/**
* modbus 读取
*
* @param ip
* @param port
* @param salveId
* @param start
* @param readLenth
* @param tcpMaster
* @return
*/
public static ByteQueue modbusRTCP0(String ip, int port, int salveId,
int start, int readLenth, ModbusMaster tcpMaster) {
if (tcpMaster == null) {System.out.println("tcpMaster is null");return null;}
tcpMaster = initTcpMaster(tcpMaster);// 初始化tcpmaster
if (tcpMaster == null) {System.out.println("tcpMaster is null");return null;
}
ModbusRequest modbusRequest = getRequest(salveId, start, readLenth,tcpMaster);// 得到requst 对象
if (modbusRequest == null) {System.out.println("request is null");return null;}
ModbusResponse response = getModbusResponse(tcpMaster, modbusRequest);// 发送请求,得到Response
ByteQueue byteQueue = new ByteQueue(12);
response.write(byteQueue);
System.out.println("功能" + modbusRequest.getFunctionCode());
System.out.println("从站地址:" + modbusRequest.getSlaveId());
System.out.println("收到的响应信息大小" + byteQueue.size());
System.out.println("收到的响应信息小:" + byteQueue);
return byteQueue;
}
/* *
* Convert byte[] to hex
* string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串
* @param src byte[] data
* @return hex string
*/
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
/**
* ***************************************************
* 起始位置15,响应数据:从站|data包含的传感器个数|data length|data*
* ***************************************************
*
* @param bq
*/
public static void ansisByteQueue(ByteQueue bq) {
byte[] result = bq.peekAll();
System.out.println("从站地址===" + result[0]);
System.out.println("data 个数===" + result[1]);
System.out.println("data 长度===" + result[2]);
byte[] temp = null;
ByteBuffer buffer = ByteBuffer.wrap(result, 3, result.length - 3);//直接获取 data
while (buffer.hasRemaining()) {
temp = new byte[2];
buffer.get(temp, 0, temp.length);
System.out.print(Integer.parseInt(bytesToHexString(temp), 16)+" ");
}
}
public static void main(String[] args) {
ByteQueue result = ModbusHandler.modbusRTCP("169.254.48.188", 502, 2,
15, 3);
ansisByteQueue(result);
short[] shor = new short[1];
shor[0] = 0x33;
ModbusHandler.modbusWTCP("169.254.48.188", 502, 2, 15, shor);
}
}
在工业自动化领域,Modbus是一种广泛应用的通信协议,它允许不同设备之间进行数据交换,尤其在PLC(可编程逻辑控制器)和上位机之间。Java作为一种通用编程语言,也支持与Modbus设备进行通讯。本篇文章将深入探讨Java如何通过RTU(Remote Terminal Unit)协议实现与Modbus设备的TCP通信,并结合提供的`modbus4j.jar`和`seroUtils.jar`库,展示一个获取设备传感器数据的实战示例。 我们要理解Modbus协议的基本概念。Modbus是基于ASCII或RTU(二进制)编码的主从结构通信协议,它定义了数据在设备间的传输格式。RTU协议适用于串行链路,而TCP协议则扩展了Modbus到网络环境。在TCP模式下,数据包以TCP/IP封装,增加了网络层的可靠性。 Java实现Modbus通讯,通常需要依赖第三方库,如本例中的`modbus4j.jar`。这个库提供了丰富的API,能够处理Modbus的TCP和RTU通信,以及读写寄存器、线圈、输入寄存器等功能。`seroUtils.jar`可能是用于串口通信辅助的库,因为RTU协议通常通过串口进行。 以下是一个简单的Java程序,使用`modbus4j`库实现与Modbus设备的TCP连接,读取设备传感器数据的步骤: 1. 引入依赖库: ```java import org.modbus4j.*; import org.modbus4j.transport.*; import org.modbus4j.ip.tcp.*; ``` 2. 创建TCP连接: ```java TcpMasterTransport transport = new TcpMasterTransport("192.168.1.100", 502); // IP地址和端口号 ModbusMaster master = new ModbusMaster(transport); ``` 3. 打开连接: ```java transport.connect(); ``` 4. 发送读取请求(例如读取输入寄存器): ```java int startingAddress = 1; // 从哪个寄存器开始读取 int numInputs = 10; // 要读取的寄存器数量 ReadInputRegistersRequest request = new ReadInputRegistersRequest(startingAddress, numInputs); ModbusResponse response = master.execute(request); ``` 5. 处理响应,获取数据: ```java ReadInputRegistersResponse resp = (ReadInputRegistersResponse) response; int[] sensorData = resp.getInputs(); for (int i : sensorData) { System.out.println("Sensor data: " + i); } ``` 6. 关闭连接: ```java transport.disconnect(); ``` 这个示例展示了如何使用Java和`modbus4j`库来实现与Modbus设备的TCP通信,获取传感器数据。在实际应用中,你可能需要根据设备手册调整寄存器地址和数量,以及处理异常情况。 总结起来,Java与Modbus通讯交互涉及到的主要知识点包括:Modbus协议的基础知识,RTU和TCP的区别,如何使用Java第三方库(如modbus4j)进行通信,以及如何构建和解析Modbus请求和响应。在实际项目中,理解这些概念并熟练应用,可以有效实现设备之间的数据交换,提升自动化系统的效率。
- 1
- #完美解决问题
- #运行顺畅
- #内容详尽
- #全网独家
- #注释完整
- 吃可爱多长大的程序员2020-09-22????没用
- 粉丝: 29
- 资源: 6
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 一维信号的低频与高频成分的小波多维分解与重构实例-附Matlab源代码.m
- 风力涡轮机缺陷检测数据集,86.6%准确识别率,11921张图片,支持yolov9格式的标注,
- 虫星社会环境研究报告.txt
- 基于粒子群算法PSO的宽带消色差超透镜 matlab核心程序 FDTD仿真
- 基于ssm的在线电影票购买系统的设计与实现源码(java毕业设计完整源码+LW).zip
- 风力涡轮机缺陷检测数据集,86.6%准确识别率,11921张图片,支持yolov8格式的标注,
- 橙色漂亮响应式的水果果汁店网站模板下载.zip
- 橙色漂亮精致的企业网站模板下载.zip
- 橙色清新的手机app应用官网网站模板下载.zip
- 橙色清新风格的抽象卡通设计网站模板下载.zip
- 橙色全屏风格的网站建设公司企业网站模板.rar
- 橙色实用风格的登录表单源码下载.zip
- 橙色三栏式的个人博客模板下载.zip
- 橙色实用风格的Movie电影门户网站模板下载.zip
- 橙色实用风格的公司企业网站模版下载.zip
- 橙色实用风格的科技企业网站模板.zip