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

佐藤屋敷

技術も文章もわかっていてもわからないことだらけ。

MQTTを試してみる( 2/2 )

MQTT Vagrant

前回に引き続きMQTTを試します。長いです。

■前回の記事

satoyashiki.hatenablog.com

■環境、用意するもの

  • Windows 8.1 64bit
  • Windows上のCentOS6.X 仮想サーバ(vargrant)でのmosquitto-1.4.5
  • Windows上のクライアントはPaho 1.1 ( JavaScrpt client )

■Paho 1.1 ( JavaScript版 )

www.eclipse.org

■前提

  • Windows上のCentOS6.Xへmosquittoをyumでインストール済み
  • mosquittoが、CentOS上で起動済みでPython接続が成功したあとの話

■以下手順続き

  1. WindowsからJavaScript接続してみる。上手くいかない。
  2. あ、mosquittoがWebSocketモードじゃないのね?設定を変える。動かない。
  3. mosquittoのRedHat/FedoraのyumのリポジトリはWebSocketが無効なのでソースコンパイルが必要とわかる。
  4. ソースコンパイルをいろいろする。
  5. やっと準備完了でmosquitto起動
  6. WindowsからJavaScript接続してみる。上手くいく。やったー。
  7. 試しにCentOSをやめてUbuntuでやってみる。WebSocketが素直にうまくいく。
  8. これは罠なので気を付けようって話。(ググったブログは結構Ubuntuのサンプルばかり。)
  9. 結局世界のStack Overflowは凄いと言うことだ。
  10. 疲れました。お疲れ様です。

1. WindowsからJavaScript接続してみる。上手くいかない。

コードはPahoからダウンロードしてきてコードを準備( 上にあるPahoページからmqttws31-min.jsを入手する )

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>TEST</title>
    <script type="text/javascript" src="mqttws31-min.js"></script>
    <script type="text/javascript" src="mqclient.js"></script>
</head>
<body>

</body>
</html>

client.js

// Create a client instance
var client = new Paho.MQTT.Client("192.168.33.20", 1883 , "clientId" + new Date().getTime());

// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;

// connect the client
client.connect({onSuccess:onConnect});

// called when the client connects
function onConnect() {
    // Once a connection has been made, make a subscription and send a message.
    console.log("onConnect");
    client.subscribe("/World");
    message = new Paho.MQTT.Message("Hello");
    message.destinationName = "/World";
    client.send(message);
}

// called when the client loses its connection
function onConnectionLost(responseObject) {
    if (responseObject.errorCode !== 0) {
        console.log("onConnectionLost:"+responseObject.errorMessage);
    }
}

// called when a message arrives
function onMessageArrived(message) {
    console.log("onMessageArrived:"+message.payloadString);
}

IPとかはvagrantで設定したものです。
ポートはmosquittoのデフォルトです。

chormeのデベロッパーツールを開いて実行。なんか上手く動いてない。
f:id:satoysan:20151112174535p:plain

WebSocket connection to 'ws://192.168.33.20:1883/mqtt' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET

2. あ、mosquittoがWebSocketモードじゃないのね?設定を変える。動かない。

WebSocketモードじゃないので設定を変えることに。

mosquitto.confの設定マニュアルeclipse.org

mosquitto.conf

# Place your local configuration in /etc/mosquitto/conf.d/

pid_file /var/run/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

#log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d

protocol websockets

protocol websocketsを追加

mosquitto再起動。

# /etc/init.d/mosquitto restart
Shutting down Mosquitto MQTT broker1447318610: mosquitto version 1.4.5 terminating
1447318610: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
                                                           [  OK  ]
Starting Mosquitto MQTT brokerError: Websockets support not available.
Error found at /etc/mosquitto/mosquitto.conf:12.
Error: Unable to open configuration file.
                                                           [FAILED]

なぜにWebsocketがサポートされとらんのじゃ!いろいろ調べる。いろいろググる。

3. mosquittoのRedHat/FedoraのyumのリポジトリはWebSocketが無効なのでソースコンパイルが必要とわかる。

stackoverflow.com
あー・・・なるほどなるほど。Answersを見ると結構衝撃。
つまり、CentOS版のパッケージはダメってことですね。Webosocketsが。

4. ソースコンパイルをいろいろする。

駆け足で行きます。

# yum remove mosquitto
# yum install gcc-c++
# yum install cmake
# yum install openssl-devel
# cd /usr/local/src/
# wget http://mosquitto.org/files/source/mosquitto-1.4.5.tar.gz
# tar zxvf mosquitto-1.4.5.tar.gz
# cd mosquitto-1.4.5
# vi config.mk

mosquittoのパッケージはさよならします。そしてコンパイルする準備で最初yumでいろいろインストールします。

config.mkをイジってWITH_WEBSOCKETS:=noをyesに変更してWebosocketsを有効に。ちなみにWITH_SRVをyesにしたままだと、c-areasというライブラリがないと怒られるので、こちらもインストールする。面倒な場合はconfig.mkでnoにすればコンパイルは通ります。他libuuid-develなんかも入れますが、WITH_UUIDをnoにすれば・・・うんぬん。

以下全部対応します。

# cd ../
# wget http://c-ares.haxx.se/download/c-ares-1.10.0.tar.gz
# tar zxvf c-ares-1.10.0.tar.gz
# cd c-ares-1.10.0
# ./configure
# make
# make install 
# cd ../
# yum install libuuid-devel
# wget http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/snapshot/libwebsockets-1.5-chrome47-firefox41.tar.gz
# tar zxvf libwebsockets-1.5-chrome47-firefox41.tar.gz
# cd libwebsockets-1.5-chrome47-firefox41
# mkdir build
# cd build
# cmake ../ -DLIB_SUFFIX=64
# make 
# make install

mosquittoのコンパイル準備完了

# cd /usr/local/src/mosquitto-1.4.5
# make
# make install
# cd /etc/mosquitto
# useradd mosquitto
# cp mosquitto.conf.example mosquitto.conf
# vi mosquitto.conf

ということで、mosquitto.confを修正してprotocol websocketsに変更

#protocol mqtt
protocol websockets

ちょっと試しでmosquitto --helpとかしてみるとエラーがでたりします。

mosquitto: error while loading shared libraries: libwebsockets.so.5: cannot open shared object file: No such file or directory

こいつに対応するにはパスを指定する必要があります。

# vi /etc/ld.so.conf.d/liblocal.conf

liblocal.conf

/usr/local/lib64
/usr/local/lib

そして適用

# ldconfig

ちょっとコマンド実行お試し。

# mosquitto --help
mosquitto version 1.4.5 (build date 2015-11-12 09:54:01+0000)

mosquitto is an MQTT v3.1 broker.

Usage: mosquitto [-c config_file] [-d] [-h] [-p port]

 -c : specify the broker config file.
 -d : put the broker into the background after starting.
 -h : display this help.
 -p : start the broker listening on the specified port.
      Not recommended in conjunction with the -c option.
 -v : verbose mode - enable all logging types. This overrides
      any logging options given in the config file.

See http://mosquitto.org/ for more information.

うまくいきました。

5. やっと準備完了でmosquitto起動。

では早速起動

# mosquitto -c /etc/mosquitto/mosquitto.conf -d
1447322705: mosquitto version 1.4.5 (build date 2015-11-12 09:54:01+0000) starting
1447322705: Config loaded from /etc/mosquitto/mosquitto.conf.
1447322705: Opening websockets listen socket on port 1883.

おお、websockets listen socketしたー!

6. WindowsからJavaScript接続してみる。上手くいく。やったー。

ようやく帰ってきました。JavaScriptのソース実行
f:id:satoysan:20151112190739p:plain

CentOSには厳しい道程があるので、気をつけよう!そのうちyumでWebSocket対応版が出ると思うけどね!*1

付録

srcコンパイルで入れたmosquittoにゃ起動シェルがないので、/etc/init.d/にシェルを置きます。
https://gist.github.com/basuke/7777918
ここは環境に合わせて修正する。

7. 試しにCentOSをやめてUbuntuでやってみる。WebSocketが素直にうまくいく。

vagrantでubuntu/trusty64boxファイルを作る。
で・・・ささっとapt-getで放り込んで実行

$ sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
$ sudo apt-get update
$ sudo apt-get install mosquitto
$ su -
# cd /etc/mosquitto/
# vi mosquitto.conf
# service mosquitto start

mosquitto.confの中を修正。protocol websocketsに。
さっきのjavascriptコードのIPが違うのでそこだけ変更して実行すると…うまくいきました。
つまりはUbuntuでやってる人はこの問題にぶち当たらないということですね!
でも本番サーバがCentOSになってたりしてハマり道を歩むという。。。

9. 結局世界のStack Overflowは凄いと言うことだ。

 ありがとう。Stack Overflow。ありがとう。Stack Overflowユーザの皆様。

*1:ついでにこの記事も死滅する運命