0

我正在尝试从 Java 应用程序内的子进程中的串行端口读取数据。这是我目前正在使用的代码:

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class Text {
    public static void main(String... arguments) throws IOException, InterruptedException {
        Process pb = new ProcessBuilder().command("/bin/sh", "-c", "(stty raw; cat) < /dev/ttyAMA0").start();
        final Scanner scanner = new Scanner(new InputStreamReader(new BufferedInputStream(pb.getInputStream())));

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (scanner.hasNextLine()) {
                    System.out.println(scanner.nextLine());
                }
            }
        });

        t.start();
        pb.waitFor();
    }
}

想法如下:我不想依赖操作系统(这里是 Raspberry Pi 上的 Raspbian)从串行端口向我发送原始输入。因此,我启动了一个子进程,该子进程使用 stty 将串行端口设置为 RAW 模式,并使用 cat 转发数据。这个技巧在命令行上完美运行。如果我随后将 stdout 重定向到 Java 程序,则数据会正确地流向其输入流。

这里的问题是,使用此代码将数据获取到子进程(不是 Java 程序的标准输入,你猜对了),我正在丢失字符。我期望 10 个 3 位数字的行,用逗号分隔,我得到 4 到 6 个数字,有时后面跟一个逗号。

我认为存在缓冲问题,我的 Java 应用程序可能无法清空(非常有限的)串行端口缓冲区。

有什么我可以在 Java 方面做的明智的事情,或者我应该在这里向 Linux 内核极客寻求一些操作系统技巧吗?

谢谢,

马修

4

3 回答 3

0

写入后尝试刷新,我想这就是你“丢失”数据的原因:)

while (scanner.hasNextLine()) {
    System.out.println(scanner.nextLine());
    System.out.flush();
}
于 2013-09-17T12:45:07.103 回答
0

只是一个黑客,但试试这个。cat 的标准输出默认是缓冲的,但你想要的是一个无缓冲的流。尝试换行:

(stty raw; cat) < /dev/ttyAMA0

(stty raw; cat -u) < /dev/ttyAMA0
于 2013-09-17T13:01:25.747 回答
0

好的,我让代码工作了,使用来自那里的输入:https ://unix.stackexchange.com/questions/40005/alternate-fifo-device-for-linux-with-a-way-bigger-buffer-while-still -吃饱

我们在这里想要的是在(不是那么多字节)串行端口缓冲区和管道中的下一个命令之间有一个更大的缓冲区。鉴于我期望 82 字节的行包含所有内容,我使用该buffer -s 82 -b 2命令,该命令允许在每个扫描仪 nextLine 调用之间将一行的两个块存储在共享内存中。

这是完整的演示,它应该会让每个尝试用 Java 读取串行数据的 Raspberry Pi 所有者感到高兴(我是唯一一个吗?):

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class Text2 {
    public static void main(String... arguments) throws IOException, InterruptedException {
        Process pb = new ProcessBuilder().command("/bin/sh", "-c", "(stty raw; cat | buffer -s 82 -b 2) < /dev/ttyAMA0").start();
        final Scanner scanner = new Scanner(new InputStreamReader(new BufferedInputStream(pb.getInputStream())));

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (scanner.hasNextLine()) {
                    System.out.println(scanner.nextLine());
                }
            }
        });

        t.start();
        pb.waitFor();
    }
}

这需要buffer实用程序,易于安装键入sudo apt-get install buffer 这也依赖于一些技巧来启用板载串行端口,如https://github.com/lurch/rpi-serial-console

感谢 brettw 提供的输入,即使它一开始就不起作用。

马修

于 2013-09-19T13:07:15.170 回答