部分代码片段:
import com.keydak.collector.core.response.LengthStrategy;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.math.BigDecimal;
import java.util.Optional;
/**
* 从响应数据 开始地址取4个长度转为Int类型, 默认高位在前、低位在后
*/
@XStreamAlias("Byte4ToIntSensorDefine")
public class Byte4ToIntSensorDefine extends SensorDefine {
/**
* 是否是小端法 默认采用大端法(false)
**/
private boolean smallHead = false;
/**
* 控制高低位 默认高位在前低位在后(false)
**/
private boolean reverse = false;
/**
* 用于获取2个字节数据,默认取高位数据(false)
**/
private boolean towBytes = false;
/**
* 是否选择 2个字节解析 默认4个字节解析(fasle)
**/
private boolean half = false;
public Byte4ToIntSensorDefine(String commandName, String chName, String enName, int registerIndex, int scale, double divider) {
super(commandName, chName, enName, registerIndex, scale, divider);
}
@Override
public BigDecimal getData(IResponseContext<LengthStrategy, byte[]> context) throws Exception {
byte[] data = {74, 22, 0, 0};
// byte[] data = context.getData(commandName, getStrategy());
return Optional.ofNullable(data).map(byteArray -> {
int actualValue = half ? bytes2IntHalf(byteArray) :
(smallHead ? bytes2IntLittle(byteArray) : bytes2IntBig(byteArray));
BigDecimal value = new BigDecimal(actualValue).divide(BigDecimal.valueOf(divider), scale, BigDecimal.ROUND_HALF_UP);
return value;
}).orElse(null);
}
@Override
protected LengthStrategy getStrategy() {
return new LengthStrategy(registerIndex, 4);
}
/**
* byte数组到int的转换(小端)
*
* @param bytes
* @return
*/
public int bytes2IntLittle(byte[] bytes) {
byte[] result = null;
if (reverse) {
result = new byte[bytes.length];
result[0] = bytes[2];
result[1] = bytes[3];
result[2] = bytes[0];
result[3] = bytes[1];
} else {
result = bytes;
}
int int1 = result[0] & 0xff;
int int2 = (result[1] & 0xff) << 8;
int int3 = (result[2] & 0xff) << 16;
int int4 = (result[3] & 0xff) << 24;
return int1 | int2 | int3 | int4;
}
/**
* byte数组到int的转换(大端)
*
* @param bytes
* @return
*/
public int bytes2IntBig(byte[] bytes) {
byte[] result = null;
if (reverse) {
result = new byte[bytes.length];
result[0] = bytes[2];
result[1] = bytes[3];
result[2] = bytes[0];
result[3] = bytes[1];
} else {
result = bytes;
}
int int1 = result[3] & 0xff;
int int2 = (result[2] & 0xff) << 8;
int int3 = (result[1] & 0xff) << 16;
int int4 = (result[0] & 0xff) << 24;
return int1 | int2 | int3 | int4;
}
/**
* 选择解析高位数据或者低位数据(2个字节)
**/
public int bytes2IntHalf(byte[] bytes) {
byte[] result = null;
if (towBytes) {
//只取低位两个字节数据
result = new byte[2];
result[0] = bytes[2];
result[1] = bytes[3];
} else {
//只取高位两个字节数据
result = new byte[2];
result[0] = bytes[0];
result[1] = bytes[1];
}
StringBuilder hexString = new StringBuilder();
for (byte b : result) {
hexString.append(String.format("%02X", b));
}
String hex = hexString.toString();
int decimal = Integer.parseInt(hex, 16);
return decimal;
}
}
采集命令 :
<ModbusRequest> <name>Jy500-SJ_AI_A5</name> <timeout>1000</timeout> <commandType>3</commandType> <description>ABC相电能</description> <length>12</length> <registerNumber>536</registerNumber> </ModbusRequest>
响应命令数据解析:
<Byte4ToIntSensorDefine> <chName>第一路A相电能</chName> <enName>Jy500-SJ_First_A_Phase_Power_Energy</enName> <registerIndex>536</registerIndex> <scale>1</scale> <commandName>Jy500-SJ_AI_A5</commandName> <divider>10</divider> <reverse>false</reverse> <half>true</half> </Byte4ToIntSensorDefine>
例子:
[15:29:38.156]发→◇01 03 02 1A 00 02 E4 74 □
[15:29:38.161]收←◆01 03 04 4A 16 00 00 0D EF
数据:
十六进制:4A 16 00 00 转十进制:74 22 00 00