7

I'm connecting a device with librxtx-java to Ubuntu. The code previously worked in 10.04, but in 12.04 it can't discover the usb-serial connected to the computer.

java.util.Enumeration<CommPortIdentifier> portEnum = CommPortIdentifier.getPortIdentifiers();
while ( portEnum.hasMoreElements() )
{
    CommPortIdentifier portIdentifier = portEnum.nextElement();
    System.out.println( portIdentifier.getName() + " - " + getPortTypeName(portIdentifier.getPortType()) );
}

This section of the code never goes into the while loop, despite the appropriate librxtx-java libraries being installed, and device being recognized (dmesg | tail shows USB "Serial Device converter detected" on one line).

Update:

It appears Ubuntu 12.04 64-bit isn't working with any usb-serial devices (although they show up in dmesg and show up as a /dev/ttyUSB, it seems to be more than just a problem with Java.

NoBugs
  • 9,310
  • 13
  • 80
  • 146

1 Answers1

14

I have Ubuntu 11.10 kernel 3.0.0-12-generic-pae and librxtx-java version 2.2pre2-8 installed. With the code below, it list my serial ports correctly. Now you have usb to serial converter installed properly? you need to check that what port is the converter use. Using the sample app below, you can try something like java -cp /usr/share/java/RXTXcomm.jar:. GetCommPorts 2

Please ensure that you have the correct permission in the ttySXX or ttyUSBXX file, in /dev/.

crw-rw---- 1 root dialout 4, 65 2012-02-29 01:08 /dev/ttyS1
crw-rw---- 1 root dialout 4, 66 2012-02-29 01:08 /dev/ttyS2

These serial ports are shown in my system and the user who want to run the application should be under group dialout. To add yourself, use:

sudo usermod -a -G dialout username

You should now be in "dialout" group.

import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;

public class GetCommPorts
{
    static Enumeration<CommPortIdentifier>            portList;
    static CommPortIdentifier portId;
    static SerialPort                 serialPort;
    static OutputStream          outputStream;
    static boolean                    outputBufferEmptyFlag = false;    


    public static class SerialReader implements SerialPortEventListener
    {
        private InputStream in;
        private byte[] buffer = new byte[1024];

        public SerialReader(InputStream in)
        {           
            this.in = in;           
        }

        @Override
        /** 
         *  treat \n as end of block.
         */
        public void serialEvent(SerialPortEvent ev)
        {
            int data;

            try
            {
                int len = 0;
                while ( (data = in.read()) > -1)
                {
                    if (data == '\n')
                    {
                        break;
                    }
                    buffer[len++] = (byte) data;
                }
                System.out.println(new String(buffer, 0, len));
            }
            catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.exit(-1);
            }           
        }       
    }

    public static class SerialWriter implements Runnable
    {
        OutputStream out;

        public SerialWriter(OutputStream out)
        {
            this.out = out;
        }

        @Override
        public void run()
        {           
            try
            {
                int c = 0;
                while ( (c = System.in.read()) > -1)
                {
                    this.out.write(c);
                }
            }
            catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.exit(-1);
            }

        }

    }

    private static String getPortTypeName ( int portType )
    {
        switch ( portType )
        {
        case CommPortIdentifier.PORT_I2C:
            return "I2C";
        case CommPortIdentifier.PORT_PARALLEL:
            return "Parallel";
        case CommPortIdentifier.PORT_RAW:
            return "Raw";
        case CommPortIdentifier.PORT_RS485:
            return "RS485";
        case CommPortIdentifier.PORT_SERIAL:
            return "Serial";
        default:
            return "unknown type";
        }
    }

    private static void listPorts()
    {
        @SuppressWarnings("unchecked")
        java.util.Enumeration<CommPortIdentifier> portEnum = CommPortIdentifier.getPortIdentifiers();

        while ( portEnum.hasMoreElements() ) 
        {
            CommPortIdentifier portIdentifier = portEnum.nextElement();
            System.out.println(portIdentifier.getName()  +  " - " +  getPortTypeName(portIdentifier.getPortType()) );           

            if (portIdentifier.getPortType() == 1)
            {
                try
                {
                    serialPort =  (SerialPort) portIdentifier.open(portIdentifier.getName(), 3000);
                }
                catch (PortInUseException e)
                {
                    System.err.print("port in use");
                    continue;
                }

                System.out.println("Baud is " + serialPort.getBaudRate());    
                System.out.println("Bits is " + serialPort.getDataBits());    
                System.out.println("Stop is " + serialPort.getStopBits());    
                System.out.println("Par is " + serialPort.getParity());
                serialPort.close();
            }
        }
    }

    private static int doReadWrite(String portName)
    {
        CommPortIdentifier portIdentifier;

        try
        {
            portIdentifier = CommPortIdentifier.getPortIdentifier(portName);

            if (portIdentifier.isCurrentlyOwned())
            {
                System.err.println("error: port is currently in use");
                return -1;
            }

            SerialPort sport = (SerialPort) portIdentifier.open(portName, 3000);
            sport.setSerialPortParams(57600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

            InputStream in = sport.getInputStream();
            OutputStream out = sport.getOutputStream();         

            (new Thread(new SerialWriter(out))).start();

            sport.addEventListener(new SerialReader(in));
            sport.notifyOnDataAvailable(true);
        }
        catch (NoSuchPortException e)
        {
            e.printStackTrace();
            return -1;
        } 
        catch (PortInUseException e)
        {
            e.printStackTrace();
            return -1;
        }
        catch (UnsupportedCommOperationException e)
        {
            e.printStackTrace();
            return -1;
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return -1;
        }
        catch (TooManyListenersException e)
        {
            e.printStackTrace();
            return -1;
        }

        return 0;       
    } 

    static void showHelp()
    {
        System.out.println("Usage " + GetCommPorts.class.getName() + "N");
        System.out.println("1 read and write from the serial port");
        System.out.println("2 list all serial ports in the system");
        System.out.println("default show this help ");
    }


    public static void main(String[] args)
    {
        int operation = 0;

        try
        {
            if (args.length != 1)
            {
                showHelp();
                return;
            }
            operation = Integer.parseInt(args[0]);
        }
        catch (NumberFormatException e)
        {

        }       

        switch (operation)
        {
        case 1:
            doReadWrite("/dev/ttyUSB0");
            break;
        case 2:
            listPorts();
            break;
        default:
            showHelp();
        }

    }


}

Output from this application:

$ java -cp /usr/share/java/RXTXcomm.jar:. GetCommPorts 2
/dev/ttyS1 - Serial
Baud is 9600
Bits is 8
Stop is 1
Par is 0
/dev/ttyS0 - Serial
Baud is 9600
Bits is 8
Stop is 1
Par is 0
David Grayson
  • 84,103
  • 24
  • 152
  • 189
Jasonw
  • 5,054
  • 7
  • 43
  • 48
  • What does :. GetCommPorts "/dev/usb-serial-converter-port" do? Is there an equivalent setting in Eclipse? Before upgrading it had worked fine without that option, I wonder if it's a problem with the non-sun jdk? – NoBugs Mar 09 '12 at 15:54
  • "/dev/usb-serial-converter-port" is the parameter to the GetCommPorts to check if the serial comm port is there. Well, I have not compile with non-sun jdk and why don't you try it, examine the output? Also, what is your comm port? – Jasonw Mar 09 '12 at 16:10
  • It shows up as /dev/ttyUSB0, is there a way to test if I'm receiving anything from the device at the system level? – NoBugs Mar 09 '12 at 18:49
  • eh? In your initial question, you are asking why is your usb-serial converter didn't show up but now you confirmed it is show up as /dev/ttyUSB0? anyway, what do you mean by receiving anything from the device at system level? Do you mean right now you are asking change to the application above to read if there is input read from the device? – Jasonw Mar 10 '12 at 02:49
  • Yes, it does not show up in Java, though it was shown in /dev and in dmesg. I was also having problem with an odbii cable (which is a usb-serial device as well) that I couldn't get working. So it is likely a problem with the usb-serial driver? – NoBugs Mar 10 '12 at 07:56
  • well, you can start by using command cat /dev/ttyUSB0 to check if there is anything from the device. Then you can modify the java app to do the reading as well. – Jasonw Mar 10 '12 at 12:24
  • cat /dev/ttyUSB0 doesn't show anything, I think the device has to be initialized before it receives though. – NoBugs Mar 12 '12 at 18:03
  • cat /dev/ttyUSB0 and then , the device should send data through the serial. Then modify the above source code to read from /dev/ttyUSB0 instead. – Jasonw Mar 15 '12 at 03:52
  • I get the same problem when I try cat /dev/ttyUSB0. Source code above wouldn't help, it does effectively the same as mine but it can't get portlist.nextelement, and would never enter the while loop. Btw what version of Oneiric kernel are you using that works? It seems it may be a kernel problem. – NoBugs Mar 15 '12 at 04:18
  • Could you do this ln -s /dev/ttyUSB0 /dev/ttyS where NN is the digit is not assigned in your system. For me, my existing system has from ttyS0 until ttyS31, so I have ttyS32 – Jasonw Mar 15 '12 at 06:35
  • 1
    Also, ensure that you have permission read and write for the port. In my system, I have this `crw-rw---- 1 root dialout 4, 64 2012-03-10 10:58 /dev/ttyS0` So your user who want to run this java application, should be in group dialout. I'm using kernel 3.0.0-12-generic-pae – Jasonw Mar 15 '12 at 06:44
  • 3
    Adding my user to "dialout", and restarting, seems to have fixed it! Thanks for the help. – NoBugs Mar 16 '12 at 02:58
  • Yay! In the end, we conquered this error together. Glad to hear that. cheers. – Jasonw Mar 16 '12 at 03:36
  • 1
    This answer has put an end to a few hours of fruitless research. Despite running the risk of having this question protected, I have to say "many thanks". – Mad Physicist Jun 17 '14 at 05:31
  • thank you for this convincing statement, it convince people once again to contribute back to SO. Sharing is caring. I hope you get something out of this answer and help you along the way. – Jasonw Jun 17 '14 at 06:08