実に興味深い

世の中には興味深いものがいっぱいある

MQTTに触れてみた その2

前回から引き続き。 kta-m.hatenablog.com

ワイルドカード

前回のおさらい。

Topicはhoge/piyo/fugaといった階層構造で指定します。 Subscriberの指定にはワイルドカードが使えるので、柔軟な受け取り指定が可能です。

使えるワイルドカードは以下の2種類。

  • hoge/piyo/#:piyo以降は何でもOK
  • hoge/+/fuga:+の部分は(1階層分)何でもOK

前回からのコードはそのまま。Brokerもそのまま。

terminal1

$ ruby subscriber.rb hoge/piyo/fuga

terminal2

$ ruby subscriber.rb hoge/piyo/#

terminal3

$ ruby subscriber.rb hoge/+/fuga

terminal4からいろいろメッセージを配信してみる。

$ ruby publisher.rb hoge/piyo/fuga message

とすると全てのsubscriberが受信。

$ ruby publisher.rb hoge/piyo/fugafuga message
$ ruby publisher.rb hoge/piyo/fuga/hogehoge message

とするとterminal2のsubscriberのみ受信

$ ruby publisher.rb hoge/piyopiyo/fuga message

とするとterminal3のsubscriberのみ受信します。

Will

未来形のアレじゃなくて、「遺言」って意味の名詞らしい。

client起動時にbrokerにwillのデータを登録しておくと、 そのclientとの通信が途切れた際に、登録されたwillのメッセージを配信してくれるしくみです。 publisherとの通信が途切れたことをsubscriberに伝えるのがメインの使い方みたい。

ちなみに通信状態の確認は、一定間隔でclientにpingを送ることで確認しているとのこと。

publisher側のコードを次のように変更します。 connectに渡す値にwill_topicwill_payloadが加わりました。 その名の通りwillのtopicと、payload(メッセージ)です。

require "mqtt"

topic = ARGV[0]
message = ARGV[1].dup
MQTT::Client.connect(host: "127.0.0.1", port: 1883,
                     will_topic: "error/disconnect",
                     will_payload: "突然の死!") do |c|
  loop do
    c.publish(topic, message)
    sleep(1)
  end
end

terminal1

$ ruby subscriber.rb hoge/piyo/fuga

terminal2

$ ruby subscriber.rb error/#

terminal3

$ ruby publisher.rb hoge/piyo/fuga message

とすると、terminal1で、hoge/piyo/fuga: messageが1秒おきに出てきます。

ここでおもむろにterminal3でCtrl+Cを押すと、terminal2にメッセージが来ます。

error/disconnect: 突然の死!

次回

RetainとかDurable Subscribeを試してみる。 QoSは…なんだか試しにくい気がする。

MQTTに触れてみた その1

奥様に1日坊主と言われて久しいですが、ちゃんとこうやって書く気はあるんですよ。

MQTT

さて、今日はMQTT(MQ Telemetry Transport)というものに触れてみました。 きたるIoT時代に大活躍しそうだと噂のプロトコルです。

多くのデバイスに向けて同期的にメッセージを配信することに特化していて、 お互いにメッセージを配信し合えばリアルタイムな双方向通信もできちゃう! FacebookMessengerにも使われているんだそうな。

ちなみにMQが何なのかは…謎です。

特徴

以下のような特徴を持っているので、 ネットワークが不安定だったり非力だったりといった困ったデバイスでもなんとかなるようになってるみたい。

  • ヘッダが軽量かつシンプルなので、通信量や処理負荷が比較的小さい
  • 通信している相手の接続が途切れたら教えてくれる(Will)
  • 配信に途中参加しても、配信済みの最新のメッセージを受け取れる(Retain)
  • 接続が途切れても、あとで受け取り損ねたメッセージを受け取れる(Durable Subscribe)
  • 状況に応じてメッセージの到達保証のレベルを指定できるので、わりとどうでもいいところに無駄なリソースを割かないようにできる(QoS

説明してくれてるところがたくさんあるので、詳細は以下を参照してください。

大雑把に説明

登場人物

  • Broker:メッセージを管理するサーバー。メッセージを受け取って、それを欲している端末に送る。
  • Client:メッセージを送受信する端末
    • Publisher:メッセージを送信しようとしているときにこう呼ばれる
    • Subscriber:メッセージを受信しようとしているときにこう呼ばれる

Topic

メッセージにはそれぞれTopicと呼ばれるデータを設定します。

SubscriberはどのTopicのメッセージが欲しいかBrokerに伝えておけば、 Brokerがそれに応じたメッセージを配信してくれるという寸法。

Topicはhoge/piyo/fugaといった階層構造で指定します。 Subscriberの指定にはワイルドカードが使えるので、柔軟な受け取り指定が可能です。

使えるワイルドカードは以下の2種類。

  • hoge/piyo/#:piyo以降は何でもOK
  • hoge/+/fuga:+の部分は(1階層分)何でもOK

f:id:Kta-M:20160113002114p:plain

インストール

今回は、BrokerとしてMosquitto、Clientとしてruby-mqttを使用します。

Broker

Macで試すのでhomebrewでインストール。

$ brew install mosquitto

Client

ruby-mqttをインストール

$ gem install mqtt

とりあえずこれで準備完了。

基本の動き

Client実装

Publisher

require "mqtt"

topic = ARGV[0]
message = ARGV[1].dup
MQTT::Client.connect(host: "127.0.0.1", port: 1883) do |c|
  c.publish(topic, message)
end

Subscriber

require "mqtt"

request_topic = ARGV[0]
MQTT::Client.connect(host: "127.0.0.1", port: 1883) do |c|
  c.get(request_topic) do |topic,message|
    puts "#{topic}: #{message}"
  end
end

動かしてみる

terminal0でBrokerを起動

$ /usr/local/opt/mosquitto/sbin/mosquitto

terminal1

$ ruby subscriber.rb hoge

terminal2

$ ruby publisher.rb hoge Hello_MQTT!

terminal1側で受信!

hoge/piyo: Hello_MQTT!

次回

とりあえず最低限動くところまで書けたので今日はここまで。 次回はワイルドカードとかWillとか試してみる。

実に楽しみだ

いきなりですが、あけましておめでとうございます。

今年はブログを書いてみようと思い立って、新年早々開設してみました。

とりあえず書きたいことは、

  • 将来的にgemを作って公開したときの情報公開
  • 将来的にiOSアプリを作ってリリースしたときの情報公開
  • RubyとかSwiftとかの技術情報(Qiitaと被るかも)
  • その他わりとどうでもいいこと

主な動機は、今年いくつかgemを作って公開するつもりでいるから。 今まで技術的なことはQiitaに書いてきたけど、 OSSとしてライブラリを公開するにあたっては、以下の利点があると会社の先輩談。

  • ライブラリと個人が紐づく
  • README.mdよりも使い方の説明がしやすい
  • 今後の展望・苦労した点などを気軽にぼやける

確かにそうだなーと思いつつ、お正月というちょうどいい区切りもあったので、満を持して始めちゃいます。 1年後には全く違うものになってるかもしれないけど、気の向くままにやっていきます。

どうそ、よろしくお願いします!