2009-09-08 19 views
7

He estado usando RXTX durante aproximadamente un año, sin demasiados problemas. Acabo de iniciar un nuevo programa para interactuar con una nueva pieza de hardware, así que reutilicé el método connect() que he usado en mis otros proyectos, pero tengo un problema extraño que nunca he visto antes.Problemas recibidos en RXTX

El problema

El dispositivo funciona bien, porque cuando me conecto con HyperTerminal, envío y recibo cosas lo que espero, y Serial Port Monitor (SPM) refleja esto.

Sin embargo, cuando ejecuto el clon de HyperTerminal simple que escribí para diagnosticar el problema que tengo con mi aplicación principal, los bytes se envían, según SPM, pero no se recibe nada, y mi SerialPortEventListener nunca se dispara. Incluso cuando verifico los datos disponibles en el ciclo principal, reader.ready() devuelve false. Si ignoro este cheque, recibo una excepción, detalles a continuación.

Sección pertinente del método connect()

// Configure and open port 
port = (SerialPort) CommPortIdentifier.getPortIdentifier(name) 
             .open(owner,1000) 
port.setSerialPortParams(baud, databits, stopbits, parity); 
port.setFlowControlMode(fc_mode); 
final BufferedReader br = new BufferedReader(
          new InputStreamReader(
           port.getInputStream(), 
           "US-ASCII")); 

// Add listener to print received characters to screen 
port.addEventListener(new SerialPortEventListener(){ 
    public void serialEvent(SerialPortEvent ev) { 
    try { 
     System.out.println("Received: "+br.readLine()); 
    } catch (IOException e) { e.printStackTrace(); } 
    } 
}); 
port.notifyOnDataAvailable(); 

Excepción

java.io.IOException: Underlying input stream returned zero bytes 
     at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:268) 
     at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306) 
     at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158) 
     at java.io.InputStreamReader.read(InputStreamReader.java:167) 
     at java.io.BufferedReader.fill(BufferedReader.java:136) 
     at java.io.BufferedReader.read(BufferedReader.java:157) 
     at <my code> 

La gran pregunta (de nuevo)

Creo que he eliminado todas las posibles problemas de hardware, entonces, ¿qué podría ser wro ng con mi código, o la biblioteca RXTX?

Editar: algo interesante

Al abrir HyperTerminal después de enviar un grupo de comandos de Java que debería haber conseguido respuestas, todas las respuestas aparecen inmediatamente, como si hubieran sido puestos en la memoria intermedia en algún lugar, pero no disponible.

Edición 2: probado algo nuevo, mismos resultados

me encontré el ejemplo de código encontró here, con los mismos resultados. No entraron datos, pero cuando cambié a un nuevo programa, todo se produjo de una vez.

Datos 3

El hardware está bien, e incluso un equipo diferente tiene el mismo problema. No estoy usando ningún tipo de adaptador USB.

Empecé a usar PortMon, también, y me está dando algunos resultados interesantes. HyperTerminal y RXTX no usan la misma configuración, y RXTX siempre sondea el puerto, a diferencia de HyperTerminal, pero aún no puedo ver qué ajustes afectarían esto. Tan pronto como pueda aislar la configuración de la encuesta constante, publicaré mis registros de PortMon.

Editar 4

¿Es posible que algún tipo de actualización de Windows en los últimos 3 meses podría haber causado esto? Ha estropeado uno de mis programas basados ​​en MATLAB mex una vez.

Editar 5

También he notado algunas cosas que son diferentes entre HyperTerminal, RXTX, y un programa separado me encontré con que se comunica con el dispositivo (pero no hace lo que yo quiero, que es por qué estoy rodando mi propio programa)

  • HyperTerminal - se establece a no control de flujo, pero RTS del puerto serie del monitor y los indicadores DTR son verdes
  • Otro programa - no está seguro de qué ajustes se piensa que está utilizando, pero sólo El indicador RTS de SPM es verde
  • RXTX: independientemente del control de flujo que configure, solo los indicadores CTS y DTR de SPM están encendidos.

De los archivos de serie del puerto de monitor de ayuda (parafraseado):

the indicators display the state of the serial control lines 

    RTS - Request To Send 
    CTS - Clear To Send 
    DTR - Data Terminal Ready 

Respuesta

7

Bien, siento que me ha llevado tanto tiempo volver a esta pregunta. Así es como hice que las cosas funcionen.

Nota: Este método NO trabajo para todos, por favor, lea a continuación antes de copiar/pegar en su propio código

public void connect(CommPortIdentifier portId) throws Failure { 
    if (portId == null) 
     throw new Failure("No port set"); 

    try { port = (SerialPort) portId.open(getClass().getName(), 10000); } 
    catch (PortInUseException e) { 
     throw new Failure("Port in use by " + e.currentOwner,e); } 

    try { 
     port.setSerialPortParams(9600, SerialPort.DATABITS_8, 
       SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); 
     port.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN 
           | SerialPort.FLOWCONTROL_RTSCTS_OUT); 
    } catch (UnsupportedCommOperationException e) { throw new Failure(e); } 

    port.setRTS(true); 

    // More setup 
} 

Por lo tanto, en mi caso, el problema era que mi dispositivo en particular requiere Control de flujo RTS. Otros dispositivos pueden requerir cosas diferentes (CTS, XON/XOFF), por lo que debe verificar el manual del dispositivo. Por defecto, RXTX desactiva todos los mecanismos de control de flujo (a diferencia de Hypertrm u otros programas). Permitir cada uno es un proceso de dos pasos.

  1. Una vez que tenga un objeto SerialPort, llame al método setFlowControlMode(), y bit a bit-O ('|') la necesaria SerialPort.FLOWCONTROL_ constantes de
  2. Establecer el control de flujo adecuado a verdadero o falso (como lo hice con port.setRTS(true))

Para las otras personas con problemas similares, si esto no funciona, sugiero

  1. Usando una serie programa de monitoreo de puertos como Serial Port Monitor y/o PortMon (ambos de Windows) para ver qué está pasando realmente.
  2. Envío por correo electrónico a los desarrolladores RXTX en [email protected] (son muy útiles)
+1

¿podría publicar el control de flujo que utilizó? gracias de antemano ... – Oso

+0

Espero que esta edición ayude –

+0

@drhorrible Veo cómo se establece el control de flujo en el objeto serialport. Eso esta limpio. Sin embargo, estoy tratando de averiguar cómo se detecta que el carácter de control de flujo ha sido enviado? Estoy usando XON XOFF vs RTS como tú. Sin embargo, supongo que debería ser similar. 0x13,0x11 son los caracteres que esperaría ver en el serialEvent que se activa? ¿Cómo pudiste detectar esto en el código? – ril3y

0

(podría ser demasiado simple, pero bien podría comenzar en alguna parte ...)

es el puerto en uso? En lugar de:

port = (SerialPort) CommPortIdentifier.getPortIdentifier(name) 
             .open(owner,1000) 

qué pasa:

CommPortIdentifier portIdentifier; 
try { 
    portIdentifier = CommPortIdentifier.getPortIdentifier(name); 
} catch (NoSuchPortException nspe) { 
    // handle? 
} 
if (portIdentifier.isCurrentlyOwned()) { 
    // handle? 
} 
port = portIdentifier.open(owner, 1000); 
if (!(port instanceof SerialPort)) { 
    // handle? 
} 

¿Está tragando excepciones?

+0

Gracias, pero el resto del método connect() detecta todas esas excepciones e imprime seguimientos de pila y troqueles. –

0

Probé RXTX hace unos meses y encontré problemas similares. Sugiero dos cosas:

  1. Crear un comportamiento virtual usando com0com. Habilite el registro de seguimiento. Compare los registros para cuando usa Hyperterminal versus cuando ejecuta su propio programa. La diferencia resaltará lo que está haciendo mal.

  2. En mi humilde opinión, el diseño de RXTX es defectuoso y su implementación es bastante defectuosa (eche un vistazo a su código fuente, ¡qué desastre!). He publicado una biblioteca alternativa en http://kenai.com/projects/jperipheral con las siguientes advertencias: es solo para Windows y no hay binarios preconstruidos. Ambos cambiarán en el futuro cercano. Si está interesado en probarlo, envíeme un correo electrónico usando http://desktopbeautifier.com/Main/contactus y le enviaré una versión preconstruida.

+1

También está disponible [purejavacomm] (https://github.com/nyholku/purejavacomm). – HRJ

2

hay una solución simple a este problema. Esto es lo que hice:

BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
    String line; 

    while (keepRunning) { 
     try { 
      while ((br.ready()) && (line = br.readLine()) != null) { 
.... 
} 

Si comprueba que el buffer "está listo" antes de leerlo no debería haber ningún problema.

2

Ok, me doy cuenta de que este hilo es extremadamente antiguo, pero ninguna de estas soluciones funcionó para mí. Tuve el mismo problema e intenté todo para solucionarlo, fue en vano. Luego hice una investigación sobre qué causa el problema y, cuando no se trata de comunicación en serie, ocurre al final de un archivo. Entonces, pensé que necesitaba agregar un final a lo que está siendo recibido por la Aplicación Java, específicamente, un retorno de línea (\ n). Y efectivamente, ¡me solucionó el problema! Esperemos que esto ayude a alguien nuevo, ya que no espero que esto ayude a nadie en este hilo ...

0

Si alguien sigue recibiendo java.io.IOException: Underlying input stream returned zero bytes después de haber leído sus caracteres usando br.readline() para RXTX (incluso cuando se está comprobando para ver si br.readline() == null), acaba de hacer este arreglo simple con un try/catch:

String line; 
while (true){ 
    try{ 
     line = br.readLine(); 
    }catch(IOException e){ 
     System.out.println("No more characters received"); 
     break; 
    } 
    //Print the line read 
    if (line.length() != 0) 
     System.out.println(line); 
} 

que he hecho un poco de búsqueda y parece que este es el mejor/La forma más fácil de solucionar este problema.

EDIT: Retiro eso. Intenté esto y todavía terminé teniendo algunos problemas. Recomiendo trabajar directamente con InputStream sin procesar e implementar su propio método de lectura/lectura mediante InputStream.read(). Eso funcionó para mí.

Cuestiones relacionadas