I am trying to use the RXTX library for blocking serial communication on Windows (XP and 7). I have tested the connection with Hyperterminal in both ends, and it works flawlessly.
I set up the connection with the following code: (exception handling and defensive checks omitted for clarity)
private InputStream inStream;
private OutputStream outStream;
private BufferedReader inReader;
private PrintWriter outWriter;
private SerialPort serialPort;
private final String serialPortName;
public StreamComSerial(String serialPortName) {
this.serialPortName = serialPortName;
CommPortIdentifier portIdentifier;
portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName);
CommPort commPort = null;
commPort = portIdentifier.open(this.getClass().getName(),500);
serialPort = (SerialPort) commPort; serialPort.setSerialPortParams(4800,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
inStream = serialPort.getInputStream();
outStream = serialPort.getOutputStream();
inReader = new BufferedReader(new InputStreamReader(inStream, Settings.getCharset()));
outWriter = new PrintWriter(new OutputStreamWriter(outStream, Settings.getCharset()));
When I use
outWriter.println("test message");
flush();
the message is recieved fine on the other end, but calling
inReader.readLine()
imidiately returns "java.io.IOException: Underlying input stream returned zero bytes".
I then decided to try and implement my own blocking read logic and wrote this:
public String readLine() throws IOException {
String line = new String();
byte[] nextByte = {-1};
while (true) {
nextByte[0] = (byte)inStream.read();
logger.debug("int read: " + nextByte[0]);
if (nextByte[0] == (byte)-1) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue;
}
logger.debug("byte read: " + nextByte[0]);
line = line + new String(nextByte);
if (nextByte[0] == (byte)13) { // 13 is carriage return in ASCII
return line;
}
}
}
But this code goes in an infinite loop and "nextByte[0] = (byte)inStream.read();" assigns -1 no matter what is sent over the serial connection. In addition, the other end stutters quite badly and only lets me send a character every 1-3 sec. and hangs for a long time if I try to send many characters in a short burst.
Any help very appreciated.
*edit - using inStream.read(nextByte) instead of "nextByte[0] = (byte)inStream.read();" does not write to the nextByte variable, no matter what I send to it through the serial connection.
*edit2 - as my code works flawlessly with the SUN javax.comm lib and a win32com.dll I got from a friend, I have ceased trying to make it work with RXTX. I am not interested in unblocking communication, which seems to be the only way other people can make RXTX work.
Use RXTX-2.2pre2, previous versions have had a bug which prevented blocking I/O from working correctly.
And do not forget to set port to blocking mode:
serialPort.disableReceiveTimeout();
serialPort.enableReceiveThreshold(1);
I think the code you wrote in your own readLine implementation is buggy. nextByte[0] is never restored to -1 after the first character is read. You should try to use the value returned by inStream.read(nextByte) to state the number of bytes read from the stream instead of the value of your byte array.
Anyway I think you should go for an event based method of reading the inputs with a SerialPortEventListener:
serialPort.addEventListener(new SerialPortEventListener() {
public void serialEvent(SerialPortEvent evt) {
switch (evt.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
dataReceived();
break;
default:
break;
}
}
});
serialPort.notifyOnDataAvailable(true);
it may not be blocking but when the stream is empty, just catch the IOE and keep reading from it. This is what I do with RXTX-2.1-7 and it works fine, I use it to read and write to an arduino:
public static class SerialReader implements Runnable {
InputStream in;
public SerialReader(InputStream in) {
this.in = in;
}
public void run() {
Boolean keepRunning = true;
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while (keepRunning) {
try {
while ((line = br.readLine()) != null) {
//DO YOUR STUFF HERE
}
} catch (IOException e) {
try {
//ignore it, the stream is temporarily empty,RXTX's just whining
Thread.sleep(200);
} catch (InterruptedException ex) {
// something interrupted our sleep, exit ...
keepRunning = false;
}
}
}
}
}
I have solved this way
try
{
if(input.ready()==true)
{
String inputLine=input.readLine();
System.out.println(inputLine);
}
} catch (Exception e)
来源:https://stackoverflow.com/questions/5219450/rxtx-serial-connection-issue-with-blocking-read