前回のエントリでELM327デバイスが動作することを確認したので、今回は簡単なプログラミングをしてみようと思います。
Bluetooth版のデバイスを自分は選んだので、BluetoothのRFCOMMを利用することになります。今回はJavaでプログラミングをすることにし、BluetoothライブラリはBluecoveを利用します。
実際のプログラミングのフローは以下のようになるかと思います。
- Bluetoothデバイスを探索する
- 探索が完了したらそのデバイスをオープンする
- ELM327の初期化
- ELM327にリクエストを発行
- ELM327から受け取ったレスポンスをparseする
- 4に戻る
デバイス探索に関してははじめに一度だけ行い、二度目からはBluetoothアドレスなどを保持しておけば再度行う必要はありません。また、2以降はおおむね他のシリアルデバイスでも同じ手順になるはずです。
デバイスのオープンはBluetoothの場合は以下のようになります。
String url = "btspp://XXXXXXXXXXXX:1;authenticate=false;encrypt=false;master=false";
StreamConnection connection = (StreamConnection) Connector.open(url);
ここでのurlは、デバイス探索後にデバイスが提供可能なサービスを調べると得られるものです。サービス探索は、bluecoveのServices Searchにサンプルがあるので参考になります(ウェブページ中間)。
その後、ELM327へのInput / Output Streamを開きます。
OutputStream os = connection.openOutputStream();
PrintWriter pw=new PrintWriter(new OutputStreamWriter(os));
InputStream is = connection.openInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
これでELM327とのお話ができるようになりました。 このPrintWriterに対して前回のエントリで紹介したようなコマンドを発行し、BufferedReaderからレスポンスを得ることになります。
pw.write("AT Z\r");
pw.flush();
のような感じでコマンドを発行します。そして、それに対してレスポンスは、
int data;
while((data = br.read()) != -1 && data != '>'){
char ch = (char)data;
System.out.print(ch);
}
このような感じで取り出せます。ELM327からの返答はプロンプト(”>”)で終わるので、それを終了判定に使えばよいです。BufferedReaderのreadLine()を使うこともできるかと思ったのですが、最後にEOFが来ないためかプロンプトが来たところでブロックしてしまうようです。
…基本的にはこれだけです。
3.のELM327の初期化は、たとえば”AT E0\r”を送ってエコーを切る(通信量を減らす)などそういったことです。
今回は単純に得られた文字を書き出しているだけですが、本来はこれを解析する必要があります。しかし単純なプログラミングなので、あとは特別問題ないかと思います。
“01 00\r”を送ると 0101から0120までのどのリクエストに応えられるかビット列で得られます、同様に”01 20\r”は0121から0140まで得られます。これらを使い、通信先の自動車がどのリクエストに反応するかを確認した上で値を取り出すことになります。
“03\r”を送ると現在その車が陥っているトラブルに関するコードが返ってきます。これらのデータが何を示しているかは、www.obd-codes.comなどを参考にすると良いと思います。
自分のRX-8とお話をしてみましたが、あまり応答スピードは速くないですね。リアルタイムにエンジン回転数を表示するというと結構カクカクするかもしれないです。なんとかせねば。