MQTTをWebブラウザで受信してみる

#はじめに
このページは，

[ドローン操作システムを作ろう](https://qiita.com/hsgucci/items/86eedb5555b4234ee0e7)

の１ページです．
全体を見たい場合は上記ページへお戻りください．

#概要

前回は，dronekit-sitl(シミュレータドローン)の機体情報を
MQTTのPythonプログラムでPublish/Subscribeしました．

今回はSubするのをPythonではなくて，JavaScriptに変更し，
Webブラウザからメッセージを見てみます．

#準備するもの

- これまで使用したLinux PC
　　今回は，このＰＣにWebサーバーを立てます．
　　MQTTのSub側のプログラムをHTML/JavaScriptで書きます.

- 前回のPub側プログラム
　　dronekit-sitlの情報をJSONでPubするプログラム，[これ](https://raw.githubusercontent.com/DCoJA/OpenUVTM/master/sitl_mqtt_pub_json.py) です．

#セットアップ(Webサーバ)

まずは，更新情報を最新のものにしておきます．

```bash:aptのリポジトリを最新に
$sudo apt update
```
次に，Webサーバ(apache2)をインストールします．
(taskselでLAMP serverをインストールしてもいいです)

```bash:aptでインストール
$sudo apt install apache2
```
インストールが完了したら，Webブラウザで`http://localhost/`を開いてみてください．
![Screenshot at 2019-05-14 19-44-47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/2c99827d-ea9e-aaa9-e7f3-f451bee9c1a0.png)
ブラウザにこんなページが表示されればインストール成功です．

#MQTTブローカーの設定

WebブラウザでMQTTを直接受信することはできないので，
**WebSocket**を利用して通信します．
これを**MQTT over WebSocket**と言います．

WebSocketの通信ができるように，MQTTブローカー(mosquitto)の設定を変更する必要があります．

mosquittoの設定ファイル
`/etc/mosquitto/mosquitto.conf`
を，コンソールであればviやnano，あるいはGUIのテキストエディタで編集します．
その際，管理者権限が必要なのでsudoを付けます．

```bash:nanoで編集する場合
$sudo nano /etc/mosquitto/mosquitto.conf
```
`mosquitto.conf`ファイルの先頭に，以下の行を追加します

```
listener 1883
listener 15675
protocol websockets
```
これは，
・MQTTを1883番ポートで受信する
・WebSocketを15675番ポートで受信する
を意味しています．

`#`はコメント行なので，実際にはこんな風になります．

```bash: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

# ここに3行追加した
listener 1883
listener 15675
protocol websockets

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

```

設定が終わったらエディタを終了します．
(nanoの場合，Ctrl+oでファイルを保存し，Ctrl+xで終了)

その後，mosquittoサービスを再起動します．

```bash:mosquittoの再起動
$sudo systemctl restart mosquitto
```

#HTMLファイルを取得する

MQTTを受信するWebページを作ります．

まずは，サンプルプログラムをダウンロードしましょう．

参考にするのは，このページです．
https://github.com/rabbitmq/rabbitmq-web-mqtt-examples
このexamplesはMQTTブローカーとしてRabbitMQを使うサンプルですが，
ポート番号さえ合っていればmosquittoでも問題なく使用できます．

このgitのprivフォルダ以下にある，`echo.html`と`mqttws31.js`が必要です．
htmlというフォルダを作ってダウンロードします．

```bash
$mkdir ~/html/
$cd ~html
$wget https://raw.githubusercontent.com/rabbitmq/rabbitmq-web-mqtt-examples/master/priv/echo.html
$wget https://raw.githubusercontent.com/rabbitmq/rabbitmq-web-mqtt-examples/master/priv/mqttws31.js
```

(wgetで直接ダウンロードしなくても，gitで
`$git clone https://github.com/rabbitmq/rabbitmq-web-mqtt-examples`
ですべてダウンロードして当該ファイルを取り出しても良いです．)

#HTMLファイルを書き換える

ダウンロードした`echo.html`を，本企画のMQTTに合わせて変更します．
適当なテキストエディタで編集してください

主な変更箇所は２つです．
**86行目**
message.destinationName = <font color="red">"/topic/test"</font>;
　↓ 
message.destinationName = <font color="blue">"drone/001"</font>;

**112行目**
client.subscribe(<font color="red">'/topic/test'</font>, {qos: 1});
　↓ 
client.subscribe(<font color="blue">'drone/#'</font>, {qos: 1});

また，RabbiMQブローカーを使っていないのに，
`RabbitMQ Web MQTT Example`
と表示されるのは気持ち悪いので，
**5行目**と**48行目**を
`Drone Control Web MQTT Example`
と書き換えました．（これは必須の作業ではありません）

変更済みのHTMLファイルを [ここ](https://raw.githubusercontent.com/DCoJA/OpenUVTM/master/chapter10/echo.html) においておきます．

**解説**

86行目は，エディットボックスに打ち込んだメッセージをMQTTでPublishする際のトピック名です．
これまでの記事で取り扱ってきたトピック名と同じ`'drone/001'`にしました．

112行目は，MQTTでSubscribeするトピック名です．
注目すべきは，`'drone/#'`となっていて`001`ではない点です．
`#`というのはMQTTトピックのワイルドカードです．
端末のコマンドラインで言えばアスタリスク`*`です．
したがって`drone/`の後には様々な文字列が入って良いことになりますから，
トピック名`drone/001`はもちろんSubしますが，
`drone/002`でも`drone/quad/05`でもSubします．
つまり，1号機，2号機，クワッド5号機，，，のように，
**<font color="red">複数台のドローンのメッセージを同時に受信できる</font>**のです．

複数のドローンの位置情報を把握し，
お互いの位置関係を見ながら操作を決めるのは，
**航空管制**にとって重要な機能ですね．


#HTMLファイルをWebサーバのフォルダに置く

編集済みの`echo.html`と`mqttws31.js`を，
Webサーバのホームディレクトリである`/var/www/html`へコピーします．
このフォルダの操作には管理者権限が必要なので，`sudo`をつける必要があります．

```bash:ファイルのコピー
$cd ~/html
$sudo cp echo.html /var/www/html/
$sudo cp mqttws31.js /var/www/html/
```

#Subscribe側のWebブラウザを開く

それでは，Webブラウザを起動し，アドレス欄にURLを
`http://localhost/echo.html`
と打ち込んでEnterキーを押してください．
WebブラウザはChromiumでもFireFoxでも，どちらでも大丈夫です．

このようなページが表示されれば，ファイルのコピーは成功です．
![Screenshot at 2019-05-16 17-30-43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/12ac5315-dbbd-a08d-e292-8f87e00bfdb3.png)

また，**Logs**と書かれたエディットボックスに注目してください．
![success.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/6237c3fd-3c3d-fe30-97d4-733d3a2953cc.png)
このように，`CONNECTION SUCCESS`と出ていれば，
MQTTブローカーへの接続が成功しています．

しかし，もしも`CONNECTION FAILURE`と出ていたら，失敗です．
![failure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/919ca035-aa9e-f1cb-4e9b-f557972911f3.png)

・MQTTブローカーが起動していない
・MQTTブローカーのWebSocket設定がうまくいっていない
・ファイアウォールが勝手にブロックしている

などの原因が考えられます．

---
次に
**Received**のボックスの下にある，
**Type here...**と書かれた一行だけのボックスに何かメッセージを打ち込んで，
Enterキーを押してみてください．

例えば，`hoge`と打ち込んでEnterすると，このようになります．
![Screenshot at 2019-05-16 18-05-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/dd34da5b-2cc2-ad20-9573-2c5f69eaed48.png)

**Logs**のボックスを見てみると，
`SEND ON drone/001 PAYLOAD hoge`
と書かれていますから，トピック名 "drone/001" メッセージ "hoge" をPublishしたことがわかります．
また，
`RECEIVE ON drone/001 PAYLOAD hoge `
と書かれているので，Pubされたメッセージを即座にSubしたこともわかります．
Subしたデータ(`hoge`)そのものは，**Received**のボックスに表示されています．

#Publish側のdronekit-sitlを起動する

それでは，Pub側のシミュレータを起動してみましょう．
前回の記事で作った`sitl_mqtt_pub_json.py`を起動します．

```bash:シミュレータの起動
$python sitl_mqtt_pub_json.py 
```

#実行結果

![Screenshot at 2019-05-16 17-43-46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/897fc88a-ac37-b074-23b3-b0bbfd07f878.png)

一連の設定がうまくできていれば，
`drone/001`というトピック名でSubされたメッセージがし，
**Received**および**Logs**に表示されます．

#おわりに

今回は，PythonのMQTTがPublishしたドローンの位置情報を，
WebブラウザでSubscribeして表示させてみました．

しかし，文字列だけが表示されるのはつまらないですね．
やはり地図上に表示させたいものです．

次回は地図の表示を行います．