2

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

  }

}
4

1 に答える 1

1

SerialWriterを実行しているスレッドを終了させないでください。

元の例では、のメソッドのwhile (System.in.read() != -1)内部にあることに気付くでしょう。それは重要です。それを実行しているスレッドはでブロックし、読み取るデータがあると、いくつかの作業を実行してから同じ場所にループバックし、さらに入力を待ちます。これは、通常の状態では終了しないはずのスレッドです。run()SerialWriterread()

重要なのは、ライターの非デーモンスレッドが実行されているということは、メインスレッド(JVMがプログラムの開始に使用したスレッド)がconnect()メソッドのステートメントを使い果たしても、JVMがすぐにシャットダウンしないことを意味します。 。

シリアルポートが独自のスレッドでコールバックしています

serialPortリスナーのメソッドを呼び出すと、public void serialEvent(SerialPortEvent)それは独自のスレッドで呼び出します。

あなたの使命は、シリアルポートのスレッドをできるだけ早く降りることです。ほとんどの場合、データを読み取り、バッファに貼り付けて、シリアルポートに通信の処理を開始させながら、別のスレッドが解析して自由に処理できるようにします。シリアルポートが独自のスレッドで呼び出している間は、シリアルポートに書き込もうとしないでください。あなたが終わるのを待っているので、あなたに応答する状態ではありません!

返信するものができるまで、「ライター」スレッドを「待機」させます。

'lock'オブジェクトを提供することにより、それを調整します。これらは現代なので、以下を使用してください。

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

並行性に関する良い本を読む

並行性には注意が必要です。あなたは実際のJava並行性を読みたいと思うでしょう。

Condition#await()上記のコードサンプルをカットアンドペーストしようとすると、がスローされることに気付くでしょうInterruptedException。それをどうするかは、この回答の範囲を超えています。:-)これwhile(true)も少し危険です。

于 2012-12-05T14:58:16.877 に答える