背景
接到客户需求,需要将一个设备的数据读取出来并保存到数据库。改设备通过网络的话是使用modbus协议进行通信的,而且客户需求读取的数据是浮点数类型,一个浮点数占设备2个寄存器,使用工具包只能一个个的寄存器的值读取出来,本文代码,可以将2个寄存器的值一次都转换成一个一个的浮点数。创作不易,希望大家能够给关注或者点赞,本人技术也有很多的欠缺和不足,欢迎大家讨论并交流。
依赖
<dependency>
<groupId>com.intelligt.modbus</groupId>
<artifactId>jlibmodbus</artifactId>
<version>1.2.9.7</version>
</dependency>
demo代码
package com.example.demo.hex;
import com.intelligt.modbus.jlibmodbus.Modbus;
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
import com.intelligt.modbus.jlibmodbus.exception.ModbusProtocolException;
import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;
import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
import java.math.BigInteger;
import java.net.InetAddress;
import java.text.DecimalFormat;
public class A1 {
public static void main(String[] args) {
/*int arry[] = new int[14];
arry[0] = 58196;
arry[1] = 16763;
arry[2] = 2097;
arry[3] = 15532;
arry[4] = 524;
arry[5] = 16611;
arry[6] = 39846;
arry[7] = 15300;
arry[8] = 35127;
arry[9] = 16621;
arry[10] = 34079;
arry[11] = 16907;
arry[12] = 11633;
arry[13] = 17435;*/
//int数组转以两个为一组,一次转换成一个个的浮点数,并打印
// convertFloat(registerValues);
try {
// 设置主机TCP参数
TcpParameters tcpParameters = new TcpParameters();
// 设置TCP的ip地址
InetAddress adress = InetAddress.getByName("192.168.3.16");
// TCP参数设置ip地址
// tcpParameters.setHost(InetAddress.getLocalHost());
tcpParameters.setHost(adress);
// TCP设置长连接
tcpParameters.setKeepAlive(true);
// TCP设置端口,这里设置是默认端口502
tcpParameters.setPort(6000);
// 创建一个主机
ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
Modbus.setAutoIncrementTransactionId(true);
int slaveId = 1;//从机地址
int offset = 0;//寄存器读取开始地址
int quantity = 10;//读取的寄存器数量
try {
if (!master.isConnected()) {
master.connect();// 开启连接
}
// 读取对应从机的数据,readInputRegisters读取的写寄存器,功能码04
//int[] registerValues = master.readInputRegisters(slaveId, offset, quantity);
//功能码03
int[] registerValues = master.readHoldingRegisters(slaveId, offset, quantity);
//int数组转以两个为一组,一次转换成一个个的浮点数,并打印
convertFloat(registerValues);
// 控制台输出
// for (int value : registerValues) {
// System.out.println("Address: " + offset++ + ", Value: " + value);
// }
} catch (ModbusProtocolException e) {
e.printStackTrace();
} catch (ModbusNumberException e) {
e.printStackTrace();
} catch (ModbusIOException e) {
e.printStackTrace();
} finally {
try {
master.disconnect();
} catch (ModbusIOException e) {
e.printStackTrace();
}
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* int数组转以两个为一组,一次转换成一个个的浮点数,并打印
* @param arry
*/
public static void convertFloat(int arry[]){
for (int i = 0; i < arry.length; i++) {
if (i == 1) {
byte bytes1[] = new byte[2];
//bytes1 = int2Bytes(arry[0], 2);
bytes1 = Int2Bytes_LE(arry[0]);
byte bytes2[] = new byte[2];
//bytes2 = int2Bytes(arry[1], 2);
bytes2 = Int2Bytes_LE(arry[1]);
byte bytes[] = new byte[4];
bytes[0]=bytes1[0];
bytes[1]=bytes1[1];
bytes[2]=bytes2[0];
bytes[3]=bytes2[1];
System.out.println(hex(bytes));
System.out.println(sfloat(hex(bytes)));
} else {
if ((i+1)%2==0) {
byte bytes1[] = new byte[2];
bytes1 = Int2Bytes_LE(arry[i-1]);
byte bytes2[] = new byte[2];
bytes2 = Int2Bytes_LE(arry[i]);
byte bytes[] = new byte[4];
bytes[0]=bytes1[0];
bytes[1]=bytes1[1];
bytes[2]=bytes2[0];
bytes[3]=bytes2[1];
System.out.println(hex(bytes));
System.out.println(sfloat(hex(bytes)));
}
}
}
}
/**
* 转小端,返回2个字节数组
* @param iValue
* @return
*/
public static byte[] Int2Bytes_LE(int iValue){
byte[] rst = new byte[2];
// 先写int的最后一个字节
rst[0] = (byte)(iValue & 0xFF);
// int 倒数第二个字节
rst[1] = (byte)((iValue & 0xFF00) >> 8 );
return rst;
}
//转大端返回4个字节数组
public static byte[] intToByteBig(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n >> 24 & 0xff);
b[1] = (byte) (n >> 16 & 0xff);
b[2] = (byte) (n >> 8 & 0xff);
b[3] = (byte) (n & 0xff);
return b;
}
//转小端返回4个字节数组
public static byte[] intToByteLittle(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}
private static String sfloat(String str){
int count = str.length()/2;
String last = "";
for(int i = count-1;i>=0;i--){
String one = str.substring(i*2,(i+1)*2);
last+=one;
}
if(!"".equals(last)) {
Float f = Float.intBitsToFloat(new BigInteger(last, 16).intValue());
//将科学计算值转可以看懂的数值
DecimalFormat fnum = new DecimalFormat("##0.000");
String dd = fnum.format(f);
return dd;
}
return "--";
}
//将一个int数转换成几个字节数组
public static byte[] int2Bytes(int value, int len) {
byte b[] = new byte[len];
for (int i = 0; i < len; i++) {
b[len - i - 1] = (byte) ((value >> 8 * i) & 0xff);
}
return b;
}
public static String hex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte aByte : bytes) {
result.append(String.format("%02x", aByte));
}
return result.toString();
}
}