Browse Source

Merge pull request #11255 from thingsboard/new_add_float_from_hex_int

TBEL: added some float methods
pull/11269/head
Viacheslav Klimov 2 years ago
committed by GitHub
parent
commit
47aca24fd4
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 199
      common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java
  2. 118
      common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java

199
common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java

@ -61,6 +61,7 @@ public class TbUtils {
private static final int HEX_LEN_MIN = -1;
private static final int HEX_LEN_INT_MAX = 8;
private static final int HEX_LEN_LONG_MAX = 16;
private static final int BYTES_LEN_INT_MAX = 4;
private static final int BYTES_LEN_LONG_MAX = 8;
private static final LinkedHashMap<String, String> mdnEncodingReplacements = new LinkedHashMap<>();
@ -117,6 +118,8 @@ public class TbUtils {
String.class)));
parserConfig.addImport("parseFloat", new MethodStub(TbUtils.class.getMethod("parseFloat",
String.class, int.class)));
parserConfig.addImport("parseHexIntLongToFloat", new MethodStub(TbUtils.class.getMethod("parseHexIntLongToFloat",
String.class, boolean.class)));
parserConfig.addImport("parseDouble", new MethodStub(TbUtils.class.getMethod("parseDouble",
String.class)));
parserConfig.addImport("parseLittleEndianHexToInt", new MethodStub(TbUtils.class.getMethod("parseLittleEndianHexToInt",
@ -159,14 +162,18 @@ public class TbUtils {
String.class)));
parserConfig.addImport("parseHexToFloat", new MethodStub(TbUtils.class.getMethod("parseHexToFloat",
String.class, boolean.class)));
parserConfig.addImport("parseBytesToFloat", new MethodStub(TbUtils.class.getMethod("parseBytesToFloat",
byte[].class, int.class, boolean.class)));
parserConfig.addImport("parseBytesToFloat", new MethodStub(TbUtils.class.getMethod("parseBytesToFloat",
byte[].class, int.class)));
parserConfig.addImport("parseBytesToFloat", new MethodStub(TbUtils.class.getMethod("parseBytesToFloat",
List.class, int.class)));
parserConfig.addImport("parseBytesToFloat", new MethodStub(TbUtils.class.getMethod("parseBytesToFloat",
byte[].class, int.class, boolean.class)));
parserConfig.addImport("parseBytesToFloat", new MethodStub(TbUtils.class.getMethod("parseBytesToFloat",
List.class, int.class, boolean.class)));
parserConfig.addImport("parseBytesToFloat", new MethodStub(TbUtils.class.getMethod("parseBytesToFloat",
List.class, int.class)));
byte[].class, int.class, int.class, boolean.class)));
parserConfig.addImport("parseBytesToFloat", new MethodStub(TbUtils.class.getMethod("parseBytesToFloat",
List.class, int.class, int.class, boolean.class)));
parserConfig.addImport("parseLittleEndianHexToDouble", new MethodStub(TbUtils.class.getMethod("parseLittleEndianHexToDouble",
String.class)));
parserConfig.addImport("parseBigEndianHexToDouble", new MethodStub(TbUtils.class.getMethod("parseBigEndianHexToDouble",
@ -179,10 +186,14 @@ public class TbUtils {
byte[].class, int.class)));
parserConfig.addImport("parseBytesToDouble", new MethodStub(TbUtils.class.getMethod("parseBytesToDouble",
byte[].class, int.class, boolean.class)));
parserConfig.addImport("parseBytesToDouble", new MethodStub(TbUtils.class.getMethod("parseBytesToDouble",
byte[].class, int.class, int.class, boolean.class)));
parserConfig.addImport("parseBytesToDouble", new MethodStub(TbUtils.class.getMethod("parseBytesToDouble",
List.class, int.class)));
parserConfig.addImport("parseBytesToDouble", new MethodStub(TbUtils.class.getMethod("parseBytesToDouble",
List.class, int.class, boolean.class)));
parserConfig.addImport("parseBytesToDouble", new MethodStub(TbUtils.class.getMethod("parseBytesToDouble",
List.class, int.class, int.class, boolean.class)));
parserConfig.addImport("toFixed", new MethodStub(TbUtils.class.getMethod("toFixed",
double.class, int.class)));
parserConfig.addImport("toFixed", new MethodStub(TbUtils.class.getMethod("toFixed",
@ -201,17 +212,17 @@ public class TbUtils {
Long.class)));
parserConfig.addImport("longToHex", new MethodStub(TbUtils.class.getMethod("longToHex",
Long.class, boolean.class)));
parserConfig.addImport("longToHex", new MethodStub(TbUtils.class.getMethod("longToHex",
parserConfig.addImport("longToHex", new MethodStub(TbUtils.class.getMethod("longToHex",
Long.class, boolean.class, boolean.class)));
parserConfig.addImport("longToHex", new MethodStub(TbUtils.class.getMethod("longToHex",
parserConfig.addImport("longToHex", new MethodStub(TbUtils.class.getMethod("longToHex",
Long.class, boolean.class, boolean.class, int.class)));
parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
Long.class)));
parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
Long.class, int.class)));
parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
Long.class, int.class, boolean.class)));
parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
parserConfig.addImport("intLongToString", new MethodStub(TbUtils.class.getMethod("intLongToString",
Long.class, int.class, boolean.class, boolean.class)));
parserConfig.addImport("floatToHex", new MethodStub(TbUtils.class.getMethod("floatToHex",
Float.class)));
@ -334,10 +345,14 @@ public class TbUtils {
}
public static Integer parseInt(String value, int radix) {
if (StringUtils.isNotBlank(value)) {
String valueP = prepareNumberString(value);
return parseInt(value, radix, true);
}
private static Integer parseInt(String value, int radix, boolean bigEndian) {
String valueP = prepareNumberString(value, bigEndian);
if (valueP != null) {
int radixValue = isValidStringAndRadix(valueP, radix, value);
if (radixValue >= 25 && radixValue <= MAX_RADIX) {
if (radixValue >= 25 && radixValue <= MAX_RADIX) {
return (Integer) compareIntLongValueMinMax(valueP, radixValue, Integer.MAX_VALUE, Integer.MIN_VALUE);
}
return switch (radixValue) {
@ -354,10 +369,14 @@ public class TbUtils {
}
public static Long parseLong(String value, int radix) {
if (StringUtils.isNotBlank(value)) {
String valueP = prepareNumberString(value);
return parseLong(value, radix, true);
}
private static Long parseLong(String value, int radix, boolean bigEndian) {
String valueP = prepareNumberString(value, bigEndian);
if (valueP != null) {
int radixValue = isValidStringAndRadix(valueP, radix, value);
if (radixValue >= 25 && radixValue <= MAX_RADIX) {
if (radixValue >= 25 && radixValue <= MAX_RADIX) {
return (Long) compareIntLongValueMinMax(valueP, radixValue, Long.MAX_VALUE, Long.MIN_VALUE);
}
return switch (radixValue) {
@ -385,6 +404,7 @@ public class TbUtils {
return Integer.parseInt(binaryString, MIN_RADIX);
}
}
private static long parseBinaryStringAsSignedLong(String binaryString) {
if (binaryString.length() != 64) {
// Pad the binary string to 64 bits if it is not already
@ -420,34 +440,58 @@ public class TbUtils {
}
public static Float parseFloat(String value) {
return parseFloat(value, 0);
return parseFloat(value, ZERO_RADIX);
}
public static Float parseFloat(String value, int radix) {
if (StringUtils.isNotBlank(value)) {
String valueP = prepareNumberString(value);
int radixValue = isValidStringAndRadix(valueP, radix, value);
if (radixValue == DEC_RADIX) {
return Float.parseFloat(value);
} else {
int bits = Integer.parseUnsignedInt(valueP, HEX_RADIX);
return Float.intBitsToFloat(bits);
String valueP = prepareNumberString(value, true);
if (valueP != null) {
return parseFloatFromString(value, valueP, radix);
}
return null;
}
private static Float parseFloatFromString(String value, String valueP, int radix) {
int radixValue = isValidStringAndRadix(valueP, radix, value);
if (radixValue == HEX_RADIX) {
int bits = (int) Long.parseLong(valueP, HEX_RADIX);
// Hex representation is a standard IEEE 754 float value (eg "0x41200000" for 10.0f).
return Float.intBitsToFloat(bits);
} else {
return Float.parseFloat(value);
}
}
public static Float parseHexIntLongToFloat(String value, boolean bigEndian) {
String valueP = prepareNumberString(value, bigEndian);
if (valueP != null) {
int radixValue = isValidStringAndRadix(valueP, HEX_RADIX, value);
if (radixValue == HEX_RADIX) {
int bits = (int) Long.parseLong(valueP, HEX_RADIX);
// If the length is not equal to 8 characters, we process it as an integer (eg "0x0A" for 10.0f).
float floatValue = (float) bits;
return Float.valueOf(floatValue);
}
}
return null;
}
public static Double parseDouble(String value) {
int radix = getRadix10_16(value);
return parseDouble(value, radix);
}
public static Double parseDouble(String value, int radix) {
if (value != null) {
String valueP = prepareNumberString(value);
return parseDouble(value, radix, true);
}
private static Double parseDouble(String value, int radix, boolean bigEndian) {
String valueP = prepareNumberString(value, bigEndian);
if (valueP != null) {
int radixValue = isValidStringAndRadix(valueP, radix, value);
if (radixValue == DEC_RADIX) {
return Double.parseDouble(prepareNumberString(value));
return Double.parseDouble(valueP);
} else {
long bits = Long.parseUnsignedLong(valueP, HEX_RADIX);
return Double.longBitsToDouble(bits);
@ -469,9 +513,7 @@ public class TbUtils {
}
public static Integer parseHexToInt(String value, boolean bigEndian) {
String hexValue = prepareNumberString(value);
String hex = bigEndian ? hexValue : reverseHexStringByOrder(hexValue);
return parseInt(hex, HEX_RADIX);
return parseInt(value, HEX_RADIX, bigEndian);
}
public static long parseLittleEndianHexToLong(String hex) {
@ -487,9 +529,7 @@ public class TbUtils {
}
public static Long parseHexToLong(String value, boolean bigEndian) {
String hexValue = prepareNumberString(value);
String hex = bigEndian ? value : reverseHexStringByOrder(hexValue);
return parseLong(hex, HEX_RADIX);
return parseLong(value, HEX_RADIX, bigEndian);
}
public static float parseLittleEndianHexToFloat(String hex) {
@ -505,9 +545,11 @@ public class TbUtils {
}
public static Float parseHexToFloat(String value, boolean bigEndian) {
String hexValue = prepareNumberString(value);
String hex = bigEndian ? value : reverseHexStringByOrder(hexValue);
return parseFloat(hex, HEX_RADIX);
String valueP = prepareNumberString(value, bigEndian);
if (valueP != null) {
return parseFloatFromString(value, valueP, HEX_RADIX);
}
return null;
}
public static double parseLittleEndianHexToDouble(String hex) {
@ -523,13 +565,11 @@ public class TbUtils {
}
public static double parseHexToDouble(String value, boolean bigEndian) {
String hexValue = prepareNumberString(value);
String hex = bigEndian ? value : reverseHexStringByOrder(hexValue);
return parseDouble(hex, HEX_RADIX);
return parseDouble(value, HEX_RADIX, bigEndian);
}
public static ExecutionArrayList<Byte> hexToBytes(ExecutionContext ctx, String value) {
String hex = prepareNumberString(value);
String hex = prepareNumberString(value, true);
int len = hex.length();
if (len % 2 > 0) {
throw new IllegalArgumentException("Hex string must be even-length.");
@ -575,6 +615,7 @@ public class TbUtils {
public static String longToHex(Long l) {
return prepareNumberHexString(l, true, false, HEX_LEN_MIN, HEX_LEN_LONG_MAX);
}
public static String longToHex(Long l, boolean bigEndian) {
return prepareNumberHexString(l, bigEndian, false, HEX_LEN_MIN, HEX_LEN_LONG_MAX);
}
@ -604,7 +645,7 @@ public class TbUtils {
return Long.toString(number, radix);
}
return switch (radix) {
case MIN_RADIX -> Long.toBinaryString(number);
case MIN_RADIX -> Long.toBinaryString(number);
case OCTAL_RADIX -> Long.toOctalString(number);
case DEC_RADIX -> Long.toString(number);
case HEX_RADIX -> prepareNumberHexString(number, bigEndian, pref, -1, -1);
@ -646,13 +687,13 @@ public class TbUtils {
private static String removeLeadingZero_FF(String hex, Long number, int hexLenMax) {
String hexWithoutZero = hex.replaceFirst("^0+(?!$)", ""); // Remove leading zeros except for the last one
hexWithoutZero = hexWithoutZero.length() % 2 > 0 ? "0" + hexWithoutZero : hexWithoutZero;
hexWithoutZero = hexWithoutZero.length() % 2 > 0 ? "0" + hexWithoutZero : hexWithoutZero;
if (number >= 0) {
return hexWithoutZero;
} else {
String hexWithoutZeroFF = hexWithoutZero.replaceFirst("^F+(?!$)", "");
hexWithoutZeroFF = hexWithoutZeroFF.length() % 2 > 0 ? "F" + hexWithoutZeroFF : hexWithoutZeroFF;
if (hexWithoutZeroFF.length() > hexLenMax) {
hexWithoutZeroFF = hexWithoutZeroFF.length() % 2 > 0 ? "F" + hexWithoutZeroFF : hexWithoutZeroFF;
if (hexWithoutZeroFF.length() > hexLenMax) {
return hexWithoutZeroFF.substring(hexWithoutZeroFF.length() - hexLenMax);
} else if (hexWithoutZeroFF.length() == hexLenMax) {
return hexWithoutZeroFF;
@ -668,7 +709,7 @@ public class TbUtils {
public static String floatToHex(Float f, boolean bigEndian) {
// Convert the float to its raw integer bits representation
int bits = Float.floatToRawIntBits(f);
int bits = Float.floatToIntBits(f);
// Format the integer bits as a hexadecimal string
String result = String.format("0x%08X", bits);
@ -719,7 +760,7 @@ public class TbUtils {
if (offset > data.length) {
throw new IllegalArgumentException("Offset: " + offset + " is out of bounds for array with length: " + data.length + "!");
}
if (length > 4) {
if (length > BYTES_LEN_INT_MAX) {
throw new IllegalArgumentException("Length: " + length + " is too large. Maximum 4 bytes is allowed!");
}
if (offset + length > data.length) {
@ -761,11 +802,11 @@ public class TbUtils {
if (offset + length > data.length) {
throw new IllegalArgumentException("Offset: " + offset + " and Length: " + length + " is out of bounds for array with length: " + data.length + "!");
}
var bb = ByteBuffer.allocate(8);
var bb = ByteBuffer.allocate(BYTES_LEN_LONG_MAX);
if (!bigEndian) {
bb.order(ByteOrder.LITTLE_ENDIAN);
}
bb.position(bigEndian ? 8 - length : 0);
bb.position(bigEndian ? BYTES_LEN_LONG_MAX - length : 0);
bb.put(data, offset, length);
bb.position(0);
return bb.getLong();
@ -784,10 +825,33 @@ public class TbUtils {
}
public static float parseBytesToFloat(byte[] data, int offset, boolean bigEndian) {
byte[] bytesToNumber = prepareBytesToNumber(data, offset, 4, bigEndian);
return ByteBuffer.wrap(bytesToNumber).getFloat();
return parseBytesToFloat(data, offset, BYTES_LEN_INT_MAX, bigEndian);
}
public static float parseBytesToFloat(List data, int offset, int length, boolean bigEndian) {
return parseBytesToFloat(Bytes.toArray(data), offset, length, bigEndian);
}
public static float parseBytesToFloat(byte[] data, int offset, int length, boolean bigEndian) {
byte[] bytesToNumber = prepareBytesToNumber(data, offset, length, bigEndian);
if (length > BYTES_LEN_INT_MAX) {
throw new IllegalArgumentException("Length: " + length + " is too large. Maximum " + BYTES_LEN_INT_MAX + " bytes is allowed!");
}
if (bytesToNumber.length < BYTES_LEN_INT_MAX) {
byte[] extendedBytes = new byte[BYTES_LEN_INT_MAX];
Arrays.fill(extendedBytes, (byte) 0);
System.arraycopy(bytesToNumber, 0, extendedBytes, 0, bytesToNumber.length);
bytesToNumber = extendedBytes;
}
float floatValue = ByteBuffer.wrap(bytesToNumber).getFloat();
if (!Float.isNaN(floatValue)) {
return floatValue;
} else {
long longValue = parseBytesToLong(bytesToNumber, offset, length, bigEndian);
BigDecimal bigDecimalValue = new BigDecimal(longValue);
return bigDecimalValue.floatValue();
}
}
public static double parseBytesToDouble(byte[] data, int offset) {
return parseBytesToDouble(data, offset, true);
@ -801,9 +865,33 @@ public class TbUtils {
return parseBytesToDouble(Bytes.toArray(data), offset, bigEndian);
}
public static double parseBytesToDouble(List data, int offset, int length, boolean bigEndian) {
return parseBytesToDouble(Bytes.toArray(data), offset, length, bigEndian);
}
public static double parseBytesToDouble(byte[] data, int offset, boolean bigEndian) {
byte[] bytesToNumber = prepareBytesToNumber(data, offset, BYTES_LEN_LONG_MAX, bigEndian);
return ByteBuffer.wrap(bytesToNumber).getDouble();
return parseBytesToDouble(data, offset, BYTES_LEN_LONG_MAX, bigEndian);
}
public static double parseBytesToDouble(byte[] data, int offset, int length, boolean bigEndian) {
byte[] bytesToNumber = prepareBytesToNumber(data, offset, length, bigEndian);
if (length > BYTES_LEN_LONG_MAX) {
throw new IllegalArgumentException("Length: " + length + " is too large. Maximum " + BYTES_LEN_LONG_MAX + " bytes is allowed!");
}
if (bytesToNumber.length < BYTES_LEN_LONG_MAX) {
byte[] extendedBytes = new byte[BYTES_LEN_LONG_MAX];
Arrays.fill(extendedBytes, (byte) 0);
System.arraycopy(bytesToNumber, 0, extendedBytes, 0, bytesToNumber.length);
bytesToNumber = extendedBytes;
}
double doubleValue = ByteBuffer.wrap(bytesToNumber).getDouble();
if (!Double.isNaN(doubleValue)) {
return doubleValue;
} else {
BigInteger bigInt = new BigInteger(1, bytesToNumber);
BigDecimal bigDecimalValue = new BigDecimal(bigInt);
return bigDecimalValue.doubleValue();
}
}
private static byte[] prepareBytesToNumber(byte[] data, int offset, int length, boolean bigEndian) {
@ -931,14 +1019,15 @@ public class TbUtils {
}
}
private static String prepareNumberString(String value) {
if (value != null) {
private static String prepareNumberString(String value, boolean bigEndian) {
if (StringUtils.isNotBlank(value)) {
value = value.trim();
value = value.replace("0x", "");
value = value.replace("0X", "");
value = value.replace(",", ".");
return bigEndian ? value : reverseHexStringByOrder(value);
}
return value;
return null;
}
private static int isValidStringAndRadix(String valueP, int radix, String value) {

118
common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java

@ -30,6 +30,7 @@ import org.mvel2.execution.ExecutionArrayList;
import org.mvel2.execution.ExecutionHashMap;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@ -47,7 +48,7 @@ public class TbUtilsTest {
private ExecutionContext ctx;
private final float floatVal = 29.29824f;
private final Float floatVal = 29.29824f;
private final float floatValRev = -5.948442E7f;
@ -256,7 +257,7 @@ public class TbUtilsTest {
@Test
public void parseFloat() {
String floatValStr = "29.29824";
String floatValStr = floatVal.toString();
Assertions.assertEquals(java.util.Optional.of(floatVal).get(), TbUtils.parseFloat(floatValStr));
String floatValHex = "41EA62CC";
Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseHexToFloat(floatValHex)));
@ -274,14 +275,41 @@ public class TbUtilsTest {
}
@Test
public void arseBytesToFloat() {
public void parseBytesToFloat() {
byte[] floatValByte = {65, -22, 98, -52};
Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseBytesToFloat(floatValByte, 0)));
Assertions.assertEquals(0, Float.compare(floatValRev, TbUtils.parseBytesToFloat(floatValByte, 0, false)));
List<Byte> floatVaList = Bytes.asList(floatValByte);
Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseBytesToFloat(floatVaList, 0)));
Assertions.assertEquals(0, Float.compare(floatValRev, TbUtils.parseBytesToFloat(floatVaList, 0, false)));
List<Byte> floatValList = Bytes.asList(floatValByte);
Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseBytesToFloat(floatValList, 0)));
Assertions.assertEquals(0, Float.compare(floatValRev, TbUtils.parseBytesToFloat(floatValList, 0, false)));
// 4 294 967 295L == {0xFF, 0xFF, 0xFF, 0xFF}
floatValByte = new byte[]{-1, -1, -1, -1};
float floatExpectedBe = 4294.9673f;
float floatExpectedLe = 4.2949673E9f;
float actualBe = TbUtils.parseBytesToFloat(floatValByte, 0, 4, true);
Assertions.assertEquals(0, Float.compare(floatExpectedBe, actualBe / 1000000));
Assertions.assertEquals(0, Float.compare(floatExpectedLe, TbUtils.parseBytesToFloat(floatValByte, 0, false)));
floatValList = Bytes.asList(floatValByte);
actualBe = TbUtils.parseBytesToFloat(floatValList, 0);
Assertions.assertEquals(0, Float.compare(floatExpectedBe, actualBe / 1000000));
Assertions.assertEquals(0, Float.compare(floatExpectedLe, TbUtils.parseBytesToFloat(floatValList, 0, false)));
// 2 143 289 344L == {0x7F, 0xC0, 0x00, 0x00}
floatValByte = new byte[]{0x7F, (byte) 0xC0, (byte) 0xFF, 0x00};
floatExpectedBe = 2143.3547f;
floatExpectedLe = -3.984375f;
actualBe = TbUtils.parseBytesToFloat(floatValByte, 0, 4, true);
Assertions.assertEquals(0, Float.compare(floatExpectedBe, actualBe / 1000000));
Assertions.assertEquals(0, Float.compare(floatExpectedLe, TbUtils.parseBytesToFloat(floatValByte, 0, 2, false)));
floatValList = Bytes.asList(floatValByte);
floatExpectedLe = 8372479.0f;
actualBe = TbUtils.parseBytesToFloat(floatValList, 0);
Assertions.assertEquals(0, Float.compare(floatExpectedBe, actualBe / 1000000));
Assertions.assertEquals(0, Float.compare(floatExpectedLe, TbUtils.parseBytesToFloat(floatValList, 0, 3, false)));
}
@Test
@ -358,9 +386,38 @@ public class TbUtilsTest {
Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseBytesToDouble(doubleValByte, 0)));
Assertions.assertEquals(0, Double.compare(doubleValRev, TbUtils.parseBytesToDouble(doubleValByte, 0, false)));
List<Byte> doubleVaList = Bytes.asList(doubleValByte);
Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseBytesToDouble(doubleVaList, 0)));
Assertions.assertEquals(0, Double.compare(doubleValRev, TbUtils.parseBytesToDouble(doubleVaList, 0, false)));
List<Byte> doubleValList = Bytes.asList(doubleValByte);
Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseBytesToDouble(doubleValList, 0)));
Assertions.assertEquals(0, Double.compare(doubleValRev, TbUtils.parseBytesToDouble(doubleValList, 0, false)));
// 4 294 967 295L == {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
doubleValByte = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1};
double doubleExpectedBe = 18446.744073709553d;
double doubleExpectedLe = 1.8446744073709552E19d;
double actualBe = TbUtils.parseBytesToDouble(doubleValByte, 0, 8, true);
Assertions.assertEquals(0, Double.compare(doubleExpectedBe, actualBe / 1000000000000000L));
Assertions.assertEquals(0, Double.compare(doubleExpectedLe, TbUtils.parseBytesToDouble(doubleValByte, 0, false)));
doubleValList = Bytes.asList(doubleValByte);
Assertions.assertEquals(0, Double.compare(doubleExpectedBe, TbUtils.parseBytesToDouble(doubleValList, 0) / 1000000000000000L));
Assertions.assertEquals(0, Double.compare(doubleExpectedLe, TbUtils.parseBytesToDouble(doubleValList, 0, false)));
doubleValByte = new byte[]{0x7F, (byte) 0xC0, (byte) 0xFF, 0x00, 0x7F, (byte) 0xC0, (byte) 0xFF, 0x00};
doubleExpectedBe = 2387013.651780523d;
doubleExpectedLe = 7.234601680440024E-304d;
actualBe = TbUtils.parseBytesToDouble(doubleValByte, 0, 8, true);
BigDecimal bigDecimal = new BigDecimal(actualBe);
// We move the decimal point to the left by 301 positions
actualBe = bigDecimal.movePointLeft(301).doubleValue();
Assertions.assertEquals(0, Double.compare(doubleExpectedBe, actualBe));
Assertions.assertEquals(0, Double.compare(doubleExpectedLe, TbUtils.parseBytesToDouble(doubleValByte, 0, 8, false)));
doubleValList = Bytes.asList(doubleValByte);
doubleExpectedLe = 5.828674572203954E303d;
actualBe = TbUtils.parseBytesToDouble(doubleValList, 0);
bigDecimal = new BigDecimal(actualBe);
actualBe = bigDecimal.movePointLeft(301).doubleValue();
Assertions.assertEquals(0, Double.compare(doubleExpectedBe, actualBe));
Assertions.assertEquals(0, Double.compare(doubleExpectedLe, TbUtils.parseBytesToDouble(doubleValList, 0, 5, false)));
}
@Test
@ -605,15 +662,52 @@ public class TbUtilsTest {
@Test
public void floatToHex_Test() {
Float value = 20.89f;
String expectedHex = "0x41A71EB8";
String valueHexRev = "0xB81EA741";
Float value = 123456789.00f;
String expectedHex = "0x4CEB79A3";
String valueHexRev = "0xA379EB4C";
String actual = TbUtils.floatToHex(value);
Assertions.assertEquals(expectedHex, actual);
Float valueActual = TbUtils.parseHexToFloat(actual);
Assertions.assertEquals(value, valueActual);
valueActual = TbUtils.parseHexToFloat(valueHexRev, false);
Assertions.assertEquals(value, valueActual);
value = 123456789.67f;
expectedHex = "0x4CEB79A3";
valueHexRev = "0xA379EB4C";
actual = TbUtils.floatToHex(value);
Assertions.assertEquals(expectedHex, actual);
valueActual = TbUtils.parseHexToFloat(actual);
Assertions.assertEquals(value, valueActual);
valueActual = TbUtils.parseHexToFloat(valueHexRev, false);
Assertions.assertEquals(value, valueActual);
value = 10.0f;
expectedHex = "0x41200000";
valueHexRev = "0x00002041";
actual = TbUtils.floatToHex(value);
Assertions.assertEquals(expectedHex, actual);
valueActual = TbUtils.parseHexToFloat(actual);
Assertions.assertEquals(value, valueActual);
valueActual = TbUtils.parseHexToFloat(valueHexRev, false);
Assertions.assertEquals(value, valueActual);
}
// If the length is not equal to 8 characters, we process it as an integer (eg "0x0A" for 10.0f).
@Test
public void parseHexIntLongToFloat_Test() {
Float valueExpected = 10.0f;
Float valueActual = TbUtils.parseHexIntLongToFloat("0x0A", true);
Assertions.assertEquals(valueExpected, valueActual);
valueActual = TbUtils.parseHexIntLongToFloat("0x0A", false);
Assertions.assertEquals(valueExpected, valueActual);
valueActual = TbUtils.parseHexIntLongToFloat("0x00000A", true);
Assertions.assertEquals(valueExpected, valueActual);
valueActual = TbUtils.parseHexIntLongToFloat("0x0A0000", false);
Assertions.assertEquals(valueExpected, valueActual);
valueExpected = 2570.0f;
valueActual = TbUtils.parseHexIntLongToFloat("0x000A0A", true);
Assertions.assertEquals(valueExpected, valueActual);
valueActual = TbUtils.parseHexIntLongToFloat("0x0A0A00", false);
Assertions.assertEquals(valueExpected, valueActual);
}
@Test

Loading…
Cancel
Save