2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.paradoxalarm.internal.util;
15 import java.io.ByteArrayOutputStream;
16 import java.io.IOException;
17 import java.nio.ByteBuffer;
18 import java.nio.ByteOrder;
19 import java.nio.charset.StandardCharsets;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * The {@link ParadoxUtil} Utility class for different calculations / manipulations of data in the model and
28 * @author Konstantin Polihronov - Initial contribution
30 public class ParadoxUtil {
32 private static final String SPACE_DELIMITER = " ";
34 private static final Logger LOGGER = LoggerFactory.getLogger(ParadoxUtil.class);
36 public static byte calculateChecksum(byte[] payload) {
38 for (byte everyByte : payload) {
42 return (byte) (result % 256);
45 public static byte getBit(int value, int bitNumber) {
46 return (byte) ((value >> bitNumber) & 1);
49 public static boolean isBitSet(int value, int bitNumber) {
50 return ((value >> bitNumber) & 1) == 1;
53 public static void printPacket(String description, byte[] array) {
54 if (LOGGER.isTraceEnabled()) {
55 LOGGER.trace("Packet payload size: {}", array[1]);
56 printByteArray(description, array, array[1] + 16);
60 public static void printByteArray(String description, byte[] array) {
62 LOGGER.trace("Array is null");
65 printByteArray(description, array, array.length);
68 public static void printByteArray(String description, byte[] array, int length) {
69 if (!LOGGER.isTraceEnabled()) {
73 String result = byteArrayToString(array, length);
74 if (!result.isEmpty()) {
75 LOGGER.trace("{}", description + SPACE_DELIMITER + result);
79 public static String byteArrayToString(byte[] array) {
80 return byteArrayToString(array, array.length);
85 * Returns passed array as HEX string. On every 8 bytes we put space for better readability. Example 16
86 * bytes array output: AA47000263000000 03EE00EEEEEEB727
92 public static String byteArrayToString(byte[] array, int length) {
94 throw new IllegalArgumentException("Array must not be null.");
96 if (length > array.length) {
97 throw new IllegalArgumentException("Length should be lower than or equal to array length. Length=" + length
98 + ". Array length=" + array.length);
100 StringBuilder sb = new StringBuilder();
101 for (int i = 0; i < length; i++) {
102 if (i != 0 && i % 8 == 0) {
103 sb.append(SPACE_DELIMITER);
105 sb.append(String.format("%02X", array[i]));
107 return sb.toString();
110 public static byte setBit(byte byteValue, int i, int j) {
112 return (byte) (byteValue | (1 << i));
114 return (byte) (byteValue & ~(1 << i));
118 public static byte getHighNibble(byte value) {
119 return (byte) ((value & 0xF0) >> 4);
122 public static byte getLowNibble(byte value) {
123 return (byte) (value & 0x0F);
126 public static byte[] mergeByteArrays(byte[]... arrays) {
128 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
129 for (byte[] array : arrays) {
130 outputStream.write(array);
132 return outputStream.toByteArray();
133 } catch (IOException e) {
134 LOGGER.warn("Exception merging arrays:", e);
139 public static byte[] intToByteArray(int value) {
140 return ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).order(ByteOrder.BIG_ENDIAN).putInt(value).array();
143 public static byte[] shortToByteArray(short value) {
144 return ByteBuffer.allocate(Short.SIZE / Byte.SIZE).order(ByteOrder.BIG_ENDIAN).putShort(value).array();
147 public static byte[] stringToBCD(String pcPassword) {
148 return stringToBCD(pcPassword, 4);
151 public static byte[] stringToBCD(String pcPassword, int numberOfDigits) {
152 byte[] result = new byte[numberOfDigits / 2];
153 for (int i = 0, j = 0; i < 2; i++, j += 2) {
154 String substring = pcPassword.substring(j, j + 1);
155 int parseInt = Integer.parseInt(substring);
156 result[i] = (byte) ((parseInt & 0x0F) << 4);
158 substring = pcPassword.substring(j + 1, j + 2);
159 parseInt = Integer.parseInt(substring);
160 result[i] |= (byte) (parseInt & 0x0F);
166 * This method fills array with 0xEE based on rate.
167 * Example: If input array length is 5 and rate is 8 the array will be extended with 3 more bytes filled with 0xEE
173 public static byte[] extendArray(byte[] inputArray, int rate) {
174 if (inputArray == null || inputArray.length % rate == 0) {
178 final int newLength = inputArray.length + (rate - inputArray.length % rate);
179 byte[] result = new byte[newLength];
180 for (int i = 0; i < result.length; i++) {
181 if (i < inputArray.length) {
182 result[i] = inputArray[i];
184 result[i] = (byte) 0xEE;
191 * Returns bytes from string with standard US_ASCII standard charset to ensure everywhere in the binding we use same
198 public static byte[] getBytesFromString(String str) {
200 throw new IllegalArgumentException("String must not be null !");
203 return str.getBytes(StandardCharsets.US_ASCII);
206 public static int[] toIntArray(byte[] input) {
208 throw new IllegalArgumentException("Input array must not be null");
210 int[] result = new int[input.length];
211 for (int i = 0; i < input.length; i++) {
212 result[i] = input[i] & 0xFF;
218 public static byte[] toByteArray(int[] input) {
220 throw new IllegalArgumentException("Input array must not be null");
222 byte[] result = new byte[input.length];
223 for (int i = 0; i < input.length; i++) {
224 result[i] = (byte) (input[i]);