MQTT クライアントとテスト用プログラムを作成しました

●MQTT を使ってみよう

センサーネットワークなどを構築するときには、センサーで取得したデータを何らかの方法で他のシステムに送信する必要がありますが、もし、センサーデバイスに TCP/IP プロトコルを載せた Ethernet インターフェイスが付いていれば、FTP, HTTPなどのプロトコルや独自のプロトコルを利用してソケット通信で簡単に転送できます。これらの標準的なプロトコルとして注目されているのが MQTT とよばれるプロトコルです。MQTT は IBM社 が開発したプロトコル ( http://mqtt.org/ )で、最近 OASIS Standard にも認定されました。特徴としては、

(1) 送信側と受信側の間に Broker とよばれる仲介サーバーを介してデータのやりとりを行う。このため、センサーデータ配信側と利用側が直接連携をとる必要がない。

(2) TCP/IP のソケット通信を使用する( WebSocket で実装されているものもあります )ので送信データが確実に伝わることが期待できる。

(3) 標準機能を実装した Broker ( http://mosquitto.org/ ) や クライアントライブラリ ( http://eclipse.org/paho/ ) が豊富に用意されている

(4) 仕様が公開されていて( http://mqtt.org/documentation ) 、(3) と相まってアプリケーションへの実装が容易

(5) QoS と呼ばれる送達保障レベルをメッセージや購読項目毎に自由に選択可能。CPU リソースが少ないセンサーノードからの通信時には簡単な送信手順が用意されているなど実装の自由度が高い。

今後、 MQTT プロトコルはセンサーネットワーク等に幅広く利用されていくと思います。

●MQTT テストクライアントを作成しました

今回、DeviceServer 製品に MQTT クライアント機能を追加することを想定して、MQTT クライアントライブラリを作成しました。また、このライブラリの機能試験を行うためにテスト用クライアントプログラム(スタンドアロンで動作します)も同時に作成しました。

このMQTT クライアントプログラムは、Windows 環境(Windows XP SP3,Windows 7 64bit で動作確認済み) で動作します。もし興味がありましたら、こちらのリンクからダウンロードできますので記事の内容を見ながら使用してみて下さい(テスト用に作成したものですが、個人用・商用問わず自由に使用していだだいて構いません)。

ダウンロードすると、プログラム本体と DLLファイル が格納されています。プログラム本体をダブルクリックすると下記の画面が表示されます。DLLファイル はメモリ監視用に組み込んでありますが気にしないでこのまま使用してください。

MQTT テストプログラムでは動作時の詳細ログ情報を ABS-9000 DeviceServer のログサーバーとログコンソールに出力しています。DeviceServer のインストールキットは此方からダウンロードできますので併せてインストールしてください。DeviceServer のライセンスはデモライセンスのままで構いません。ログサーバーとログコンソールはデモライセンス期間に関係なく何時までも使用することができます。

●iot.eclipse.org で公開されている MQTT Broker を使用します

クライアントプログラムだけでは試験できませんので、接続先の MQTT Broker を用意する必要があります。ここでは http://iot.eclipse.org が試験目的で使用可能な Broker を提供していていますの最初はこれを利用すると簡単に MQTT を試せます。この Broker はユーザー登録などは不要で常に利用可能になっているようなので早速接続してみます。

“Broker HostName” に “iot.eclipse.org” を指定して、”Port” には “1883″ を指定します。その他の設定は初期値のままにしておいて下さい。 “Open” ボタンを押すとソケット接続を開始します。このとき、ログコンソールプログラムを起動していると下記の様に表示されます。”connecting…” と表示されている部分がソケット接続時のメッセージになります。

エラー無く接続されたら、以降は MQTT のメッセージをやり取りすることになります。

最初に “CONNECT” ボタンを押して、CONNECT メッセージを送信します。すると直後に Broker 側から CONNACK が返ってくるのをログで確認できます。現状ではユーザー名やパスワードは指定しなくても “iot.eclipse.org” の Broker には接続できるようです。

次に、”定期的にPING送信” にチェックを付けます。チェックをつけなくても、”PINGREQ” ボタンを1分以内に1回程度の頻度で手動で押しても構いません。これによって PINGREQ メッセージをBroker に送信して、クライアントがまだちゃんと動作していることを伝えることができます。送信しない状態で “KeepAlive” 値に設定した秒数+α 経過すると Broker は勝手に接続を切ってしまいます。

次に “SUBSCRIBE” ボタンを押します。これで、”hello/world” と “センサー/ノード1″ という2つのトピックの購読を Broker に伝えます。トピックのメッセージを受け取るときにはそれぞれ QoS の 2 と 0 のプロトコルを使用することを指定しています。ここでは1度に2つのトピックと QoS をカンマ区切りで指定していますが、”SUBSCRIBE” ボタンを複数回押してトピックの購読を後から追加していくこともできます。

最後に、”PUBLISH(str)” ボタンを押して、トピック名 “hello/world” でメッセージを送信します。このときにペイロードに格納されるデータは “PublishData(str)” のテキストエリアに入力されている文字列(UTF8文字列)になります。送信するときに指定する QoS はデフォルトで2になっています。

ログには、クライアントプログラムから送信された PUBLISH データと Broker 側からクライアント側に配信されて戻ってきたデータを確認できます。ログ中の “—- PublishData —-” と表示されている部分が購読しているトピックのデータを受信したときのログになります。Broker 側から配信されたデータが 256Bytes 以内の場合には、データバイト列を UTF8 文字列に変換してログにも表示します。また同時に、クライアントプログラムが配置されているフォルダには受信したデータバイト列がファイルとして保存されます。

“Pub_xxxxxxxxxxxxx.dat” のファイル名で保存されているのが受信した PUBLISH のペイロード部分をファイル書き出したものです。このファイルは PUBLISH メッセージを受信する度に増えていきますので、いらなくなったら削除して下さい。

Brokerとの接続を切るときには、最初に “DISCONNECT” ボタンを押します。その後、”Close” ボタンを押してソケットを閉じます。このとき、”Close” を押さずにプログラムを終了するとMQTT接続で使用しているリソースに関するメモリー情報がダイアログに出力されますが、気にしないで下さい。

●クライアントを複数起動してチャット(LINE?) のような事もできます

MQTT クライアントプログラムは同じ PC 上で複数同時に起動することもできます。下記の画面をご覧ください。

このとき、”CONNECT” ボタンを押すときに “ClientID” エリアに入力されているデフォルト文字列が必ず異なっていることを確認してください。数字部分を乱数で生成していますのでそのままで大丈夫だと思います。

ここで、双方のアプリで “SUBSCRIBE” を押して “PUBLISH(str)” で好きなメッセージを送信することができます。同じトピック “hello/world” を購読していますのでチャットのような動作になります。

“PUBLISH(str)” ボタンを押すときに “PublishQoS” を 0, 1,2 にそれぞれ変更すると、MQTT プロトコルでやり取りされるパケットの種類が変化するのをログで確認できると思います。

●RaspberryPi にMQTT Broker をインストール

ここからは、Will メッセージ送信やデータファイル送信などを試してみたいと思います。強制的にソケットを切断したり、Broker に負荷がかかるデータ送信試験などを行いたいので、パブリックに公開されている Broker を使用しないでここからは、自前で用意した Broker を使用します。

ここでは、RaspberryPi (下記写真) に MQTT Broker をインストールします。

RaspberryPi には Raspbian OS が動作しています。ここに、オープンソースで開発されている MQTT Broker “mosquitto” をインストールします。(蚊?スペルが似てるからですね…)

インストールの方法は http://mosquitto.org/ に詳しく書かれています。RaspberryPi 用には予めコンパイル済みのパッケージを利用できますのでこれを利用するのが簡単です。インストールするときのコマンド例のみを以下に紹介しますが、詳しい手順については http://mosquitto.org/2013/01/mosquitto-debian-repository/ に詳しく書かれていますので確認してください。

(1) レポジトリにパッケージ追加

wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key

cd /etc/apt/sources.list.d/
sudo wget http://repo.mosquitto.org/debian/mosquitto-stable.list

(2) パッケージアップデート

apt-get update

(3) mosquitto Broker とクライアントプログラムをインストール

apt-get install mosquitto
apt-get install mosquitto-clients

これでインストール完了です。mosquitto Broker をインストールすると自動的に MQTT Broker プロセスが起動している筈ですが、起動していない場合や手動で起動する場合には、下記の様にコマンドを実行します。

これで、自前の Broker が作成できました。ここからはこの Broker を使用して試験をします。

●Will メッセージを受信する

MQTT プロトコルには、予期しないネットワーク切断が発生したときにSubscribe しているクライアントに対してメッセージを出力する機能 “Will Message” が用意されています。先ほど RaspberryPi に作成した Broker を使用してこのメッセージを出力してみます。

最初に、MQTT クライアントプログラムを使用して RaspberryPi (この例ではIP アドレス 192.168.100.14 になっています)に接続します。

“Broker HostName” にRaspberryPi の IP アドレスを設定して “Open” を押します。その後、”WillTopic” と “WillMessage” に文字列が設定されているのを確認した後、”CONNECT” を押して Broker に接続します。ここで、”SUBSCRIBE” を押した後、”PUBLISH(str)” ボタンでデータを送信するたびに、Broker 側から同じ文字列が配信されてくる様子をログで確認してください。

ここで、別のコンソールを使用して RaspberryPi に接続して RaspberryPi 上でも Subscribe を実行します(MQTT クライアントプログラムをもう一つ起動する方法でも構いません)。 コマンド “mosquitto_sub -d -v -t hello/my_will ” を実行してください。ここで指定する “hello/my_will” は、クライアントプログラムで “CONNECT” したときに指定した WillTopic の内容に合わせています。

ここで、クライアントプログラムの “Close” ボタンを押すと RaspberryPi のコンソールには WillMessage (この例では “さようなら”) が表示されると思います。”DISCONNECT” ボタンを押してから “Close” を押した場合には正常な切断方法ですので WillMessage は表示されません。

ちなみに、クライアント側からの切断だけでなく Broker 側からの切断時にも WillMessage が配信されます。クライアントプログラムで “CONNECT” ボタンを押した後にもう一度 “CONNECT” を押してみて下さい。このときには Broker で異常事態を検出してソケットを勝手に切断してしまいます。このときにも RaspberryPi のコンソールにWillMessage が表示されるのを確認できると思います。

●大きなサイズのメッセージを Publish する

MQTT クライアントで送信するデータは、MQTT PUBLISH メッセージフレーム中のペイロードと呼ばれるエリアに格納されます。今までの動作例ではこの部分に UTF-8 エンコードされた文字列データを格納していました。

MQTT の仕様上 PUBLISH ペイロードは格納するデータ内容は自由なので、任意のバイナリデータを格納することもできます。また、ペイロード部分とヘッダ情報を合わせて最大 256MBytes までのデータを PUBLISH メッセージに格納することができる仕様になっています。

もちろん、Broker を動作させるRaspberryPi の搭載メモリやCPUパワー、クライアントプログラムの動作環境に依存しますので、常に 256MBytes のデータをやり取りすることはできないと思います。そこで、どれぐらいのデータサイズまで PUBLISH 可能かを試してみます。

MQTT クライアントアプリには “PUBLISH(file)” ボタンが用意されています。これを利用するとファイルの内容をバイナリ列として PUBLISH フレーム中のペイロードに格納して送信できます。そこで 20MBytes 程度のファイルを転送してみます。(**注意** 必ずローカルに設置した自前の Broker で試験してください。高い負荷がかかると Broker 側がハングする可能性があります!! また、他の人が同じ Topic を購読していると大変なことになります!!)

ここでは、適当な映像ファイル (test2.wmv) ファイルを PUBLISH すると同時に、配信されてきたデータを受信します。このとき Broker 側から受信したデータはMQTTテストクライアントプログラムと同じフォルダにファイルの形で格納されますのでこのファイルの内容を確認します。

Pub_xxxxxxx.dat のファイル拡張子を元のファイルと同じ “.wmv” へ変更すると、内容が正しく配信されているかを再生することで確認できます。一々再生しなくても MD5 ハッシュ値を求めて確認する方法がスマートかもしれません。

私の環境で RaspberryPi を Broker に使用した場合には、実用的な速度で送信可能な最大サイズは 20MBytes ぐらいになりました。そこで、どうしても 100MBytes を転送してみたくなったので、Windowsマシン(Windows7 64Bit,CPU i7-4770,メモリ 16G)に Windows 版 mosquitto Broker をインストールして試してみました。

コマンドプロンプトから Broker を起動して、MQTT クライアントアプリを localhost に接続して試験した様子です。なんとか転送できているのを確認することができます。(同じ環境で 200MBytes までは正常な転送を確認できました!!)

実際の環境では Subscribe を依頼しているエンドポイントの数だけ Broker から送信しますので、実用的には数MBytes が限度かもしれません。

今回紹介した MQTT クライアントプログラムを使っていて、不具合を見つけた場合や要望などがありましたら、遠慮なく contact@allbluesystem.com までメールお寄せ下さい。

それではまた。