Edited at

IoT時代のプログラミング(主にMQTTについて)

More than 1 year has passed since last update.


IoTにおけるソフトと特徴


  • Arduino


    • イベント駆動



  • MQTT


    • 軽量プロトコル

    • publish/subscribe型のMQ





Arduinoとは


  • 無償で使えるマイコン用プログラム作成アプリ


    • マイコン毎にアドオンがある(ex, ESP8266)



  • スケッチ(=プログラム)はsetup/loopで構成


    • setup: 電源入り後一度だけ呼ばれる

    • loop: (電源切るまで)繰り返し呼ばれる



  • 提供されているスケッチ例を改造して動かす

$brew cask install arduino



MQTTとは


  • Message Queuing Telemetry Transport

  • 非常に軽量なプロトコル


    • 2000年代初めに登場し標準化

    • TCP/IP上で動く



  • publish/subscribe型のメッセージ転送

  • IoT/モバイルに適する


    • センサーデバイス

    • Facebook Messengerで使われている





HTTPよりも


  • 軽量(ヘッダが最小2バイト)1・優れた処理速度・省電力


    • HTTPではヘッダのオーバーヘッドが高い

    • AgostoのテストによるとHTTPSの10倍以上オーバーヘッドが低い



  • IoTの利用場面に適している


    • 貧弱な電波環境(通信帯域制限)

    • バイト毎に料金・バッテリーを消費する環境





HTTPヘッダとの比較

$curl --head https://www.yahoo.co.jp/

HTTP/1.1 200 OK
Date: Tue, 18 Jul 2017 18:10:57 GMT
(中略)
$curl --head https://www.yahoo.co.jp/ | wc -c
703


  • 最小まで減らすとしたらHTTP/1.1 200 OKの15byte

  • MQTTでは最小2バイト1

  • 通信量が膨大になるほどこの10byteの差が意味を持つ



暗号化


  • TLSを使った暗号接続が可能


    • port: 8883



  • ただし通信毎に認証が必要なので軽量さは失われる2


    • メッセージ全体のサイズが大きいならヘッダの10バイト差は誤差

    • MQTTとHTTPsどちらが適しているか要検討





HTTPとのすみ分け

protocol
適した用途

http
1対1で画像など大きなデータをやりとりしたい, secureな通信がしたい

mqtt
複数台から小さいデータを大量にもらいたい



Publish/Subscribe

pub-sub.jpg


  • メッセージの送信者(publisher)が特定の受信者(subscriber)に直接メッセージを送信しない

  • メッセージのやりとりにはBrokerと呼ばれる中継serverが必要


    • サーバーがメッセージを保管するため受信側の状態に関係なくメッセージを送れる


      • オフラインでもOK



    • publisher/subscriberがMQTT client



  • 接続時のデバイスIDが被ると古い接続が切れる

出典: Securing MQTT - BuildingIoT 2016 slides



message(= topic + data)

pub-sub-model.png


  1. subscriberはbrokerへtopicの受信を申し込む


    • 接続後一度だけで良い



  2. brokerはtopicへのpublishがあると接続中のtopicを申し込んだsubscriberへmessageを送信


    • 過去分は送れない(最後のmessageはオプションで受け取れる)

    • publisherにsubscriberのアクセス情報は通知されない



出典: Paho Python client for MQTT and G-code Visualization Talks, Chennaipy



topic


  • 一般的に/(スラッシュ)で階層化3


    • ex, tokyoA/temp



  • ワイルドカード(#,+)

  • mosquittoなどの一部ブローカーにはACL機能有り



QoS


  • client間のメッセージ到達保証レベル(Quality of Service)

  • 通常は0、コントロール系のメッセージは1以上、が基本


    • 1以上はbrokerでstoreが必要



  • Kafkaの例だが佐伯さんのスライドがわかりやすい

level
desc
example

0
At most once(メッセージ到達保証無)
subscriberの受信失敗時のケアがない、など

1
At least once(届くけど重複するかも)
subscriberのACK受信失敗時に再送、など

2
Exactly once(確実に重複無く届ける)
transaction制御、速度低下



(閑話)ログの質が精度を分ける


  • 米テックジャイアントのログ収集は実は雑


    • 重複やロストは気にしない

    • ログ設計はすごい。デモグラなど混ぜて1レコードに豊富な情報量



  • 重複もロストも許さないログでディープラーニングにかけたら、モデルの精度がテックジャイアントより高かった


    • precision/recallがほぼ1

    • 1レコードは購買やPVなど基本情報のみ

    • 日本向けサービス同士の比較なので、日本語の壁など外的要因な可能性も



※社外秘のため詳細は公開しません



MQTTブローカー



MQTTクライアント



mosquitto & paho by Python

MQTT通信の実例

Macで下記セットアップ

$brew install mosquitto

# mosquitto起動のため以下のどちらかを実行
# bg
$brew services start mosquitto
# fg
$/usr/local/opt/mosquitto/sbin/mosquitto -c /usr/local/etc/mosquitto/mosquitto.conf

$pip install paho-mqtt



paho pub.py

Pythonクライアントのチュートリアルを真似つつ


pub.py

import paho.mqtt.client as mqtt

import time

client = mqtt.Client()
client.connect('localhost', 1883, keepalive=60)
client.loop_start()
while True:
client.publish('world/darai0512', 'test')
time.sleep(1)




paho sub.py


sub.py

import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, respons_code):
print('connected')
client.subscribe('world/#')

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

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect('localhost', 1883, keepalive=60)
client.loop_forever()




Let's try MQTT

$python pub.py &

$python sub.py
world/darai0512 test
world/darai0512 test
...