/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.ebus.internal.utils; import java.math.BigDecimal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A helper class to encode all eBus data types and telegrams. * * @author Christian Sowada * @since 1.7.1 */ public class EBusCodecUtils { private static final Logger logger = LoggerFactory.getLogger(EBusCodecUtils.class); /** * Decodes a byte buffer to a number value * * @param type * @param data * @param replaceValue * @return */ public static Number decode(String type, byte[] data, Number replaceValue) { Number n = null; Number repVal = 0; if (type.equals("data1b")) { n = decodeDATA1b(data[0]); repVal = -128; } else if (type.equals("data1c")) { n = decodeDATA1c(data[0]); repVal = 255; } else if (type.equals("data2b")) { n = decodeDATA2b(data); repVal = -128; } else if (type.equals("data2c")) { n = decodeDATA2c(data); repVal = -2048; } else if (type.equals("word") || type.equals("uint")) { n = decodeWord(data); repVal = 65535; } else if (type.equals("char")) { n = encodeChar(data[0]); repVal = 255; } else if (type.equals("int")) { n = decodeInt(data); repVal = 32768; } else if (type.equals("byte") || type.equals("uchar")) { n = decodeUChar(data[0]); repVal = 255; } else if (type.equals("bcd")) { n = decodeBCD(data[0]); repVal = 255; } else { throw new RuntimeException( "Unable to encode data type \"" + type + "\", maybe currently not supported ..."); } // if replace value parameter set if (replaceValue != null) { repVal = replaceValue; } BigDecimal b = NumberUtils.toBigDecimal(n); BigDecimal c = NumberUtils.toBigDecimal(repVal); // equals replace value, than return null if (b != null && c != null && b.compareTo(c) == 0) { logger.trace("Replace value found, skip value ..."); n = null; } return n; } /** * Encodes a number value to a byte buffer * * @param type * @param value * @return */ public static byte[] encode(String type, Object value) { if (value instanceof Number) { Number n = (Number) value; if (type.equals("data1b")) { return new byte[] { encodeDATA1b(n.byteValue()) }; } else if (type.equals("data1c")) { return new byte[] { encodeDATA1c(n.floatValue()) }; } else if (type.equals("data2b")) { return encodeDATA2b(n.floatValue()); } else if (type.equals("data2c")) { return encodeDATA2c(n.floatValue()); } else if (type.equals("word") || type.equals("uint")) { return encodeWord(n.shortValue()); } else if (type.equals("int")) { return encodeInt(n.shortValue()); } else if (type.equals("byte") || type.equals("uchar")) { return new byte[] { encodeUChar(n.byteValue()) }; } else if (type.equals("char")) { return new byte[] { encodeChar(n.byteValue()) }; } else if (type.equals("bcd")) { return new byte[] { encodeBCD(n.byteValue()) }; } } throw new RuntimeException("Unable to encode data type " + type + ", maybe currently not supported ..."); } /** * Convert the value to a bcd value * * @param data The encoded value * @return The bcd value */ public static byte decodeBCD(byte data) { return (byte) ((data >> 4) * 10 + (data & (byte) 0x0F)); } /** * Convert eBus Type CHAR * * @param data * @return The decoded value */ public static short decodeChar(byte data) { return data; } /** * Convert eBus Type DATA1B * * @param data The encoded value * @return The decoded value */ public static short decodeDATA1b(byte data) { return decodeChar(data); } /** * Convert eBus Type DATA1C * * @param data The encoded value * @return The decoded value */ public static float decodeDATA1c(byte data) { return decodeUChar(data) / 2; } /** * Convert eBus Type DATA2b * * @param data The encoded bytes * @return The decoded value */ public static float decodeDATA2b(byte[] data) { return decodeInt(data) / 256f; } /** * Convert eBus Type DATA2c * * @param data The encoded bytes * @return The decoded value */ public static float decodeDATA2c(byte[] data) { return decodeInt(data) / 16f; } /** * Convert eBus Type Int * * @param data The encoded bytes * @return The decoded value */ public static short decodeInt(byte[] data) { return (short) (data[0] << 8 | data[1] & 0xFF); } /** * Convert eBus Type UCHAR * * @param data * @return The decoded value */ public static short decodeUChar(byte data) { return (short) (data & 0xFF); } /** * Convert eBus Type WORD * * @param The encoded bytes * @return The decoded value */ public static short decodeWord(byte[] data) { return (short) (decodeInt(data) & 0xffff); } /** * Encodes a BCD value * * @param data * @return */ public static byte encodeBCD(byte data) { return (byte) ((byte) ((byte) (data / 10) << 4) | data % 10); } /** * Encodes a CHAR value * * @param data * @return */ public static byte encodeChar(byte data) { return data; } /** * Encodes a DATA1b value * * @param data * @return */ public static byte encodeDATA1b(byte data) { return encodeChar(data); } /** * Encodes a DATA1c value * * @param data * @return */ public static byte encodeDATA1c(float data) { return encodeUChar((short) (data * 2)); } /** * Encodes a DATA2b value * * @param data * @return */ public static byte[] encodeDATA2b(float data) { return encodeInt((short) (data * 256)); } /** * Encodes a DATA2c value * * @param data * @return */ public static byte[] encodeDATA2c(float data) { return encodeInt((short) (data * 16)); } /** * Encodes a INT value * * @param data * @return */ public static byte[] encodeInt(short data) { return new byte[] { (byte) (data >> 8), (byte) data }; } /** * Encodes a UCHAR value * * @param data * @return */ public static byte encodeUChar(short data) { return (byte) (data & 0xFF); } /** * Encodes a WORD value * * @param data * @return */ public static byte[] encodeWord(short data) { return encodeInt((short) (data & 0xFFFF)); } }