2025年7月28日月曜日

paho-mqtt でタイムアウトを設定する方法

paho-mqtt でタイムアウトを設定する方法

概要

前回 paho-mqtt v2 の使い方を紹介しました
今回は connect と publish 時のタイムアウトを設定する方法を紹介します

環境

  • macOS 15.5
  • Python 3.12.11
  • paho-mqtt 2.1.0

サンプルコード

  • vim app.py
from paho.mqtt.client import Client
from paho.mqtt.enums import CallbackAPIVersion


class CustomClient(Client):
    def __init__(self):
        super().__init__(callback_api_version=CallbackAPIVersion.VERSION2)

    def custom_on_disconnect(self, client, userdata, flags, reason_code, properties):
        print("on_disconnect")
        print(client)
        print(userdata)
        print(flags)
        print(reason_code)
        print(properties)

    def custom_on_publish(self, client, userdata, mid, reason_code, properties):
        print("on_publish")
        print(client)
        print(userdata)
        print(mid)
        print(reason_code)
        print(properties)
        self.disconnect()


if __name__ == "__main__":
    print("start")
    client = CustomClient()
    client.on_disconnect = client.custom_on_disconnect
    client.on_publish = client.custom_on_publish
    # 接続タイムアウトを60秒に設定
    client.connect_timeout = 60
    # ここで60秒待つことを確認する
    client.connect("127.0.0.1", port=1883, keepalive=60, bind_address="")
    info = client.publish(
        topic="default", payload='{"payload": "hoge"}', qos=0, retain=False
    )
    # wait_for_publish は、publish の完了を待つためのメソッド、ACKを待ち来ない場合はタイムアウトする
    info.wait_for_publish(timeout=60)
    print("end")

解説

内部的には Client クラスの self._connect_timeout で接続時間のタイムアウトを管理しておりデフォルトでは 5.0 秒になっています

socket.create_connection(addr, timeout=self._connect_timeout, source_address=source)

もし上書きしたい場合は setter 用の connect_timeout があるのでこれを使います
もし connect 時に指定したブローカーに接続できない場合には timeout 秒待ってからエラーになります

publish 時のタイムアウトは接続時とは少し違い ACK を受け取るまでのタイムアウトを指定します
基本的に publish は非同期なので送ったら送りっぱなしになります
もし送信できたかの確認をしたい場合は ACK 信号を受け取るようにします
その ACK 信号を受け取るためのメソッドが wait_for_publish になっておりその信号を受け取るまでのタイムアウトを指定することができます

最後に

paho-mqtt でタイムアウトを設定する方法を紹介しました
基本的にブローカーに接続できれば publish はできるはずなので connect 側のタイムアウトを設定すれば OK かなと思います

Subscribe などでブローカーと常に接続しておく必要がある場合は timeout + keepalive で接続を確保するようにしておきましょう

参考サイト

0 件のコメント:

コメントを投稿