mosquittoでMQTTとWebSocket両方に対応させる
久々にMQTTブローカーサーバ使ってたら、mosquittoがMQTTとWebSocketに対応していたのでメモ
何が嬉しいか
今まではMQTTとWebSocketをバインドするためにNode.jsなどを使い、MQTTからWebSocketへ変換していました。例えばこんな感じに。 まぁこの頃はSocket.IOとか使ってたので、すでに古いのですが・・・
// WebSocket -> MQTT io.sockets.on('connection', function(socket) { socket.on('message', function(data) { // MQTTで送信 client.publish(PUSH_LOCATION, JSON.stringify(data.value)); }); }); // MQTT -> WebSocket client.on('message', function (topic, message) { // WebSocketで送信 io.sockets.emit('SYS_STATUS', message); });
これがmosquittoをWebSocketに対応させることでNode.jsは必要なく、nginx + HTML + JSで済むようになります。
画面をデザイナーさんに頼むときにNode.js動かさないと画面作れなかったりしたんですが、HTML + JSだとデザインする方もファイルだけなのでかなり楽になるんじゃないかと思います。
mosquittoの設定ファイルの修正
対応しているmosquittoのバージョンはver1.4.2以降のようです。Ubuntuではバイナリがすでに対応済みなのでそれを導入しますが、デフォルトではWebSocketには対応していません。
$ sudo apt-get install mosquitto
Ubuntuでaptでインストールした場合、設定ファイルは /etc/mosquitto/mosquitto.confになります。
# Place your local configuration in /etc/mosquitto/conf.d/ # # A full description of the configuration file is at # /usr/share/doc/mosquitto/examples/mosquitto.conf.example 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
これに以下の行を追加して、WebSocketに対応するようにします。
listener 1883 listener 9090 protocol websockets
WebSocketに対応させるにはprotocol websocketsだけで良いみたいですが、その場合MQTTが動作しなくなります。 この例ではMQTTは1883ポート、WebSocketは9090ポートで動作します。
設定ファイルを書き換えたら、サービスをリスタートさせます。
$ sudo service mosquitto restart
mosquittoのログ(/var/log/mosquitto/mosquitto.log)を見てみると、起動時にMQTTとWebSocketの両方が動作しているはずです。
1453293506: mosquitto version 1.4.7 (build date Tue, 22 Dec 2015 12:47:28 +0000) starting 1453293506: Config loaded from /etc/mosquitto/mosquitto.conf. 1453293506: Opening ipv4 listen socket on port 1883. 1453293506: Opening ipv6 listen socket on port 1883. 1453293506: Opening websockets listen socket on port 9090.
HTML + JS の記述例
動作環境はnginxにHTML + JSです。まずはHTMLファイル。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>TEST</title> <script type="text/javascript" src="mqttws31.js"></script> <script type="text/javascript" src="client.js"></script> </head> <body> </body> </html>
mqttw31.jsは Paho MQTTのJavaScriptクライアントです。こちらからダウンロードします。
次にJavaScriptファイル(client.js)の例です。サーバアドレスにはmqtt://やws://などのスキーマは不要です。ポートにmosquitto.confで追加したWebSocketの9090を指定しています。
// Create a client instance var client = new Paho.MQTT.Client("サーバアドレス", 9090 , "clientId" + new Date().getTime()); // set callback handlers 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("PUBLIC/log/#"); } // called when a message arrives function onMessageArrived(message) { console.log('payload: ' + message.payloadString); }
これで、他クライアントからMQTTでデータをブローカーサーバに送信すると、subscribeしていればデータを受信してペイロードを取得できます。
実際の動作としては、mqttw31.jsがMQTTクライアントとして公開されているので、WebSocketは関係なくて、ブラウザレベルでMQTTで接続できるんじゃないか?と思いますが、このMQTTクライアントは内部でWebSocketに変換しています。そのため、ブローカーがWebSocketに対応する必要があります。
これでNode.jsでサーバアプリ書かなくてもよくなるので、かなり楽になるんじゃないかなーと。。。