この記事は The Qt Blog の Introducing QtMqtt を翻訳したものです。
執筆: Maurice Kalinowski, 2017年8月14日
最近、オートメーション分野にむけたアプローチについての議論が活発に行われています。興味のある方は、こちら と別の ブログ記事 も合わせてご覧ください。
オートメーションむけのプロジェクトを開始するにあたって、最初の障壁は適切なコミュニケーションスタックの構築です。MQTT はテレメトリデータ(センサーからのデータの収集やデバイスの状態など)の管理で、ここ数年でとても注目を集めている技術で、今回これをサポートすることで開発のワークフローの単純化に対応することにしました。
MQTT の自身の説明 を引用します。
"It was designed as an extremely lightweight publish/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is required and/or network bandwidth is at a premium."
(MQTT は究極的に軽量にメッセージの発行、取得ができるように設計されています。コードのフットプリントの小ささが求められるような場所やネットワークの帯域が非常に高価な場所との遠隔通信に威力を発揮します。)
パブリッシャー/サブスクライバー方式の採用により、ルーティングはすべてのクライアントが接続するサーバー側(この場合「メッセージブローカー」と呼ぶ)の担当になります。メッセージの伝搬を保証するため、複数のレベルのサービスの質の指定が可能です。
接続自体は通常は TCP 接続の上で行われますが、オーダー型でロスレスで双方向通信であればどれでも利用可能です。
QtMqtt はクライアント側の実装で、デバイスからの送信や、データの受信や管理のモニタリングのソリューションを提供します。ブローカー側は対象外です。
ここで明記したいのは、QtMqtt を仕様に完全準拠したものにしたいということで、具体的には以下の対応を意味します。
では QtMqtt の実際の使い方を見てみましょう。
データの送信:
QMqttClient publisher;
publisher.setHostname(“some.brokerlocation.com”);
publisher.setPort(1883);
publisher.connectToHost();
…
publisher.publish(“sensor_1/dataset/foo”, “values”, qosLevel);
データの受信:
QMqttClient subscriber;
subscriber.setHostname(“some.brokerlocation.com”);
subscriber.setPort(1883);
subscriber.connectToHost();
. . .
QSharedPointer<QMqttSubscription> sub = subscriber.subscribe(“sensor_1/#”, qosLevel);
connect(sub.data(), &QMqttSubscription::messageReceived, [&](QMqttMessage msg) {
qDebug() << “New Message:” << msg.payload();
});
すべての通信がセキュアで安全であることは非常に重要です。QtMqtt は2つの方法でこれを実現します:
後者では、QtNetwork に含まれる QSslSocket を利用することが可能です。QMqttClient では connectToHostEncrypted() メソッドを実行することで、QSslSocket と同じように利用することができます。
MQTT は TCP 上で利用されるケースがほとんどですが、それに限定されているわけではありません。QtMqtt でも他の通信方式を指定することが可能で、QIODevice か QAbstractSocket を指定することができます。これにより、独自の通信方式を実装し、接続前の QMqttClient に渡すことも可能になります。
Qt が提供している機能でいくと、MQTT を websocket 上で動かすのがいい例でしょう。QWebSocket は送受信の意味合いが異なるため、QAbstractSocket を継承してはいません。ですが、MQTT のデータを websoket 上で送出するための仕様はとても明確です(バイナリデータとして送る、一つのデータグラムに割り当てる、などなど…)。このため、その間を取り持つクラスの実装はとても簡単です。QtMqtt モジュールのサンプルの中にすでにこれを実現したものがありますので、ぜひ見てみてください。
この記事に興味がある方は、プレリリースバージョンを提供いたしますので、是非 お問い合わせ ください。