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设置端口,这里设置是默认端口502
tcpParameters.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