diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/util/HexUtils.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/util/HexUtils.java index 0d8584b6d..c62852804 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/util/HexUtils.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/util/HexUtils.java @@ -12,6 +12,7 @@ */ package org.openhab.core.util; +import java.math.BigInteger; import java.nio.charset.StandardCharsets; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -123,6 +124,47 @@ public class HexUtils { return hexToBytes(hexString, "(?<=\\G.{2})"); } + /** + * Convert a white space delimited hex block to a byte array. + * + * @param hexBlock the hex block + * @return the byte array + * @throws IllegalArgumentException if a value is invalid + */ + public static byte[] hexBlockToBytes(String hexBlock) throws IllegalArgumentException { + String plainHex = hexBlock.replaceAll("\\s+", ""); + if (plainHex.length() % 2 != 0) { + throw new IllegalArgumentException("Hex string must have even length"); + } + int length = plainHex.length(); + byte[] result = new byte[length / 2]; + for (int i = 0; i < length; i += 2) { + int hi = Character.digit(plainHex.charAt(i), 16); + int lo = Character.digit(plainHex.charAt(i + 1), 16); + if (hi == -1 || lo == -1) { + throw new IllegalArgumentException( + "Invalid hex character: " + plainHex.charAt(i) + plainHex.charAt(i + 1)); + } + result[i / 2] = (byte) ((hi << 4) + lo); + } + return result; + } + + /** + * Convert a white space delimited hex block to a {@link BigInteger}. + * + * @param hexBlock the hex block + * @return the BigInteger value + * @throws IllegalArgumentException if a value is invalid + */ + public static BigInteger hexBlockToBigInteger(String hexBlock) throws IllegalArgumentException { + String plainHex = hexBlock.replaceAll("\\s+", ""); + if (plainHex.length() % 2 != 0) { + throw new IllegalArgumentException("Hex string must have even length"); + } + return new BigInteger(plainHex, 16); + } + public static byte hexToByte(byte high, byte low) { return (byte) ((unhex(high) << 4) | unhex(low)); } diff --git a/bundles/org.openhab.core/src/test/java/org/openhab/core/util/HexUtilsTest.java b/bundles/org.openhab.core/src/test/java/org/openhab/core/util/HexUtilsTest.java index 18bbf12fd..95304cf1b 100644 --- a/bundles/org.openhab.core/src/test/java/org/openhab/core/util/HexUtilsTest.java +++ b/bundles/org.openhab.core/src/test/java/org/openhab/core/util/HexUtilsTest.java @@ -14,6 +14,8 @@ package org.openhab.core.util; import static org.junit.jupiter.api.Assertions.*; +import java.math.BigInteger; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; @@ -72,4 +74,24 @@ public class HexUtilsTest { final byte[] output = HexUtils.hexToBytes(str); assertArrayEquals(input, output); } + + @Test + public void testHexBlockToBytes() { + final String input = """ + 0000 0000 + F00f + """; + final byte[] output = HexUtils.hexBlockToBytes(input); + assertArrayEquals(new byte[] { 0, 0, 0, 0, (byte) 240, (byte) 15 }, output); + } + + @Test + public void hexBlockToBigInteger() { + final String input = """ + 0000 0000 + F00f + """; + final BigInteger output = HexUtils.hexBlockToBigInteger(input); + assertEquals(new BigInteger("61455"), output); + } }