/** * 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.insteonplm.internal.message; import org.openhab.binding.insteonplm.internal.device.InsteonAddress; import org.openhab.binding.insteonplm.internal.utils.Utils; /** * An Insteon message has several fields with known type and offset * within the message. This class represents a single field, and * holds name, type, and offset (but not value!). * * @author Daniel Pfrommer * @since 1.5.0 */ public final class Field { private final String m_name; private final int m_offset; private final DataType m_type; public String getName() { return m_name; } public int getOffset() { return m_offset; } public DataType getType() { return m_type; } public Field(String name, DataType type, int off) { m_name = name; m_type = type; m_offset = off; } private void check(int arrayLen, DataType t) throws FieldException { checkSpace(arrayLen); checkType(t); } private void checkSpace(int arrayLen) throws FieldException { if (m_offset + m_type.getSize() > arrayLen) { throw new FieldException("field write beyond end of msg"); } } private void checkType(DataType t) throws FieldException { if (m_type != t) { throw new FieldException("field write type mismatch!"); } } @Override public String toString() { return getName() + " Type: " + getType() + " Offset " + getOffset(); } public String toString(byte[] array) { String s = m_name + ":"; try { switch (m_type) { case BYTE: s += Utils.getHexByte(getByte(array)); break; case INT: s += Integer.toString(getInt(array)); break; case ADDRESS: s += getAddress(array).toString(); break; default: break; } } catch (FieldException e) { // will just return empty string } return s; } public void set(byte[] array, Object o) throws FieldException { switch (getType()) { case BYTE: setByte(array, (Byte) o); break; case INT: setInt(array, (Integer) o); break; // case FLOAT: setFloat(array, (float) o); break; case ADDRESS: setAddress(array, (InsteonAddress) o); break; default: throw new FieldException("Not implemented data type " + getType() + "!"); } } /** * Writes a byte value to a byte array, at the proper offset. * Use this function to set the value of a field within a message. * * @param array the destination array * @param b the value you want to set the byte to * @throws FieldException */ public void setByte(byte[] array, byte b) throws FieldException { check(array.length, DataType.BYTE); array[m_offset] = b; } /** * Writes the value of an integer field to a byte array * Use this function to set the value of a field within a message. * * @param array the destination array * @param i the integer value to set */ public void setInt(byte[] array, int i) throws FieldException { check(array.length, DataType.INT); array[m_offset] = (byte) ((i >>> 24) & 0xFF); array[m_offset + 1] = (byte) ((i >>> 16) & 0xFF); array[m_offset + 2] = (byte) ((i >>> 8) & 0xFF); array[m_offset + 3] = (byte) ((i >>> 0) & 0xFF); } /** * Writes the value of an InsteonAddress to a message array. * Use this function to set the value of a field within a message. * * @param array the destination array * @param adr the insteon address value to set */ public void setAddress(byte[] array, InsteonAddress adr) throws FieldException { check(array.length, DataType.ADDRESS); adr.storeBytes(array, m_offset); } /** * Fetch a byte from the array at the field position * * @param array the array to fetch from * @return the byte value of the field */ public byte getByte(byte[] array) throws FieldException { check(array.length, DataType.BYTE); return array[m_offset]; } /** * Fetch an int from the array at the field position * * @param array the array to fetch from * @return the int value of the field */ public int getInt(byte[] array) throws FieldException { check(array.length, DataType.INT); byte b1 = array[m_offset]; byte b2 = array[m_offset + 1]; byte b3 = array[m_offset + 2]; byte b4 = array[m_offset + 3]; int value = ((b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0)); return value; } /** * Fetch an insteon address from the field position * * @param array the array to fetch from * @return the address */ public InsteonAddress getAddress(byte[] array) throws FieldException { check(array.length, DataType.ADDRESS); InsteonAddress adr = new InsteonAddress(); adr.loadBytes(array, m_offset); return adr; } /** * Equals test */ @Override public boolean equals(Object o) { if (o instanceof Field) { Field f = (Field) o; return (f.getName().equals(getName())) && (f.getOffset() == getOffset()); } else { return false; } } }