Java RXTX 接收问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1391402/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 11:34:53  来源:igfitidea点击:

Issues receiving in RXTX

javaserial-portrxtx

提问by Nate Parsons

I've been using RXTX for about a year now, without too many problems. I just started a new program to interact with a new piece of hardware, so I reused the connect() method I've used on my other projects, but I have a weird problem I've never seen before.

我已经使用 RXTX 大约一年了,没有太多问题。我刚刚启动了一个新程序来与新硬件进行交互,所以我重用了我在其他项目中使用过的 connect() 方法,但是我遇到了一个我以前从未见过的奇怪问题。

The Problem

问题

The device works fine, because when I connect with HyperTerminal, I send things and receive what I expect, and Serial Port Monitor(SPM) reflects this.

该设备工作正常,因为当我与超级终端连接时,我发送和接收我期望的内容,串行端口监视器(SPM) 反映了这一点。

However, when I run the simple HyperTerminal-clone I wrote to diagnose the problem I'm having with my main app, bytes are sent, according to SPM, but nothing is received, and my SerialPortEventListener never fires. Even when I check for available data in the main loop, reader.ready()returns false. If I ignore this check, then I get an exception, details below.

但是,当我运行简单的 HyperTerminal-clone 来诊断我的主应用程序遇到的问题时,根据 SPM 发送了字节,但没有收到任何内容,并且我的 SerialPortEventListener 永远不会触发。即使我在主循环中检查可用数据,也会reader.ready()返回false. 如果我忽略此检查,则会出现异常,详情如下。

Relevant section of connect() method

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();

Exception

例外

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>

The big question (again)

大问题(再次)

I think I've eliminated all possible hardware problems, so what could be wrong with my code, or the RXTX library?

我想我已经消除了所有可能的硬件问题,那么我的代码或 RXTX 库有什么问题呢?

Edit: something interesting

编辑:有趣的事情

When I open HyperTerminal after sending a bunch of commands from java that should have gotten responses, all of the responses appear immediately, as if they had been put in the buffer somewhere, but unavailable.

当我从 java 发送一堆应该得到响应的命令后打开超级终端时,所有响应立即出现,就好像它们已被放入缓冲区中的某处,但不可用。

Edit 2: Tried something new, same results

编辑 2:尝试了一些新的东西,结果相同

I ran the code example found here, with the same results. No data came in, but when I switched to a new program, it came all at once.

我运行了此处找到的代码示例,结果相同。没有数据进来,但是当我切换到一个新程序时,它一下子就进来了。

Edit 3

编辑 3

The hardware is fine, and even a different computer has the same problem. I am not using any sort of USB adapter.

硬件没问题,甚至不同的电脑也有同样的问题。我没有使用任何类型的 USB 适配器。

I've started using PortMon, too, and it's giving me some interesting results. HyperTerminal and RXTX are not using the same settings, and RXTX always polls the port, unlike HyperTerminal, but I still can't see what settings would affect this. As soon as I can isolate the configuration from the constant polling, I'll post my PortMon logs.

我也开始使用PortMon,它给了我一些有趣的结果。超级终端和 RXTX 使用的设置不同,RXTX 总是轮询端口,不像超级终端,但我仍然看不到什么设置会影响这个。一旦我可以将配置与持续轮询隔离开来,我就会发布我的 PortMon 日志。

Edit 4

编辑 4

Is it possible that some sort of Windows update in the last 3 months could have caused this? It has screwed up one of my MATLAB mex-based programs once.

是否有可能是过去 3 个月内的某种 Windows 更新导致了这种情况?它曾经搞砸了我的一个基于 MATLAB mex 的程序。

Edit 5

编辑 5

I've also noticed some things that are different between HyperTerminal, RXTX, and a separate program I found that communicates with the device (but doesn't do what I want, which is why I'm rolling my own program)

我还注意到 HyperTerminal、RXTX 和我发现与设备通信的单独程序之间的一些不同之处(但没有做我想要的,这就是我滚动自己的程序的原因)

  • HyperTerminal - set to no flow control, but Serial Port Monitor's RTS and DTR indicators are green
  • Other program - not sure what settings it thinks it's using, but only SPM's RTS indicator is green
  • RXTX - no matter what flow control I set, only SPM's CTS and DTR indicators are on.
  • 超级终端 - 设置为无流量控制,但串口监视器的 RTS 和 DTR 指示灯为绿色
  • 其他程序 - 不确定它认为它在使用什么设置,但只有 SPM 的 RTS 指示器是绿色的
  • RXTX - 无论我设置什么流量控制,只有 SPM 的 CTS 和 DTR 指示灯亮起。

From Serial Port Monitor's help files (paraphrased):

从串行端口监视器的帮助文件(释义):

the indicators display the state of the serial control lines

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

采纳答案by Nate Parsons

OK, sorry it's taken me so long to come back to this question. Here's how I got things working.

好的,对不起,我花了这么长时间才回到这个问题。这就是我如何工作。

Note: This method will NOTwork for everyone, please read below before copy/pasting into your own code

注意:此方法不适用于所有人,请在复制/粘贴到您自己的代码之前阅读以下内容

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
}

So, in my case, the problem was that my particular device requires RTS flow control. Other devices may require different things (CTS, XON/XOFF), so check that device's manual. By default, RXTX disables all flow control mechanisms (unlike Hypertrm or other programs). Enabling each one is a two-step process.

因此,就我而言,问题在于我的特定设备需要 RTS 流控制。其他设备可能需要不同的东西(CTS、XON/XOFF),因此请查看该设备的手册。默认情况下,RXTX 禁用所有流量控制机制(与 Hypertrm 或其他程序不同)。启用每一个是一个两步过程。

  1. Once you have a SerialPort object, call the setFlowControlMode()method, and bitwise-OR ('|') the necessary SerialPort.FLOWCONTROL_constants
  2. Set the appropriate flow control to true or false (like I did with port.setRTS(true))
  1. 一旦你有一个 SerialPort 对象,调用该setFlowControlMode()方法,并按位或(' |')必要的SerialPort.FLOWCONTROL_常量
  2. 将适当的流控制设置为 true 或 false(就像我所做的那样port.setRTS(true)

For the others with similar problems, if this doesn't work, I suggest

对于其他有类似问题的人,如果这不起作用,我建议

  1. Using a serial port monitoring program like Serial Port Monitorand/or PortMon(both Windows) to see what is actually going on.
  2. Emailing the RXTX developers at [email protected] (they are very helpful)
  1. 使用串行端口监控程序(如Serial Port Monitor和/或PortMon(均为 Windows))查看实际发生的情况。
  2. 通过 [email protected] 向 RXTX 开发人员发送电子邮件(他们非常有帮助)

回答by Tom Clift

(might be too simple, but might as well start somewhere...)

(可能太简单了,但不妨从某个地方开始……)

Is the port in use? Rather than:

端口是否在使用中?而不是:

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

what about:

关于什么:

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

Are you swallowing any exceptions?

你吞下任何例外吗?

回答by Gili

I tried RXTX a few months ago and ran into similar problems. I suggest two things:

几个月前我尝试过 RXTX 并遇到了类似的问题。我建议两件事:

  1. Create a virtual comport using com0com. Enable trace logging. Compare the logs for when you use Hyperterminal versus when you run your own program. The difference will highlight what you are doing wrong.

  2. In my humble opinion, RXTX's design is flawed and its implementation is quite buggy (take a look at its source-code, what a mess!). I've published an alternative library at http://kenai.com/projects/jperipheralwith the following caveats: It's Windows-only and there are no pre-built binaries. Both of these will change in the near future. If you are interested in trying it out send me an email using http://desktopbeautifier.com/Main/contactusand I'll send you a pre-built version.

  1. 使用 com0com 创建虚拟端口。启用跟踪日志记录。比较使用超级终端和运行自己的程序时的日志。差异将突出您做错了什么。

  2. 以我的拙见,RXTX 的设计是有缺陷的,它的实现也有很多问题(看看它的源代码,真是一团糟!)。我在http://kenai.com/projects/jperipheral上发布了一个替代库,但有以下警告:它仅适用于 Windows,并且没有预构建的二进制文件。这两者都将在不久的将来发生变化。如果您有兴趣试用,请使用http://desktopbeautifier.com/Main/contactus给我发送电子邮件,我将向您发送预构建版本。

回答by Ovid

There is a simpler solution to this problem. This is what I did:

这个问题有一个更简单的解决方案。这就是我所做的:

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

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

If you check that the buffer "is ready" before you read it there should be no problem.

如果您在阅读之前检查缓冲区“已准备好”,则应该没有问题。

回答by djl911djl911

Ok, I do realize this thread is extremely old, but none of these solutions worked for me. I had the same problem and I tried everything to fix it, to no avail. Then I did some research on what causes the problem, and, when not dealing with Serial Communication, it happens at the end of a file. So, I figured I needed to add an ending to whatever is being received by the Java Application, specifically, a line return (\n). And sure enough, it fixed the problem for me! Hopefully this helps someone new, as I'm not expecting this to help anyone already on this thread...

好的,我确实意识到这个线程非常古老,但是这些解决方案都不适合我。我遇到了同样的问题,我想尽一切办法解决它,但无济于事。然后我对导致问题的原因进行了一些研究,并且在不处理串行通信时,它发生在文件末尾。所以,我想我需要为 Java 应用程序接收到的任何内容添加一个结尾,特别是行返回 (\n)。果然,它为我解决了问题!希望这能帮助新人,因为我不希望这能帮助已经在这个线程上的任何人......

回答by GordonFreeman

If anyone is still getting java.io.IOException: Underlying input stream returned zero bytesafter you've read your characters using br.readline() for RXTX (even when you are checking first to see if br.readline() == null), just do this simple fix with a try/catch:

如果java.io.IOException: Underlying input stream returned zero bytes在您使用 br.readline() for 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);
}

I've done some searching and it appears that this is the best/easiest way to get around this problem.

我已经做了一些搜索,似乎这是解决这个问题的最好/最简单的方法。

EDIT : I take that back. I tried this and still ended up having some problems. I'd recommend working with the raw InputStream directly, and implementing your own read/readLine method using InputStream.read(). That worked for me.

编辑:我收回。我试过这个,但最终还是遇到了一些问题。我建议直接使用原始 InputStream,并使用 InputStream.read() 实现您自己的 read/readLine 方法。那对我有用。