// Path: src/us/pfrommer/insteon/utils/ByteArrayIO.java
// public class ByteArrayIO {
// 	public static final int DEFAULT_SIZE = 2048;
// 	
// 	private byte	m_buf[]; // the actual buffer
// 	private	int		m_count; // number of valid bytes
// 	private int 	m_index = 0; // current read index
// 
// 	/**
// 	 * Constructor for ByteArrayIO with dynamic size
// 	 * @param size initial size, but will grow dynamically
// 	 */
// 	public ByteArrayIO(int size) {
// 		m_buf = new byte[size];
// 	}
// 
// 	/**
// 	 * Uses a default size of 2048
// 	 */
// 	public ByteArrayIO() {
// 		this(DEFAULT_SIZE);
// 	}
// 
// 	/**
// 	 * Number of unread bytes
// 	 * @return number of bytes not yet read
// 	 */
// 	public synchronized int remaining() {
// 		return m_count - m_index;
// 	}
// 
// 	/**
// 	 * Blocking read of a single byte
// 	 * @return byte read
// 	 */
// 	public synchronized byte get() throws InterruptedException {
// 		while (remaining() < 1) {
// 			try {
// 				wait();
// 			} catch (InterruptedException e) {
// 				throw e;
// 			}
// 		}
// 		return m_buf[m_index++];
// 	}
// 	/**
// 	 * Blocking read of multiple bytes
// 	 * @param bytes destination array for bytes read
// 	 * @param off offset into dest array
// 	 * @param len max number of bytes to read into dest array
// 	 * @return number of bytes actually read
// 	 */
// 	public synchronized int get(byte[] bytes, int off, int len) throws InterruptedException {
// 		while (remaining() < 1) {
// 			try {
// 				wait();
// 			} catch (InterruptedException e) {
// 				throw e;
// 			}
// 		}
// 		int b = Math.min(len, remaining());
// 		System.arraycopy(m_buf, m_index, bytes, off, b);
// 		m_index += b;
// 		return b;
// 	}
// 	/**
// 	 * Adds bytes to the byte buffer
// 	 * @param b byte array with new bytes
// 	 * @param off starting offset into buffer
// 	 * @param len number of bytes to add
// 	 */
// 	private synchronized void add(byte b[], int off, int len) {
// 		if ((off < 0) || (off > b.length) || (len < 0) ||
// 				((off + len) > b.length) || ((off + len) < 0)) {
// 			throw new IndexOutOfBoundsException();
// 		} else if (len == 0) {
// 			return;
// 		}
// 		int nCount = m_count + len;
// 		if (nCount > m_buf.length) {
// 			// dynamically grow the array
// 			m_buf = Arrays.copyOf(m_buf, Math.max(m_buf.length << 1, nCount));
// 		}
// 		// append new data to end of buffer
// 		System.arraycopy(b, off, m_buf, m_count, len);
// 		m_count = nCount;
// 		notifyAll();
// 	}
// 	/**
// 	 * Adds bytes to the byte buffer 
// 	 * @param b the new bytes to be added 
// 	 */
// 	public void add(byte[] b) {
// 		add(b, 0, b.length);
// 	}
// 
// 	/**
// 	 * Shrink the buffer to smallest size possible
// 	 */
// 	public synchronized void compact() {
// 		if (m_index == 0) return;
// 		byte[] newBuf = new byte[remaining()];
// 		System.arraycopy(m_buf, m_index, newBuf, 0, newBuf.length);
// 		m_index	= 0;
// 		m_count	= newBuf.length;
// 		m_buf	= newBuf;
// 	}
// }


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import us.pfrommer.insteon.utils.ByteArrayIO;
			throw new IOException("Bad authentication...access forbidden");
		return EntityUtils.toString(res.getEntity());
    }
	
	public void run() {
		while(!Thread.currentThread().isInterrupted()) {
			try {
				poll();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				Thread.sleep(m_pollTime);
			} catch (InterruptedException e) {
				break;
			}
		}
	}

	public static byte[] s_hexStringToByteArray(String s) {
	    int len = s.length();
	    byte[] data = new byte[len / 2];
	    for (int i = 0; i < len; i += 2) {
	        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
	                             + Character.digit(s.charAt(i+1), 16));
	    }
	    return data;
	}
	
	public class HubInputStream extends InputStream {	
// Path: src/us/pfrommer/insteon/utils/ByteArrayIO.java
// public class ByteArrayIO {
// 	public static final int DEFAULT_SIZE = 2048;
// 	
// 	private byte	m_buf[]; // the actual buffer
// 	private	int		m_count; // number of valid bytes
// 	private int 	m_index = 0; // current read index
// 
// 	/**
// 	 * Constructor for ByteArrayIO with dynamic size
// 	 * @param size initial size, but will grow dynamically
// 	 */
// 	public ByteArrayIO(int size) {
// 		m_buf = new byte[size];
// 	}
// 
// 	/**
// 	 * Uses a default size of 2048
// 	 */
// 	public ByteArrayIO() {
// 		this(DEFAULT_SIZE);
// 	}
// 
// 	/**
// 	 * Number of unread bytes
// 	 * @return number of bytes not yet read
// 	 */
// 	public synchronized int remaining() {
// 		return m_count - m_index;
// 	}
// 
// 	/**
// 	 * Blocking read of a single byte
// 	 * @return byte read
// 	 */
// 	public synchronized byte get() throws InterruptedException {
// 		while (remaining() < 1) {
// 			try {
// 				wait();
// 			} catch (InterruptedException e) {
// 				throw e;
// 			}
// 		}
// 		return m_buf[m_index++];
// 	}
// 	/**
// 	 * Blocking read of multiple bytes
// 	 * @param bytes destination array for bytes read
// 	 * @param off offset into dest array
// 	 * @param len max number of bytes to read into dest array
// 	 * @return number of bytes actually read
// 	 */
// 	public synchronized int get(byte[] bytes, int off, int len) throws InterruptedException {
// 		while (remaining() < 1) {
// 			try {
// 				wait();
// 			} catch (InterruptedException e) {
// 				throw e;
// 			}
// 		}
// 		int b = Math.min(len, remaining());
// 		System.arraycopy(m_buf, m_index, bytes, off, b);
// 		m_index += b;
// 		return b;
// 	}
// 	/**
// 	 * Adds bytes to the byte buffer
// 	 * @param b byte array with new bytes
// 	 * @param off starting offset into buffer
// 	 * @param len number of bytes to add
// 	 */
// 	private synchronized void add(byte b[], int off, int len) {
// 		if ((off < 0) || (off > b.length) || (len < 0) ||
// 				((off + len) > b.length) || ((off + len) < 0)) {
// 			throw new IndexOutOfBoundsException();
// 		} else if (len == 0) {
// 			return;
// 		}
// 		int nCount = m_count + len;
// 		if (nCount > m_buf.length) {
// 			// dynamically grow the array
// 			m_buf = Arrays.copyOf(m_buf, Math.max(m_buf.length << 1, nCount));
// 		}
// 		// append new data to end of buffer
// 		System.arraycopy(b, off, m_buf, m_count, len);
// 		m_count = nCount;
// 		notifyAll();
// 	}
// 	/**
// 	 * Adds bytes to the byte buffer 
// 	 * @param b the new bytes to be added 
// 	 */
// 	public void add(byte[] b) {
// 		add(b, 0, b.length);
// 	}
// 
// 	/**
// 	 * Shrink the buffer to smallest size possible
// 	 */
// 	public synchronized void compact() {
// 		if (m_index == 0) return;
// 		byte[] newBuf = new byte[remaining()];
// 		System.arraycopy(m_buf, m_index, newBuf, 0, newBuf.length);
// 		m_index	= 0;
// 		m_count	= newBuf.length;
// 		m_buf	= newBuf;
// 	}
// }


// Path: src/us/pfrommer/insteon/msg/hub/InsteonHub.java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import us.pfrommer.insteon.utils.ByteArrayIO;

			throw new IOException("Bad authentication...access forbidden");
		return EntityUtils.toString(res.getEntity());
    }
	
	public void run() {
		while(!Thread.currentThread().isInterrupted()) {
			try {
				poll();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				Thread.sleep(m_pollTime);
			} catch (InterruptedException e) {
				break;
			}
		}
	}

	public static byte[] s_hexStringToByteArray(String s) {
	    int len = s.length();
	    byte[] data = new byte[len / 2];
	    for (int i = 0; i < len; i += 2) {
	        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
	                             + Character.digit(s.charAt(i+1), 16));
	    }
	    return data;
	}
	
	public class HubInputStream extends InputStream {	
		private ByteArrayIO m_buffer = new ByteArrayIO(1024);