/* ==================================================================
* SerialUtils.java - 25/10/2014 7:28:41 AM
*
* Copyright 2007-2014 SolarNetwork.net Dev Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
* ==================================================================
*/
package net.solarnetwork.node.io.serial;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility methods for working with serial IO.
*
* @author matt
* @version 1.0
*/
public final class SerialUtils {
/** The UTF-8 character set name. */
public static final String UTF8_CHARSET = "UTF-8";
/** The US-ASCII character set name. */
public static final String ASCII_CHARSET = "US-ASCII";
private static final Logger LOG = LoggerFactory.getLogger(SerialUtils.class);
private SerialUtils() {
// can't create me
}
/**
* Parse a big-endian 32-bit float value from a data array.
*
* @param data
* the data array
* @param offset
* the offset within the array to parse the value from
* @return the float, or <em>null</em> if not available
*/
public static Float parseBigEndianFloat32(Integer[] data, int offset) {
Float result = null;
if ( data != null && offset >= 0 && data.length > (offset + 1) ) {
result = SerialUtils.parseBigEndianFloat32(new Integer[] { data[offset], data[offset + 1] });
}
return result;
}
/**
* Parse a 32-bit float value from raw Modbus register values. The
* {@code data} array is expected to have a length of at least
* {@code offset} + {@code 1}, and be arranged in big-endian order.
*
* @param data
* the data array
* @return the parsed float, or <em>null</em> if not available or parsed
* float is {@code NaN}
*/
public static Float parseBigEndianFloat32(final int[] data, int offset) {
Float result = null;
if ( data != null && (offset + 1) < data.length ) {
result = parseFloat32(data[0], data[1]);
}
return result;
}
/**
* Parse a 32-bit float value from raw integer values.
*
* @param high
* the high 16 bits
* @param low
* the low 16 bits
* @return the parsed float, or <em>null</em> if not available or parsed
* float is {@code NaN}
*/
public static Float parseFloat32(final int high, final int low) {
Float result = Float.intBitsToFloat(((high & 0xFFFF) << 16) | (low & 0xFFFF));
if ( result.isNaN() ) {
LOG.trace("Data results in NaN: {} {}", high, low);
result = null;
}
return result;
}
/**
* Parse a 32-bit float value from raw integer values. The {@code data}
* array is expected to have a length of {@code 2}, and be arranged in
* big-endian order.
*
* @param data
* the data array
* @return the parsed float, or <em>null</em> if not available or parsed
* float is {@code NaN}
*/
public static Float parseBigEndianFloat32(final Integer[] data) {
Float result = null;
if ( data != null && data.length == 2 ) {
result = Float.intBitsToFloat(((data[0].intValue() & 0xFFFF) << 16)
| (data[1].intValue() & 0xFFFF));
if ( result.isNaN() ) {
LOG.trace("Data results in NaN: {}", (Object) data);
result = null;
}
}
return result;
}
/**
* Parse a big-endian 64-bit integer value from a data array.
*
* @param data
* the data array
* @param offset
* the offset within the array to parse the value from
* @return the long, or <em>null</em> if not available
*/
public static Long parseBigEndianInt64(Integer[] data, int offset) {
Long result = null;
if ( data != null && offset >= 0 && data.length > (offset + 3) ) {
result = SerialUtils.parseBigEndianInt64(new Integer[] { data[offset], data[offset + 1],
data[offset + 2], data[offset + 3] });
}
return result;
}
/**
* Parse a 64-bit long value from raw integer values. The {@code data} array
* is expected to have a length of {@code 4}, and be arranged in big-endian
* order.
*
* @param data
* the data array
* @return the parsed long
*/
public static Long parseBigEndianInt64(final Integer[] data) {
Long result = null;
if ( data != null && data.length == 4 ) {
result = parseInt64(data[0], data[1], data[2], data[3]);
}
return result;
}
/**
* Parse a 64-bit long value from raw integer values.
*
* @param h1
* bits 63-48
* @param h2
* bits 47-32
* @param l1
* bits 31-16
* @param l2
* bits 15-0
* @return the parsed long
*/
public static Long parseInt64(final int h1, final int h2, final int l1, final int l2) {
return ((((long) h1 & 0xFFFF) << 48) | (((long) h2 & 0xFFFF) << 32)
| (((long) l1 & 0xFFFF) << 16) | ((long) l2 & 0xFFFF));
}
/**
* Parse a 32-bit long value from raw integer values. The {@code data} array
* is expected to have a length of at least {@code offset} + {@code 1}, and
* be arranged in big-endian order. <b>Note</b> a {@code Long} is returned
* to support unsigned 32-bit values.
*
* @param data
* the data array
* @param offset
* the offset in the array to parse the 32-bit value
* @return the parsed long
*/
public static Long parseBigEndianInt32(final int[] data, int offset) {
Long result = null;
if ( data != null && (offset + 1) < data.length ) {
result = ((long) ((data[offset] & 0xFFFF) << 16) | (long) (data[offset + 1] & 0xFFFF));
}
return result;
}
}