Package org.openpnp.machine.reference.driver

Source Code of org.openpnp.machine.reference.driver.AbstractSerialPortDriver

package org.openpnp.machine.reference.driver;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.TimeoutException;

import jssc.SerialPort;
import jssc.SerialPortException;
import jssc.SerialPortTimeoutException;

import org.openpnp.machine.reference.ReferenceDriver;
import org.simpleframework.xml.Attribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A base class for basic SerialPort based Drivers. Includes functions
* for connecting, disconnecting, reading and sending lines.
*/
public abstract class AbstractSerialPortDriver implements ReferenceDriver, Closeable {
    private static final Logger logger = LoggerFactory.getLogger(AbstractSerialPortDriver.class);
   
    @Attribute
    protected String portName;
    @Attribute
    protected int baud;
   
    protected SerialPort serialPort;
    protected SerialInputStream input;
    protected OutputStream output;
   
    protected synchronized void connect() throws Exception {
        disconnect();
        serialPort = new SerialPort(portName);
        serialPort.openPort();
        serialPort.setParams(
                baud,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE,
                false,
                false);
        input = new SerialInputStream(serialPort);
        input.setTimeout(500);
        output = new SerialOutputStream(serialPort);
    }
   
    protected synchronized void disconnect() throws Exception {
        if (serialPort != null && serialPort.isOpened()) {
            serialPort.closePort();
            input = null;
            output = null;
            serialPort = null;
        }
    }

    /**
     * Read a line from the serial port. Blocks for the default timeout. If
     * the read times out a TimeoutException is thrown. Any other failure
     * to read results in an IOExeption;
     *
     * @return
     * @throws TimeoutException
     * @throws IOException
     */
    protected String readLine() throws TimeoutException, IOException {
        StringBuffer line = new StringBuffer();
        while (true) {
            try {
                int ch = input.read();
                if (ch == -1) {
                    return null;
                }
                else if (ch == '\n' || ch == '\r') {
                    if (line.length() > 0) {
                        return line.toString();
                    }
                }
                else {
                    line.append((char) ch);
                }
            }
            catch (IOException ex) {
                if (ex.getCause() instanceof SerialPortTimeoutException) {
                    throw new TimeoutException(ex.getMessage());
                }
                throw ex;
            }
        }
    }

    @Override
    public void close() throws IOException {
        try {
            disconnect();
        }
        catch (Exception e) {
            throw new IOException(e);
        }
    }

//    /**
//     * Send the given String s to the serial port.
//     * @param s
//     * @throws Exception
//     */
//    protected synchronized void send(String s) throws Exception {
//       
//    }
//   
//    /**
//     * Wait for a line from the serial port to match the specified regExp. If
//     * no match is found within timeout milliseconds the method returns null.
//     * @param regExp
//     * @param timeout
//     * @return A Matcher containing the matched string or null if no match is
//     * found within the timeout period.
//     * @throws Exception
//     */
//    protected synchronized Matcher expect(String regExp, long timeout) throws Exception {
//        return null;
//    }
//
//    @Override
//    public void serialEvent(SerialPortEvent serialPortEvent) {
//        if (serialPortEvent.isRXCHAR()) {
//            try {
//                System.out.print(new String(serialPort.readBytes()));
//            }
//            catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//    }
   
   
   
    /**
     * SerialInputStream and SerialOutputStream are from the pull request
     * referenced in:
     * https://github.com/scream3r/java-simple-serial-connector/issues/17
     *
     * If that pull request is ever merged we can update and remove these.
     */
   
   
    /**
     * Class that wraps a {@link SerialPort} to provide
     * {@link InputStream} functionality.  This stream
     * also provides support for performing blocking reads
     * with timeouts.
     * <br>
     * It is instantiated by passing the constructor a {@link SerialPort}
     * instance.  Do not create multiple streams for the
     * same serial port unless you implement your own
     * synchronization.
     * @author Charles Hache <chalz@member.fsf.org>
     *
     */
    public class SerialInputStream extends InputStream {
       
        private SerialPort serialPort;
        private int defaultTimeout = 0;

        /** Instantiates a SerialInputStream for the given {@link SerialPort}
         * Do not create multiple streams for the same serial port
         * unless you implement your own synchronization.
         * @param sp The serial port to stream.
         */
        public SerialInputStream(SerialPort sp) {
            serialPort = sp;
        }
       
        /** Set the default timeout (ms) of this SerialInputStream.
         * This affects subsequent calls to {@link #read()}, {@link #blockingRead(int[])},
         * and {@link #blockingRead(int[], int, int)}
         * The default timeout can be 'unset' by setting it to 0.
         * @param time The timeout in milliseconds.
         */
        public void setTimeout(int time) {
            defaultTimeout = time;
        }

        /** Reads the next byte from the port.
         * If the timeout of this stream has been set, then this method
         * blocks until data is available or until the timeout has been hit.
         * If the timeout is not set or has been set to 0, then this method
         * blocks indefinitely.
         */
        @Override
        public int read() throws IOException {
            return read(defaultTimeout);
        }
       
        /** The same contract as {@link #read()}, except overrides
         * this stream's default timeout with the given
         * timeout in milliseconds.
         * @param timeout The timeout in milliseconds.
         * @return The read byte.
         * @throws IOException On serial port error or timeout
         */
        public int read(int timeout) throws IOException {
            byte[] buf = new byte[1];
            try {
                if (timeout > 0) {
                    buf = serialPort.readBytes(1, timeout);
                } else {
                    buf = serialPort.readBytes(1);
                }
                return buf[0];
            } catch (Exception e) {
                throw new IOException(e);
            }
        }
       
        /** Non-blocking read of up to buf.length bytes from the stream.
         * This call behaves as read(buf, 0, buf.length) would.
         * @param buf The buffer to fill.
         * @return The number of bytes read, which can be 0.
         * @throws IOException on error.
         */
        @Override
        public int read(byte[] buf) throws IOException {
            return read(buf, 0, buf.length);
        }
       
        /** Non-blocking read of up to length bytes from the stream.
         * This method returns what is immediately available in the input
         * buffer.
         * @param buf The buffer to fill.
         * @param offset The offset into the buffer to start copying data.
         * @param length The maximum number of bytes to read.
         * @return The actual number of bytes read, which can be 0.
         * @throws IOException on error.
         */
        @Override
        public int read(byte[] buf, int offset, int length) throws IOException {
           
            if (buf.length < offset + length)
                length = buf.length - offset;
           
            int available = this.available();
           
            if (available > length)
                available = length;
           
            try {
                byte[] readBuf = serialPort.readBytes(available);
                System.arraycopy(readBuf, 0, buf, offset, length);
                return readBuf.length;
            } catch (Exception e) {
                throw new IOException(e);
            }
        }
       
        /** Blocks until buf.length bytes are read, an error occurs, or the default timeout is hit (if specified).
         * This behaves as blockingRead(buf, 0, buf.length) would.
         * @param buf The buffer to fill with data.
         * @return The number of bytes read.
         * @throws IOException On error or timeout.
         */
        public int blockingRead(byte[] buf) throws IOException {
            return blockingRead(buf, 0, buf.length, defaultTimeout);
        }
       
        /** The same contract as {@link #blockingRead(byte[])} except
         * overrides this stream's default timeout with the given one.
         * @param buf The buffer to fill.
         * @param timeout The timeout in milliseconds.
         * @return The number of bytes read.
         * @throws IOException On error or timeout.
         */
        public int blockingRead(byte[] buf, int timeout) throws IOException {
            return blockingRead(buf, 0, buf.length, timeout);
        }
        /** Blocks until length bytes are read, an error occurs, or the default timeout is hit (if specified).
         * Saves the data into the given buffer at the specified offset.
         * If the stream's timeout is not set, behaves as {@link #read(byte[], int, int)} would.
         * @param buf The buffer to fill.
         * @param offset The offset in buffer to save the data.
         * @param length The number of bytes to read.
         * @return the number of bytes read.
         * @throws IOException on error or timeout.
         */
        public int blockingRead(byte[] buf, int offset, int length) throws IOException {
            return blockingRead(buf, offset, length, defaultTimeout);
        }
       
        /** The same contract as {@link #blockingRead(byte[], int, int)} except
         * overrides this stream's default timeout with the given one.
         * @param buf The buffer to fill.
         * @param offset Offset in the buffer to start saving data.
         * @param length The number of bytes to read.
         * @param timeout The timeout in milliseconds.
         * @return The number of bytes read.
         * @throws IOException On error or timeout.
         */
        public int blockingRead(byte[] buf, int offset, int length, int timeout) throws IOException {
            if (buf.length < offset + length)
                throw new IOException("Not enough buffer space for serial data");
           
            if (timeout < 1)
                return read(buf, offset, length);
           
            try {
                byte[] readBuf = serialPort.readBytes(length, timeout);
                System.arraycopy(readBuf, 0, buf, offset, length);
                return readBuf.length;
            } catch (Exception e) {
                throw new IOException(e);
            }
        }
       
        @Override
        public int available() throws IOException {
            int ret;
            try {
                ret = serialPort.getInputBufferBytesCount();
                if (ret >= 0)
                    return ret;
                throw new IOException("Error checking available bytes from the serial port.");
            } catch (Exception e) {
                throw new IOException("Error checking available bytes from the serial port.");
            }
        }

    }   
   
    /**
     * Class that wraps a {@link SerialPort} to provide
     * {@link OutputStream} functionality.
     * <br>
     * It is instantiated by passing the constructor a {@link SerialPort}
     * instance.  Do not create multiple streams for the
     * same serial port unless you implement your own
     * synchronization.
     *
     * @author Charles Hache <chalz@member.fsf.org>
     *
     */
    public class SerialOutputStream extends OutputStream {
       
        SerialPort serialPort;

        /** Instantiates a SerialOutputStream for the given {@link SerialPort}
         * Do not create multiple streams for the same serial port
         * unless you implement your own synchronization.
         * @param sp The serial port to stream.
         */
        public SerialOutputStream(SerialPort sp) {
            serialPort = sp;
        }

        @Override
        public void write(int b) throws IOException {
            try {
                serialPort.writeInt(b);
            } catch (SerialPortException e) {
                throw new IOException(e);
            }
        }
       
        @Override
        public void write(byte[] b) throws IOException {
            write(b, 0, b.length);
           
        }
       
        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            byte[] buffer = new byte[len];
            System.arraycopy(b, off, buffer, 0, len);
            try {
                serialPort.writeBytes(buffer);
            } catch (SerialPortException e) {
                throw new IOException(e);
            }
        }
    }   
}
TOP

Related Classes of org.openpnp.machine.reference.driver.AbstractSerialPortDriver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.