springBoot 整合ModBus TCP的详细过程
作者:雁归来时
ModBus是什么:
ModBus是一种串行通信协议,主要用于从仪器和控制设备传输信号到主控制器或数据采集系统,例如用于测量温度和湿度并将结果传输到计算机的系统。(百度答案)
ModBus 有些什么东西:
ModBus其分为两个站点,一个是主站一个是从站
主站和从站之间可以进行相互通讯,这里的主从站和JAVA程序中的主从关系应该是不一致的,博主在寻找资料的时候发现,所谓的从站就是用的仿真机进行模拟的,就是实打实的硬件设备,而主站才是中枢,是获取设备从站推送的数据和对设备数据进行编写的地方。
在实际业务开发过程中,对于从站的约束,需要和设备供应商进行对接,而逻辑处理业务集中在主站中。
Modbus Slave(打手)
Modbus Slave就是上面提到的仿真机,它可以在进行业务开发的过程中,充当设备的角色,方便主站获取和编写数据。
Modbus Slave下载地址
安装完成之后在Connection–>connect 里面输入激活码即可
Modbus Slave使用(刷副本)
上面说过,它就是一个仿真机,我们进行使用的时候需要先了解一下它有那些东西,我们需要对它进行那些操作
它有四个功能类型
然后设置完成这些之后,可以对其属性值进行编辑处理,根据不同的数据类型,可以设置多种数据值
更加具体的操作可以另行查找资料
获取Slave数据
数据已经存在了, 那么如何进行获取数据,这边以ModbusTcp的方式进去编写一个写入和读取的案例
导入POM依赖
pom依赖国内是无法进行下载的,所以我们需要指定国外镜像或者下载ZIP进行打包编译成我们需要的依赖文件,博主使用的是通过ZIP文件进行打包编译导入的。(博主资源中有ZIP包,需要的可以自行获取)
解压ZIP文件之后,通过IDEA进行打包编译即可,有需要的可以通过 maven deploy方法进行推送到maven仓库中
pom文件中添加依赖即可
<dependency> <groupId>com.infiniteautomation</groupId> <artifactId>modbus4j</artifactId> <version>3.1.1-SNAPSHOT</version> </dependency>
读取数据
package com.example.modbusserve.Test; import com.serotonin.modbus4j.BatchRead; import com.serotonin.modbus4j.BatchResults; import com.serotonin.modbus4j.ModbusFactory; import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.code.DataType; 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; /** * modbus通讯工具类,采用modbus4j实现(读取) * */ public class Modbus4jUtils { /** * 工厂。 */ static ModbusFactory modbusFactory; static { if (modbusFactory == null) { modbusFactory = new ModbusFactory(); } } /** * 获取master * */ public static ModbusMaster getMaster() throws ModbusInitException { IpParameters params = new IpParameters(); params.setHost("192.168.1.7"); params.setPort(502); // 采用 Modbus RTU over TCP/IP,第二个参数为 true,即 modbusFactory.createTcpMaster(params, true),这里用的是TCP协议 ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 master.init(); return master; } /** * 读取[01 Coil Status 0x]类型 开关数据 * * @param slaveId * slaveId * @param offset * 位置 * @return 读取值 */ public static Boolean readCoilStatus(int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 01 Coil Status BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset); Boolean value = getMaster().getValue(loc); return value; } /** * 读取[02 Input Status 1x]类型 开关数据 * * @param slaveId * @param offset * @return */ public static Boolean readInputStatus(int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 02 Input Status BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset); Boolean value = getMaster().getValue(loc); return value; } /** * 读取[03 Holding Register类型 2x]模拟量数据 * * @param slaveId * slave Id * @param offset * 位置 * @param dataType * 数据类型,来自com.serotonin.modbus4j.code.DataType */ public static Number readHoldingRegister(int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 03 Holding Register类型数据读取 BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType); Number value = getMaster().getValue(loc); return value; } /** * 读取[04 Input Registers 3x]类型 模拟量数据 * * @param slaveId * slaveId * @param offset * 位置 * @param dataType * 数据类型,来自com.serotonin.modbus4j.code.DataType * @return 返回结果 */ public static Number readInputRegisters(int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 04 Input Registers类型数据读取 BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType); Number value = getMaster().getValue(loc); return value; } /** * 批量读取使用方法 * * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ public static void batchRead() throws ModbusTransportException, ErrorResponseException, ModbusInitException { BatchRead<Integer> batch = new BatchRead<Integer>(); batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.FOUR_BYTE_FLOAT)); batch.addLocator(1, BaseLocator.inputStatus(1, 0)); ModbusMaster master = getMaster(); batch.setContiguousRequests(false); BatchResults<Integer> results = master.send(batch); System.out.println(results.getValue(0)); System.out.println(results.getValue(1)); } /** * 测试 * * @param args */ public static void main(String[] args) { try { // 01测试 Boolean v011 = readCoilStatus(1, 0); Boolean v012 = readCoilStatus(1, 1); System.out.println("v011:" + v011); System.out.println("v012:" + v012); // // 02测试 // Boolean v021 = readInputStatus(1, 0); // Boolean v022 = readInputStatus(1, 1); // Boolean v023 = readInputStatus(1, 2); // System.out.println("v021:" + v021); // System.out.println("v022:" + v022); // System.out.println("v023:" + v023); // // // 03测试 // Number v031 = readHoldingRegister(1, 1, DataType.FOUR_BYTE_FLOAT);// 注意,float // Number v032 = readHoldingRegister(1, 3, DataType.FOUR_BYTE_FLOAT);// 同上 // System.out.println("v031:" + v031); // System.out.println("v032:" + v032); // // // 04测试 // Number v041 = readInputRegisters(1, 0, DataType.FOUR_BYTE_FLOAT);// // Number v042 = readInputRegisters(1, 2, DataType.FOUR_BYTE_FLOAT);// // System.out.println("v041:" + v041); // System.out.println("v042:" + v042); // // 批量读取 // batchRead(); } catch (Exception e) { e.printStackTrace(); } } }
其中slaveId和offset对应的就是仿真机中的从站编码和地址码
通过不同的读取方法,可以读取不同业务类型中的数据。返回值仿真机中只能存数字(只是有误符号的区别),所以固定是Number
写入数据
package com.example.modbusserve.Test; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.serotonin.modbus4j.ModbusFactory; import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.code.DataType; 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; import com.serotonin.modbus4j.msg.ModbusResponse; import com.serotonin.modbus4j.msg.WriteCoilRequest; import com.serotonin.modbus4j.msg.WriteCoilResponse; import com.serotonin.modbus4j.msg.WriteCoilsRequest; import com.serotonin.modbus4j.msg.WriteCoilsResponse; import com.serotonin.modbus4j.msg.WriteRegisterRequest; import com.serotonin.modbus4j.msg.WriteRegisterResponse; import com.serotonin.modbus4j.msg.WriteRegistersRequest; /** * modbus4j写入数据 * * @author xq * */ public class Modbus4jWriteUtils { static Log log = LogFactory.getLog(Modbus4jWriteUtils.class); /** * 工厂。 */ static ModbusFactory modbusFactory; static { if (modbusFactory == null) { modbusFactory = new ModbusFactory(); } } /** * 获取tcpMaster * * @return * @throws ModbusInitException */ public static ModbusMaster getMaster() throws ModbusInitException { IpParameters params = new IpParameters(); params.setHost("localhost"); params.setPort(502); ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false); tcpMaster.init(); return tcpMaster; } /** * 写 [01 Coil Status(0x)]写一个 function ID = 5 * * @param slaveId * slave的ID * @param writeOffset * 位置 * @param writeValue * 值 * @return 是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeCoil(int slaveId, int writeOffset, boolean writeValue) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求 WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue); // 发送请求并获取响应对象 WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request); if (response.isException()) { return false; } else { return true; } } /** * 写[01 Coil Status(0x)] 写多个 function ID = 15 * * @param slaveId * slaveId * @param startOffset * 开始位置 * @param bdata * 写入的数据 * @return 是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeCoils(int slaveId, int startOffset, boolean[] bdata) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求 WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata); // 发送请求并获取响应对象 WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request); if (response.isException()) { return false; } else { return true; } } /*** * 保存寄存器 * 写[03 Holding Register(4x)] 写一个 function ID = 6 * @param slaveId * @param writeOffset * @param writeValue */ public static boolean writeRegister(int slaveId, int writeOffset, short writeValue) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求对象 WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue); WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request); if (response.isException()) { log.error(response.getExceptionMessage()); return false; } else { return true; } } /** * * 写入[03 Holding Register(4x)]写多个 function ID=16 * * @param slaveId * modbus的slaveID * @param startOffset * 起始位置偏移量值 * @param sdata * 写入的数据 * @return 返回是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeRegisters(int slaveId, int startOffset, short[] sdata) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求对象 WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata); // 发送请求并获取响应对象 ModbusResponse response = tcpMaster.send(request); if (response.isException()) { log.error(response.getExceptionMessage()); return false; } else { return true; } } /** * 写入数字类型的模拟量(如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long) * * @param slaveId * @param offset * @param value * 写入值,Number的子类,例如写入Float浮点类型,Double双精度类型,以及整型short,int,long * @param registerCount * ,com.serotonin.modbus4j.code.DataType * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ public static void writeHoldingRegister(int slaveId, int offset, Number value, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 类型 BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType); tcpMaster.setValue(locator, value); } public static void main(String[] args) { try { //@formatter:off // 测试01 boolean t01 = writeCoil(1, 4, true); System.out.println("T01:" + t01); // 测试02 // boolean t02 = writeCoils(1, 0, new boolean[] { true, false, true }); // System.out.println("T02:" + t02); // 测试03 // short v = -3; // boolean t03 = writeRegister(1, 0, v); // System.out.println("T03:" + t03); // 测试04 // boolean t04 = writeRegisters(1, 0, new short[] { -3, 3, 9 }); // System.out.println("t04:" + t04); //写模拟量 // writeHoldingRegister(1,0, 10.1f, DataType.FOUR_BYTE_FLOAT); //@formatter:on } catch (Exception e) { e.printStackTrace(); } } }
代码中独有相对于的注释,可以自行参考使用
到此这篇关于springBoot 整合ModBus TCP的文章就介绍到这了,更多相关springBoot 整合ModBus TCP内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!