提示:可以使用Modbus slave工具模拟Modbus数据站并添加一些数据。
1、pom引入依赖
<dependency>
<groupId>com.intelligt.modbus</groupId>
<artifactId>jlibmodbus</artifactId>
<version>1.2.9.7</version>
</dependency>
2、创建modbus主机连接
public class JlibModbusBase {
static ModbusMaster modbusMaster;
public static void initJlibModbusMaster(String ip) {
// 如果连接不存在,创建一个主机连接
if (ObjectUtils.isEmpty(modbusMaster)) {
// 设置主机TCP参数
TcpParameters tcpParameters = new TcpParameters();
// 设置TCP的ip地址-本地地址
InetAddress address = null;
try {
address = InetAddress.getByName(ip);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
tcpParameters.setHost(address);
// TCP设置长连接
tcpParameters.setKeepAlive(true);
// TCP设置端口,这里设置是默认端口502
tcpParameters.setPort(502);
modbusMaster = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
Modbus.setAutoIncrementTransactionId(true);
}
}
public static void release() {
if (modbusMaster != null) {
try {
modbusMaster.disconnect();
} catch (ModbusIOException e) {
throw new RuntimeException(e);
}
}
}
}
3、通过连接获取功能码0x04与0x03的数据
public class JlibModbusBaseTool {
/**
* "功能码0x04"
* 读取HoldingRegister数据
*
* @param slaveId 寄存器地址ID
* @param offset 寄存器读取开始地址
* @param quantity 读取寄存器数量
* @return int数组
*/
public static int[] readInputRegisters(int slaveId, int offset, int quantity) {
try {
return modbusMaster.readInputRegisters(slaveId, offset, quantity);
} catch (ModbusProtocolException | ModbusNumberException | ModbusIOException e) {
throw new RuntimeException(e);
} finally {
release();
}
}
/**
* "功能码0x03"
* 读取HoldingRegister数据
*
* @param slaveId 寄存器地址ID
* @param offset 寄存器读取开始地址
* @param quantity 读取寄存器数量
* @return int数组
*/
public static int[] readHoldingRegisters(int slaveId, int offset, int quantity) {
try {
return modbusMaster.readHoldingRegisters(slaveId, offset, quantity);
} catch (ModbusProtocolException | ModbusNumberException | ModbusIOException e) {
throw new RuntimeException(e);
} finally {
release();
}
}
4、根据具体业务情况,进行方法的调用与数据解析。在本人实际业务中,存在两个IP地址(实际中上文的主机连接,可以根据IP的不同,实时创建不同的连接)。因为读取寄存器数量时,最多可以读取124个寄存器。所以根据业务实际情况,进行多次的循环取数。文章来源:https://www.toymoban.com/news/detail-508200.html
//读取的寄存器数量,一次读取两台设备寄存器数据
//因为实际使用中数据为float数据,下文还会进行数据的转换
int quantity = 96;
int[] result = null;
int salveId = 0;
//获取数据
result = JlibModbusBaseTool.readInputRegisters(salveId,offset,quantity);
//首先将int[]转化为集合,然后将读取到的数据集合,分成两个集合
List<Integer> intList = Arrays.stream(result).boxed().toList();
int LIMIT_TOW = 48;
ArrayList<List<Integer>> dataList = new ArrayList<>();
Stream.iterate(0, n -> n + 1).limit(countStep(intList.size(), LIMIT_TOW)).forEach(i -> {
dataList.add(intList.stream().skip(i * LIMIT_TOW).limit(LIMIT_TOW).collect(Collectors.toList()));
});
//计算分组数量
public static Integer countStep(Integer size,int limt) {
return (size + limt - 1) / limt;
}
//然后读取int[]数据,转化为浮点类型
// 两个数据一组,组成16进制字符转,转化为float数据类型
public static CcElectricityMeterNew convertFloat(int[] array, CcElectricityMeterNew meterNew){
for (int i = 0; i < array.length; i++) {
if ((i+1)%2==0) {
int first = array[i-1];
int second = array[i];
//在进行字符串转化时,转化的16进制会存在缺少一位的情况,进行左侧补零操作
String hexStr = addZeroForStr(Integer.toHexString(first),4,1)+""+addZeroForStr(Integer.toHexString(second),4,1);
System.out.println(new BigDecimal(sfloat(hexStr)));
}
}
return meterNew;
}
//将字符串类型的16进制数据,转化为float字符串
private static String sfloat(String str){
Float value = Float.intBitsToFloat(new BigInteger(str, 16).intValue());
return String.valueOf(value);
}
/**
* 给字符串的左补0或右补0
* @param str 要处理的字符串
* @param length 补0后字符串总长度
* @return 返回补零字符串
*/
public static String addZeroForStr(String str, int length,int type) {
int strLen = str.length();
if (strLen < length) {
while (strLen < length) {
StringBuffer sb = new StringBuffer();
if(type==1){
// 左补0
sb.append("0").append(str);
}else if(type==2){
//右补0
sb.append(str).append("0");
}
str = sb.toString();
strLen = str.length();
}
}
return str;
}
备注:使用jlibmodbus读取Modbus TCP数据是非常简单的,在使用中需要根据自己需要的数据类型进行转化;同时一次获取寄存器的数量需要注意,合理进行循环的数据获取。在进行modbus数据获取时,碰到一个问题,在大量进行重复连接数据获取时,modbus存在Connection reset 的问题,导致数据获取无法进行后续数据获取中断,暂时没有找到问题的原因,如果有知道原理的大神,希望给与解答!!!文章来源地址https://www.toymoban.com/news/detail-508200.html
到了这里,关于Java实现使用jlibmodbus读取Modbus TCP数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!