MyEnigma

とある自律移動システムエンジニアのブログです。#Robotics #Programing #C++ #Python #MATLAB #Vim #Mathematics #Book #Movie #Traveling #Mac #iPhone

ロボットエンジニアのためのMQTT (Message Queue Telemetry Transport) 入門


MQTT Essentials - A Lightweight IoT Protocol

目次

はじめに

ロボットによく使われる通信プロトコルとしては、

ROSで使われるXML-RPC通信

ysuga.net

ROS2で使われるDDS(Data Distribution Service),

ja.wikipedia.org

WEBで広く利用されるHTTP

myenigma.hatenablog.com

Googleが開発しているgRPC

myenigma.hatenablog.com

などがありますが、

MQTT (Message Queue Telemetry Transport) もよく利用されます。

 

今回の記事では、MQTTの概要と

MQTTを利用した通信のサンプルコードについて紹介したいと思います。

MQTTとは?

MQTTは、IBMとEurotechが1999年に開発し、標準化された、通信プロトコルです。

www.ibm.com

kfep.jp

 

MQTTはOASISという団体が管理しており、

www.oasis-open.org

2019年の3月にv5.0が発表されました。

docs.oasis-open.org

 

データ量や、消費電力が小さく、

IoT向けの通信プロトコルであると言われています。

 

様々なクラウドサービスも、MQTTの通信向けのサービスを提供しています。

これらのサービスを利用することで、

後述するMQTTのMessage Brokerをクラウドに置いて、

IoT機器の通信データを処理することができます。

docs.aws.amazon.com

docs.microsoft.com

cloud.google.com

 

MQTTの特徴

MQTTの特徴をまとめると下記のようになります。

Pub/Sub型の通信により1 対多の非同期通信が可能

MQTTでは、MQTT Brokerという、

メッセージサーバを仲介して、Pub/Sub型の通信を実現します。

このMQTT BrokerはROS1で言うところのROS coreと同じような役割です。

 

Pub/Sub型の通信であるため、1対多、多対1、多対多などの、

様々な形の通信が可能です。

またROSbagと同様、バスに流れるすべてのデータをロギングしたりなどが、

簡単に実現できます。

 

また、Pub/Sub型の通信であるため、

HTTPなどの同期通信とは異なり、

非同期の通信が可能です。

これにより、通信が不安定な環境でも、

安定した処理を実現することができます。

また、データの受信側のことを考慮することなく、

データの送信側はデータを送信することができます。

これはIoTには非常に良い通信モデルです。

 

また、下記の記事にある通り、Brokerの処理能力にもよりますが、

数万の接続数レベルであれば、単一のBrokerで通信が可能なようです。

qiita.com

 

MQTTの通信モデルに関しては、下記を参照ください。

devcenter.magellanic-clouds.com

 

通信データ量が小さい

IoTのための通信プロトコルとして設計されたため、

通信に必要なプロトコルヘッダが小さくなっています。

例えば、HTTPとMQTTのプロトコルヘッダサイズを比べると

HTTPは最低でも50byte必要なのに対して、

MQTTは2byteから通信可能となります。

 

通信データのペイロードが大きい場合、

このヘッダサイズの差は無視できますが、

小さいペイロードのデータを、高頻度で送信すると

大きな差になってきます。

 

消費電力や計算スペックが小さい

前述のように、MQTTは通信のデータサイズをできるだけ

小さくするように設計されているので、

通信に必要な消費電力や、計算量が小さいという特徴があります。

 

これによりバッテリーの消費を抑えたいモバイルや

小さいpayloadのデータを、高頻度で送信する必要があるIoT向けの通信に

適していると言われます。

 

データの順序と欠落がないことが保証される。

一般的に、MQTTは、TCPとWebSocket上で利用されるため、

データの順序と欠落が無いことが保証されます。

 

Durable SubscriptionとRetain

MQTTには、Durable Subscriptionという機能があります。

これは、クライアントとブローカー間が、

なにかの理由で通信できないときに、

通信のデータをブローカー内で保持する機能です。

これにより、再度通信可能になった時に、

自動でトピックの送受信が再開されます。

また、切断していた間に発行されていたメッセージも送受信されます。

 

しかし、一つ注意点として、MQTTでは、

各トピックの通信毎に、Durable Subscriptionを設定できません。

一つのクライアントとブローカーとのコネクション毎に

Durable Subscriptionを設定できます。

 

また、Retainという機能を使うことにより、

トピック毎の最新のメッセージをサーバに保存することができます。

これにより、クライアントが通信を開始したときに、

そのトピックの最新のデータを受信することができます。

現時点では、30 分間トピック毎の最新メッセージが保存できます。

 

メッセージの伝送保証(QoS)

MQTTでは、通信状況が悪い環境で便利な、

メッセージの伝送保証(Quality of Service)を設定することができます。

 

現状のMQTTでは、QoSとして下記の3 つのレベルを設定することができます。

Level 伝送保証 確認応答 メッセージの再送 メッセージの重複 主な用途
0 最大1回 センサーデータなど、あるデータが失われても次のデータを受信できるもの
1 少なくとも1回 ある機能のON-OFF情報など、重複しても問題ないが、必ず必要なデータ
2 かならず1回 課金システムなど、必ず一回送信されるべきもの

 

上記のQoSのレベルが上がるほど、通信のオーバヘッドは高くなります。

また、このQoSのレベルは、

PublisherとBroker間、SubscriberとBroker間のそれぞれで設定することができます。

 

クライアント障害時などに、Will(遺言)を送信することが可能

MQTTでは

クライアントとBroker間の接続が意図しない理由で途切れた際に、

他のクライアントに登録したメッセージを送ることができます。

これがWill(遺言)機能です。

このWillには、任意のトピック名やQoLを設定することができます。

 

MQTTを使う時に注意すべきこと

前述の通り、MQTTは様々な良い特徴がありますが、

注意すべきところもいくつかあります。

 

しかし、下記の問題点に関しては、

いくつかは最新のv5.0の仕様で改善されています。

qiita.com

 

一度に送れる最大データサイズとトピック名の最大サイズ

下記の記事の通り、MQTTの仕様として、

一度におくれる最大データサイズは268MB,

トピック名の長さは65kBに設定されています。

stackoverflow.com

これより大きなデータを送信したい場合は、

HTTPなど別の通信方式を使うか、

複数のMQTTのパケットをアプリケーション側でつなげる処理が必要です。

 

データフォーマットを規定しない(No Interoperability)

MQTTはデータのバイト列を送受信するのみなので、

データの構造化に関しては、アプリケーション側で実装する必要があります。

gRPCにおけるProtocol bufferのように、

データのシリアライズまでは含まれていないため、

別途検討が必要です。

 

トピックを検索する機構がない

MQTTではデータの通信をトピック名で実施しますが、

Subscriber側が現在利用できるトピックを検索するような機能は規定しておらず、

別途実装する必要があります。

 

常にTCPのコネクションをkeepし続ける必要がある

MQTTでは、TCPを利用して通信をするため、

TCPのコネクションをキープし続ける必要があるため、

Sleepなどをすることが難しいという問題があります。

 

セキュリティに関しては別途検討が必要

MQTTでは、通信の暗号化やセキュリティに関しては、

特に規定は無いため、TSLなどを使って、

別途対策が必要です。

 

MQTTを使った実用例

下記のようなアプリケーションでMQTTが利用されているようです。

  • 油田パイプラインの監視のための、衛星との通信

  • Facebook Messenger (開発当初)

  • ロボットの遠隔操作

  • 自動車同士(V2V)、自動車とスマホアプリの通信

  • 医療機器の通信

 

MQTT通信のサンプルコード

MQTTを使った通信のクライアントコードを作成したい場合、

下記のeclipse pahoというプロジェクトで公開されている

公式ライブラリを利用することができます。

www.eclipse.org

 

また、このeclipse pahoプロジェクトでは、

URL: mqtt.eclipse.org

Port: 1883

で、MQTT Brokerのサービスを公開しています。

こちらを使って、インターネット越しの

MQTTの通信のテストを実施することができます。

 

今回の記事では、

様々な方法でMQTTで通信する方法を紹介します。

こちらで公開しているサンプルコードは、

下記のGitHubリポジトリで公開しています。

github.com

 

コマンドラインツール

公式のMQTTクライアントと同じEclipse foundationが公開している

Mosquittoというコマンドラインツールを使うことで、

コマンドライン上でMQTTの通信が可能になります。

mosquitto.org

 

Macでは、brewでインストールできます。

$ brew install mosquitto

 

実際に簡単な通信をしてみると、

まず、下記のコマンドでMQTTのメッセージブローカーサービスを起動し、

$ brew services start mosquitto

下記のコマンドでSubscriberを起動した状態で、

$ mosquitto_sub -t "sample/demo"

下記のコマンドでPublisherからHello worldをpublishすると、

$ mosquitto_pub -t "sample/demo" -m "hello world!"

Subscriberのコンソールでメッセージが確認でき、

通信できることが確認できると思います。

 

Python

PythonでMQTT通信をしたい場合は、

下記の公式ライブラリを利用できます。

www.eclipse.org

github.com

  下記のコマンドでインストールできます。

$ pip install paho-mqtt

 

Publisherは下記のように実装できます。

今回はローカルのBrokerではなく、

前述のEclipse Pahoの公開Brokerを利用しています。

import paho.mqtt.client

def on_connect(client, userdata, flags, respons_code):
    topic = 'sample/demo'
    print('subscribe %s' % topic)
    client.subscribe(topic)

def on_message(client, userdata, msg):
    print(msg.topic + ':' + str(msg.payload))

def main():
    client = paho.mqtt.client.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect('mqtt.eclipse.org', 1883)
    client.loop_forever()


if __name__ == '__main__':
    main()

 

Subscriberは下記のように実装できます。

import paho.mqtt.client

def on_connect(client, userdata, flags, respons_code):
    topic = 'sample/demo'
    print('subscribe %s' % topic)
    client.subscribe(topic)

def on_message(client, userdata, msg):
    print(msg.topic + ':' + str(msg.payload))

def main():
    client = paho.mqtt.client.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect('mqtt.eclipse.org', 1883)
    client.loop_forever()


if __name__ == '__main__':
    main()

 

参考資料

MQTT とはなんだったのか · GitHub

qiita.com

tech-blog.optim.co.jp

www.rtautomation.com

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com


MQTT Essentials - A Lightweight IoT Protocol

 

MyEnigma Supporters

もしこの記事が参考になり、

ブログをサポートしたいと思われた方は、

こちらからよろしくお願いします。

myenigma.hatenablog.com