Javaは新しいjavax.commパッケージでシリアルサポートを取得します

Java Communications(別名javax.comm)APIは、通信アプリケーションの作成者がプラットフォームに依存しない方法で通信ポートにアクセスするJavaソフトウェアを作成できるようにする提案された標準拡張機能です。このAPIは、端末エミュレーションソフトウェア、FAXソフトウェア、スマートカードリーダーソフトウェアなどの作成に使用できます。

優れたソフトウェアを開発するということは、通常、明確に定義されたインターフェースを持つことを意味します。この図に、APIインターフェースレイヤーの概要図を示します。

この記事では、javax.commを使用してRS-232ベースのシリアルデバイスと通信する方法を紹介します。また、javax.commAPIが提供するものと提供しないものについても説明します。このAPIを使用してシリアルポートと通信する方法を示す小さなサンプルプログラムを紹介します。記事の最後に、このjavax.comm APIが他のデバイスドライバーとどのように連携するかを簡単に説明し、このAPIの特定のOSへのネイティブポートを実行するための要件について説明します。

非同期イベントの通信の独自のモデルが付属している従来のドライバーとは異なり、javax.comm APIは、Javaイベントモデル(java.awt.eventパッケージ)に基づくイベントスタイルのインターフェースを提供します。入力バッファに新しいデータがあるかどうかを知りたいとしましょう。ポーリングまたはリスニングの2つの方法でそれを見つけることができます。ポーリングでは、プロセッサはバッファを定期的にチェックして、バッファに新しいデータがあるかどうかを確認します。リスニングでは、プロセッサは入力バッファに新しいデータの形式でイベントが発生するのを待ちます。新しいデータがバッファに到着するとすぐに、プロセッサに通知またはイベントを送信します。

利用可能なさまざまなシリアルインターフェースの中で、最も人気のある2つは、電気信号レベルとさまざまな信号線の意味を定義するRS-232CおよびRS-422規格です。低速シリアルインターフェースは通常、データを方形波としてクロック出力し、クロック調整はスタートビットとストップビットによって提供されます。

RS-232はRecommendStandard232の略です。Cは、単に標準の最新のリビジョンを指します。ほとんどのコンピュータのシリアルポートは、RS-232C規格のサブセットを使用しています。完全なRS-232C規格では、25ピンの「D」コネクタが指定されており、そのうち22ピンが使用されています。これらのピンのほとんどは、通常のPC通信には必要ありません。実際、ほとんどの新しいPCには、9ピンしかないオスのDタイプコネクタが装備されています。RS-232の詳細については、「リソース」セクションを参照してください。

注:他のドライバーが過去に行ったことを理解するには、UnixのtermioマニュアルページまたはBSDUnixドライバーソースのバリエーションであるOpenBSDUnixを参照してください。これはインターネットで無料で入手できます。詳細については、「リソース」セクションを参照してください。

javax.comm API:提供されるもの

javax.comm APIは、開発者に次の機能を提供します。

  • シリアルおよびパラレル通信ポートの完全なAPI仕様。(この記事では、シリアルポートのみを検討します。)開発作業に共通のAPIがないと、シリアルデバイスにサポートを提供する必要があるため、ワークロードが増加します。

  • すべてのシリアルフレーミングパラメータ(ボーストップビット、パリティ、ビット/フレーム)の完全な制御、およびフロー制御ラインの手動または自動制御。通常、RS-232には2本の信号線があり、残りは制御線用です。通信のタイプ(同期または非同期)に応じて、選択される制御ラインの数は異なる場合があります。このAPIは、基礎となる制御信号へのアクセスを提供します。

    ここでの簡単な迂回は、パリティとスタートビットとストップビットについて何かを理解するのに役立つかもしれません。通信回線にノイズが発生する可能性があるため、RS-232にパリティが追加されました。16進数で0x30(またはバイナリで00110000)に等しいASCII 0を送信するとしますが、途中で誰かが磁石を持って通過し、ビットの1つが変化します。その結果、意図したとおりに8ビットを送信する代わりに、送信されたビットの最初の文字列に追加のビットが追加され、送信されたビットの合計が偶数または奇数になります。voilà!あなたはパリティを持っています。

    シリアル通信プロトコルにスタートビットとストップビットが追加され、受信者が送信される文字を同期できるようになりました。 1ビットパリティではエラー訂正はできません。検出のみです。この問題の解決策は、シリアルAPIの上に階層化されたプロトコルから得られます。最近のほとんどのシリアル通信では、チェックサム(受信機で生成され、送信されたチェックサムと比較できる数学関数)を備えたブロックプロトコルが使用されており、より大きなビットグループでエラーを検出できます。 PPPを介してISPと通信している場合、パケットはチェックサム付きのパケットあたり128バイトになる可能性があります。それらが一致する場合、データに問題がないことを99.999%確信しています。

    このスキームが機能しない場合があります。たとえば、太陽系から非常に離れた場所にあるデバイスに重要なコマンドを送信する場合、前方補正プロトコルを使用できます。再送信の時間がない可能性があり、スペースには多くの電磁ノイズがあるため、前方補正プロトコルが必要です。

    さて、javax.commAPIによって提供される機能のリストに戻りましょう。

  • JavaIOストリームのサブクラスを介した基本的なI / O。入力と出力には、javax.commAPIがストリームを使用します。ストリームの概念は、すべてのJavaプログラマーによく知られている必要があります。新しい機能を構築するときはJavaの概念を再利用することが重要です。そうしないと、APIが扱いにくくなります。

  • クライアントフロー制御としきい値制御を提供するために拡張できるストリーム。たとえば、バッファに10文字ある場合や、文字の場所が10個しか残っていない場合にアラートが必要になる場合があります。インターフェイスを介して接続された2つのデバイスが互いに追いついていない場合、フロー制御は重要です。フロー制御がないと、オーバーランまたはアンダーランが発生する可能性があります。オーバーラン状態では、処理前にデータを受信したため、データが失われました。アンダーランでは、データの準備はできていましたが、利用できませんでした。通常、これらの状態はUSART(Universal Synchronous Asynchronous Receiver Transmitter)で発生します。これは、ボーレートに一致するタイミングでバイトをシリアル波形に変換するハードウェアです。

    javax.comm APIは、Javaイベントモデルを使用して、さまざまなシグナルラインの変更とバッファステータスの通知を提供します。状態の変化は、RS-232規格で指定されている明確に定義された信号を指します。たとえば、キャリア検出は、モデムが別のモデムと接続したこと、またはキャリアトーンを検出したことを通知するために使用されます。接続の確立またはキャリアトーンの検出はイベントです。イベントの検出と変更の通知は、このAPIに実装されています。

提供されていないもの

javax.commAPIは以下を提供しません。

  • ラインディシプリンタイプの処理、ダイヤラ管理、またはモデム管理。行の規律とは、入力文字または出力文字の追加処理を指します。たとえば、一般的な後処理オプションの1つは、CRからCRLFへの変換です。これらの用語は、テレタイプの初期に由来しています。 CR(キャリッジリターン)とは、キャリッジを単純に左マージンに戻すことを意味します。アラビア語の世界では、これが適切なマージンになります。 LF(改行)は、印刷領域を1つ上に進めます。ビットマップ画面とレーザープリンタが登場したとき、これらの用語はそれほど重要ではなくなりました。

    ダイヤラ管理モデム管理は、javax.commAPIを使用して作成できる追加のアプリケーションです。ダイヤラ管理は通常、モデム管理のATコマンドインターフェイスへのインターフェイスを提供します。ほとんどすべてのモデムにはATコマンドインターフェイスがあります。このインターフェイスは、モデムのマニュアルに記載されています。

    おそらく、少しの例でこの概念が明確になります。COM1にモデムがあり、電話番号をダイヤルしたいとします。Javaダイヤラ管理アプリケーションは、電話番号を照会し、モデムに問い合わせます。これらのコマンドは、解釈を行わないjavax.commによって実行されます。たとえば、番号918003210288をダイヤルするために、ダイヤラ管理者はおそらく「OK」を返すことを期待して「AT」を送信し、続いてATDT918003210288を送信します。ダイヤラ管理とモデム管理の最も重要なタスクの1つは、エラーとタイムアウトに対処することです。

  • シリアルポート管理用のGUI。通常、シリアルポートには、シリアルポートを構成するダイアログボックスがあり、ユーザーはボーレートやパリティなどのパラメータを設定できます。次の図は、Javaからシリアルポートへのデータの読み取りや書き込みに関係するオブジェクトを示しています。

  • Support for X, Y, and Z modem protocols. These protocols provide support error detection and correction.

The programming basics

Too often, programmers dive right into a project and code interactively with an API on the screen without giving any thought to the problem they are trying to solve. To avoid confusion and potential problems, gather the following information before you start a project. Remember, programming devices usually requires that you consult a manual.

  1. Get the manual for the device and read the section on the RS-232 interface and RS-232 protocol. Most devices have a protocol that must be followed. This protocol will be carried by the javax.comm API and delivered to the device. The device will decode the protocol, and you will have to pay close attention to sending data back and forth. Not getting the initial set-up correct can mean your application won't start, so take the time to test things out with a simple application. In other words, create an application that can simply write data onto the serial port and then read data from the serial port using the javax.comm API.

  2. Try to get some code samples from the manufacturer. Even if they are in another language, these examples can be quite useful.

  3. Find and code the smallest example you can to verify that you can communicate with the device. In the case of serial devices, this can be very painful -- you send data to a device connected to the serial port and nothing happens. This is often the result of incorrect conditioning of the line. The number one rule of device programming (unless you are writing a device driver) is to make sure you can communicate with the device. Do this by finding the simplest thing you can do with your device and getting that to work.

  4. If the protocol is very complicated, consider getting some RS-232 line analyzer software. This software allows you to look at the data moving between the two devices on the RS-232 connection without interfering with the transmission.

Using the javax.comm API successfully in an application requires you to provide some type of interface to the device protocol using the serial API as the transport mechanism. In other words, with the exception of the simplest devices, there is usually another layer required to format the data for the device. Of course the simplest protocol is "vanilla" -- meaning there is no protocol. You send and receive data with no interpretation.

Overview of suggested steps for using javax.comm

In addition to providing a protocol, the ISO layering model used for TCP/IP also applies here in that we have an electrical layer, followed by a very simple byte transport layer. On top of this byte transport layer you could put your transport layer. For example, your PPP stack could use the javax.comm API to transfer bytes back and forth to the modem. The role of the javax.comm layer is quite small when looked at in this context:

  1. Give the javax.comm API control of some of the devices. Before you use a device, the javax.comm API has to know about it.

  2. Open the device and condition the line. You may have a device that requires a baud rate of 115 kilobits with no parity.

  3. Write some data and/or read data following whatever protocol the device you are communicating with requires. For example, if you connect to a printer, you may have to send a special code to start the printer and/or end the job. Some PostScript printers require you to end the job by sending CTRL-D 0x03.

  4. Close the port.

Initializing the javax.comm API registry with serial interface ports

The javax.comm API can only manage ports that it is aware of. The latest version of the API does not require any ports to be initialized. On start-up, the javax.comm API scans for ports on the particular host and adds them automatically.

You can initialize the serial ports your javax.comm API can use. For devices that do not follow the standard naming convention, you can add them explicitly using the code segment below.

// Register the device CommPort ttya = new javax.comm.solaris.SolarisSerial("ttya","/dev/ttya"); CommPortIdentifier.addPort(ttya,CommPortIdentifier.PORT_SERIAL); CommPort ttyb = new javax.comm.solaris.SolarisSerial("ttyb","/dev/ttyb"); CommPortIdentifier.addPort(ttyb,CommPortIdentifier.PORT_SERIAL); 

Opening and conditioning devices

This next code sample demonstrates how to add, condition, and open a device. Details on the specific method calls are in the API pages for javax.comm. This example sets the device called XYZSerialDevice to be accessible with name GenericSerialReader. The device connected on this line has a baud rate of 9600, 1 stop bit, a character of 8 bits (yes, they can be smaller), and no parity. The result of all of this is to provide two streams -- one for reading and another for writing.