こんにちは、まろCです。
幼い頃から本が嫌いで、読み始めると数ページで眠くなってたんですが、最近読めるようになりました。なんと、Kindleで読むと眠くならないのです!
もっと言うと、Kindleで行間を空けて、文字を大きくし、1ページで見える文字数をなるべく少なくしたら睡眠魔術が効かなくなってきたのです。
それはさておき、今回は最近話題のMQTTについて、MQTTブローカーサービス「sango」を使ってチャットツールをつくってみたので、そのことを書きたいと思います。実装はフロントのみ!
https://sango.shiguredo.jp/mqtt
一言で言うならば、「あらゆるモノをつなぐ軽量プロトコルで、パブリッシャー(送信者)とサブスクライパー(購読者)の間に位置するMQTTブローカーサーバーを介して、メッセージをやりとりする」といったところ。
ちなみに、Facebook MessengerもMQTTでメッセージのやりとりを行っています。
MQTTブローカーサーバーを構築するには、
を使うようですが、今回は作らずにサービスを使います。
使うのはこちら。サーバーもsangoのようなサービスを使うことで、構築せずに気軽に始められるのがいいですね。
GitHubアカウントで一発登録です。素晴らしい。すぐに使うことができるんですよ!
ここからステータスを見ることができます。
簡単なチャットアプリを作りたいと思います。
1ページ内にメッセージをpublishする入力フォームと、自分を含めた誰かが送信したメッセージを受け取るsubscribeの機能を作っていきます。
参考:sangoの使い方 – JavaScript WebSocket 編 — Sango ドキュメント
https://sango.shiguredo.jp/docs/mqtt_javascript.html
MQTTクライアントライブラリはpahoを使います。
Paho – Open Source messaging for M2M
https://eclipse.org/paho/clients/js/
JavaScriptだけでなく、いろいろな言語に対応しています。
まず、pahoライブラリを使ってMQTTブローカーサーバーに接続するところ、メッセージを配信するところ、メッセージを受信するところを実装します。
var client; var clientID = 'maroc'; //何でもいいみたい var topic = '{ユーザー名}/test'; //トピックを任意に作成 function connetct() { //sangoで表示されている情報 var userName = {ユーザー名}; var password = 'PASSWORD'; var websocketUrl = 'ws://lite.mqtt.shiguredo.jp:8080/mqtt'; // Pahoの接続clientをnew client = new Paho.MQTT.Client(websocketUrl, clientID); // ブローカー(sango)に接続 client.connect({ userName: userName, password: password, onSuccess: onConnect, onFailure: failConnect }); client.onConnectionLost = onConnectionLost; // メッセージがSubscribe(購読者)に届いたらのイベントを登録 client.onMessageArrived = onMessageArrived; } // sangoと接続できなかったら function failConnect(e) { console.log('failed!'); console.log(e); } // sangoと接続できたら function onConnect() { console.log('connecct'); // 接続した時点で購読をスタートさせる。一回で後は誰かがメッセージを送ったらonMessageArrivedが呼ばれる subscribe(); } // ブローカーにメッセージを送信 function publish(msg){ message = new Paho.MQTT.Message(msg); message.destinationName = topic; client.send(message); } // 購読をする function subscribe() { console.log('subscribe'); client.subscribe(topic); } // メッセージが到着したら function onMessageArrived(message) { console.log('onMessageArrived:'+ message.payloadString); msgView.update(message.payloadString); //vue.jsのメソッド } // 接続が切れたら function onConnectionLost(responseObject) { if (responseObject.errorCode !== 0) { console.log("onConnectionLost:"+responseObject.errorMessage); } } connetct();
次に、フォームに名前を入れて、内容を送信するところを実装していきます。
inputのエンターを押した時点で、イベントを発火させ、メッセージをsangoに送信します。
送信すると、sangoは接続している全ての購読者に配信します。もちろん自分自身もonConnectで購読者となっていますので、メッセージを受け取ります。それをmsgViewに反映させます。
<div id="input" class="input"> <input v-on="keyup:submit | key 13" v-model="msg.c"> </div> <div id="name" class="name"> <input v-model="uName">{{uName}} </div> <div id="msgView" class="msg-view"> <div v-repeat="msg" class="{{classname}}"> <p class="from"><span>{{from}}</span></p> <div class="message"><span class="baloon">{{{c}}}</span><span class="date">{{read}}<br>{{date}}</span></div> <div> </div> <script src="vue.min.js"></script>
var name = new Vue({ el: '#name', data: { uName: 'なまえ' } }); new Vue({ el: '#input', data: { msg: { c: '', from: '', date: '', read: '', classname: '' } }, methods: { submit: function(e){ e.stopPropagation(); // console.log(this.msg); if (this.msg.c.length > 0) { var now = new Date(); var hour = now.getHours(); var min = ("0"+ now.getMinutes()).slice(-2); this.msg.from = name.uName; this.msg.date = hour+ ':'+ min; publish(JSON.stringify(this.msg)); this.msg = {}; } // subscribe(); //onConnectで一回でいい } } }); var msgView = new Vue({ el: '#msgView', data: { msg: [] }, methods: { update: function(msg) { var received = JSON.parse(msg); var _msg = {}; _msg.c = received.c; _msg.from = received.from; _msg.date = received.date; _msg.read = '既読'; var classname = ''; var regexp = new RegExp('^'+name.uName, 'g'); console.log(msg.match(regexp)); if (_msg.from.match(regexp) !== null) { //じぶん classname = 'right_balloon'; } else { classname = 'left_balloon'; } _msg.classname = classname; this.msg.push(_msg); } } });
すごく簡単に記述できますね。
データバインディングもvue.jsがサクッとやってくれるので最高です。
ローカルサーバーは、pythonのSimpleHTTPServerを使います。
Macだと最初から入っているので、ローカルでサーバーに上げたいときはこれ一発でOKです。
python -m SimpleHTTPServer 9000
PCで2つブラウザを開いて、あらかさんにスマホからメッセージを送ってもらいました。自分とあらかさんのやりとりが、もうひとつのブラウザでもしっかり反映されています。
グループチャットも簡単に実装できました!
MQTTの特徴にもあるように、送るだけの軽いキーワードであれば、スマホはもちろんのことウェアラブルデバイスやマイコンボードといった、IoTよりなものに向いていると言えます。
今回は時雨堂さんのブローカーサービスsangoを使い、フロントエンドの実装だけでチャットをつくることができました。プロトコルと言うとちょっと難しい気がしますが、このようなサービスがあることでより理解への距離が縮まり、なにができるんだろうとワクワクします。
いま、そのワクワクから僕の中ですごいアイデアが生まれました!
今日作ったものにスタンプ機能や電話帳からの友だち追加機能、無料電話をつけたりして例えばiPhoneやAndroidでアプリとして展開すれば、何でしょう、、世界展開もできるような気がします!
それでは。
【チャットツールを作る方法は他にもあります!】
※ インタラクティブコンテンツを作ろう!milkcocoaで5分のチャットアプリ制作
※ ChatWorkがメッセージ取得APIを解禁したのでHubotと連携させてみよう!(業界初かも)
※ チャットツールをGitとNode.jsとHerokuでDIYする方法〜環境構築編〜