趣味で作ってるロボット用ソフトウェア
 All Classes Files Functions Enumerations Enumerator Friends Pages
通信モジュールのクラス構成

概要

このプロジェクトでの通信モジュールは RS-232 (USB) と Ethernet の TCP/IP を扱えるようにします。
RS-232 に USB がカッコ付きで表記されているのは RS-232 機器として認識される USB 接続のデバイスも RS-232 用のクラスで扱えることを示しています。 (USB 接続の GPS など、USB 機器によっては RS-232 と同じ実装で通信を処理できるものがあります。)

クラス構成とインターフェース

では C++ でのクラス構成を定義します。
hrk::Connection というインターフェースのクラスを定義し RS-232 実装の hrk::Serial クラスと TCP/IP 実装の hrk::Tcpip クラスがそのインターフェースを実装しています。

dot_inline_dotgraph_1.png

hrk::Connection クラスは、通信の基本的なメソッドのみを提供します。
具体的には、

などです。
データ通信を開始するときに使う open() は扱うデバイスで引数が変わる可能性があるので Connection を実装するクラスが提供することにしています。

connection_open.png


connection_read_write.png
connection_close.png

このクラスを使って "COM1" として認識された RS-232 デバイスに対して "hello" という文字列を送信する場合のプログラムは、以下のようになります。

// Serial オブジェクトを生成し、文字列を送信する
hrk::Serial serial;
serial.open("COM1", 115200);
serial.write("hello", 5);
serial.close();

また Serial と Tcpip が Connection インターフェースを継承していることで Serial と Tcpip で共通になる処理を共通にできます。
以下は、"hello" という文字列を送信する処理を、Serial と Tcpip で共通にした例です。

// Connection オブジェクトを受け取り "hello" という文字列を送信する関数
void hello(hrk::Connection& connection)
{
connection.write("hello", 5);
}
void some_function(void)
{
// RS-232 で "hello" と送信する
hrk::Serial serial;
serial.open("COM1", 115200);
hello(serial);
serial.close();
// Ethernet の TCP/IP で "hello" と送信する
hrk::Tcpip tcpip;
tcpip.open("192.168.0.10", 57577);
hello(tcpip);
tcpip.close();
}

Connection クラスを使った機能の実装

Connection クラスを使った、より実際の運用に近い実装例として、通信の送受信データを記録しながら通信するためのクラスを考えてみます。
クラスの UML 図は、以下のようになります。このクラスには、Connection オブジェクトを登録するためのメソッドが追加されています。

dot_inline_dotgraph_2.png

また Logging_connection のメソッドは以下のように実装されるはずです。
要は、渡された Connection オブジェクトを操作しつつ得られたデータを保存する処理を行っています。

int Logging_connection::set_connection(Connection& connection)
{
// ロギング対象のオブジェクトを登録する
pimpl->connection_ = connection;
}
int Logging_connection::write(const char* data, size_t data_size)
{
int ret = pimpl->connection_.write(data, data_size);
// data をファイルに書き出す処理
pimpl->fout_.write(data, data_size);
return ret;
}

このクラスは「Serial か Tcpip のオブジェクトを Logging_connection に登録して利用する」という風に使います。
以下に、このクラスを用いて Serial の送受信データを記録するときの例を紹介します。(もちろん Tcpip の送受信データも同様に記録できます。)

hrk::Serial serial;
serial.open("COM1", 115200);
// 送受信したデータが記録されるように serial を logging_connection に登録する
// 以降は logging_connection を用いて通信処理を行う
Logging_connection logging_connection;
logging_connection.set_connection(serial);
// logging_connection を用いた処理
// 送受信したデータは記録される
hello(logging_connection);

このプロジェクトにおいては 動作のレコーディング & プレイバック の処理に Connection を使ったこのような実装がなされています。