Javaシリアル通信¶
計算機の通信手段として古くから使われ、現在でも組み込み・制御系でよく使われているシリアル通信をJavaから利用する方法をまとめます。
シリアル通信の構成¶
RS-232としてPCなどの端末装置(Data Terminal Equipment: DTE)とモデムなどの回線終端装置(Data Circuit Terminating Equipment: DCE)とを結ぶ通信のための電気信号・コネクタ等が規定されました。汎用性が高く、DTEとDCEの間の通信だけではなく、産業機器の機器間通信に広く使われています。RS-232Cの信号は10m程度は通信可能とされていますが、さらにノイズ耐性を高めたRS-485では1000m以上の距離の通信も可能とされています。
Javaからシリアル通信を使う方法¶
Java SE 標準APIにはシリアル通信は含まれていませんが、Sun Microsystemsが拡張APIとしてシリアル通信のAPIである Java Serial Communication API を定義しました。そして、このAPIの実装が同じくSun Microsystemsから提供されていました。
しかし、バージョン3.0からはWindows版の実装が除外されてしまい、他のOS版もその後アップデートもされなくなりました。
Sun MicrosystemsのJava Serial Communication API実装の代替として、RXTXと呼ぶオープンソースのシリアル通信ライブラリが存在します。配布サイトは維持されていますがバージョンアップは久しく行われていません。RXTXの実装にはいろいろ課題もあるようです。
http://rxtx.qbang.org/wiki/index.php/Main_Page
RXTX以外にもいくつかオープンソースのシリアル通信ライブラリが登場しています。
jSerialComm
http://fazecast.github.io/jSerialComm/
APL2とLGPLv3のデュアルライセンス。RXTXの安定した代替を目指している。
2015年にv1.0.0がリリース、以降2018年にv2.0.0がリリース、こまめにアップデート中で、2022年2月にはv2.9.0がリリース。
PureJavaComm
http://www.sparetimelabs.com/purejavacomm/purejavacomm.php
修正BSDライセンス。JNAを使いネイティブコードを使わない実装をしている。
2016年にv1.0.1がリリース、2017年にv1.0.2、2019年にv1.0.3がリリース。
Java Simple Serial Connector (JSSC)
https://code.google.com/archive/p/java-simple-serial-connector/
LGPLv3ライセンス。2014年にv2.8.0がリリースされ、その後は更新ないようです。
商用製品のライブラリもいくつかあります。
Java Serial Port
https://www.serialio.com/java-developer
Javaシリアル通信の実現¶
シリアル通信開発環境¶
Windowsマシンに仮想シリアルポートを設ける¶
com0com を用いた仮想シリアルポートの設定¶
Windows OS上に2つの相互にクロスケーブルで結ばれた設定での仮想COMポートを作成するオープンソースのツール com0com を使います。
http://com0com.sourceforge.net/
同一マシン上で2つのシリアル通信プログラムを実行し、相互にシリアル通信をさせることができるので、シリアルポートがないマシンで開発・テストをするのに有用です。
シリアル通信あれこれ¶
メッセージ定義¶
キャラクタと開始・終了¶
シリアル通信では、一般的にはキャラクタ(8bit)単位で通信を行う。データは文字列(ASCII)の範囲とし、先頭と最後に識別用データ(STX、ETX)を付与することが多い。
バイト列 | 02H | 48H | 65H | 6cH | 6cH | 6fH | 03H |
---|---|---|---|---|---|---|---|
キャラクタ | STX | 'H' | 'e' | 'l' | 'l' | 'o' | ETX |
ACKとNAK¶
要求・応答で組み合わせるメッセージでは、正常応答時はACKを、異常応答時はNAKを返すことが多い。
バイト列 | 06H | 6fH | 6bH | 03H |
---|---|---|---|---|
キャラクタ | ACK | 'o' | 'k' | ETX |
チェックサム¶
modulo-2 加算¶
2進数の1桁同士をXORで演算した結果となります。バイト列のチェックサムをmodulo-2加算で計算する場合は、各バイトをXORします。
バイト ビット並び 02H 0 0 0 0 0 0 1 0 48H 0 1 0 0 1 0 0 0 65H 0 1 1 0 0 1 0 1 6cH 0 1 1 0 1 1 0 0 6cH 0 1 1 0 1 1 0 0 6fH 0 1 1 0 1 1 1 1 03H 0 0 0 0 0 0 1 1 -------------------------- sum 0 1 0 0 0 0 1 1 ===> 43H
jshell> System.out.printf("%x%n", 0x02 ^ 0x48 ^ 0x65 ^ 0x6c ^ 0x6c ^ 0x6c ^0x6f); 43