反编译代码确实可以计算温度:
正如您所怀疑的那样,反编译的代码 class a
能够计算温度。方法 double a()
具有该算法。尽管反编译的代码无法编译,但经过一番努力,已经进行了修正(见下文),并根据您的输入和期望值准确地计算出温度。
结果:(使用 mapKey=77)
30.506 => 01:53:4e:98
30.460 => 01:53:8e:94
30.425 => 01:53:8e:91
30.391 => 01:53:8e:8e
30.391 => 01:53:4e:8e
12.338 => 01:52:88:b1
15.990 => 01:52:c9:cf
18.636 => 01:52:ca:a5
21.127 => 01:52:8b:74
校准:
方法a()
,现在称为calculateTemperature()
,如果您选择使用它,则似乎已经内置了校准。在4个参数中,第一个是十六进制字符串(算法仅使用其中两个八位字节),其他三个可以校准结果。很难知道如何使用这些值。但是,如果像我在main()
中所示那样将它们保留为默认值,则计算出的温度是正确的。也许您知道为什么要校准结果。其中一个校准需要传递一个值介于65和85之间(我使用的是77)。还有另一个类似的参数,它会导致结果的乘法(零将忽略该参数)。我发现使用mapKey=77会产生结果稍微偏低(但78稍微偏高)。我发现使用100175的比例使结果更接近预期值。第三个校准是+/-类型的校准(零将忽略该参数)。
可能的电压计算
在计算出温度后,有一些代码将在温度在33.2到36.0之间时分配大约0.2-2.0的值。我称之为电压,但不知道它是什么。对于您的输入值,温度始终低于33.2,因此代码的这部分实际上是无用的。
方法c()的未知含义
有一个小方法c()
。它为您提供的值返回大约4.16-4.18的值。这对您有任何意义吗?
工作代码:
main()
方法演示了如何从十六进制字符串获取温度,并打印输入数据的结果。该代码在您提到的网站上运行。值得注意的是,3个校准参数不需要是byte[]
数组,并且可以更简单地理解和使用为类型int
。如果您对代码有任何疑问,请在评论区(或聊天中)与我联系,我会向您解释。
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Meter {
private List<Double> parameterList = new ArrayList<>();
private Map<Integer, Double> scaleMap = new HashMap<>(21);
public static void main(String[] args) {
Meter meter = new Meter();
meter.initData();
int mapKey = 77;
String[] values = { "01:53:4e:98", "01:53:8e:94", "01:53:8e:91", "01:53:8e:8e",
"01:53:4e:8e", "01:52:88:b1", "01:52:c9:cf", "01:52:ca:a5", "01:52:8b:74" };
ByteBuffer key = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(mapKey);
ByteBuffer scale = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(0);
ByteBuffer offset = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(0);
for (int i=0; i<values.length; i++) {
double tempC = meter.calculateTemperature(hexStringToByteArray(values[i]), key.array(), scale.array(), offset.array());
System.out.printf("%2.3f => %s\n", tempC, values[i]);
}
}
static byte[] hexStringToByteArray(String hexString) {
hexString = hexString.replaceAll(":", "");
int len = hexString.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i+1), 16));
}
return data;
}
private void initData() {
scaleMap.put(65, 29.629);
scaleMap.put(66, 29.660);
scaleMap.put(67, 29.691);
scaleMap.put(68, 29.722);
scaleMap.put(69, 29.753);
scaleMap.put(70, 29.784);
scaleMap.put(71, 29.815);
scaleMap.put(72, 29.846);
scaleMap.put(73, 29.877);
scaleMap.put(74, 29.908);
scaleMap.put(75, 29.939);
scaleMap.put(76, 29.970);
scaleMap.put(77, 30.001);
scaleMap.put(78, 30.032);
scaleMap.put(79, 30.063);
scaleMap.put(80, 30.094);
scaleMap.put(81, 30.125);
scaleMap.put(82, 30.156);
scaleMap.put(83, 30.187);
scaleMap.put(84, 30.218);
scaleMap.put(85, 30.249);
parameterList.add(52.94);
parameterList.add(49.61);
parameterList.add(46.51);
parameterList.add(43.62);
parameterList.add(40.94);
parameterList.add(38.44);
parameterList.add(36.12);
parameterList.add(33.95);
parameterList.add(31.93);
parameterList.add(30.05);
parameterList.add(28.29);
parameterList.add(26.61);
parameterList.add(25.05);
parameterList.add(23.59);
parameterList.add(22.23);
parameterList.add(20.96);
parameterList.add(19.76);
parameterList.add(18.65);
parameterList.add(17.60);
parameterList.add(16.63);
parameterList.add(15.71);
parameterList.add(14.84);
parameterList.add(14.02);
parameterList.add(13.25);
parameterList.add(12.53);
parameterList.add(11.86);
parameterList.add(11.22);
parameterList.add(10.63);
parameterList.add(10.07);
parameterList.add(9.541);
parameterList.add(9.046);
parameterList.add(8.572);
parameterList.add(8.126);
parameterList.add(7.706);
parameterList.add(7.311);
parameterList.add(6.938);
parameterList.add(6.588);
parameterList.add(6.257);
parameterList.add(5.946);
parameterList.add(5.651);
parameterList.add(5.374);
parameterList.add(5.109);
parameterList.add(4.859);
parameterList.add(4.623);
parameterList.add(4.400);
parameterList.add(4.189);
parameterList.add(3.990);
parameterList.add(3.801);
parameterList.add(3.623);
parameterList.add(3.454);
parameterList.add(3.294);
parameterList.add(3.141);
parameterList.add(2.996);
parameterList.add(2.858);
parameterList.add(2.728);
parameterList.add(2.604);
parameterList.add(2.487);
parameterList.add(2.376);
parameterList.add(2.270);
parameterList.add(2.170);
parameterList.add(2.075);
parameterList.add(1.984);
parameterList.add(1.897);
parameterList.add(1.815);
parameterList.add(1.737);
parameterList.add(1.662);
parameterList.add(1.591);
parameterList.add(1.524);
parameterList.add(1.459);
parameterList.add(1.398);
parameterList.add(1.340);
parameterList.add(1.284);
parameterList.add(1.231);
parameterList.add(1.180);
parameterList.add(1.132);
parameterList.add(1.086);
parameterList.add(1.042);
parameterList.add(1.000);
parameterList.add(0.9599);
parameterList.add(0.9216);
parameterList.add(0.8851);
parameterList.add(0.8501);
parameterList.add(0.8168);
parameterList.add(0.7849);
parameterList.add(0.7545);
parameterList.add(0.7254);
parameterList.add(0.6974);
parameterList.add(0.6707);
parameterList.add(0.6451);
parameterList.add(0.6207);
parameterList.add(0.5973);
parameterList.add(0.5743);
parameterList.add(0.5523);
parameterList.add(0.5313);
parameterList.add(0.5112);
parameterList.add(0.4920);
parameterList.add(0.4736);
parameterList.add(0.4560);
parameterList.add(0.4392);
parameterList.add(0.4230);
parameterList.add(0.4076);
parameterList.add(0.3925);
parameterList.add(0.3781);
parameterList.add(0.3642);
parameterList.add(0.3510);
parameterList.add(0.3383);
parameterList.add(0.3261);
parameterList.add(0.3144);
parameterList.add(0.3032);
parameterList.add(0.2925);
parameterList.add(0.2822);
parameterList.add(0.2722);
parameterList.add(0.2626);
parameterList.add(0.2534);
parameterList.add(0.2445);
parameterList.add(0.2360);
parameterList.add(0.2279);
parameterList.add(0.2201);
parameterList.add(0.2126);
parameterList.add(0.2054);
parameterList.add(0.1984);
parameterList.add(0.1917);
parameterList.add(0.1852);
parameterList.add(0.1790);
parameterList.add(0.1731);
parameterList.add(0.1673);
parameterList.add(0.1618);
parameterList.add(0.1564);
parameterList.add(0.1513);
parameterList.add(0.1464);
parameterList.add(0.1416);
parameterList.add(0.1370);
parameterList.add(0.1326);
parameterList.add(0.1283);
parameterList.add(0.1242);
parameterList.add(0.1203);
parameterList.add(0.1164);
parameterList.add(0.1128);
parameterList.add(0.1092);
parameterList.add(0.1058);
parameterList.add(0.1026);
}
public double calculateTemperature(byte[] b1array, byte[] mapKey, byte[] byte1Scale, byte[] byte1Offset) {
double scale;
int scaleMicroValue = ByteBuffer.wrap(byte1Scale).order(ByteOrder.LITTLE_ENDIAN).getInt();
if (scaleMicroValue == 0) {
scale = 1.0D;
} else {
scale = scaleMicroValue / 1000000.0D;
}
double offsetValue = ByteBuffer.wrap(byte1Offset).order(ByteOrder.LITTLE_ENDIAN).getInt() / 1000000.0D;
byte byte2 = b1array[2];
byte byte3 = b1array[3];
int bitValue = (byte3 & 0xFF | (byte2 & 0x3F) << 8);
double scaledBitValue = bitValue * scale - offsetValue;
int key = (byte) (mapKey[0] & 0xFF);
double mapValue = scaleMap.containsKey(key) ? scaleMap.get(key) : scaleMap.get(77);
double param1 = 0.0;
double param2 = parameterList.get(0);
double result = 33.0D / scaledBitValue * (8191.0D - scaledBitValue) / mapValue;
int i = 0;
int j = parameterList.size();
double minParameter = parameterList.get(j - 1);
if (param2 < result || minParameter > result)
return 0;
int index = 0;
boolean process = true;
while (i < j && process) {
if (result >= parameterList.get(i)) {
if (i == 0) {
param1 = parameterList.get(i);
param2 = parameterList.get(i + 1);
index = i;
process = false;
}
if (process) {
param1 = parameterList.get(i - 1);
param2 = parameterList.get(i);
index = i - 1;
}
process = false;
}
if (process)
i++;
}
if (process) {
index = 0;
param2 = 0;
}
double voltage = 0.0;
double tempC = index + (result - param1) / (param2 - param1) - 40.0D;
if ((tempC < 34.0D) && (tempC >= 33.2D)) {
voltage = 1.95D;
}
while (true) {
if ((tempC < 34.1D) && (tempC >= 34.0D)) {
voltage = 1.881D;
} else if ((tempC < 34.2D) && (tempC >= 34.1D)) {
voltage = 1.805D;
} else if ((tempC < 34.3D) && (tempC >= 34.2D)) {
voltage = 1.71D;
} else if ((tempC < 34.4D) && (tempC >= 34.3D)) {
voltage = 1.615D;
} else if ((tempC < 34.5D) && (tempC >= 34.4D)) {
voltage = 1.52D;
} else if ((tempC < 34.6D) && (tempC >= 34.5D)) {
voltage = 1.4249999999999998D;
} else if ((tempC < 34.7D) && (tempC >= 34.6D)) {
voltage = 1.3299999999999998D;
} else if ((tempC < 34.8D) && (tempC >= 34.7D)) {
voltage = 1.2349999999999999D;
} else if ((tempC < 34.9D) && (tempC >= 34.8D)) {
voltage = 1.14D;
} else if ((tempC < 35.0D) && (tempC >= 34.9D)) {
voltage = 1.045D;
} else if ((tempC < 35.1D) && (tempC >= 35.0D)) {
voltage = 0.95D;
} else if ((tempC < 35.2D) && (tempC >= 35.1D)) {
voltage = 0.855D;
} else if ((tempC < 35.3D) && (tempC >= 35.2D)) {
voltage = 0.76D;
} else if ((tempC < 35.4D) && (tempC >= 35.3D)) {
voltage = 0.6649999999999999D;
} else if ((tempC < 35.5D) && (tempC >= 35.4D)) {
voltage = 0.57D;
} else if ((tempC < 35.6D) && (tempC >= 35.5D)) {
voltage = 0.475D;
} else if ((tempC < 35.7D) && (tempC >= 35.6D)) {
voltage = 0.38D;
} else if ((tempC < 35.8D) && (tempC >= 35.7D)) {
voltage = 0.285D;
} else if ((tempC < 35.9D) && (tempC >= 35.8D)) {
voltage = 0.19D;
} else {
if (tempC >= 36.0D) {
break;
}
if (tempC < 35.9D) {
break;
}
voltage = 0.095D;
}
}
return tempC;
}
public double m(byte[] bArray) {
int byte2 = bArray[2];
int byte1 = bArray[1];
int byte0 = bArray[0];
return 0.003077674645823156D * (((byte0 & 0x3) << 2 | (byte1 & 0xC0) >> 6) << 8
| (byte2 & 0xC0) >> 6 | (byte1 & 0x3F) << 2);
}
}
编辑:接受十六进制字符串作为参数,并输出温度的方法
public static void main(String[] args) {
Meter meter = new Meter();
meter.initData();
int mapKey = 77;
ByteBuffer key = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(mapKey);
ByteBuffer scale = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(1000180);
ByteBuffer offset = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(0);
byte[] hexString = hexStringToByteArray(args[0]);
double tempC = meter.calculateTemperature(hexString, key.array(), scale.array(), offset.array());
System.out.printf("%.2f", tempC);
}
a()
看起来像是返回一个温度,但它却操作了四个四字节数组。方法m()
只操作了一个四字节数组,但给出的示例输入它返回的值约为4.16。考虑到该方法中巧妙的位操作,猜测这些值是如何计算的毫无意义。这不像是对原始输入进行处理,而更像是故意混淆。 - Wladimir Palantfor (;;) { return d3 + d1; if ((d3 < 34.1D) && (d3 >= 34.0D)) {...
。换句话说,那个for
循环完全没有用,因为第一个语句是一个return
语句,而在return
语句下面的所有内容都永远不会被执行。实际上,这甚至不应该编译通过(参见示例)。无论如何,看起来反编译器不起作用,或者代码已经通过能够跳过编译检查的混淆器运行了。 - Radiodef