Blog | Admin | Archives

Java and Com Ports

Win32Driver…
javax.comm…

This is ridiculous!

It shouldn’t be this hard, Sun.

One of my implementations:


import java.io.*;
import java.util.*;
import javax.comm.*;
import com.sun.comm.Win32Driver;

/**
 * Open a serial port using Java
 *
 * @author Ryan McElroy
 */
public class WinComPort implements LowLevelInterface
{
	// Implementation-specific stuff
	private List<CommPortIdentifier> portList;
	private CommPortIdentifier portId;
	private SerialPort serialPort;
	private OutputStream outputStream;
	private InputStream inputStream;
	private String portName;
	private ComPortListener cpl;
	
	// General stuff
	protected Parser parser;
	public PrintStream so;
	
	public WinComPort(String port, int baud)
	{
		so = System.out;
		portName = port;
		init();
		if (validate() && open() && setBaud(baud))
		{
			cpl = new ComPortListener();
		}
		else
		{
			throw new NullPointerException(\"Couldn\'t open com port\");
		}
	}
	
	public void setParser (Parser p)
	{
		// cpl is inner class, so this works beautifully
		parser = p;
		if (cpl != null)
		{
			cpl.start();
		}
	}
	
	public void finalize()
	{
		disconnect();
	}
	
	public void disconnect()
	{
		if (cpl != null)
		{
			synchronized (this)
			{
				cpl.running = false;
				try
				{
					wait();
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
			}
		}
		cpl = null;
		inputStream = null;
		outputStream = null;
		serialPort.close();
		serialPort = null;
		
	}
	
	/**
	 * Sets portId to com port if com port is valid
	 * @return FLIC_SUCCESS or FLICERR_PORT_NOT_FOUND
	 */
	private boolean validate()
	{
		portList = getComPorts();
		portId = validatePort(portList, portName);
		
		return (portId != null && portId.getPortType() == CommPortIdentifier.PORT_SERIAL);
	}
	
	/**
	 * Sets baud rate of port
	 */
	private boolean setBaud(int baud)
	{
		try
		{
			serialPort.setSerialPortParams(baud, SerialPort.DATABITS_8,
					SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
		}
		catch (UnsupportedCommOperationException e)
		{
			return false;
		}
		return true;
	}
	
	/**
	 * Opens serial port and sets of inputSteam and outputStream
	 */
	private boolean open()
	{
		try
		{
			serialPort = (SerialPort) portId.open(\"Plus Protocol\", 2000);
		}
		catch (PortInUseException e)
		{
			so.println(\"Port In Use\");
			return false;
		}
		try
		{
			outputStream = serialPort.getOutputStream();
			inputStream = serialPort.getInputStream();
		}
		catch (IOException e)
		{
			so.println(\"IO Exception\");
			return false;
		}
		return true;
	}

	/**
	 * Sends the specified plus packet
	 * @param packet the packet (a byte array) to send
	 * @param length the length of the packet in the byte array
	 */
	public synchronized void putBytes(byte[] packet, int offset, int length)
	{
		try
		{
			outputStream.write(0x0D);
			
			// wait 100ms (double the required 50ms wakeup)
			try
			{
				Thread.sleep(100);
			}
			catch (InterruptedException e)
			{
				// don\'t care...
			}
			outputStream.write(packet, offset, length);
		}
		catch (IOException e)
		{
			// don\'t care?
		}
	}
	
	public synchronized void putByte(byte b)
	{
		try
		{
			outputStream.write(b);
		}
		catch (IOException e)
		{
			// don\'t care?
		}
	}
	
	public void flush()
	{
		// not needed for serial
	}
	
	private static void init()
	{
		try
		{
			// Initialize the native com port drivers 
			Win32Driver w32Driver = new Win32Driver();
			w32Driver.initialize();
		}
		catch (Exception e)
		{
			System.out.println(\"Could not initialize Win32 Drivers: \" + e);
		}
	}
	
	private static CommPortIdentifier validatePort(
			List<CommPortIdentifier> valid, String name)
	{
		for (CommPortIdentifier id : valid)
		{
			if (id.getName().equalsIgnoreCase(name))
				return id;
		}
		return null;
	}

	public static List<CommPortIdentifier> getComPorts()
	{
		Enumeration ids = null;
		List<CommPortIdentifier> ports = new ArrayList<CommPortIdentifier>();

		try
		{
			ids = CommPortIdentifier.getPortIdentifiers();
		}
		catch (Exception e)
		{
			System.out.println(\"Could not get list of com ports! \" + e);
		}
		finally
		{
			while (ids.hasMoreElements())
			{
				ports.add((CommPortIdentifier) ids.nextElement());
			}
		}
		return ports;
	}
	
	private class ComPortListener extends Thread
	{
		public static final int TIMEOUT = 1000;	// in ms
		
		private int sleepTime;
		
		public boolean running;
		
		public ComPortListener ()
		{
			running = true;
		}		
		
		public void run()
		{
			System.out.println(\"Running\");
			while (running)
			{
				int available;
				try
				{
					available = inputStream.available();
					// so.println(\"available: \" + available);
				}
				catch (IOException e)
				{
					so.println(e);
					continue;
				}
				if (available == 0)
				{
					sleepTime++;
					if (sleepTime * 100 >= TIMEOUT)
					{
						parser.reset(true);
						sleepTime = 0;
					}
					try
					{
						Thread.sleep(100);
					}
					catch (InterruptedException e)
					{
						// don\'t care?
					}
				}
				else
				{
					//System.out.print(\"!\");
					sleepTime = 0;
					byte[] buf = new byte[512];
					int size = 0;
					try
					{
						size = inputStream.read(buf, 0, available);
						//so.print(\"(sz:\"+size+\")\");
						//System.out.print(\"\\n[\");
						for (int i=0; i < size; i++)
						{
							//so.printf(\"%X,\", (buf[i] & 0x000000FF));
							parser.newByte(buf[i]);
							if (parser.isValid())
							{
								parser.dispatch();
							}
						}
						//System.out.println(\"]\");
					}
					catch (IOException e)
					{
						System.out.println(e);
					}
				}
			}
			System.out.println(\"Stopped\");
			synchronized(WinComPort.this)
			{
				WinComPort.this.notifyAll();
			}
		}
	}
}

One Response to “Java and Com Ports”

  1. Daniel Marsh Says:

    Were you working on this last night to try to interface with the CMU Cam 2? I know Joel and Rachel were having a lot of problems with the JAVA CMU CAM Gui software.

Leave a Reply