[AWS IoT Core] MQTT v5 を使用してレスポンスコードの確認を実装して見ました

2022.12.03

1 はじめに

CX 事業本部のデリバリー部の平内(SIN)です。

AWS re:Invent 2022 で発表された、AWS IoT Core での MQTT v5 対応に反応して、色々入門しています。

今回は、MQTT v5 が返す応答に含まれるレスポンスコードについて確認してみました。

なお、現時点(2022/11/30)では、AWS で提供される SDK は、MQTT v5 に対応していないため、サンプル作成には、paho.mqtt を使用させて頂きました。

2022/12/05 追記 Python SDK が開発者プレビューで MQTT v5 対応となりました。
参考:https://dev.classmethod.jp/articles/aws-iot-core-mqtt-v5-sdk-for-python

2 レスポンスコード

MQTT v3.1 では、正常系、異常系ともに、必要最低限の情報以外の情報を返すことはできませんでしたが、MQTT v5 になってレスポンスコードにより、応答(Sussecc/Error)の理由が詳細に表現されるようになりました。

AWS IoT Core では、以下の Response Code が定義されています。

Value Hex Reason Codename Command
0 0x00 Success, Granted QoS 0 CONNACK , PUBLISH, SUBACK, UNSUBACK
1 0x01 Granted QoS 1 SUBACK
2 0x02 Granted QoS 2 SUBACK
128 0x80 Unspecified error CONNACK , PUBLISH, SUBACK, UNSUBACK
129 0x81 Malformed Packet DISCONNECT
130 0x82 Protocol Error DISCONNECT
133 0x85 Client Identifier not valid CONNACK
134 0x86 Bad User Name or Password CONNACK
135 0x87 Not authorized CONNACK , PUBLISH, DISCONNECT, SUBACK
139 0x8B Server shutting down DISCONNECT
141 0x8D Keep Alive timeout DISCONNECT
142 0x8E Session taken over DISCONNECT
143 0x8F Topic Filter invalid DISCONNECT ,SUBACK, UNSUBACK
144 0x90 Topic Name invalid CONNACK , PUBLISH, DISCONNECT
145 0x91 Packet identifier in use PUBLISH ,SUBACK, UNSUBACK
147 0x93 Receive Maximum exceeded DISCONNECT
148 0x94 Topic Alias invalid DISCONNECT
151 0x97 Quota exceeded CONNACK , PUBLISH ,DISCONNECT ,SUBACK
152 0x98 Administrative action DISCONNECT
155 0x9B QoS not supported CONNACK , DISCONNECT
161 0xA1 Subscription Identifiers not supported DISCONNECT

https://docs.aws.amazon.com/iot/latest/developerguide/mqtt.html#mqtt5

3 実装例

以下が、実装したコードです。

Connect の後、Topic Alias を指定して、3 回の publish を行っています。

import ssl
import os
import time
import paho.mqtt.client as mqtt
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes

endpoint = "xxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com"
port = 8883

dir = os.path.dirname(os.path.abspath(__file__))
certs = {
    "cafile": "{}/certificates/AmazonRootCA1.pem".format(dir),
    "certfile": "{}/certificates/client-cert.pem".format(dir),
    "keyfile": "{}/certificates/private-key.pem".format(dir),
}

def on_connect(client, user_data, flags, reason_code, properties=None):
    print("on_connect")

def on_publish(client,userdata, result,properties=None):
    print("on_publish")

def on_disconnect(mqttc, user_data, reason_code, properties=None):
    print("on_disconnect reason: {}".format(reason_code))
    exit()


def main():
    client = mqtt.Client("client_id", protocol = mqtt.MQTTv5)
    client.tls_set(certs["cafile"],
            certfile=certs["certfile"],
            keyfile=certs["keyfile"],
            cert_reqs=ssl.CERT_REQUIRED,
            tls_version=ssl.PROTOCOL_TLSv1_2,
            ciphers=None)

    client.on_connect = on_connect
    client.on_disconnect = on_disconnect
    client.on_publish = on_publish

    client.connect(endpoint, port, properties = None)
    client.loop_start()

    time.sleep(1)

    properties = Properties(PacketTypes.PUBLISH)
    topic = "sensors/device1"
    payload = "message"

    # 1回目のpublish (Topic Alias = 7)
    properties.TopicAlias = 7
    client.publish(topic, payload, qos=1, properties=properties)
    time.sleep(1)

    # 2回目のpublish (Topic Alias = 8)
    properties.TopicAlias = 8
    client.publish(topic, payload, qos=1, properties=properties)
    time.sleep(1)

    # 3回目のpublish (Topic Alias = 9)
    properties.TopicAlias = 9
    client.publish(topic, payload, qos=1, properties=properties)
    time.sleep(1)


if __name__ == "__main__":
    main()

この時のログ出力は、以下のようになります。

% python3 index.py
on_connect
on_publish
on_publish
on_disconnect reason: Topic alias invalid

AWS IoT Core では、Topic Alias の制限(デフォルト値)が、8なので、8以上を指定した 3 回目の publish は、成功せず、connect自体が切断されています。 そして、disponnect 時に、その切断理由「Topic alias invalid」が、reason_code で確認できています。

なお、エラー事由は、AWS IoT Core から返ってきているものであり、特に何か実装しているわけではありません。

4 最後に

Reason Code の一覧を見ると、とりわけ異常系において、失敗の理由が各種定義されているため、この Reason Code を利用して実装することで、エラー処理がよりシンプルかつ、漏れなく記述できるようになりそうです。

なお、拡張されたプロパティ領域の、User Propertyで、こちらでシステム固有の理由などを返すことも有効でしょう。 [AWS IoT Core] MQTT v5 を使用してユーザープロパティを実装して見ました

5 参考リンク


Introducing new MQTTv5 features for AWS IoT Core to help build flexible architecture patterns
[AWS IoT Core] MQTT v5 を使用してリクエスト・レスポンス パターンを実装して見ました
[AWS IoT Core] MQTT v5 を使用してユーザープロパティを実装して見ました
[AWS IoT Core] MQTT v5 を使用してトピック・エイリアスを実装して見ました
[AWS IoT Core] MQTT v5 を使用してメッセージ及び、セッション有効期限とクリーンスタートを実装して見ました