springboot读取modbus数据
1、引入依赖 jlibmodbus
<dependency><groupId>com.intelligt.modbus</groupId><artifactId>jlibmodbus</artifactId><version>1.2.9.7</version>
</dependency>
2、数据获取
public String processData(String ip) {try {// 设置主机TCP参数TcpParameters tcpParameters = new TcpParameters();// 设置TCP的ip地址InetAddress adress = InetAddress.getByName(ip);// TCP参数设置ip地址tcpParameters.setHost(adress);// TCP设置长连接tcpParameters.setKeepAlive(true);// TCP设置端口,这里设置是默认端口502tcpParameters.setPort(Modbus.TCP_PORT);// 创建一个主机ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);Modbus.setAutoIncrementTransactionId(true);final int SLAVE_ID = 1;//从机地址final int START_ADDRESS = 1;//寄存器读取开始地址 尝试从设备地址 减1 开始final int QUANTITY = 66;//读取的寄存器数量 不能大于设备设置的最大值否则会报错;try {if (!master.isConnected()) {master.connect();// 开启连接}// 读保持寄存器,功能码03 // 注意:这里读取的数据都是整型的需要根据plc设备设置的进行相应的转换int[] values = master.readHoldingRegisters(SLAVE_ID, START_ADDRESS, QUANTITY); for (int i = 0; i < values.length; i++) {System.out.println(i + ": " + values[i]);}// 获取长整型数据PlcUtils.getLongValue(values[0],values[1]);}} catch (ModbusProtocolException e) {log.error("Modbus 协议异常,ip: {},异常信息:{}", ip, e.getMessage());e.printStackTrace();} catch (ModbusNumberException e) {log.error("Modbus 编号异常,ip: {},异常信息:{}", ip, e.getMessage());e.printStackTrace();} catch (ModbusIOException e) {log.error("Modbus IO 异常,ip: {},异常信息:{}", ip, e.getMessage());e.printStackTrace();} finally {try {master.disconnect();} catch (ModbusIOException e) {log.error("Modbus 连接断开异常,ip: {},异常信息:{}", ip, e.getMessage());e.printStackTrace();}}} catch (RuntimeException e) {throw e;} catch (Exception e) {e.printStackTrace();}return "数据获取成功!";}
3、数据处理工具
/*** @author liang* @version 1.0* @date 2024/10/28 10:06*/
public class PlcUtils implements Serializable {/*** 获取长整型数据* 低字节在前(Little-Endian) 对应 最不重要的寄存器优先的*/public static int getLongValue(int[] registers) {if (registers.length < 2) {throw new IllegalArgumentException("需要至少2个寄存器来组成32位整型");}return ((registers[1] & 0xFFFF) << 16) | (registers[0] & 0xFFFF);}/*** 高字节在前(Big-Endian) 对应 最重要的寄存器优先* 获取长整型数据** @param registers* @return*/private static int combineIntValue(int[] registers) {if (registers.length < 2) {throw new IllegalArgumentException("需要至少2个寄存器来组成32位整型");}return ((registers[0] & 0xFFFF) << 16) | (registers[1] & 0xFFFF);}/*** 获取浮点型数据** @param registers* @return*/public static float getFloatValue(int[] registers) {return Float.intBitsToFloat(getLongValue(registers));}/*** 获取二进制数据** @param val* @return*/public static String getBinaryString(int val) {return Integer.toBinaryString(val);}// 将4个16位寄存器组合成一个64位长整型值private static long combineLongValue(int[] registers) {if (registers.length < 4) {throw new IllegalArgumentException("需要至少4个寄存器来组成长整型");}return ((long)(registers[0] & 0xFFFF) << 48) |((long)(registers[1] & 0xFFFF) << 32) |((long)(registers[2] & 0xFFFF) << 16) |((long)(registers[3] & 0xFFFF));}}
4、模拟设备设置
服务端 modsim32 一次只能模拟一种数据类型,需要多种时切换即可
客户端 modscan32