はじめに
Qtは、異なるハードウェアプラットフォームやオペレーティングシステム上で動作するソフトウェアを開発するためのクロスプラットフォームのフレームワークおよびツールキットです。Qtフレームワークには豊富なライブラリとツールが含まれており、開発者はネイティブのUIとパフォーマンスを持つアプリケーションを簡単に構築できます。組み込みデバイスやIoTソフトウェアの作成に広く使用されています。
MQTTは、パブリッシュ/サブスクライブモデルに基づく軽量なIoTメッセージングプロトコルです。非常に少ないコードと帯域幅で、ネットワーク接続されたデバイスにリアルタイムで信頼性の高いメッセージングサービスを提供できます。
このブログでは、Qt6でシームレスな通信を行うためにMQTTを使用するステップバイステップのガイドを提供します。Qt MQTTモジュールをコンパイルし、それを使用して接続を確立し、トピックの購読・購読解除、メッセージのパブリッシュ、リアルタイムでのメッセージ受信を行う方法を学びます。
Qt6プロジェクトの準備
このブログ記事では、M2チップを搭載したMacBookでQt v6.6.2を使用しました。Qtのオープンソース版はこちらからダウンロードしてインストールできます。
インストール前にQtアカウントを登録することをお勧めします。
Qtをインストールした後、g++とXCodeをインストールし、いくつかの環境変数を設定する必要があります。Qtの公式ドキュメントには、macOSでの設定方法が記載されています。
CMakeでQt MQTTモジュールをコンパイル
Qt MQTTモジュールは、MQTTプロトコル仕様の標準準拠の実装を提供する公式のQtライブラリです。しかし、これはオープンソースのインストールには含まれておらず、ソースからコンパイルする必要があります。
まず、GitHubからQt MQTTのソースコードをダウンロードします。お使いのマシンにインストールされているQtのバージョンと一致するQt MQTTのバージョンを確保してください。
git clone git://code.qt.io/qt/qtmqtt.git -b 6.6.2
次に、QtCreatorでQt MQTTをコンパイルします。Qt6では、qmakeまたはCMakeのどちらかを使用してコードをビルドできます。このブログではCMakeを使用しました。Qt CreatorでqtmqttのCMakeLists.txtファイルを開き、プロジェクトをコンパイルします。
コンパイルが成功すると、build-qtmqtt-Desktop_arm_darwin_generic_mach_o_64bit-Release
という新しいフォルダが作成されます。すべての静的および動的ライブラリが生成され、このフォルダ内に保存されます。
Qt MQTTモジュールの追加
コンパイル後、使用する方法は2つあります。1つは、qtmqttをプロジェクト内のサードパーティモジュールとしてインポートする方法で、もう1つはコンパイルされたファイルをQtのインストールディレクトリに直接配置する方法です。このブログでは2番目の方法を使用します。
-
Qt/6.6.2/macos/include/
ディレクトリにQtMqtt
という新しいフォルダを作成します。次に、qtmqtt/src/mqtt/
内のすべてのファイルを新しく作成したフォルダにコピーします。 - 生成された静的および動的ライブラリをQtのインストールディレクトリにコピーします。
-
build-qtmqtt-Desktop_arm_darwin_generic_mach_o_64bit-Release/lib
ディレクトリ内のすべてのファイルとフォルダをQt/6.6.2/macos/lib/
フォルダにコピーします。置き換える必要のあるファイルがある場合は、置き換えてください。 -
build-qtmqtt-Desktop_arm_darwin_generic_mach_o_64bit-Release/lib/cmake
からQt6Mqtt
フォルダをQt/6.6.2/macos/lib/cmake
にコピーします。 -
build-qtmqtt-Desktop_arm_darwin_generic_mach_o_64bit-Release/mkspecs/modules
から2つの.pri
ファイルをQt/6.6.2/macos/mkspecs/modules
にコピーします。
-
コミュニティのDiego Schulzさんが、Qt MQTTモジュールをビルドしてインストールするためのより良い方法を提供しています。こちらに参考として掲載しています。
MQTTブローカーの準備
先に進む前に、通信およびテスト用のMQTTブローカーを用意してください。
このガイドでは、EMQが提供する無料のパブリックMQTTブローカーを利用します。これはEMQXプラットフォーム上に構築されています。サーバーアクセスの詳細は以下のとおりです。
- ブローカー:
broker.emqx.io
- TCPポート:1883
- SSL/TLSポート:8883
- WebSocketポート:8083
- セキュアWebSocketポート:8084
詳細については、無料のパブリックMQTTブローカーをご覧ください。
QtでのMQTTの使用
シンプルなQt MQTTアプリケーション
これで、QtでQt MQTTモジュールを使用できます。これは、その機能を示すいくつかのサンプルを提供しています。
このブログでは、シンプルなMQTTクライアントのサンプルを使用して、MQTTを使用してMQTTブローカーと通信するアプリケーションを作成する方法を説明します。QtCreatorでサンプルプロジェクトを開き、このアプリケーションがどのように動作するかを見てみましょう。
先ほどgit clone git://code.qt.io/qt/qtmqtt.git -b 6.6.2
コマンドでダウンロードしたディレクトリに戻り、simpleclientのサンプルプロジェクトのディレクトリに移動します。
cd qtmqtt
cd examples/mqtt/simpleclient
その中のCMakeLists.txt
ファイルを見つけます。これをQt Creatorで開き、以下のオプションでプロジェクトを構成します。
構成が完了したら、前の手順でQtMqttライブラリがローカル環境にインストールされているため、プログラムを正常に実行できます。
起動したグラフィカルアプリケーションで、ホストの入力ボックスにbroker.emqx.io
、ポートに1883
を入力します。順にConnect、Subscribe、Publishボタンをクリックすると、以下のような出力が得られます。
これで、シンプルなMQTTクライアントが正常に動作しました。
MQTTクライアントの作成
まず、QMqttClientクラスを使用してMQTTクライアントを作成します。このクラスは、一意のクライアントIDや接続先のブローカーのホスト名とポートを設定するためのプロパティを提供します。
// mainwindow.cppの19行目
m_client = new QMqttClient(this);
m_client->setHostname(ui->lineEditHost->text());
m_client->setPort(static_cast<quint16>(ui->spinBoxPort->value()));
クライアントIDは設定せず、自動的に生成されます。
次に、QMqttClient::messageReceived()に接続し、ブローカーから送信されたすべてのメッセージを受信します。
// mainwindow.cppの26行目
connect(m_client, &QMqttClient::messageReceived, this, [this](const QByteArray &message, const QMqttTopicName &topic) {
const QString content = QDateTime::currentDateTime().toString()
+ " 受信したトピック: "_L1
+ topic.name()
+ " メッセージ: "_L1
+ message
+ u'\n';
ui->editLog->insertPlainText(content);
});
ブローカーへの接続・切断
サンプルプログラムでは、Connect/Disconnectボタンをクリックして以下の関数をトリガーし、MQTTブローカーへの接続・切断を行います。
// mainwindow.cppの52行目
void MainWindow::on_buttonConnect_clicked()
{
if (m_client->state() == QMqttClient::Disconnected) {
ui->lineEditHost->setEnabled(false);
ui->spinBoxPort->setEnabled(false);
ui->buttonConnect->setText(tr("Disconnect"));
m_client->connectToHost();
} else {
ui->lineEditHost->setEnabled(true);
ui->spinBoxPort->setEnabled(true);
ui->buttonConnect->setText(tr("Connect"));
m_client->disconnectFromHost();
}
}
ポイントは、m_client->connectToHost() / m_client->disconnectFromHost()メソッドを呼び出すことで、MQTTブローカーへの接続・切断が行えることです。
トピックの購読・購読解除
同様に、QMqttClient::subscribeとQMqttClient::unsubscribeを呼び出すことで、トピックの購読・購読解除を行えます。
// mainwindow.cppの9行目:
void MainWindow::on_buttonSubscribe_clicked()
{
auto subscription = m_client->subscribe(ui->lineEditTopic->text());
if (!subscription) {
QMessageBox::critical(this, u"エラー"_s,
u"購読できませんでした。有効な接続がありますか?"_s);
return;
}
}
購読が正常に作成されると、MQTTブローカーはそのトピックのメッセージをクライアントにプッシュし、Qt MQTTは先ほど設定したQMqttClient::messageReceived
コールバック関数を呼び出します。
メッセージのパブリッシュ
QMqttClient::publishを呼び出すことで、指定したトピックにメッセージ内容をパブリッシュできます。
// mainwindow.cppの93行目
void MainWindow::on_buttonPublish_clicked()
{
if (m_client->publish(ui->lineEditTopic->text(), ui->lineEditMessage->text().toUtf8()) == -1)
QMessageBox::critical(this, u"エラー"_s, u"メッセージをパブリッシュできませんでした"_s);
}
完全なコード
すべてのサンプルコードは以下で見つけることができます:Github qtmqtt/example
Qt Creatorでの一般的なコンパイルエラー
-
Qt6Config.cmake
またはqt6-config.cmake
を提供する「Qt6」というパッケージ構成ファイルが見つかりませんでした。qtmqttをQt Creatorにインポートした後、以下のエラーが発生することがあります。
[cmake] CMake Error at CMakeLists.txt:14 (find_package): [cmake] Could not find a package configuration file provided by "Qt6" (requested [cmake] version 6.6.2) with any of the following names: [cmake] [cmake] Qt6Config.cmake [cmake] qt6-config.cmake [cmake] [cmake] Add the installation prefix of "Qt6" to CMAKE_PREFIX_PATH or set "Qt6_DIR" [cmake] to a directory containing one of the above files. If "Qt6" provides a
解決策は、デスクトップ(arm-xx)用のビルドターゲットのQtバージョンが正しいことをキット管理で確認する必要があります。
まとめ
このブログでは、Qt MQTTモジュールをコンパイルし、MQTTブローカーと通信するアプリケーションを作成するためのステップバイステップのガイドを提供しました。このガイドに従うことで、MQTTを活用し、Qt6でスケーラブルで効率的なIoTアプリケーションを構築するスキルを身につけることができます。