MQTTを調べている

`この項目は、書きかけの項目です。この項目を加筆・訂正などしてくださる協力者を求めています。`

# はじめに

MQTTに関しては、ここに[MQTT Essentials](https://www.hivemq.com/mqtt/)という素晴らしいリソースがある。なにはともあれこれを読まないと始まらない。


# MQTT

MQ Telemetry Transport（MQTT）はブローカーベースの軽量なパブリッシュ / サブスクライブ・メッセージング・プロトコルであり、オープンでシンプル、軽量で、実装が簡単。これらの特性により、ネットワークが高価である、帯域幅が狭い、または信頼性が低い、プロセッサまたはメモリリソースが限られている組み込みデバイスで実行する、といったような制約のある環境での使用に最適（であるが、それだけに限定はされない）

プロトコルが軽量だからIoT向けだよ、いうところが強調されがちだが、個人的にMQTTの真の強みは「不安定なネットワークでもメッセージをちゃんと届ける」ところだと思う。そのための仕組みがいろいろある。ブローカーを中心とするアーキテクチャなので、極端な話、ネットワークが不安定でTCPコネクションが切れても、その間メッセージをブローカーに貯めておいて、再接続時に再送するとかできる。コネクティッド・モビリティーとかでつかうとピッタリ。

現在の最新バージョンは`5.0`っぽい。`3.1.1`からの変更は以下に。
[MQTT Version 5.0 でできること](https://tech-blog.optim.co.jp/entry/2020/09/25/110000)。

# 特徴

- 1対多のメッセージ配信とアプリケーションからの分離を提供する、Pub / Sub メッセージパターン
- ペイロードの内容（Plaintext, JSON, XML, etc）に依存しないメッセージ転送方式
- TCP/IPによる基本的なネットワーク接続を提供
- メッセージ配信の3つのサービスレベル：

|   レベル   | 内容 |
|:---------|:----|
|QoS0<br>At most once<br>（最大1回）|メッセージは下層となるTCP/IPネットワークに基づきベストエフォートで配信。メッセージの損失または重複が発生する可能性がある。このレベルは、たとえば、次のデータがすぐに送信されるため、個々の測定値が失われても問題にならない（温度測定などの）環境センサーデータで使用される|
|QoS1<br>At least once<br>（少なくとも1回）|メッセージは確実に到着するが、重複が発生する可能性がある|
|QoS2<br>Exactly once<br>（正確に1回）|メッセージが1回だけ到着することが保証される。メッセージが重複したり失われたりすると誤った料金が適用される可能性がある、課金システムなどで使用でされる。実装の費用対効果が悪いと考えられがちで、サポートしない実装も多い。|

- 小さな転送オーバーヘッド（固定長ヘッダーはわずか2バイト）およびネットワークトラフィックを削減するためプロトコル交換を最小化
- Retain Message, LWT（Last Will and Testament）, Persisstent Sessionなど不安定なネットワークでもメッセージを届けようという思いの伝わる仕様
- ペイロードの最大は 256M byte[^1] （プロトコル仕様上の話で個々の実装は知らない）
- 名前にMQとあるが、いわゆるMessage Queueの機能はない（メッセージの順序保証などはされない）

[^1]: 256MBは結構でかいな

# 標準化

- もともと IBM と Eurotech 社が策定
- 現在は [OASIS](http://mqtt.org/2013/02/mqtt-proposed-as-an-oasis-standard) が標準化を行っている
- 公開されている仕様
    - [MQTT3.1](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html)
    - [MQTT5.0](https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html)

# さくっとわかりたい

- [~~MQTT の仕様~~](http://devcenter.magellanic-clouds.com/learning/mqtt-spec.html)
- [MQTTについてのまとめ](http://tdoc.info/blog/2014/01/27/mqtt.html)
- [IoT時代を支えるプロトコル「MQTT」（前編）](https://codezine.jp/article/detail/8000)

# アプリケーション

センサデータ収集系かチャットアプリ系で使用されることが多いようだ。MQTT標準ではないが、商用のMQTTブローカーはHTTPやWebScoketをサポートするものも多く、デバイスだけでなく、Webやモバイルアプリもブローカーに繋げてアプリケーションを作れるものが多い。


# 実装

様々な言語での実装がある。中途半端にリストするのはやめて [Awesome MQTT](https://github.com/hobbyquaker/awesome-mqtt) へのリンクとしたい。やや更新が滞っている感があるので、Pull requestも見ると良い。

# リンク集

- [MQTT Essentials](https://www.hivemq.com/tags/mqtt-essentials/)：英語だがMQTTの仕様とベストプラクティスがうまくまとまっている。オススメ
    - [MQTT3.1.1](https://www.youtube.com/watch?v=jTeJxQFD8Ak)
    - [MQTT5.0](https://www.youtube.com/watch?v=RPf_rr1ZDvE)
- [MQTT とはなんだったのか](https://gist.github.com/voluntas/e0a90f3e22316144ed3a)：2017年の時点の情報。実際の実装経験から、MQTTの勘違いしやすいポイントがまとまっている。すばらしい。
- [MQTTのパケットを覗いてみた(1)](https://mm011106.github.io/2014/12/20/mqtt-packets/)
- [Understanding the MQTT Protocol Packet Structure](http://www.steves-internet-guide.com/mqtt-protocol-messages-overview/)：パケットやプロトコルの図解がよい
- [MQTTバージョン5の概要 2018年版](https://qiita.com/toast-uz/items/b9f933b72467981562a3)：パケットやプロトコルの図解がよい。パケットフォーマットはMQTT3と5の比較で解説してありわかりやすい
- [MQTT Version 3.1.1 をふりかえる](https://tech-blog.optim.co.jp/entry/2019/08/20/163000)
- [MQTTバージョン5の概要 第5回 考察 MQTTはIoTにおいてHTTP/RESTを完全に駆逐する](https://qiita.com/toast-uz/items/00cb2050ae68b45bb931)：MQTT5.0がMQTT3の短所をどう解決したか、またHTTPと比べてどうかの考察が良い

# サービス

- [CloudMQTT](https://www.cloudmqtt.com/)：フリー版が SOLD OUT とかになってておしい...
- [ユーザー登録不要、無料ですぐに使えるMQTTブローカを提供しています](https://mqtt.uko.jp/)
- 以前に時雨堂さんが Sango というサービスを作っていたようだ（今はない）
- [shiftr.io](https://shiftr.io/)：これ、メッセージを可視化してくれるようなサービスか？あとで触ってみよう。
- [Adafruit IO](https://io.adafruit.com/)

# シリーズ

- [DockerとMosquitto™でMQTTに触れる](https://qiita.com/narutaro/items/e48def9dca38036f01f9)
- [MQTTを調べている](https://qiita.com/narutaro/items/1837e392ef3255c9d6b2)
- [MQTTの通信を可視化する - shiftr.io](https://qiita.com/narutaro/items/5a9102f4a2e29e4525db)
- [Azure IoT Hub に Mosquitto™ から MQTT なげてみる](https://qiita.com/narutaro/items/1a16ff1321f5044afaf0)
- [MQTT.js でブラウザから MQTTブローカ に Pub/Sub する](https://qiita.com/narutaro/items/2819ce79eb82a87357eb)