mqtt Advent Calandar 1日目
はじめに
mqttのアドベントカレンダーを書き始めようと思います。この記事では基本的な事柄を抑えてから、動作環境の説明をしたいと思います。
mqttのアドベントカレンダーを通じて実際に手を動かして確かめていただけたら嬉しいです。
基礎となる知識
PythonやGoなど基本的なプログラムの構造がわかっていれば読めます。動作させるプログラムはできるだけ完全な状態で掲載しようと思います。
mqttプロトコルについて
mqttについて、記事はすでにたくさんありますが改めて、規格書OASIS MQTT Version 3.1.1の記事を引用し、確認します。
MQTT is a Client Server publish/subscribe messaging transport protocol. It is light weight, open, simple, and designed so as to be easy to implement. These characteristics make it ideal for use in many situations, including constrained environments such as for communication in Machine to Machine (M2M) and Internet of Things (IoT) contexts where a small code footprint is required and/or network bandwidth is at a premium.
下記は意訳です
MQTTはPub/Subメッセージトランスポートプロトコルで軽量、オープン、シンプルそして実装が簡単なように設計されています。たくさんの場合において最適ですが、M2MやIoTのような小さいコードフットプリントが求められて、ネットワーク帯域幅が限られているM2MやIoTといった環境における通信に最適です。
だそうです。「シンプルなプロトコル」かどうかは筆者的には疑問ですが、IoT界隈においては割とメジャーなプロトコルです。
実際の例
有名なのはIoTではAWS IoT Coreが対応しているということかど思います。
また、オープンであることでベンダロックインになりづらいところもIoTとしては強みになると思っています。
OSI参照モデル的に、MQTTのプロトコルの下にあるプロトコルとしては「欠損がない」、「順番が入れ替わらない」「双方向のデータが可能」なプロトコルの上ならなんでも良いですが、一般的にはTCP/IPもしくはWebsocketがデファクトスタンダードとなっています。本アドベントカレンダーを通じてはTCP/IPを前提にします。
動作させてみよう
サーバ起動
サーバとしては2つ使います。当初はmochiのみを使用していましたが、規格通りの実装がされていないところが一部あり、mosquittoも使用します。有名なのはmosquittoかと思います。
mosquitto
mosquittoは有名なmqtt brokerでmqttの規格の準拠度合いに関しては信頼感があります。
前提
- Dockerがインストールされていること
version: "3"
services:
mqtt:
image: eclipse-mosquitto
container_name: mqtt
expose:
- 1883
ports:
- 1883:1883
restart: unless-stopped
volumes:
- ./mosquitto/config:/mosquitto/config
set_tcp_nodelay true
listener 1883
allow_anonymous true
[~/qiita/mosquitto]$tree
.
├── docker-compose.yml
└── mosquitto
└── config
└── mosquitto.conf
起動は下記のように行います
canceled
[~/qiita/mosquitto]$docker compose up
[+] Building 0.0s (0/0) docker:desktop-linux
[+] Running 1/0
✔ Container mqtt Created 0.0s
Attaching to mqtt
mqtt | 1764385187: mosquitto version 2.0.18 starting
mqtt | 1764385187: Config loaded from /mosquitto/config/mosquitto.conf.
mqtt | 1764385187: Opening ipv4 listen socket on port 1883.
mqtt | 1764385187: Opening ipv6 listen socket on port 1883.
次に別のブローカーを立ち上げるためCtrl + Cで停止します
mochi-co mqtt broker
mochi-co mqtt brokerはGoで書かれたmqtt brokerです。システムに組み込みやすいインターフェイスやカスタマイズしやすいフックの仕組みを備えています。
前提
- goがインストールされていること
mochi-mqttからソースをダウンロードしてexampleのなかから一番シンプルな設定を起動します。
[~/qiita]$git clone https://github.com/mochi-mqtt/server.git
[~/qiita]$cd server/
[~/qiita/server]$cd cmd
[~/qiita/server/cmd]$go build -o mqtt && ./mqtt
time=2025-11-11T21:42:53.199+09:00 level=INFO msg
...
このあとのクライアントの動作確認のため、端末を開きっぱなしにしておきます。
クライアント作成
Pythonの人気が高いのでPythonとクライアントとしてはメジャーなpaho-mqttで作成することにしました。
準備
前提
- pythonが動作すること
- 特にこだわりはありませんが筆者はuvで動作させています(なんでもよいです)
[~/qiita/1day]$uv init .
[~/qiita/1day]$uv add paho-mqtt
ソースコード(main.py)
端末をいろいろ開くのが面倒なのでマルチスレッドにします。Threadingを使ってPubとSubを非同期にします。
やっていること
- 受信するスレッドを立ち上げて、次に1秒ごとに5回送信して終了します
- daemon=Trueになっているのでメインの送信プログラムが終了したら受信するスレッドも自動的に終了します
import paho.mqtt.client as mqtt
import threading
import time
BROKER = "localhost"
TOPIC = "test/topic"
# ======================
# Subscriber
# ======================
def on_message(client, userdata, msg):
print(f"[受信] {msg.topic}: {msg.payload.decode()}")
def subscriber():
sub = mqtt.Client(client_id="sub-client", callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
sub.on_message = on_message
sub.connect(BROKER, 1883, 60)
sub.subscribe(TOPIC)
sub.loop_forever()
# =================
# Publisher
# =================
def publisher():
pub = mqtt.Client(client_id="pub-client", callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
pub.connect(BROKER, 1883, 60)
for i in range(5):
msg = f"Hello {i}"
pub.publish(TOPIC, msg)
print(f"[送信] {msg}")
time.sleep(1)
pub.disconnect()
# ======================
# メイン処理
# ======================
if __name__ == "__main__":
# 受信スレッドを起動
t = threading.Thread(target=subscriber, daemon=True)
t.start()
# 少し待ってから送信
time.sleep(1)
publisher()
# 終了待ち
time.sleep(2)
実行
mochi mqttを相手にしてデータを送信し、サブスクライバーから受信されることを確認しましょう。
[~/qiita/1day]$uv run main.py
[送信] Hello 0
[受信] test/topic: Hello 0
[送信] Hello 1
[受信] test/topic: Hello 1
[送信] Hello 2
[受信] test/topic: Hello 2
[送信] Hello 3
[受信] test/topic: Hello 3
[送信] Hello 4
[受信] test/topic: Hello 4
まとめ
mqttの概要を説明し、簡単に送受信を試してみました。
アドベントカレンダーを通じて、わからないところを調べながら実際に手を動かして試すような記事を書いていければいいなと思っています。
著作権情報
Copyright © OASIS Open 2014. All Rights Reserved.
Available at: https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html