使用RXTX和Java继续与串行设备通信

时间:2012-12-05 13:50:32

标签: java serial-port rxtx

我需要修改RXTX“基于事件的双向通信”(参见http://rxtx.qbang.org/wiki/index.php/Event_based_two_way_Communication),以便我能够将关于其先前消息的特定响应写回串行设备。

我通过发送第一个命令开始通信。到目前为止一切正常。现在我从序列号中得到答案。我用另一个命令对答案作出反应。但我不能再写了,因为写线程已经结束了。

有人知道如何处理这个问题吗? 非常感谢!

public class TwoWaySerialComm {
    public TwoWaySerialComm() {
        super();
    }

public static void main(String[] args) {
        try {

            // 0. call connect()
            (new TwoWaySerialComm()).connect("COM1");

        } catch (Exception e) {
            e.printStackTrace();
        }
}

void connect(String portName) throws Exception {

                // 1. get CommPortIdentifier, open etc...

                // 2. then do
                InputStream in = serialPort.getInputStream();
                OutputStream out = serialPort.getOutputStream();

                // 4. start writer thread
                (new Thread(new SerialWriter(out))).start();

                // 5. instantiate SerialReader 
                serialPort.addEventListener(new SerialReader(in));
                serialPort.notifyOnDataAvailable(true);

}

public static class SerialWriter implements Runnable {

        OutputStream out;

        public SerialWriter(OutputStream out) {
            this.out = out;
        }

        public void run() {
            try {

                // establish a communication by sending the first command. the serial device will answer!   
                String toSend = "blablabla";
                this.out.write(toSend);

                // thread ended???

}

public static class SerialReader implements SerialPortEventListener {

        private InputStream in;

        public SerialReader(InputStream in) {
            this.in = in;

        }

        public void serialEvent(SerialPortEvent arg0) {

            // event occurs beacause device answers after writing.

            int data;

            try {

                StringBuffer sb = new StringBuffer();
                String LineOfData=null;

                while ((data = in.read()) > -1) {

                    if (data == '\n') {
                        break;
                    }

                    sb.append(Integer.toHexString(data));
                    LineOfData = sb.toString();

                }
                // I store the answer and send it to an EventIterpreter. Regarding the answer, it creates an appropriate response itselves.
                EventInterpreter e = new EventInterpreter(LineOfData);  
                String result = e.getData

HERE >> // Now I want to send this response back to the device. But the thread is already ended.


            } catch (IOException e) {
                e.printStackTrace();
                System.exit(-1);
            }
        }

  }

}

1 个答案:

答案 0 :(得分:1)

不要让运行SerialWriter的线程完成。

在原始示例中,您会注意到while (System.in.read() != -1)的{​​{1}}方法中有run()。这很重要。在SerialWriter上运行它的线程阻止然后,一旦它有一些数据需要读取,它会做一些工作,然后循环回到同一个地方,等待更多的输入。这是一个在正常条件下不能假设的线程。

重要的是,编写器的非守护程序线程正在运行这一事实意味着,当您的主线程(JVM用于启动程序的线程)用完connect()方法中的语句时,JVM不会立即关闭。

串口正在回调自己的线程

read()调用您的侦听器的serialPort方法时,会在其自己的线程上执行此操作。

您的任务现在是尽快离开serialPort的线程。几乎,读取数据,将其粘贴在缓冲区中,您的另一个线程可以在其中解析并在闲暇时对其进行操作,同时让serialPort继续处理通信。当你在自己的线程上调用时,你当然不应该尝试写入串口。没有任何状态可以回复你,因为它等着你完成!

你希望你的'作家'主题'等待',直到有回复的内容

通过提供“锁定”对象来安排。由于这些是现代的,请使用:

public void serialEvent(SerialPortEvent)

阅读一本关于并发的好书

并发很棘手。您需要阅读Java Concurrency in Practice

当您尝试切断上面的代码示例时,您会注意到import java.util.concurrent.locks.*; // accessible to both reader and writer ... Lock lock = new ReentrantLock(); Condition dataAvailable = lock.newCondition(); byte[] buffer; // in the writer ... public void run() { while(true) { lock.lock(); try { dataAvailable.await(); // writer thread dozes doStuff(buffer); } finally { lock.unlock(); } } } // in the reader ... public void onEvent() { lock.lock(); try { buffer = readData(); dataAvailable.signal(); // writer thread wakes up } finally { lock.unlock(); } } 抛出Condition#await()。究竟如何处理这个问题超出了这个答案的范围。 :-) InterruptedException也有点狡猾。