java与modbusRtu(COM口)通讯

2024-09-04 06:18
文章标签 java com 通讯 modbusrtu

本文主要是介绍java与modbusRtu(COM口)通讯,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • modbous协议通讯byte数据解析含义
  1. 依赖的modbus包请看java与modbusTcp通讯
  2. JDK中配置串口通讯能力 提取码:hmfn
  3. 串口模拟工具 提取码: npqx
  4. 依赖串口协议包:
<dependency><groupId>org.rxtx</groupId><artifactId>rxtx</artifactId><version>2.1.7</version>
</dependency>
  • 实现代码 1 抽象类
import com.serotonin.modbus4j.serial.SerialPortWrapper;
import gnu.io.SerialPort;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;public abstract class AbstractSerialPortWrapper implements SerialPortWrapper {private SerialPort serialPort = null;private Integer baudRate;private String port;protected AbstractSerialPortWrapper(String port,Integer baudRate){this.port = port;this.baudRate = baudRate;}@Overridepublic void close() throws Exception {if(serialPort != null){serialPort.close();}}@Overridepublic void open() throws Exception {serialPort = serialPort(port);}@Overridepublic InputStream getInputStream() {try {if(serialPort != null){return serialPort.getInputStream();}} catch (IOException e) {throw new RuntimeException("对象空指针异常");}throw new RuntimeException("对象空指针异常");}@Overridepublic OutputStream getOutputStream() {try {if(serialPort != null){return serialPort.getOutputStream();}} catch (IOException e) {throw new RuntimeException("对象空指针异常");}throw new RuntimeException("对象空指针异常");}@Overridepublic int getBaudRate() {return baudRate;}@Overridepublic int getFlowControlIn() {return SerialPort.FLOWCONTROL_NONE;}@Overridepublic int getFlowControlOut() {return SerialPort.FLOWCONTROL_NONE;}@Overridepublic int getDataBits() {return SerialPort.DATABITS_8;}@Overridepublic int getStopBits() {return SerialPort.STOPBITS_1;}@Overridepublic int getParity() {return SerialPort.PARITY_EVEN;}public abstract SerialPort serialPort(String portName);
}
  • 实现代码 2 支持类
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;public class SerialPortSupport extends AbstractSerialPortWrapper {public SerialPortSupport(String port,Integer baudRate){super(port,baudRate);}/*** 查找所有可用端口** @return 可用端口名称列表*/@SuppressWarnings("all")public static List<String> findPorts() {// 获得当前所有可用串口Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();List<String> portNameList = new ArrayList<String>();// 将可用串口名添加到List并返回该Listwhile (portList.hasMoreElements()) {String portName = portList.nextElement().getName();portNameList.add(portName);}return portNameList;}@Overridepublic SerialPort serialPort(String portName) {try {// 通过端口名识别端口CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);// 打开端口,并给端口名字和一个timeout(打开操作的超时时间)CommPort commPort = portIdentifier.open(portName, 2000);// 判断是不是串口if (commPort instanceof SerialPort) {SerialPort serialPort = (SerialPort) commPort;try {// 设置一下串口的波特率等参数 // 数据位:8 // 停止位:1 // 校验位:NoneserialPort.setSerialPortParams(getBaudRate(), getDataBits(), getStopBits(), getParity());} catch (UnsupportedCommOperationException e) {throw new RuntimeException("打开串口异常");}return serialPort;}} catch (Exception e1) {throw new RuntimeException("打开串口异常");}return null;}
}
  • 实现代码 3 通讯类
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.msg.*;
import com.serotonin.modbus4j.serial.SerialPortWrapper;
import com.sotring.asd.modbus.suport.SerialPortSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.Arrays;public class RtuMasterWrapper {private static final Logger log = LoggerFactory.getLogger(RtuMasterWrapper.class);private int slaveId;private ModbusMaster rutMaster;private boolean connected;public RtuMasterWrapper(int slaveId) {this.slaveId = slaveId;log.info("slaveId: {}",  slaveId);}public boolean connect() {disconnect();try {SerialPortWrapper port = new SerialPortSupport("COM1",9600);rutMaster = new ModbusFactory().createRtuMaster(port);rutMaster.setTimeout(3000);rutMaster.init();connected = true;} catch (ModbusInitException ex) {log.error("connect error, try to disconnect...", ex);disconnect();}return isConnected();}private void disconnect() {if (rutMaster != null) {rutMaster.destroy();}connected = false;log.info("disconnect");}private boolean isConnected() {return connected;}/*** 读取单个线圈(01功能码)* @param startOffset 读取地址*/public Boolean readCoils(int startOffset) throws ModbusTransportException {ReadCoilsRequest request = new ReadCoilsRequest(slaveId,startOffset,1);ReadCoilsResponse response = (ReadCoilsResponse) rutMaster.send(request);if (response!= null && response.isException()) {throw new ModbusTransportException(response.getExceptionMessage());} else if(response!= null){return response.getBooleanData()[0];}connected = false;return null;}/*** 写入单个地址* @param startOffset 写入地址* @param value 写入值*/public void writeCoils(int startOffset,boolean value) throws ModbusTransportException {WriteCoilRequest request = new WriteCoilRequest(slaveId,startOffset,value);WriteCoilResponse response = (WriteCoilResponse) rutMaster.send(request);if (response!= null && response.isException()) {throw new ModbusTransportException(response.getExceptionMessage());}}/*** 写多个线圈(01功能码)* @param startOffset 写入开始地址* @param value 写入值集合* @throws ModbusTransportException*/public void writeCoilsMultiple(int startOffset,boolean[] value) throws ModbusTransportException {WriteCoilsRequest request = new WriteCoilsRequest(slaveId,startOffset,value);WriteCoilsResponse response = (WriteCoilsResponse) rutMaster.send(request);if (response!= null && response.isException()) {throw new ModbusTransportException(response.getExceptionMessage());}}/*** 读取单个离散线圈(02功能码)* @param startOffset 读取地址*/public Boolean readDiscrete(int startOffset) throws ModbusTransportException {ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId,startOffset,1);ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) rutMaster.send(request);if (response!= null && response.isException()) {throw new ModbusTransportException(response.getExceptionMessage());} else if(response!= null){return response.getBooleanData()[0];}connected = false;return null;}/*** 读取单个保持寄存器(03功能码)* @param startOffset 读取地址*/public Short readHoldingRegisterValue(int startOffset) throws ModbusTransportException {ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, startOffset, 1);log.info("Reading Holding Register, startAddress: {}", startOffset);ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse)rutMaster.send(request);if (response != null && response.isException()) {log.error("Modbus execution failed: \nslaveId: {}, startAddress: {}", slaveId, startOffset);return null;} else if (response != null && response.getShortData().length > 0) {return response.getShortData()[0];}connected = false;return null;}/*** 读取多个保持寄存器(03功能码)* @param startOffset 开始读取位置* @param numberOfRegisters 读取个数*/public short[] readHoldingRegisterValues(int startOffset, int numberOfRegisters) throws ModbusTransportException {ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, startOffset, numberOfRegisters);log.info("Reading Holding Registers, startAddress: {}, len: {}", startOffset, numberOfRegisters);ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse)rutMaster.send(request);if (response != null && response.isException()) {log.error("Modbus execution failed: \nslaveId: {}, startAddress: {}, len: {}", slaveId, startOffset, numberOfRegisters);return null;} else if (response != null) {return response.getShortData();}connected = false;return null;}/*** 写入保持寄存器多个值(03功能码)* @param startOffset 写入开始地址* @param values 写入多个数据集合*/public void writeRegisterValues(int startOffset, short[] values) throws ModbusTransportException {WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, values);log.info(String.format("WRITE Holding Register, startOffset: %d, values: %s",startOffset, Arrays.toString(values)));WriteRegistersResponse response = (WriteRegistersResponse) rutMaster.send(request);if (response!= null && response.isException()) {throw new ModbusTransportException(response.getExceptionMessage());}}/*** 写入保持寄存器(03功能码)* @param startOffset 写入地址* @param value 写入值*/public void writeRegisterValue(int startOffset, short value) throws ModbusTransportException {WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, new short[]{value});log.info(String.format("Writing Holding Register, startAddress: %d, value: %d", startOffset, value));WriteRegistersResponse response = (WriteRegistersResponse) rutMaster.send(request);if (response!= null && response.isException()) {throw new ModbusTransportException(response.getExceptionMessage());}}/*** 读取输入寄存器(04功能码)* @param startOffset 读取地址*/public Short readInput(int startOffset) throws ModbusTransportException {ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId,startOffset,1);ReadInputRegistersResponse response = (ReadInputRegistersResponse) rutMaster.send(request);if (response!= null && response.isException()) {throw new ModbusTransportException(response.getExceptionMessage());} else if(response!= null){return response.getShortData()[0];}connected = false;return null;}
}

这篇关于java与modbusRtu(COM口)通讯的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1135226

相关文章

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J

将Java项目提交到云服务器的流程步骤

《将Java项目提交到云服务器的流程步骤》所谓将项目提交到云服务器即将你的项目打成一个jar包然后提交到云服务器即可,因此我们需要准备服务器环境为:Linux+JDK+MariDB(MySQL)+Gi... 目录1. 安装 jdk1.1 查看 jdk 版本1.2 下载 jdk2. 安装 mariadb(my

SpringBoot中配置Redis连接池的完整指南

《SpringBoot中配置Redis连接池的完整指南》这篇文章主要为大家详细介绍了SpringBoot中配置Redis连接池的完整指南,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以... 目录一、添加依赖二、配置 Redis 连接池三、测试 Redis 操作四、完整示例代码(一)pom.

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

基于Java实现回调监听工具类

《基于Java实现回调监听工具类》这篇文章主要为大家详细介绍了如何基于Java实现一个回调监听工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录监听接口类 Listenable实际用法打印结果首先,会用到 函数式接口 Consumer, 通过这个可以解耦回调方法,下面先写一个

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析