/**
 *Provides functionality of reading and writing on a serial port using
 *the Keyspan USB-to-serial adapter. Reads byte imput and writes  
 *int  or String.
 *This class require rxtx-2.1-7.<p>
 *See http://www.rxtx.org/
 *@author Jim Burnette and Kevin Lease
 *Copyright (c) Jim Burnette, Kevin Lease, and Jay Hirsh, University of Virginia.
 *All rights reserved.
 *@version 1.0
 */



package edu.virginia.jburnette.io;

import gnu.io.*;
     //import javax.comm when using on win32
import java.io.*;

import java.util.*;


public class SerialReadWrite{
    private static CommPortIdentifier       portId ;
    private static String                   messageString = "B";    
    private static Enumeration              portList;
    private DataInputStream                 inputStream;
    private PrintStream                     outputStream;
    private SerialPort                      serialPort;
    private Thread                          readThread;
    private String                          theMessage;
    private String                          defaultPort;
    private boolean                         portOpen = false;
 
    /**
     * Opens a connection on the serial port. Eventually will take a port
     *address. Right now uses /dev/tty.USA19H181P1.1. This must be
     *changed and the code compiled if the port address changes. Exceptions must 
     *handled by the caller. If the port is opened portOpen is set to True. Check by calling wasPortOpened().
     *@exception PortNotFoundException thrown if the port did not open.
     */
     //This constructor is part of the rxtx examples and the
     //java.sun.Comm API examples.
     //The PortNotFoundException is my addtion to notify the calling code
     //that the port did not open.
    public SerialReadWrite() throws PortInUseException, PortNotFoundException {
        boolean           portFound = false;
        //defaultPort = "/dev/tty.USA19H623P1.1";
        defaultPort = "/dev/tty.USA19H181P1.1";
        portList = CommPortIdentifier.getPortIdentifiers();
        while (portList.hasMoreElements()) {
            portId = (CommPortIdentifier) portList.nextElement();
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                if (portId.getName().equals(defaultPort)) {
                    portFound = true;
                } 
            } 
        } 
        if (!portFound) {
            throw new PortNotFoundException();
        } 
        serialPort = (SerialPort) portId.open("SimpleReadApp", 2000);
        //may throw PortInUseException
        try {
            inputStream = new DataInputStream(serialPort.getInputStream());
            outputStream = new PrintStream(serialPort.getOutputStream(), true);
        } catch (IOException e) {
        }
        try {
            serialPort.setSerialPortParams(2400, SerialPort.DATABITS_8, 
                       SerialPort.STOPBITS_1, 
                       SerialPort.PARITY_NONE);
        } catch (UnsupportedCommOperationException e) {
        }
        portOpen = true;
    }
    /**
     *Opens the specified port.
     *@param port User specified port.
     */ 
    public SerialReadWrite(String port) throws PortInUseException, PortNotFoundException {
        boolean           portFound = false;
        //defaultPort = "/dev/tty.USA19H623P1.1";
        defaultPort = port;
        portList = CommPortIdentifier.getPortIdentifiers();
        while (portList.hasMoreElements()) {
            portId = (CommPortIdentifier) portList.nextElement();
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                if (portId.getName().equals(defaultPort)) {
                    portFound = true;
                } 
            } 
        } 
        if (!portFound) {
            throw new PortNotFoundException();
        } 
        serialPort = (SerialPort) portId.open("SimpleReadApp", 2000);
        //may throw PortInUseException
        try {
            inputStream = new DataInputStream(serialPort.getInputStream());
            outputStream = new PrintStream(serialPort.getOutputStream(), true);
        } catch (IOException e) {
        }
        try {
            serialPort.setSerialPortParams(2400, SerialPort.DATABITS_8, 
                       SerialPort.STOPBITS_1, 
                       SerialPort.PARITY_NONE);
        } catch (UnsupportedCommOperationException e) {
        }
        portOpen = true;
    }
    /**
     *Reads and returns the byte from the serial device.
     *In calling code (assuming the device is sending byte65:
     *
     *      while((int)nums[0] != 65){
                    try {
                        nums = readWrite.read();
                    } catch (IOException ioe) {}
                }
              
     *@return the byte sent by the serial device.
     */
    public byte[] read() throws IOException {
        byte [] nums = new byte[2];
        inputStream.read(nums);
        return nums;
    }
    /**
     *Sends an int to the serial device.
     *@param output Number to send
     */
    public void write(int output) {
        outputStream.print(output);
    }
    /**
     *Sends a java.lang.String to the serial device.
     *@param output String to send
     */
    public void write(String output) {
        outputStream.print(output);
    }
    /**
     *Convience method for testing writing. Returns a message if sending worked.
     *Sends a '0' followed by a 'Z' to the serial device.
     *@return 'Sent 0 then Z.' returned if all went well.
     */
    public String writeOut() {
        int turnflag = 0;
         outputStream.print(turnflag);
         outputStream.print("Z");
         //thePlugin.showMessage("Took a picture\n");
         return "Sent 0 then Z.";
    }
    /**
     *Attempt to close the port. Doesn't work becuase cannot re-open the port latter.
     */
    public void stop() throws IOException{
            inputStream.close();
            outputStream.close();
            serialPort.close();
    }
    /**
     *Returns true if the port opened. False if it did not.
     *@return port state.
     */
    public boolean wasPortOpened() {
        return portOpen;
    }
} // closes SerialReadWrite class