無料でシリアル通信をモニタする方法

仮想シリアルポートcom0comと、簡単なプログラムを書いて、シリアル通信の内容をモニタします。javaからのシリアル通信は、java-simple-serial-connector(jSSC)がイケてます。

検証環境まとめ

windows8.1 64bit
jSCC 2.6 / Java1.7
仮想シリアルポート com0com 2.2.2.0
実シリアルポート USB-serial変換器

やりたいこと

シリアルポートを使ったアプリ+シリアル機器が、実際に送っている通信内容を覗き見したい。

具体的にはこのロボです。
KHR-2HV | 近藤科学

専用アプリからロボットを操作する方法と、コマンドリファレンス(通信プロトコル)は公開されているのですが、なかなか理解しずらいので、通信内容を覗いて理解を深めたい。(ということになりました、関わっている工業高校の研究にて。)

シリアル通信のモニタは、ソフトウェアにしてもハードウェアにしても結構お高い。自作できないのか考えてたところ Null-modem emulator(com0com)というよく知られた仮想シリアルポートがあることを知りました。これを利用して、仮想シリアルポートと実シリアルポートの間をのぞき見するプログラムを作ってみました。



仮想シリアルケーブル com0com をインストール

Null-modem emulator (com0com)
http://sourceforge.net/projects/com0com/
最新版のcom0com-3.0は全くインストールがうまくいかないので、version 2.2.2を使いました。
http://sourceforge.net/projects/com0com/files/com0com/2.2.2.0/

インストールはちょっと面倒で、Windows OS自体をテストモードにしないとcom0comがインストールできません。
こちらの手順どおりにインストールしました。設定方法なども参考になります。
NonSoft - com0comのインストールと設定方法(Windows8)

インストール後のシリアルポートはこうなります。



こっちがリアル。



仮想シリアルと実シリアルをつなぐ

次に COM12(仮想) と COM3(リアル) 間のシリアル通信プログラムをJavaで書きます。

古くからJavaのハードウェア通信といえばJava Communication API とその実装RXTXがありました(※)が、シリアル通信に限れば今はjava-simple-serial-connectorがかなりイケてるようです。
java-simple-serial-connector

APIがすっきりしていて、Java Native InterfaceにありがちなJRE環境汚染もなく、インストールは使いたいプロジェクトのCLASSPATHにjarを入れるだけ。

通信プログラムといっても、とりあえずは、それぞれのポートで受けたbyteを相手側に流してやるだけなので、こんな感じのコードになります。


import jssc.*;

public class SerialMonitor {

  static SerialPort serialPort1;
  static SerialPort serialPort2;

  public static void main(String[] args) {
    serialPort1 = new SerialPort("COM3");
    serialPort2 = new SerialPort("COM12");
    try {
      serialPort1.openPort();
      serialPort1.setParams(9600, 8, 1, 0);
      serialPort1.addEventListener(new SerialPortReader1());

      serialPort2.openPort();
      serialPort2.setParams(9600, 8, 1, 0);
      serialPort2.addEventListener(new SerialPortReader2());
    } catch (SerialPortException ex) {
      ex.printStackTrace();
    }
  }

  // COM3 -> COM12 にデータを流す
  static class SerialPortReader1 implements SerialPortEventListener {
    public void serialEvent(SerialPortEvent event) {
      try {
        byte[] buffer = serialPort1.readBytes();
        System.out.println(bin2hex(buffer));
        serialPort2.writeBytes(buffer);
  } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  // COM12 -> COM3 にデータを流す
  static class SerialPortReader2 implements SerialPortEventListener {
    public void serialEvent(SerialPortEvent event) {
      try {
        byte buffer[] = serialPort2.readBytes();
        serialPort1.writeBytes(buffer);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  static String bin2hex(byte[] data) {
    StringBuffer sb = new StringBuffer();
    for (byte b : data) {
      String s = Integer.toHexString(0xff & b);
      if (s.length() == 1) sb.append("0");
      sb.append(s);
    }
    return sb.toString();
  }
}

COM3 -> COM12 のデータを簡単にHEXダンプしてみました。
手元にあったシリアル機器として、Ciscoルーターがあったので、つないで、PuttyからCOM11を相手にコマンドたたいてみたところ。



正常に動いて、ダンプもうまくとれました。

ポート接続以外はただのI/Oプログラムなので、データ整形、マクロ化、ネットワークからシリアル叩く、シリアル機器の異常をメール通知する、などいろんなことができるはず。



(※)古くからRXTXというJava Communication APIの実装がありましたが、今は本家がメンテされておらず、Fork版がこちらからダウンロードできるようです。
mfizz:RXTX for Java

コメント

コメントしてください

closed.