Hi,

I am developing a Java application that uses a serial port to communicate. The communication part is working fine but if I close the serialport using the close method on the SerialPort object and then try to open it again using the open method on a CommPortIdentifier object I get a runtime exception saying "Device busy". If I restart the application the port is opened without problems.

Should I do something else besides calling close on the SerialPort object before trying to open it again?

My platform is Sparc Solaris 10 and I'm using Sun's Commapi.

Thanks in advance,

Bufo

Recommended Answers

All 5 Replies

> "Device busy"

Most probably this means that the device is still in use i.e. all the communication channels opened to the device have not been properly closed. In case you are playing around with streams obtained obtained from the port, you should try closing them. But then again, this is just a speculation since I haven't done any serial port programming. Feel free to post the relevant piece of code, I'll try and see what can be done.

Thanks s.o.s. I do close the streams I have gotten from the port.

Here is some code.

Port initialization:
(The exception happens at line 20 where I call open on a CommPortIdentifier object.)

portList = CommPortIdentifier.getPortIdentifiers(); //enumeration

        boolean found = false;
        while (portList.hasMoreElements()) {
            portId = (CommPortIdentifier) portList.nextElement();
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL && portId.getName().equals(portname)) {
                found = true;
                break;
            }
        }

        if (!found) {
            LogHandler.getLogger().error("Specified serial port could not be found.");
            return false;
        }


        try {
            port = (SerialPort) portId.open("Comm", 2000);
        } catch (Exception exc) {
            LogHandler.getLogger().error("Unable to open serial port.");
            LogHandler.getLogger().debug("Details: " + Formatter.getStackTraceString(exc));
            return false;
        }
        
        try {
            inStream = port.getInputStream();
            portReader = new BufferedReader(new InputStreamReader(inStream), 1);
            outStream = port.getOutputStream();
        } catch (IOException exc) {
            LogHandler.getLogger().error("Unable to get input and/or outputstreams from serialport.");
            LogHandler.getLogger().debug("Details: " + Formatter.getStackTraceString(exc));
            return false;
        }

        port.notifyOnDataAvailable(true);
        port.notifyOnBreakInterrupt(true);
        port.notifyOnCTS(true);
        port.notifyOnCarrierDetect(true);
        port.notifyOnDSR(true);
        port.notifyOnFramingError(true);
        port.notifyOnOutputEmpty(true);
        port.notifyOnOverrunError(true);
        port.notifyOnParityError(true);
        port.notifyOnRingIndicator(true);


        try {
            port.setSerialPortParams(Settings.getIntParameter("baudrate"),
                    Settings.getIntParameter("databits"),
                    Settings.getIntParameter("stopbits"),
                    Settings.getIntParameter("parity"));
        } catch (Exception exc) { 
            LogHandler.getLogger().error("Unable to set serialport parameters.");
            LogHandler.getLogger().debug("Details: " + Formatter.getStackTraceString(exc));
            return false;
        }

        try {
            port.addEventListener(this);
        } catch (TooManyListenersException exc) {
            LogHandler.getLogger().error("Unable to add serial port event listener. Too many listeners.");
            LogHandler.getLogger().debug("Details: " + Formatter.getStackTraceString(exc));
            return false;
        }

        port.setDTR(true);
            return false;

And port closing:

portReader.close();
            inStream.close();
            outStream.close();
            portReader=null;
            inStream=null;
            outStream=null;
            port.close();
            port.removeEventListener();
            port=null;

-Anguinus

Though you did post the code, I am still unclear as to how this all fits in your current application flow. Without the flow, it would be kind of difficult to point out the fault. How about a test snippet which showcases your problem?

Anyways, try this snippet and let us know if you are still facing the same issue:

Port port = null;
for(int i = 0; i < 3; ++i) {
  port = (SerialPort)portId.open("comm", 2000);
  InputStream in = port.getInputStream();
  OutputStream out = port.getOutputStream();
  // write and read some junk data
  Thread.sleep(2000);

  in.close();
  out.close();
  Thread.sleep(2000);
}

If the above code works, you can be pretty sure it has got something to do with your application logic. If even your test code fails, post the stack trace with the sample code as it is.

Your very statement "If I restart the application the port is opened without problems." points to a possibility of a resource being held by the application.

Thank you again, s.o.s. The code you posted worked without problems (I added a port.close()-call) and the port closed and opened fine in the loop.

The whole point of this exercise has been recovering from an error in the serial communication, e.g. unplugging/plugging the cable or remote end doing something funny.

The basic flow is:

1. catch I/O exception
2. close the port and streams
3. try to open the port again

Closing and opening works if there is no I/O error but if I produce an error the port stays busy until I stop and start the application.

I have tried a lot of different approaches but it seems that only shutting down the VM will free the port after an error.

-Wildpointer

Though it seems like an obvious thing to ask, but are you closing your resources in `finally'?

try {
  Port p = null;
  InputStream in = null;
  OutputStream out = null;
  try {
    // acquire streams and do something
  } finally {
    if(in != null) in.close();
    if(out != null) out.close();
    if(port != null) port.close();
  }
} catch(Exception e) {
  e.printStackTrace();
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.