Проблемы с получением в RXTX

Я использую RXTX около года без особых проблем. Я только запустил новую программу для взаимодействия с новым оборудованием, поэтому я повторно использовал метод connect(), который я использовал в других своих проектах, но у меня есть странная проблема, которую я никогда раньше не видел.

Эта проблема

Устройство работает нормально, потому что когда я подключаюсь к HyperTerminal, я отправляю и получаю то, что ожидаю, и Serial Port Monitor(SPM) отражает это.

Однако, когда я запускаю простой HyperTerminal-клон, который я написал, чтобы диагностировать проблему, с которой я сталкиваюсь с моим основным приложением, байты отправляются, согласно SPM, но ничего не получается, и мой SerialPortEventListener никогда не срабатывает. Даже когда я проверяю доступные данные в основном цикле, reader.ready() возвращается false, Если я проигнорирую эту проверку, то получу исключение, подробности ниже.

Соответствующий раздел метода 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();

исключение

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>

Большой вопрос (снова)

Я думаю, что я устранил все возможные аппаратные проблемы, так что может быть не так с моим кодом или библиотекой RXTX?

Редактировать: что-то интересное

Когда я открываю HyperTerminal после отправки набора команд из Java, которые должны были получить ответы, все ответы появляются немедленно, как если бы они были помещены в буфер где-то, но недоступны.

Редактировать 2: пробовал что-то новое, те же результаты

Я запустил пример кода, найденный здесь, с теми же результатами. Данные не поступали, но когда я переключился на новую программу, она пришла сразу.

Редактировать 3

Аппаратное обеспечение в порядке, и даже другой компьютер имеет ту же проблему. Я не использую какой-либо USB-адаптер.

Я тоже начал использовать PortMon, и это дает мне интересные результаты. HyperTerminal и RXTX не используют одинаковые настройки, а RXTX всегда опрашивает порт, в отличие от HyperTerminal, но я до сих пор не вижу, какие настройки повлияют на это. Как только я смогу изолировать конфигурацию от постоянного опроса, я опубликую свои логи PortMon.

Редактировать 4

Возможно ли, что какое-то обновление Windows за последние 3 месяца могло вызвать это? Однажды он испортил одну из моих программ на основе MATLAB mex.

Редактировать 5

Я также заметил некоторые отличия между HyperTerminal, RXTX и отдельной программой, которая, как я обнаружил, связывается с устройством (но не делает то, что я хочу, поэтому я запускаю свою собственную программу)

  • HyperTerminal - отключено управление потоком, но индикаторы RTS и DTR монитора последовательного порта горят зеленым
  • Другая программа - не уверен, какие настройки он использует, но только индикатор RTS SPM горит зеленым
  • RXTX - независимо от того, какое управление потоком я установил, включены только индикаторы CTS и DTR в SPM.

Из файлов справки монитора последовательного порта (перефразировано):

the indicators display the state of the serial control lines

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

6 ответов

Решение

Хорошо, извини, что я так долго возвращался к этому вопросу. Вот как у меня все работает.

Примечание: этот метод не будет работать для всех, пожалуйста, прочитайте ниже, прежде чем копировать / вставлять в свой собственный код

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
}

Итак, в моем случае проблема заключалась в том, что мое конкретное устройство требует управления потоком данных RTS. Другие устройства могут требовать разные вещи (CTS, XON/XOFF), поэтому проверьте руководство этого устройства. По умолчанию RXTX отключает все механизмы управления потоком (в отличие от Hypertrm или других программ). Включение каждого из них - двухэтапный процесс.

  1. Если у вас есть объект SerialPort, вызовите setFlowControlMode() метод и побитовое ИЛИ (' | ') необходимость SerialPort.FLOWCONTROL_ константы
  2. Установите соответствующий контроль потока на true или false (как я сделал с port.setRTS(true))

Для других с подобными проблемами, если это не работает, я предлагаю

  1. Используя программу мониторинга последовательного порта, такую ​​как Serial Port Monitor и / или PortMon (обе Windows), чтобы увидеть, что на самом деле происходит.
  2. По электронной почте разработчикам RXTX по адресу rxtx@qbang.org (они очень полезны)

Существует более простое решение этой проблемы. Вот что я сделал:

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

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

Если вы проверяете, что буфер "готов", прежде чем читать его, проблем не должно быть.

Хорошо, я понимаю, что эта тема очень старая, но ни одно из этих решений не помогло мне. У меня была такая же проблема, и я пытался все исправить, но безрезультатно. Затем я провел некоторое исследование того, что вызывает проблему, и, когда не имеет дело с последовательной связью, это происходит в конце файла. Итак, я решил, что мне нужно добавить окончание к тому, что получает Java-приложение, в частности, строку возврата (\n). И, конечно же, это решило проблему для меня! Надеюсь, это поможет кому-то новому, так как я не ожидаю, что это поможет кому-то уже в этой теме...

Я попробовал RXTX несколько месяцев назад и столкнулся с подобными проблемами. Я предлагаю две вещи:

  1. Создайте виртуальный компорт, используя com0com. Включите ведение журнала трассировки. Сравните журналы, когда вы используете Hyperterminal и когда вы запускаете свою собственную программу. Разница в том, что вы делаете неправильно.

  2. По моему скромному мнению, дизайн RXTX несовершенен, а его реализация довольно глючная (посмотрите на его исходный код, какой беспорядок!). Я опубликовал альтернативную библиотеку по адресу http://kenai.com/projects/jperipheral со следующими предостережениями: она предназначена только для Windows и в ней нет встроенных двоичных файлов. Оба они изменятся в ближайшем будущем. Если вы хотите попробовать его, отправьте мне письмо по http://desktopbeautifier.com/Main/contactus и я вышлю вам предварительно собранную версию.

Если кто-то все еще получает java.io.IOException: Underlying input stream returned zero bytes после того, как вы прочитали свои символы, используя br.readline() для RXTX (даже когда вы сначала проверяете, является ли br.readline() == null), просто сделайте это простое исправление с помощью 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);
}

Я провел некоторые поиски, и кажется, что это лучший / самый простой способ обойти эту проблему.

РЕДАКТИРОВАТЬ: Я беру это обратно. Я попробовал это и все еще заканчивал тем, что имел некоторые проблемы. Я бы порекомендовал работать непосредственно с необработанным InputStream и реализовывать собственный метод read / readLine с помощью InputStream.read(). Это сработало для меня.

(может быть слишком простым, но может с чего-то начать...)

Порт используется? Скорее, чем:

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

как насчет:

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?
}

Вы глотаете какие-либо исключения?

Другие вопросы по тегам