Embedded Freaks..

August 9, 2008

Managing Serial Port Ownership (in rxtx)

Filed under: java — Tags: , , — kunilkuda @ 10:44 am

Okay..I want to build an application that is nice enough to other application. So, if other application asking my port ownership, my application may give it (or not, depends on the user response).

I may also need to be notified, if I get or lose the port’s ownership. Therefore, I can do connection retry, before sending the data to serial port that I don’t own.

Hence, I’ve done some simple test on rxtx, and the result is quite suprising.

The Theory

To handle the ownership event, you’ll need a class that implements CommPortOwnershipListener. Something like this:

class SerialOwnershipHandler implements CommPortOwnershipListener
{
    public void ownershipChange(int type) {
        switch (type) {
            case CommPortOwnershipListener.PORT_OWNED:
                System.out.println("We got the port");
                break;
            case CommPortOwnershipListener.PORT_UNOWNED:
                System.out.println("We've just lost our port ownership");
                break;
            case CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED:
                System.out.println("Someone is asking our port's ownership");
                break;
        }
    }
}

After that, we need to register our event handler to CommPortIdentifier class (using CommPortIdentifier’s addPortOwnershipListener() method).

And, here’s what the class supposed to do:

  • If the port has just been owned (ie. CommPortIdentifier’s open() method is called and success), the CommPortOwnershipListener.PORT_OWNED will be returned in ownershipChange(), printing “We got the port” to the stdout.
  • If the port has just been released (ie. SerialPort’s close() method is called), the CommPortOwnershipListener.PORT_UNOWNED will be returned in ownershipChange(), printing “We’ve just lost our port ownership” to the stdout.
  • If other application asks our port’s ownership, the CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED will be returned in ownershipChange(), printing “Someone is asking our port’s ownership” to the stdout.

The Test Result

  • CORRECT: If the port has just been owned (ie. CommPortIdentifier’s open() method is called and success), the CommPortOwnershipListener.PORT_OWNED will be returned in ownershipChange(), printing “We got the port” to the stdout.
  • CORRECT: If the port has just been released (ie. SerialPort’s close() method is called), the CommPortOwnershipListener.PORT_UNOWNED will be returned in ownershipChange(), printing “We’ve just lost our port ownership” to the stdout.
  • FALSE: If other application asks our port’s ownership, the CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED will be returned in ownershipChange(), printing “Someone is asking our port’s ownership” to the stdout.

For the last case, where other application is run after rxtx get the ownership, I’ve tried using GNU screen (screen /dev/ttyUSB0 57600) and other rxtx application demo. I couldn’t generate the third case at all.

After several trial, I found out that the last case can only be done, if the CommPortIdentifier’s open() method is called more than once in the SAME application (same process ID..even other java program with rxtx cannot generate the last case because it used different process ID).

In case someone interested in the test program that I use, here’s the source code


public class SerialOwnership {

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

    public void connect(String portName, String id) throws IOException {
        try {
            // Obtain a CommPortIdentifier object for the port you want to open
            CommPortIdentifier portId =
                    CommPortIdentifier.getPortIdentifier(portName);

            // Add ownership event listener
            portId.addPortOwnershipListener(new SerialOwnershipHandler(id));

            // 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;
        }
    }

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

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

    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();
        }
    }

    /**
     * Sets the serial port parameters
     */
    private void setSerialPortParameters() throws IOException {
        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");
        }
    }

    private class SerialOwnershipHandler implements CommPortOwnershipListener
    {
        String id;

        public SerialOwnershipHandler(String id) {
            this.id = id;
        }

        public void ownershipChange(int type) {
            switch (type) {
                case CommPortOwnershipListener.PORT_OWNED:
                    System.out.println(id +
                            ":We got the port");
                    break;
                case CommPortOwnershipListener.PORT_UNOWNED:
                    System.out.println(id +
                            ":We've just lost our port ownership");
                    break;
                case CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED:
                    System.out.println(id +
                            ":Someone is asking our port's ownership");
                    break;
            }
        }
    }

    public static void main(String[] args) {
        SerialOwnership serialOwnershipTest = new SerialOwnership();

        try {
            serialOwnershipTest.connect("/dev/ttyUSB0", "1");
            Thread.sleep(10000);

            // Uncomment this to generate the third case
            //new SerialOwnership().connect("/dev/ttyUSB0", "2");
            Thread.sleep(10000);
        } catch (InterruptedException ex) {
        } catch (IOException ex) {
            System.err.println(ex.getMessage());
        }

        serialOwnershipTest.disconnect();
    }
}

This test is run on Linux Suse Enterprise Desktop 10 (kernel 2.6.16), Sun Java 1.6.0, and Rxtx 2.1.7

About these ads

5 Comments »

  1. Your blog is interesting!

    Keep up the good work!

    Comment by Alex — August 16, 2008 @ 6:25 pm

  2. good work!!!

    Actually i need to perform asyncronous comm. with help of queuing to open a port when commm is available and close it

    Comment by kalyan — February 18, 2009 @ 1:16 pm

  3. Hi Daniel,
    great work!
    I have fighted (and won) with RXTX as well, but I have found your RXTX solutions later, while looking for AtMega128 RTOS informations :).

    So – from this thread I have understood (and confirmed my discovery) that practically there is no way in RXTX Ownership methods, to identify that comm port is used outside THIS ONE Java app.

    Only way is to try to open each port from ports list and if this is impossible conclusing that is used…

    Regards
    Mariusz

    Comment by mariusz.dec — November 29, 2009 @ 5:08 pm

  4. Thank you, your code help me a lot. I hope you have gotten a solution for your problem since a long.

    Comment by pach — December 2, 2010 @ 1:38 am

  5. If you look at this page:

    http://www.oracle.com/technetwork/java/index-jsp-141752.html

    you will see that it says:

    “Asynchronous event option for notification of:
    Port ownership changes *within a single JVM*”

    The javadocs leave this issue a bit ambiguous as they talk about ‘applications’ in connection of the ownership events.

    But still, I think rxtx behavior is the same as JavaComm and thus correct.

    Of course, this is a bit useless feature if it does not work between applications, OTH, even if it worked between different JVMs, I see no way this could work between Java and applications in other languages since there is no API in any of the OSs that would support this concept, hence I think that it was originally an error to include this in the JavaComm API.

    Comment by nyholku — May 20, 2011 @ 3:41 pm


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

The Silver is the New Black Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: