// Path: src/us/pfrommer/insteon/msg/Msg.java
// public enum Direction {
// 	TO_MODEM("TO_MODEM"),
// 	FROM_MODEM("FROM_MODEM");
// 		
// 	private static HashMap<String, Direction> s_map = new HashMap<String, Direction>();
// 		
// 	private String m_directionString;
// 		
// 	static {
// 		try {
// 			s_map.put(TO_MODEM.getDirectionString(), TO_MODEM);
// 			s_map.put(FROM_MODEM.getDirectionString(), FROM_MODEM);
// 		} catch (Exception e) {
// 			e.printStackTrace();
// 		}
// 	}
// 		
// 	Direction(String dirString) {
// 		m_directionString = dirString;
// 	}
// 	public String getDirectionString() {
// 		return m_directionString;
// 	}
// 	public static Direction s_getDirectionFromString(String dir) {
// 		return s_map.get(dir);
// 	}
// }
// 
// Path: src/us/pfrommer/insteon/utils/Utils.java
// public class Utils {
// 	public static String readFile(File f) throws IOException {
// 		return read(new FileInputStream(f));
// 	}
// 	public static String read(InputStream in) throws IOException {
// 		BufferedReader r = new BufferedReader(new InputStreamReader(in));
// 		StringBuilder b = new StringBuilder();
// 		
// 		String line = null;
// 		while((line = r.readLine()) != null) {
// 			b.append(line);
// 			b.append('\n');
// 		}
// 		
// 		return b.toString();
// 	}
// 	
// 	
// 	public static String toHex(int b) {
// 		String result =  String.format("%02X", b & 0xFF);
// 		return result;
// 	}
// 	public static String toHex(byte b) {
// 		String result =  String.format("%02X", b);
// 		return result;
// 	}
// 
// 	public static String toHex(byte[] b) {
// 		return toHex(b, 0, b.length);
// 	}
// 	
// 	public static String toHex(byte[] b, int off, int len) {
// 		return toHex(b, off, len, "");
// 	}
// 
// 	public static String toHex(byte[] b, int off, int len, String separator) {
// 		StringBuilder result = new StringBuilder();
// 		for (int i = 0; i < b.length && i < len; i++) {
// 			result.append(toHex(b[i]));
// 			if (i != b.length - 1) result.append(separator);
// 		}
// 		return result.toString();
// 	}
// 	
// 	public static int fromHexString(String string) {
// 		return Integer.parseInt(string, 16);
// 	}
// 	
// 	public static int from0xHexString(String string) {
// 		String hex = string.substring(2);
// 		return fromHexString(hex);
// 	}
// 	
// 	public static String toHexByte(byte b) {
// 		return String.format("0x%02X", b & 0xFF);
// 	}
// 	
// 	public static String toHexByte(int b) {
// 		return String.format("0x%02X", b);
// 	}
// 	
// 	public static class DataTypeParser {
// 		public static Object s_parseDataType(DataType type, String val) {
// 			switch(type) {
// 			case BYTE: 		return s_parseByte(val);
// 			case INT:		return s_parseInt(val);
// 			case FLOAT: 	return s_parseFloat(val);
// 			case ADDRESS:	return s_parseAddress(val);
// 			default : throw new IllegalArgumentException("Data Type not implemented in Field Value Parser!");
// 			}
// 		}
// 		
// 		public static byte s_parseByte(String val) {
// 			if (val != null && !val.trim().equals("")) {
// 				return (byte) Utils.from0xHexString(val.trim());
// 			} else return 0x00;
// 		}
// 		public static int s_parseInt(String val) {
// 			if (val != null && !val.trim().equals("")) {
// 				return Integer.parseInt(val);
// 			} else return 0x00;
// 		}
// 		public static float s_parseFloat(String val) {
// 			if (val != null && !val.trim().equals("")) {
// 				return Float.parseFloat(val.trim());
// 			} else return 0;
// 		}
// 		public static InsteonAddress s_parseAddress(String val) {
// 			if (val != null && !val.trim().equals("")) {
// 				return InsteonAddress.s_parseAddress(val.trim());
// 			} else return new InsteonAddress();
// 		}
// 	}
// 	/**
// 	 * Exception to indicate various xml parsing errors.
// 	 */
// 	@SuppressWarnings("serial")
// 	public static class ParsingException  extends Exception { 
// 		public ParsingException(String msg) {
// 			super(msg);
// 		}
// 		public ParsingException(String msg, Throwable cause) {
// 			super(msg, cause);
// 		}
// 	}
// }


import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import us.pfrommer.insteon.msg.Msg.Direction;
import us.pfrommer.insteon.utils.Utils;
package us.pfrommer.insteon.msg;



/**
 * This class takes data coming from the serial port and turns it
 * into an message. For that, it has to figure out the length of the 
 * message from the header, and read enough bytes until it hits the
 * message boundary. The code is tricky, partly because the Insteon protocol is.
 * Most of the time the command code (second byte) is enough to determine the length
 * of the incoming message, but sometimes one has to look deeper into the message
 * to determine if it is a standard or extended message (their lengths differ).
 * 
 * @author Bernd Pfrommer
 * @author Daniel Pfrommer
 * @since 1.5.0
 */
public class MsgReader {
	private static final Logger logger = LoggerFactory.getLogger(MsgReader.class);
	// no idea what the max msg length could be, but
	// I doubt it'll ever be larger than 4k
	private final static int	MAX_MSG_LEN = 4096;
	private byte[] 				m_buf = new byte[MAX_MSG_LEN];
	private int					m_end = 0;	// offset of end of buffer

// Path: src/us/pfrommer/insteon/msg/Msg.java
// public enum Direction {
// 	TO_MODEM("TO_MODEM"),
// 	FROM_MODEM("FROM_MODEM");
// 		
// 	private static HashMap<String, Direction> s_map = new HashMap<String, Direction>();
// 		
// 	private String m_directionString;
// 		
// 	static {
// 		try {
// 			s_map.put(TO_MODEM.getDirectionString(), TO_MODEM);
// 			s_map.put(FROM_MODEM.getDirectionString(), FROM_MODEM);
// 		} catch (Exception e) {
// 			e.printStackTrace();
// 		}
// 	}
// 		
// 	Direction(String dirString) {
// 		m_directionString = dirString;
// 	}
// 	public String getDirectionString() {
// 		return m_directionString;
// 	}
// 	public static Direction s_getDirectionFromString(String dir) {
// 		return s_map.get(dir);
// 	}
// }
// 
// Path: src/us/pfrommer/insteon/utils/Utils.java
// public class Utils {
// 	public static String readFile(File f) throws IOException {
// 		return read(new FileInputStream(f));
// 	}
// 	public static String read(InputStream in) throws IOException {
// 		BufferedReader r = new BufferedReader(new InputStreamReader(in));
// 		StringBuilder b = new StringBuilder();
// 		
// 		String line = null;
// 		while((line = r.readLine()) != null) {
// 			b.append(line);
// 			b.append('\n');
// 		}
// 		
// 		return b.toString();
// 	}
// 	
// 	
// 	public static String toHex(int b) {
// 		String result =  String.format("%02X", b & 0xFF);
// 		return result;
// 	}
// 	public static String toHex(byte b) {
// 		String result =  String.format("%02X", b);
// 		return result;
// 	}
// 
// 	public static String toHex(byte[] b) {
// 		return toHex(b, 0, b.length);
// 	}
// 	
// 	public static String toHex(byte[] b, int off, int len) {
// 		return toHex(b, off, len, "");
// 	}
// 
// 	public static String toHex(byte[] b, int off, int len, String separator) {
// 		StringBuilder result = new StringBuilder();
// 		for (int i = 0; i < b.length && i < len; i++) {
// 			result.append(toHex(b[i]));
// 			if (i != b.length - 1) result.append(separator);
// 		}
// 		return result.toString();
// 	}
// 	
// 	public static int fromHexString(String string) {
// 		return Integer.parseInt(string, 16);
// 	}
// 	
// 	public static int from0xHexString(String string) {
// 		String hex = string.substring(2);
// 		return fromHexString(hex);
// 	}
// 	
// 	public static String toHexByte(byte b) {
// 		return String.format("0x%02X", b & 0xFF);
// 	}
// 	
// 	public static String toHexByte(int b) {
// 		return String.format("0x%02X", b);
// 	}
// 	
// 	public static class DataTypeParser {
// 		public static Object s_parseDataType(DataType type, String val) {
// 			switch(type) {
// 			case BYTE: 		return s_parseByte(val);
// 			case INT:		return s_parseInt(val);
// 			case FLOAT: 	return s_parseFloat(val);
// 			case ADDRESS:	return s_parseAddress(val);
// 			default : throw new IllegalArgumentException("Data Type not implemented in Field Value Parser!");
// 			}
// 		}
// 		
// 		public static byte s_parseByte(String val) {
// 			if (val != null && !val.trim().equals("")) {
// 				return (byte) Utils.from0xHexString(val.trim());
// 			} else return 0x00;
// 		}
// 		public static int s_parseInt(String val) {
// 			if (val != null && !val.trim().equals("")) {
// 				return Integer.parseInt(val);
// 			} else return 0x00;
// 		}
// 		public static float s_parseFloat(String val) {
// 			if (val != null && !val.trim().equals("")) {
// 				return Float.parseFloat(val.trim());
// 			} else return 0;
// 		}
// 		public static InsteonAddress s_parseAddress(String val) {
// 			if (val != null && !val.trim().equals("")) {
// 				return InsteonAddress.s_parseAddress(val.trim());
// 			} else return new InsteonAddress();
// 		}
// 	}
// 	/**
// 	 * Exception to indicate various xml parsing errors.
// 	 */
// 	@SuppressWarnings("serial")
// 	public static class ParsingException  extends Exception { 
// 		public ParsingException(String msg) {
// 			super(msg);
// 		}
// 		public ParsingException(String msg, Throwable cause) {
// 			super(msg, cause);
// 		}
// 	}
// }


// Path: src/us/pfrommer/insteon/msg/MsgReader.java
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import us.pfrommer.insteon.msg.Msg.Direction;
import us.pfrommer.insteon.utils.Utils;

package us.pfrommer.insteon.msg;



/**
 * This class takes data coming from the serial port and turns it
 * into an message. For that, it has to figure out the length of the 
 * message from the header, and read enough bytes until it hits the
 * message boundary. The code is tricky, partly because the Insteon protocol is.
 * Most of the time the command code (second byte) is enough to determine the length
 * of the incoming message, but sometimes one has to look deeper into the message
 * to determine if it is a standard or extended message (their lengths differ).
 * 
 * @author Bernd Pfrommer
 * @author Daniel Pfrommer
 * @since 1.5.0
 */
public class MsgReader {
	private static final Logger logger = LoggerFactory.getLogger(MsgReader.class);
	// no idea what the max msg length could be, but
	// I doubt it'll ever be larger than 4k
	private final static int	MAX_MSG_LEN = 4096;
	private byte[] 				m_buf = new byte[MAX_MSG_LEN];
	private int					m_end = 0;	// offset of end of buffer

	private Direction			m_direction = Direction.FROM_MODEM;