Raspberry PiでMQTTの動作環境を作る(RabbitMQ + Paho + Python)

rasp_matt_2

恥ずかしながら、IoT向けの通信プロトコルでMQTT (Message Queuing Telemetry Transport)というものがあることを最近知りました。知っておいて損はないかなーということで、Sparkの環境構築に使ったRaspberry Pi 2 × 2台を使って動作検証環境を作ることにしました。

MQTTを実現するにはPublisher – Broker – Subscriberの3役が必要なのですが、ここでは以下のように割り振ります。

  • Broker & Subscriber … Raspberry Pi 2 (A)
  • Publisher … Raspberry Pi 2 (B)

Raspberry Piが2台ない場合は(←そっちの方が普通だと思いますが)、全部の役を1台に割り振って動作確認することもできます(SubscriberとPublisherの接続先を”localhost”にすればOK)。

Brokerには、とりあえずよく名前を聞くRabbitMQを使って、PublisherとSubscriberには、これまたよく名前を聞くPahoのPythonパッケージを使うことにします。Pythonを使う理由は「うまくやれば後々Sparkと組み合わせられるかも?」という期待からです。

では、早速。

まずRaspberry Pi 2 (A)に、Brokerとして動作させるRabbitMQをインストールします。RaspbianをインストールしているRaspberry Piであれば、基本的に公式ページ(Debian / Ubuntu版)の手順通りやればOKです。

まず、”/etc/qpt/sourece.list”の末尾に以下を追加します。

deb http://www.rabbitmq.com/debian/ testing main

あとは以下のコマンドを順に実行するだけです。

$ wget https://www.rabbitmq.com/rabbitmq-signing-key-public.asc
$ sudo apt-key add rabbitmq-signing-key-public.asc
$ sudo apt-get update
$ sudo apt-get install rabbitmq-server

別件でCent OSに入れたときには、事前にerlangとかを入れなくちゃいけなかったので、それに比べれば簡単です。

試しに起動させてみます。

$ sudo service rabbitmq-server start

この状態でMQTT用のプラグインと、管理UI用のプラグインを突っ込んでおきます。

$ sudo rabbitmq-plugins enable rabbitmq_mqtt
$ sudo rabbitmq-plugins enable rabbitmq_management

プラグインを有効にするため、rabbitmq-serverを再起動します。

$ sudo service rabbitmq-server restart

管理UIが有効になっているか確認します。同じローカルネットのPCから、ブラウザで”http://(Raspberry PiのIP):15672″にアクセスします。

raspb_matt_1

こんな感じのログインが出てくればとりあえずOKです。

ログインするには、RabbitMQの方で事前にユーザを登録しておく必要があります(”guest”でログインできるのは同一マシン上のブラウザからのアクセスのみ)。ユーザの登録については、以下を参照させてもらっています。

ここではユーザsparkをパスワードhogehogeで登録します。

$  sudo rabbitmqctl add_user spark hogehoge

続いて、追加したユーザがすべてのリソースにアクセスできるようにパーミッションを設定します。

$ sudo rabbitmqctl set_permissions spark ".*" ".*" ".*"

最後に、管理UIが参照するためのタグを設定します。

$ sudo rabbitmqctl set_user_tags spark administrator

ここまで済めば、先ほどの管理UIから、設定したユーザ名とパスワードでログインできるようになっているハズです。

rasp_matt_2

こんな感じです。

 

さて、Brokerの設定は一旦ここまでにしておいて、次はSubscriberクライアントの作成に入ります。

Python用のPahoパッケージをインストールするため、パッケージ管理ツールであるpipを先にインストールします(pipの導入が済んでいない場合)。

$ sudo apt-get install python-pip

pipが導入されたら、Pahoパッケージをインストールします。

$ sudo pip install paho-mqtt

PahoパッケージはPython 2.7以上が必要ですが、Raspberry Pi 2向けのRaspbianは初めから2.7.3がインストールされているので、Pythonのバージョンアップは特に必要ありません。

ではでは、Subscriberのサンプルを作成します。このあたりを参考にさせていただきます。

# -*- coding: utf-8 -*- 
import paho.mqtt.client as mqtt

def on_connect(client, userdata, rc):
  print("Connected with result code " + str(rc))
  client.subscribe("hello/world")

def on_disconnect(client, userdata, rc):
  if  rc != 0:
    print("Unexpected disconnection.")

def on_message(client, userdata, msg):
  print("Received message '" + str(msg.payload) + "' on topic '" + msg.topic + "' with QoS " + str(msg.qos))

client = mqtt.Client()
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message

client.connect("localhost", 1883, 60) 

client.loop_forever()

今はRabbitMQとSubscriberが同じRaspberry Pi 2上で動いているので、connectの引数は”localhost”になります。

 

最後に、Publisherクライアントの作成です。Publisherクライアント用のRaspberry Pi 2 (B)でも、Subscriber用と同じようにPythonのPahoパッケージを導入してから、サンプルを作成します。

# -*- coding: utf-8 -*- 
import paho.mqtt.client as mqtt
from time import sleep

def on_connect(client, userdata, rc):
  print("Connected with result code " + str(rc))

def on_disconnect(client, userdata, rc):
  if rc != 0:
     print("Unexpected disconnection.")

def on_publish(client, userdata, mid):
  print("publish: {0}".format(mid))

def main():
  client = mqtt.Client()
  client.on_connect = on_connect
  client.on_disconnect = on_disconnect
  client.on_publish = on_publish
  client.username_pw_set("spark","hogehoge")
  client.connect("192.168.24.51", 1883, 60) 

  client.loop_start()
  while True:
    client.publish("hello/world","Hello, World!")
    sleep(3)

if __name__ == '__main__':
  main()

connectの引数は、RabbitMQの動いているRaspberry Pi 2 (A)のIPアドレスになります。

 

それでは、動作確認します。Raspberry Pi 2 (A)の方で、RabbitMQを立ち上げます。

$ sudo service rabbitmq-server start

立ち上がったら、Subscriberプログラムを実行します。

$ python sample_sub.py &

続いて、Raspberry Pi 2 (B)の方で、Publisherプログラムを立ち上げます。

$ python sample_pub.py &

これらを実行した結果、Raspberry Pi 2 (A)側のコンソールで以下のように出力されていれば成功です。

Connected with result code 0
Received message 'Hello, World!' on topic 'hello/world' with QoS 0
Received message 'Hello, World!' on topic 'hello/world' with QoS 0
Received message 'Hello, World!' on topic 'hello/world' with QoS 0
Received message 'Hello, World!' on topic 'hello/world' with QoS 0

もう少し実用的にしようと思ったら、メッセージの形をJSONにしてパースするとかも必要かもしれませんが、動作確認という意味ではこれで十分かな、と思います。

また、ここまでやっておいてなんですが、実はBrokerはRabbitMQよりも、Mosquittoを入れる方が導入としては扱いやすかったかも。。。試してはいませんが。

 

余談ですが、「わざわざRaspberry Pi 2を2台用意せんでも、Virtual Boxで仮想マシンを2つ立ち上げれば無料で同じように環境作れるぜヘイヘイ!」ということもできるのかもしれませんが、自分はそのへんよくわかっておらず、物理的に2台ある方が話がわかりやすいので、この形で環境を作っています。こんなアナログ(?)な人間には本当にありがたい存在です、Raspberry Pi。