Embedded Freaks..

October 8, 2008

RXTX Serial Port Helper

Filed under: java — Tags: , , — kunilkuda @ 2:06 pm

Well, the conclusion of the RXTX posts in this blog may have been written in this code sample. It will help you to establish serial port operations (connect / disconnect / add data available listener / get serial port’s OutputStream/InputStream).

I put this on the blog, because I keep moving around project to project. Hence, it always take a lot of time to find it from one of the project folders. At least, if I keep it online, google will help me to find it when I need it.

/*
 * Copyright (c) 2008, Daniel Widyanto
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Daniel Widyanto ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Daniel Widyanto BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.kunilkuda.sms;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.UnsupportedCommOperationException;
import java.util.TooManyListenersException;

import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

import java.util.ArrayList;
import java.util.Enumeration;

/**
 * \brief Additional help to handle serial connect / disconnect, and registering
 *        interrupt handler
 */
public class SerialHelper {

    private SerialPort serialPort;
    private OutputStream outStream;
    private InputStream inStream;

    /**
     * \brief List the available serial ports
     *
     * \return Array of string for the available serial port names
     */
    public static String[] listSerialPorts() {
        Enumeration ports = CommPortIdentifier.getPortIdentifiers();
        ArrayList portList = new ArrayList();
        String portArray[] = null;
        while (ports.hasMoreElements()) {
            CommPortIdentifier port = (CommPortIdentifier) ports.nextElement();
            if (port.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                portList.add(port.getName());
            }
        }
        portArray = (String[]) portList.toArray(new String[0]);
        return portArray;
    }

    /**
     * \brief Connect to the selected serial port with 57600bps-8N1 mode
     */
    public void connect(String portName) throws IOException {
        try {
            // Obtain a CommPortIdentifier object for the port you want to open
            CommPortIdentifier portId =
                    CommPortIdentifier.getPortIdentifier(portName);

            // Get the port's ownership
            serialPort = (SerialPort) portId.open("Demo application", 5000);

            // Set the parameters of the connection.
            setSerialPortParameters();

            // Open the input and output streams for the connection.
            // If they won't open, close the port before throwing an
            // exception.
            outStream = serialPort.getOutputStream();
            inStream = serialPort.getInputStream();
        } catch (NoSuchPortException e) {
            throw new IOException(e.getMessage());
        } catch (PortInUseException e) {
            throw new IOException(e.getMessage());
        } catch (IOException e) {
            serialPort.close();
            throw e;
        }
    }

    /**
     * \brief Get the serial port input stream
     * \return The serial port input stream
     */
    public InputStream getSerialInputStream() {
        return inStream;
    }

    /**
     * \brief Get the serial port output stream
     * \return The serial port output stream
     */
    public OutputStream getSerialOutputStream() {
        return outStream;
    }

    /**
     * \brief Sets the serial port parameters to 57600bps-8N1
     */
    protected void setSerialPortParameters() throws IOException {

        final int baudRate = 57600; // 57600bps

        try {
            // Set serial port to 57600bps-8N1..my favourite
            serialPort.setSerialPortParams(
                    baudRate,
                    SerialPort.DATABITS_8,
                    SerialPort.STOPBITS_1,
                    SerialPort.PARITY_NONE);

            serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
        } catch (UnsupportedCommOperationException ex) {
            throw new IOException("Unsupported serial port parameter");
        }
    }

    /**
     * \brief Register listener for data available event
     *
     * @param dataAvailableListener The data available listener
     */
    public void addDataAvailableListener(SerialPortEventListener dataAvailableListener)
            throws TooManyListenersException {
        // Add the serial port event listener
        serialPort.addEventListener(dataAvailableListener);
        serialPort.notifyOnDataAvailable(true);
    }

    /**
     * \brief Disconnect the serial port
     */
    public void disconnect() {
        if (serialPort != null) {
            try {
                // close the i/o streams.
                outStream.close();
                inStream.close();
            } catch (IOException ex) {
                // don't care
            }
            // Close the port.
            serialPort.close();
            serialPort = null;
        }
    }

    /**
     * \brief Private inner class to test and debug the SerialHelper class
     */
    public static class SerialHelperTester implements SerialPortEventListener {

        public static void main(String[] args) {
            if (args.length < 1) {
                System.out.println(
                        "Usage: java SerialHelperTester <dataToBeSentToSerialPort>");
                System.exit(1);
            }

            SerialHelper serialHelper = new SerialHelper();

            checkListSerialPorts(serialHelper);
            checkConnect(serialHelper);
            checkAddDataAvailableListener(serialHelper, args[0]);
            checkDisconnect(serialHelper);
        }

        private static void checkListSerialPorts(SerialHelper serialHelper) {
            System.out.println("Check the listSerialPorts");
            System.out.println("-------------------------");
            String[] serialPorts = SerialHelper.listSerialPorts();
            if (serialPorts != null) {
                for (int i = 0; i < serialPorts.length; i++) {
                    System.out.println("Port name: " + serialPorts&#91;i&#93;);
                }
            }
            System.out.println();
        }

        private static void checkConnect(SerialHelper serialHelper) {
            // Replace it with the tested serial port
            final String serialPort = "/dev/ttyACM0";

            System.out.println("Connect to serial port");
            System.out.println("-------------------------");
            try {
                serialHelper.connect(serialPort);
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }

            System.out.println();
        }

        private static void checkAddDataAvailableListener(
                SerialHelper serialHelper, String data) {
            System.out.println("Check data available listener");
            System.out.println("-----------------------------");

            SerialHelperTester tester =
                    new SerialHelperTester(serialHelper.getSerialInputStream(),
                    serialHelper.getSerialOutputStream());

            try {
                serialHelper.addDataAvailableListener(tester);
            } catch (TooManyListenersException ex) {
                System.err.println(ex.getMessage());
            }

            OutputStream outStream = serialHelper.getSerialOutputStream();
            data = data + "\r";
            try {
                outStream.write(data.getBytes());
            } catch (IOException ex) {
                System.err.println(ex.getMessage());
            }

            try {
                // Sleep for 10-secs
                Thread.sleep(10000);
            } catch (InterruptedException ex) {
            }
        }

        private static void checkDisconnect(SerialHelper serialHelper) {
            System.out.println("Disconnect from serial port");
            System.out.println("---------------------------");
            serialHelper.disconnect();
            System.out.println("done");
        }
        /**
         * Buffer to hold the reading
         */
        private byte&#91;&#93; readBuffer = new byte&#91;400&#93;;
        /**
         * I/O stream for serial port
         */
        private InputStream inStream;
        private OutputStream outStream;

        public SerialHelperTester(InputStream inStream, OutputStream outStream) {
            this.inStream = inStream;
            this.outStream = outStream;
        }

        private void readSerial() {
            try {
                int availableBytes = inStream.available();
                if (availableBytes > 0) {
                    // Read the serial port
                    inStream.read(readBuffer, 0, availableBytes);

                    // Print it out
                    System.out.println("Recv :" +
                            new String(readBuffer, 0, availableBytes));
                }
            } catch (IOException e) {
            }
        }

        public void serialEvent(SerialPortEvent events) {
            switch (events.getEventType()) {
                case SerialPortEvent.DATA_AVAILABLE:
                    readSerial();
            }
        }
    }
}
Advertisements

4 Comments »

  1. Hi Daniel

    maybe you can help me. I’m using the RXTX library inside a Tomcat application (I’m trying to perform a control for remote instrumentation). When the method SerialPort.close() is called, it throws a deadlock. Do u have any idea ?

    Comment by SpaghettiProgrammer — October 10, 2008 @ 12:03 am

  2. Hi SpaghettiProgrammer,

    Sorry, I’m not familiar with J2EE (or Tomcat, JSP, glassfish, etc). But I notice that there was a report of RXTX SerialPort’s close() deadlock in http://mailman.qbang.org/pipermail/rxtx/2005-September/2824832.html

    Maybe, the scenario that the writer describes similar with your application. I’m not sure whether it still happens on RXTX 2.1.7 or not. I’ll check it once my project deals with RXTX again.

    Comment by kunilkuda — October 10, 2008 @ 9:43 am

  3. Niel

    thank’s for your code 🙂

    Comment by Wahyu — March 30, 2009 @ 3:49 pm

  4. Hi, cheers for this. May take me a while to work out what it is doing though. Guess I’ll have to read the previous posts.
    J.

    Comment by JH — July 20, 2009 @ 12:50 am


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: