1

Java のシリアル ポートからバイナリ プロトコルを読み取ろうとしています。RXTX ライブラリを使用して、シリアル ポートから読み取ります。

プロトコルは、GPS 受信機用の SiRF バイナリ プロトコルです。構造は次のとおりです。

  • 最初の 2 バイトは 0xA0 と 0xA2 で、データ フレームの開始を定義します。
  • 次の 2 バイトはペイロード長 n
  • 次の n バイトはペイロードです
  • 最後の 2 バイトは 0xB0 と 0xB3 で、データ フレームの終わりを定義します。

この構造は非常に単純ですが、データを正しく読み取ることができません。私は2つの異なる方法を試しました:

  1. InputStreamから読み取り、入力を 0xA0 と比較するスレッドを書きました。これが一致する場合、スレッドは次のバイトを読み取り、0xA2 と比較します。これが再び一致すると、次の 2 バイトを読み取り、ペイロードの長さを計算します。その後、長さ n バイトのペイロードを読み取ります。最後に、最後の 2 バイトを読み取り、それらを 0xB0 および 0xB3 と比較します。すべてが一致すると、入力から 16 進文字列が作成され、キューに保存されます。これが私のコードです:

    try {
        byte[] size = new byte[2];
        byte[] checkSum = new byte[2];
        byte[] packet;
        int bytesRead = -1;
        while (in.available() > 0) {
            if (getInput() == 0xA0) {
                if (getInput() == 0xA2) {
                    System.out.print("160,162,");
                    bytesRead = in.read(size);
                    int payLoadLength = (size[0] << 8) | (size[1] & 0xFF);
                    byte[] payload = new byte[payLoadLength];
                    bytesRead = in.read(payload);
                    bytesRead = in.read(checkSum);
                    if (getInput() == 0xB0) {
                        if (getInput() == 0xB3) {
                    System.out.println("out");
                    packet = new byte[2 + 2 + payLoadLength + 2 + 2];
                    packet[0] = (byte) START_1;
                    packet[1] = (byte) START_2;
                    packet[2] = size[0];
                    packet[3] = size[1];
                    for (int i = 0; i < payload.length; i++) {
                        packet[i + 4] = payload[i];
                    }
                    packet[packet.length - 4] = checkSum[0];
                    packet[packet.length - 3] = checkSum[1];
                    packet[packet.length - 2] = (byte) END_1;
                    packet[packet.length - 1] = (byte) END_2;
                    StringBuffer hexString = new StringBuffer();
                    int[] output = new int[packet.length];
                    for (int i = 0; i < packet.length; i++) {
                        output[i] = 0xFF & packet[i];
                        hexString.append(Integer.toHexString(output[i]));
                    }
                    TransportMessage tm = new TransportMessage(hexString.toString());
                    boolean b = queue.offer(tm);
                    System.out.println(hexString.toString().toUpperCase());
                    if(!b)
                        System.err.println("TransportMessageQueue voll!");
                }
            } else {
                System.out.println();
            }
        }
    } 
        }
    } catch (IOException e) {
        System.out.println(e);
    }
    

    getInput()からバイトを読み取るだけInputStreamです。

  2. SerialPortEventListenerRXTX ライブラリの を使用しました。シリアル ポートで何かが発生するたびに、SerialPortEvent が発生し、最初の方法と同様の方法でデータを読み取ります。

デバッグ上の理由からSystem.out.println()、スレッドによって正確に何が読み取られるかを示すためにいくつかの呼び出しを追加しましたInputStream

私の質問は次のとおりです: からそのようなプロトコルを読み取る最良の方法は何InputStreamですか? 私の意見では、読み取り作業をシリアル ポートからのデータと同期させる必要がありますが、Java でそれを行う方法がわかりません。

4

1 に答える 1