当前位置: 首页 > news >正文

SpringBoot+modbus4j实现ModebusTCP通讯读取数据

场景

Windows上ModbusTCP模拟Master与Slave工具的使用:

Windows上ModbusTCP模拟Master与Slave工具的使用-CSDN博客

Modebus TCP

Modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准。

1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:ModbusTCP。

Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。

标准的Modbus协议物理层接口有RS232、RS422、RS485和以太网接口,采用master/slave方式通信。

Modbus的操作对象有四种:

线圈、离散输入、保持寄存器、输入寄存器。

Modbus功能码:

关于Java的开源库:

Jamod:

Java Modbus实现:Java Modbus库。该库由Dieter Wimberger实施。

ModbusPal:

ModbusPal是一个正在进行的Java项目,用于创建逼真的Modbus从站模拟器。

下面介绍基于Modebus4j实现读线圈状态数据。

由于预定义的数学函数和/或Python脚本,寄存器值是动态生成的。

ModbusPal依赖于RxTx进行串行通信,而Jython则依赖于脚本支持。

Modbus4J:

Serotonin Software用Java编写的Modbus协议的高性能且易于使用的实现。

支持ASCII,RTU,TCP和UDP传输作为从站或主站,自动请求分区,响应数据类型解析和节点扫描。

JLibModbus:

JLibModbus是java语言中Modbus协议的一种实现。jSSC和RXTX用于通过串行端口进行通信。

该库是一个经过积极测试和改进的项目。

注:

博客:
霸道流氓气质_C#,架构之路,SpringBoot-CSDN博客

实现

1、基于modbus4j实现线圈状态数据的读取。

modbus4j

GitHub - MangoAutomation/modbus4j: A high-performance and ease-of-use implementation of the Modbus protocol written in Java. Supports ASCII, RTU, TCP, and UDP transports as slave or master, automatic request partitioning and response data type parsing.

按照官网介绍,需要在pom文件中添加repository的配置

    <repositories><repository><releases><enabled>false</enabled></releases><snapshots><enabled>true</enabled></snapshots><id>ias-snapshots</id><name>Infinite Automation Snapshot Repository</name><url>https://maven.mangoautomation.net/repository/ias-snapshot/</url></repository><repository><releases><enabled>true</enabled></releases><snapshots><enabled>false</enabled></snapshots><id>ias-releases</id><name>Infinite Automation Release Repository</name><url>https://maven.mangoautomation.net/repository/ias-release/</url></repository></repositories>

添加位置

然后添加依赖

        <dependency><groupId>com.infiniteautomation</groupId><artifactId>modbus4j</artifactId><version>3.0.3</version></dependency>

2、新建modbus4j工具类

package com.badao.demo.utils;import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.BaseLocator;public class Modbus4jUtils {/*** 工厂。*/static ModbusFactory modbusFactory;static {if (modbusFactory == null) {modbusFactory = new ModbusFactory();}}/*** 获取master** @return* @throws ModbusInitException*/public static ModbusMaster getMaster(String ip,int port) throws ModbusInitException {IpParameters params = new IpParameters();params.setHost(ip);params.setPort(port);// modbusFactory.createRtuMaster(wapper); //RTU 协议// modbusFactory.createUdpMaster(params);//UDP 协议// modbusFactory.createAsciiMaster(wrapper);//ASCII 协议ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议master.init();return master;}/*** 读取[01 Coil Status 0x]类型 开关数据** @param slaveId*            slaveId* @param offset*            位置* @return 读取值* @throws ModbusTransportException*             异常* @throws ErrorResponseException*             异常*/public static Boolean readCoilStatus(ModbusMaster master,int slaveId, int offset)throws ModbusTransportException, ErrorResponseException {// 01 Coil StatusBaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset);Boolean value = master.getValue(loc);return value;}/*** 读取[02 Input Status 1x]类型 开关数据** @param slaveId* @param offset* @return* @throws ModbusTransportException* @throws ErrorResponseException*/public static Boolean readInputStatus(ModbusMaster master,int slaveId, int offset)throws ModbusTransportException, ErrorResponseException {// 02 Input StatusBaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset);Boolean value = master.getValue(loc);return value;}/*** 读取[03 Holding Register类型 2x]模拟量数据** @param slaveId*            slave Id* @param offset*            位置* @param dataType*            数据类型,来自com.serotonin.modbus4j.code.DataType* @return* @throws ModbusTransportException*             异常* @throws ErrorResponseException*             异常*/public static Number readHoldingRegister(ModbusMaster master,int slaveId, int offset, int dataType)throws ModbusTransportException, ErrorResponseException {// 03 Holding Register类型数据读取BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);Number value = master.getValue(loc);return value;}/*** 读取[04 Input Registers 3x]类型 模拟量数据** @param slaveId*            slaveId* @param offset*            位置* @param dataType*            数据类型,来自com.serotonin.modbus4j.code.DataType* @return 返回结果* @throws ModbusTransportException*             异常* @throws ErrorResponseException*             异常*/public static Number readInputRegisters(ModbusMaster master,int slaveId, int offset, int dataType)throws ModbusTransportException, ErrorResponseException {// 04 Input Registers类型数据读取BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType);Number value = master.getValue(loc);return value;}/*** 批量读取使用方法** @throws ModbusTransportException* @throws ErrorResponseException* @throws ModbusInitException* @return*/public static BatchResults<Integer> batchRead(ModbusMaster master,BatchRead<Integer> batchRead) throws ModbusTransportException, ErrorResponseException, ModbusInitException {// 是否连续请求batchRead.setContiguousRequests(false);BatchResults<Integer> results = master.send(batchRead);return results;}
}

3、使用方式

新建master

ModbusMaster master = Modbus4jUtils.getMaster(modebustcpIp, port);

这里的ip和端口来自配置文件

单个读取数据

Boolean aBoolean = Modbus4jUtils.readCoilStatus(master, 1, 0);

这里1代表slaveId,0代表offset

批量读取数据

        BatchRead<Integer> batch = new BatchRead<>();List<Locator> locatorList = locatorConfig.getLocatorList();locatorList.forEach(locator -> batch.addLocator(locator.getId(), BaseLocator.coilStatus(locator.getSlaveId(),locator.getOffset())));BatchResults<Integer> batchResults = Modbus4jUtils.batchRead(master, batch);Boolean valueOne = (Boolean) batchResults.getValue(0);Boolean valueTwo = (Boolean) batchResults.getValue(1);Boolean valueThree = (Boolean) batchResults.getValue(2);

这里批量读取的配置来自配置文件

4、业务示例

在定时任务中批量读取指定slaveId和offset的线圈状态数据

import com.badao.demo.config.LocatorConfig;
import com.badao.demo.entity.Locator;
import com.badao.demo.utils.Modbus4jUtils;
import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.locator.BaseLocator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.time.LocalDateTime;
import java.util.List;@Configuration
@EnableScheduling
public class GetModbusTCPDataTask {@Value("${modebustcp.ip}")private String modebustcpIp;@Value("${modebustcp.port}")private Integer port;@Autowiredprivate LocatorConfig locatorConfig;@Scheduled(fixedRateString = "2000")public void  getData() throws ModbusInitException {ModbusMaster master = Modbus4jUtils.getMaster(modebustcpIp, port);BatchRead<Integer> batch = new BatchRead<>();List<Locator> locatorList = locatorConfig.getLocatorList();locatorList.forEach(locator -> batch.addLocator(locator.getId(), BaseLocator.coilStatus(locator.getSlaveId(),locator.getOffset())));try {//单个读取//Boolean aBoolean = Modbus4jUtils.readCoilStatus(master, 1, 0);//批量读取BatchResults<Integer> batchResults = Modbus4jUtils.batchRead(master, batch);Boolean valueOne = (Boolean) batchResults.getValue(0);Boolean valueTwo = (Boolean) batchResults.getValue(1);Boolean valueThree = (Boolean) batchResults.getValue(2);System.out.println(LocalDateTime.now());System.out.println("valueOne:"+valueOne);System.out.println("valueTwo:"+valueTwo);System.out.println("valueThree:"+valueThree);} catch (ModbusTransportException e) {e.printStackTrace();} catch (ErrorResponseException e) {e.printStackTrace();} catch (ModbusInitException e) {e.printStackTrace();}}
}

5、本地测试效果

6、线上测试效果

线上使用RS485转以太网模块,会将其转换成MODBUS TCP服务端,端口为默认502,slaveid为2

通讯测试效果

7、SpringBoot中进行ModbusTCP通讯时提示:

com.serotonin.modbus4j.exception.ErrorResponseException:Illegal function

这是因为功能码不对应,使用Modbus Slave Definition定义的功能码为03 Holding Register(4x),而在代码中连接后执行的是读取线圈状态的功能码

所以将功能码修改对应即可

相关文章:

SpringBoot+modbus4j实现ModebusTCP通讯读取数据

场景 Windows上ModbusTCP模拟Master与Slave工具的使用&#xff1a; Windows上ModbusTCP模拟Master与Slave工具的使用-CSDN博客 Modebus TCP Modbus由MODICON公司于1979年开发&#xff0c;是一种工业现场总线协议标准。 1996年施耐德公司推出基于以太网TCP/IP的Modbus协议&…...

Linux性能优化全景指南

Part1 Linux性能优化 1、性能优化性能指标 高并发和响应快对应着性能优化的两个核心指标&#xff1a;吞吐和延时 应用负载角度&#xff1a;直接影响了产品终端的用户体验系统资源角度&#xff1a;资源使用率、饱和度等 性能问题的本质就是系统资源已经到达瓶颈&#xff0c;但…...

树莓派 ubuntu20.04下 python调讯飞的语音API,语音识别和语音合成

目录 1.环境搭建2.去讯飞官网申请密钥3.语音识别&#xff08;sst&#xff09;4.语音合成&#xff08;tts&#xff09;5.USB声卡可能报错 1.环境搭建 #环境说明&#xff1a;(尽量在ubuntu下使用, 本次代码均在该环境下实现) sudo apt-get install sox # 安装语音播放软件 pip …...

分布式系统架构设计之分布式系统实践案例和未来展望

分布式系统在过去的几十年里经历了长足的发展&#xff0c;从最初的简单分布式架构到今天的微服务、云原生等先进架构&#xff0c;取得了丰硕的成果。本文将通过实际案例分享分布式系统的架构实践&#xff0c;并展望未来可能的发展方向。 一、实践案例 1、微服务化实践 背景 …...

【办公软件】Excel双坐标轴图表

在工作中整理测试数据&#xff0c;往往需要一个图表展示两个差异较大的指标。比如共有三个数据&#xff0c;其中两个是要进行对比的温度值&#xff0c;另一个指标是两个温度的差值&#xff0c;这个差值可能很小。 举个实际的例子&#xff1a;数据如下所示&#xff0c;NTC检测温…...

彻底理解前端安全面试题(1)—— XSS 攻击,3种XSS攻击详解,建议收藏(含源码)

前言 前端关于网络安全看似高深莫测&#xff0c;其实来来回回就那么点东西&#xff0c;我总结一下就是 3 1 4&#xff0c;3个用字母描述的【分别是 XSS、CSRF、CORS】 一个中间人攻击。当然 CORS 同源策略是为了防止攻击的安全策略&#xff0c;其他的都是网络攻击。除了这…...

UE5.1_AI随机漫游

UE5.1_AI随机漫游 目录 UE5.1_AI随机漫游 AI随机漫游方法 方法1:AI角色蓝图直接写方法...

智慧城市新型基础设施建设综合方案:文件全文52页,附下载

关键词&#xff1a;智慧城市建设方案&#xff0c;智慧城市发展的前景和趋势&#xff0c;智慧城市项目方案&#xff0c;智慧城市管理平台&#xff0c;数字化城市&#xff0c;城市数字化转型 一、智慧城市新基建建设背景 1、城市化进程加速&#xff1a;随着城市化进程的加速&am…...

GitHub Copilot 终极详细介绍

编写代码通常是一项乏味且耗时的任务。现代开发人员一直在寻找新的方法来提高编程的生产力、准确性和效率。 像 GitHub Copilot 这样的自动代码生成工具可以使这成为可能。 GitHub Copilot 到底是什么&#xff1f; GitHub Copilot 于 2021 年 10 月推出&#xff0c;是 GitHub 的…...

LeetCode第63题 - 不同路径 II

题目 解答 class Solution {public int uniquePathsWithObstacles(int[][] obstacleGrid) {int m obstacleGrid.length;int n obstacleGrid[0].length;if (obstacleGrid[0][0] 1) {return 0;}if (obstacleGrid[m - 1][n - 1] 1) {return 0;}int[][] dp new int[m][n];dp…...

python+django网上银行业务综合管理系统vue_bvj8b

本课题主要研究如何用信息化技术改善传统网上银行综合管理行业的经营和管理模式&#xff0c;简化网上银行综合管理的难度&#xff0c;根据管理实际业务需求&#xff0c;调研、分析和编写系统需求文档&#xff0c;设计编写符合银行需要的系统说明书&#xff0c;绘制数据库结构模…...

【软件工程】走进瀑布模型:传统软件开发的经典之路

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; 软件工程 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言&#xff1a; 正文 主要阶段&#xff1a; 优点&#xff1a; 缺点&#xff1a; 应用范围&#xff1a; 结语 我的其他博客 前言&am…...

两个字符串间的最短路径问题 (100%用例)C卷 (JavaPythonNode.jsC语言C++)

给定两个字符串,分别为字符串A与字符串B。例如A字符串为ABCABBA,B字符串为CBABAC可以得到下图m*n的二维数组,定义原点为(0,0),终点为(m,n),水平与垂直的每一条边距离为1,映射成坐标系如下图 从原点(0,0)到(0,A)为水平边,距离为1,从(0,A)到(A,C)为垂直边,距离为1;假设两…...

通过ADB来实现脚本来控制手机

ADB 简介 adb的全称为Android Debug Bridge,安卓调试桥,可以通过调试命令来控制手机,诸如开机,关机等按键控制;或者启动,关闭应用;异或进行触摸模拟. 通过学习adb,可以实现简单的脚本控制,最大的特点是不需要root,对于普通手机都可以进行,帮助我们完成一些简单的重复性事件,…...

机器学习之K-means聚类

概念 K-means是一种常用的机器学习算法,用于聚类分析。聚类是一种无监督学习方法,它试图将数据集中的样本划分为具有相似特征的组(簇)。K-means算法的目标是将数据集划分为K个簇,其中每个样本属于与其最近的簇中心。 以下是K-means算法的基本步骤: 选择簇的数量(K值)…...

SSH 端口转发:如何将服务绑定到本地 IP 地址

在日常工作中&#xff0c;我们经常需要访问位于远程服务器上的服务&#xff0c;如数据库、Web 应用程序或其他类型的服务器。直接访问这些服务可能会因为安全限制或网络配置而变得复杂或不可能。这时&#xff0c;SSH 端口转发就成了我们的得力助手。在本篇博客中&#xff0c;我…...

回归预测 | MATLAB实ZOA-LSTM基于斑马优化算法优化长短期记忆神经网络的多输入单输出数据回归预测模型 (多指标,多图)

回归预测 | MATLAB实ZOA-LSTM基于斑马优化算法优化长短期记忆神经网络的多输入单输出数据回归预测模型 &#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实ZOA-LSTM基于斑马优化算法优化长短期记忆神经网络的多输入单输出数据回归预测模型 &#xff08;…...

python实现图像的二维傅里叶变换——冈萨雷斯数字图像处理

原理 二维傅里叶变换是一种在图像处理中常用的数学工具&#xff0c;它将图像从空间域&#xff08;我们通常看到的像素排列&#xff09;转换到频率域。这种变换揭示了图像的频率成分&#xff0c;有助于进行各种图像分析和处理&#xff0c;如滤波、图像增强、边缘检测等。 在数学…...

We are a team - 华为OD统一考试

OD统一考试 题解&#xff1a; Java / Python / C 题目描述 总共有 n 个人在机房&#xff0c;每个人有一个标号 (1<标号<n) &#xff0c;他们分成了多个团队&#xff0c;需要你根据收到的 m 条消息判定指定的两个人是否在一个团队中&#xff0c;具体的: 消息构成为 a b …...

NFC物联网智慧校园解决方案

近场通信(Near Field Communication&#xff0c;NFC)又称近距离无线通信&#xff0c;是一种短距离的高频无线通信技术&#xff0c;允许电子设备之间进行非接触式点对点数据传输交换数据。这个技术由免接触式射频识别(RFID)发展而来&#xff0c;并兼容 RFID&#xff0c;主要用于…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...