概要
MQTT(Message Queuing Telemetry Transport)は、TCP/IP上で動作する軽量なPub/Sub(発行/購読)型メッセージングプロトコルです。もともと1999年にIBMのAndy Stanford-ClarkとArcom(現Eurotech)のArlen Nipperが、油田パイプラインの監視システム向けに設計しました。現在はOASIS標準となっており、IoTデバイスが少ないリソースでクラウドやサーバーと通信するためのデファクトスタンダードとして広く使われています。
MQTTの最大の特徴は「軽量さ」にあります。ヘッダの最小サイズはわずか2バイトであり、帯域幅が限られたLPWAやセルラーIoT回線、あるいはメモリが少ないMCU上でも動作できます。また、Pub/Subモデルを採用することで、センサーデバイスと処理サーバーを完全に疎結合にでき、スケーラブルなシステムを構築しやすくなっています。
歴史・背景
1999年にIBMとArcomが衛星回線を介した石油パイプライン監視のために開発したのがMQTTの始まりです。当初は独自プロトコルでしたが、2010年にロイヤリティフリーで仕様を公開し、2013年にはOASISによって標準化プロセスが開始されました。
2014年にMQTT 3.1.1がOASIS標準として正式リリースされ、同年ISO/IEC 20922としても承認されました。その後、2019年にはMQTT 5.0がリリースされ、エラーレポートの強化・セッション有効期限・共有サブスクリプション・トピックエイリアスなど多くの機能追加が行われました。
2010年代のIoTブームを経て、AWS IoT Core・Azure IoT Hub・Google Cloud IoT Coreなどの主要クラウドプラットフォームがMQTTを標準サポートしたことで、デファクトスタンダードとして確固たる地位を占めるようになりました。
技術仕様
プロトコル基本仕様
| 項目 | 仕様 |
|---|---|
| トランスポート層 | TCP/IP(MQTT over TLS/SSLも標準) |
| 標準ポート | 1883(非暗号化)、8883(TLS) |
| 最小ヘッダサイズ | 2バイト |
| 最大メッセージペイロード | 256MB(MQTT 3.1.1)、理論上は同じ(MQTT 5.0) |
| QoSレベル | 0・1・2の3段階 |
| プロトコルバージョン | 3.1、3.1.1、5.0 |
QoS(Quality of Service)レベル
MQTTはメッセージ配信の信頼性をQoSで制御します。
- QoS 0(At most once): 送りっぱなし。確認なし。最も軽量だが、ネットワーク障害時にメッセージが失われる可能性がある。センサーデータの高頻度送信など、多少のロストが許容できる用途に向く。
- QoS 1(At least once): 少なくとも1回配信。ブローカーからのACKを待つ。重複配信の可能性がある。
- QoS 2(Exactly once): 正確に1回配信。4ウェイハンドシェイクで重複を防ぐ。最も信頼性が高いが、通信オーバーヘッドも最大。
トピック構造
MQTTのメッセージはトピックと呼ばれる階層的な文字列で分類されます。スラッシュ(/)で階層を区切り、ワイルドカード(+・#)で購読範囲を指定できます。
# トピック例
factory/line1/sensor/temperature
building/floor3/room201/humidity
device/ESP32-001/status
# ワイルドカード購読(+は1階層、#は複数階層)
factory/+/sensor/temperature # 全ラインの温度
factory/line1/# # line1配下の全データ
MQTT 5.0の主要追加機能
- セッション有効期限(Session Expiry Interval): セッションをサーバー上に保持する期間を秒単位で指定
- 理由コード(Reason Code): ACKパケットに詳細なエラーコードを付与
- ユーザープロパティ(User Properties): 任意のキーバリューペアをメッセージに添付
- 共有サブスクリプション(Shared Subscriptions): 負荷分散のため複数クライアントでトピックを共有
- トピックエイリアス(Topic Alias): 長いトピック名を短い数値で代替してペイロードを削減
動作原理
MQTTは「ブローカー」と呼ばれる中継サーバーを介した通信を行います。デバイス(パブリッシャー)はブローカーにメッセージを送信し、ブローカーはそのトピックを購読しているクライアント(サブスクライバー)にメッセージを転送します。
[デバイス A] ---PUBLISH---> [ブローカー] ---PUSH---> [クラウドサーバー]
^
[デバイス B] ---SUBSCRIBE---------|
接続シーケンス
- クライアントがブローカーにTCP接続を確立
CONNECTパケットを送信(クライアントID、KeepAlive、認証情報等を含む)- ブローカーが
CONNACKで応答(接続受理/拒否) - クライアントが
SUBSCRIBEでトピックを登録 - ブローカーが
SUBACKで確認 - パブリッシャーが
PUBLISHでメッセージ送信 - ブローカーがサブスクライバーへ
PUBLISHで転送
Retain機能とLast Will
Retain(保持): ブローカーが最後に受信したメッセージをトピックに保持します。新規サブスクライバーは接続直後に最新値を取得でき、センサーの現在値を即座に知ることができます。
Last Will and Testament(LWT): 接続時にLWTメッセージを登録しておくと、デバイスが異常切断した場合にブローカーが自動的にそのメッセージを発行します。デバイスのオフライン通知に活用されます。
用途・ユースケース
センサーデータ収集
温度・湿度・圧力などのセンサー値を定期的にブローカーへパブリッシュする用途が最も基本的な活用例です。QoS 0または1を使い、低消費電力・低帯域での継続的なデータ収集を実現します。
デバイス制御・コマンド送信
クラウドからデバイスへのコマンド(LED点灯・モーター制御・設定変更)もMQTTで実現できます。デバイスが制御用トピックをサブスクライブしておき、サーバーからコマンドをパブリッシュする構成が一般的です。
OTA(無線アップデート)
ファームウェアの更新通知や更新ファイルのダウンロードURLをMQTTで配信し、デバイス側でファームウェアを取得・適用するOTA更新フローに利用されます。
産業IoT(IIoT)
PLCやセンサーからのデータをMQTTでクラウドへ集約し、生産ラインの監視・品質管理・予知保全を行うユースケースが増加しています。
実装・開発のポイント
ブローカーの選定
| ブローカー | 特徴 |
|---|---|
| Eclipse Mosquitto | 軽量・OSSの定番。組み込みデバイス向けにも使われる |
| EMQX | 高スループット・クラスタリング対応のエンタープライズ向け |
| HiveMQ | エンタープライズ機能豊富・クラウドマネージド対応 |
| AWS IoT Core | AWSサービスとの統合・マネージドサービス |
ESP32でのMQTT実装例
ESP32のArduinoフレームワークでPubSubClientライブラリを用いた実装例です。
#include <WiFi.h>
#include <PubSubClient.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
const char* mqtt_server = "broker.example.com";
const int mqtt_port = 1883;
WiFiClient espClient;
PubSubClient client(espClient);
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
void reconnect() {
while (!client.connected()) {
if (client.connect("ESP32Client")) {
client.subscribe("device/ESP32-001/command");
} else {
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(500);
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) reconnect();
client.loop();
// 温度データをパブリッシュ(1秒ごと)
static unsigned long lastMsg = 0;
if (millis() - lastMsg > 1000) {
lastMsg = millis();
float temperature = 25.3; // センサー読み取り値
String payload = "{\"temperature\":" + String(temperature) + "}";
client.publish("factory/line1/sensor/temperature", payload.c_str());
}
}
セキュリティのポイント
- TLS/SSL暗号化: ポート8883でMQTT over TLSを使用し、通信を暗号化する
- クライアント証明書認証: ユーザー名/パスワードより強固な認証として証明書・PKIを活用
- ACL(アクセス制御リスト): ブローカー側でパブリッシュ・サブスクライブ可能なトピックをクライアントごとに制限
- LWTを活用した異常検知: デバイスの不正切断を素早く検知してアラートを発行
KeepAliveとセッション管理
KeepAlive値は接続を維持するための定期pingの間隔です。接続時に秒単位で指定し、この1.5倍の時間内に通信がないとブローカーは切断とみなします。電波が不安定な環境では適切な値(30〜60秒程度)に調整することが重要です。
他技術との比較
| 比較項目 | MQTT | CoAP | AMQP | HTTP/HTTPS |
|---|---|---|---|---|
| プロトコルモデル | Pub/Sub | Request/Response | Pub/Sub + Queue | Request/Response |
| トランスポート | TCP | UDP | TCP | TCP |
| ヘッダサイズ | 最小2バイト | 4バイト | 数十バイト〜 | 数百バイト〜 |
| 双方向通信 | ○ | △(Observe) | ○ | △(WebSocket併用) |
| 信頼性制御 | QoS 0/1/2 | CON/NON | 強力なACK | TCPに依存 |
| 向き | 軽量IoT全般 | 制約機器 | エンタープライズ | Web全般 |
MQTTは軽量さと実装の容易さ、豊富なクライアントライブラリ(C/Python/Java/JavaScript等)のエコシステムにより、IoT分野で最も広く採用されているプロトコルです。MQTT-SNはUDP上でMQTTに近い機能を提供し、さらに制約の強いセンサーデバイスへの対応を可能にしています。