読者です 読者をやめる 読者になる 読者になる

.logbook

学んだことを書き綴る、言わば航海日誌です。

mruby-mqttを使ってMQTTクライアントを作成する

MQTTによる通信

MQTTクライアントを作成する前に、MQTTでは複数のクライアントがどのように通信を行うか理解する必要があります。

MQTTによる通信では「MQTTブローカ」と呼ばれるサーバが必要です。MQTTブローカが複数のクライアントと接続し、クライアントはMQTTブローカを経由して情報を配信します。MQTTブローカの立ち上げは以下の記事でまとめています。

通信の流れを簡単に説明します。

まず、クライアントはMQTTブローカに対して接続します。

f:id:ylgbk:20150314182136p:plain

受信側クライアントはMQTTブローカに対して、受信したい情報を登録します。この情報を「topic」、登録操作のことを「subscribe」と呼びます。「/programming/mruby」といった風に/(スラッシュ)で区切られた文字列がtopicで、ディレクトリ等と同様に階層構造で定義・指定できます。

f:id:ylgbk:20150314182505p:plain

送信側クライアントはMQTTブローカに対して、「topic」を指定してメッセージを送信します。この送信操作のことを「publish」と呼びます。

f:id:ylgbk:20150314182533p:plain

MQTTには他にも様々な便利機能が定義されているのですが、それはまた別途。本日は上記の受信側・送信側クライアントをmruby上で動作させます。

mruby-mqttをインストール

mruby上でMQTTの機能を利用する手段として、mruby-mqttと呼ばれるmrbgemsを利用する方法があります。

build_config.rbに必要なmrbgemsを追記します。:githubを指定することで、ビルド時にgithubから自動的にcloneされます。(mrubyにおけるmrbgemsの設定方法 - .logbook)

MQTT機能はシングルトンとして実装されるため、mruby-singletonを、 通信待ちループなどでsleepできると便利なので、mruby-sleepを併せてインストールします。

build_config.rb

MRuby::Build.new do |conf|
  # (省略)

  # 以下、3行を追加
  conf.gem :github => 'ksss/mruby-singleton', :branch => 'master'
  conf.gem :github => 'hiroeorz/mruby-mqtt', :branch => 'master'
  conf.gem :github => 'matsumoto-r/mruby-sleep', :branch => 'master'

  # (省略)
end
$ cd (mrubyのルートディレクトリ)
$ make clean
$ make

以上でmrubyの準備は完了です。

受信側クライアント

受信側のプログラムを作成します。MQTTブローカはIPが192.168.11.150とします。ポートはmosquittoがデフォルトで使用する1883です。

subscribe.rb

# MQTTブローカへconnectする
MQTTClient.connect("192.168.11.150:1883", "client_a") do |c|
  # メッセージ受信したら表示する
  # (コールバックとして登録)
  c.on_message = -> (message) {
    puts "#{message.topic}: #{message.payload}"
  }
  # connectに成功したらMQTTブローカへsubscribeする
  # (コールバックとして登録)
  c.on_connect = -> {
    c.subscribe("/programming/ruby")
  }
end

# イベントを待つ
while(true) do
  sleep 5
end

発生したイベントに対してコールバックを登録する形をとっています。使用可能なコールバック関数はgithubに記載されているので参考にしてください。

送信側クライアント

送信側のプログラムを作成します。MQTTブローカのIPとポートは受信側のプログラムと同じにします。

# MQTTブローカへconnectする
MQTTClient.connect("192.168.11.150:1883", "client_b") do |c|
  # 送信メッセージ
  MESSAGE = "Ruby is dynamic programming language of open source."
  # connectに成功したらMQTTブローカへpublishする
  c.on_connect   = -> {
    c.publish("/programming/ruby", MESSAGE)
  }
end

# イベントを待つ
while(true) do
  sleep 5
end

動作確認

プログラムが出来上がったら動作確認をしてみましょう。

まずはMQTTブローカを起動します。筆者はRaspberryPi上で起動させました。

$ mosquitto

次に受信側のプログラムを起動します。ここからはRaspberryPiと接続したPC上で実施します。

$ mruby subscribe.rb

最後に送信側のプログラムを起動します。

$ mruby publish.rb

すると受信側に受信メッセージが表示されます。

/programming/ruby: Ruby is dynamic programming language of open source.