Topic Alias
Topic AliasはPublishで送信するトピックにエイリアスを設定することができる機能です。mqtt5で追加されました。
エイリアス(alias)とは, 別名、通称のこと
メリットとして、何度も使うトピックに対して、1回目の送信でエイリアスを設定することで、それ以降、送信する際のパケット容量を節約することができます。
サーバー、クライアント双方で受け入れ可能なTopic Aliasの最大値はConnect/Connackのvariable header/Properties/Topic Alias Maximumに乗せて取り交わします。
実践
サーバ側:
- サーバからのTopic Alias Maximumを確認します
- クライアントからもTopic Alias Maximumとして受け入れ可能な最大値5を設定します
- 最初のPublishにプロパティとしてTopicAliasを設定すると、それ以降、Topicに何も設定しなくてもTopicAliasに番号を設定するだけで、設定したトピック(test/topic)として送信できるはずです
topicalias.py
import paho.mqtt.client as mqtt
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes
import threading
import time
BROKER = "localhost"
TOPIC = "test/topic"
TOPIC_ALIAS = 1
# ============================
# Subscriber
# ============================
def on_message(client, userdata, msg):
print(f"[受信] {msg.topic}: {msg.payload.decode()}")
def on_connect_sub(client, userdata, flags, reason_code, properties):
print("[Subscriber CONNACK] Connected")
# TopicAliasMaximum を安全に取得
max_alias = getattr(properties, "TopicAliasMaximum", None)
if max_alias is None:
print(" サーバは TopicAliasMaximum を返さなかった")
else:
print(f" サーバが受け入れる TopicAliasMaximum = {max_alias}")
def subscriber():
# CONNECT プロパティ(Subscriber が受信可能な TopicAlias の最大値)
sub_props = Properties(PacketTypes.CONNECT)
sub_props.TopicAliasMaximum = 10
print(f"[Subscriber CONNECT] TopicAliasMaximum={sub_props.TopicAliasMaximum}")
sub = mqtt.Client(
client_id="sub-client",
protocol=mqtt.MQTTv5,
callback_api_version=mqtt.CallbackAPIVersion.VERSION2
)
sub.on_connect = on_connect_sub
sub.on_message = on_message
sub.connect(BROKER, 1883, 60, properties=sub_props)
sub.subscribe(TOPIC)
sub.loop_forever()
# ============================
# Publisher
# ============================
def on_connect_pub(client, userdata, flags, reason_code, properties):
print("[Publisher CONNACK] Connected")
max_alias = getattr(properties, "TopicAliasMaximum", None)
if max_alias is None:
print(" サーバは TopicAliasMaximum を返さなかった(MQTT 3.1.1 / 未対応)")
else:
print(f" サーバが受け入れる TopicAliasMaximum = {max_alias}")
def publisher():
# CONNECT プロパティ(Publisher 側の TopicAliasMaximum)
pub_props = Properties(PacketTypes.CONNECT)
pub_props.TopicAliasMaximum = 5
print(f"[Publisher CONNECT] TopicAliasMaximum={pub_props.TopicAliasMaximum}")
pub = mqtt.Client(
client_id="pub-client",
protocol=mqtt.MQTTv5,
callback_api_version=mqtt.CallbackAPIVersion.VERSION2
)
pub.on_connect = on_connect_pub
pub.connect(BROKER, 1883, 60, properties=pub_props)
# ---- ① 最初の Publish(Topic + Alias で登録) ----
props = Properties(PacketTypes.PUBLISH)
props.TopicAlias = TOPIC_ALIAS
first_msg = "First Hello (with Topic)"
pub.publish(TOPIC, first_msg, qos=0, properties=props)
print(f"[送信] {first_msg} (Topic付き / Alias={TOPIC_ALIAS})")
time.sleep(1)
# ---- ② 2回目以降(Topic="" + Alias) ----
for i in range(3):
props2 = Properties(PacketTypes.PUBLISH)
props2.TopicAlias = TOPIC_ALIAS
msg = f"Hello by Alias {i}"
pub.publish("", msg, qos=0, properties=props2)
print(f"[送信] {msg} (Topicなし / Alias={TOPIC_ALIAS})")
time.sleep(1)
pub.disconnect()
# ============================
# Main
# ============================
if __name__ == "__main__":
# Subscriber(常時受信)
t = threading.Thread(target=subscriber, daemon=True)
t.start()
# Subscriber 接続後に Publisher 実行
time.sleep(1)
publisher()
time.sleep(2)
[~/qiita/client]$uv run topicalias.py
[Subscriber CONNECT] TopicAliasMaximum=10
[Subscriber CONNACK] Connected
サーバは TopicAliasMaximum を返さなかった
[Publisher CONNECT] TopicAliasMaximum=5
[送信] First Hello (with Topic) (Topic付き / Alias=1)
[受信] test/topic: First Hello (with Topic)
[送信] Hello by Alias 0 (Topicなし / Alias=1)
[受信] : Hello by Alias 0
[送信] Hello by Alias 1 (Topicなし / Alias=1)
[受信] : Hello by Alias 1
[送信] Hello by Alias 2 (Topicなし / Alias=1)
[受信] : Hello by Alias 2
[~/qiita/client]$
- トピックなしでもAliasを設定して送信できることが確認できました
- TopicAliasMaximumは実験で使用したブローカー(mochi-co)では設定されていませんでした
まとめ
Topic Aliasについて確認し、実際に使ってみました。IoTの場面では容量を節約できるのは嬉しい場合があるのではないでしょうか?