Node-REDのAedes MQTT Brokerを使用してチャットシステムを作ってみた。

# はじめに

HerokuにデプロイされたNode-RED環境でMQTTを試そうと思ったが、CloudMQTTの追加オプションで無料プラン(Cute Cat)が使えなくなっていた。
(厳密には、HerokuのページにはCute Catを選択できるように表示されているが、CloudMQTTのページを見ると有料プラン($5/月)を使えと書かれている。)

https://elements.heroku.com/addons/cloudmqtt

https://www.cloudmqtt.com/blog/cloudmqtt-cute-cat-free-plan-out-of-stock.html

Heroku環境はウェブアクセスしか許可されていない。(ポート番号(80/443)のみ開放されている)
MQTT Brokerを使用する場合、ポート番号(1883/8883)が開放されていないため、代替手段としてMQTT over WebSocketを使用する必要がある。
Node-REDのAedes MQTT BrokerはMQTT over WebSocketにも対応しているため、試しにブラウザで利用できるチャットシステムを作ってみた。

![スクリーンショット 2022-05-04 1.04.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/2cb7188b-af99-187a-a892-7a4b0f17dcd8.png)

### Node-REDのMQTT BrokerはMoscaからAedesへ

「Node-REDのMQTT Brokerと言えばMoscaじゃないの？！」と思った方で、MoscaからAedesへ変わった背景について興味がある方はこちらをご覧ください。

https://www.slideshare.net/kitazaki/20210805-nodered-park-kitazaki-v1

https://youtu.be/zp5-2fLKEnM


# Node-REDフロー

Node-REDのフローは非常にシンプルでこれだけです。
MQTT inノード(MQTT Subscribe)とMQTT outノード(MQTT Publish)はテスト用なので、実質的にはAedes MQTT Brokerノードだけで動作します。

![スクリーンショット 2022-05-03 22.45.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/2c737b1a-b1ce-d625-4d9b-d389fb352c83.png)

### Aedes MQTT Brokerノードの設定

WebSocketの設定をします。

- WS Bind → path　　・・port(ポート)ではなくpath(パス)を選択します
- WS path → /mqtt 　・・任意(他のWebSocketのパスと重複しないようにします)

![aedes.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/fc6ad1fe-6407-eee4-cb03-ec12fadd317d.jpeg)

### MQTT inノードとMQTT outノードの設定

サーバとトピックの設定をします。

- サーバ → localhost:1883　　・・サーバはlocalhost、ポートは1883を設定します
- トピック → Test/chat　　・・任意(他のMQTTアプリケーションのトピックと重複しないようにします)

「あれ？！MQTT inノードとMQTT outノードはMQTT over WebSocketではなく、MQTT接続でいいの？！」と思うかもしれませんが、Node-REDが動いているノード内での接続(localhost接続)なので、Heroku環境の外部からの接続制限の影響を受けません。

![mqtt_in.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ee9a73f7-5c8b-0d75-bdb7-0611cabf4856.jpeg)

![スクリーンショット 2022-05-04 1.58.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/37da4a76-d2bd-52f6-3ec8-53424c6581fa.png)

![mqtt_out.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/6ca501d9-b9a3-f7ad-edaf-0e46492ac330.jpeg)

# ブラウザのチャットアプリ

MQTT ClientライブラリはPaho MQTT Javascriptライブラリを使用しました。
絵文字も利用可能です。

![chat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f23279b4-dc3a-5717-9357-2be3c8bf37fc.png)

### バージョン1.0.1での問題点

最初によく利用されているバージョン1.0.1を使用して実装しましたが、Heroku環境の外部からの接続制限の影響で、無通信状態だと一定時間で接続が切られる(socketがclosedになる)事象が発生しました。

### バージョン1.1.0での注意点

接続が切れた場合に自動で再接続するオプションが追加されたバージョンを試すために、HTMLファイルで読み込むスクリプトのURLを変更し、connectOptionsでreconnectを有効にしたところ、サンプルコードがエラーになりました。

調査したところ、まさに同じ事象に遭遇した情報にたどり着くことができました。

![スクリーンショット 2022-05-03 22.22.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c5a5fab8-3962-7597-1806-9d407eaa184b.png)

https://github.com/eclipse/paho.mqtt.javascript/issues/101

原因はPaho MQTT Javascriptライブラリのバージョンアップで、ネームスペースがPaho.MQTTからPahoへ変わったことでした。(サンプルコードはPaho.MQTT.ClientからPaho.Clientへ書き換えて解決)

"Previously the Client’s Namepsace was Paho.MQTT, as of version 1.1.0 (develop branch) this has now been simplified to Paho."

https://pi3g.com/2019/05/17/correct-way-to-instantiate-paho-client-in-javascript-for-wss-secure-websocket/

### サンプルコード

ソースコードをGithubに置きました。
バージョン1.1.0のサンプルコードを使用すれば問題ありませんが、参考(差分を確認するため)にバージョン1.0.1のサンプルコードも置いておきます。

- index.html　　・・Paho MQTT Javascriptライブラリ (バージョン1.1.0)
- index_old.html　　・・Paho MQTT Javascriptライブラリ (バージョン1.0.1)

https://github.com/kitazaki/chat_using_mqtt_over_websocket

サンプルコードを使用する場合は、Heroku環境にデプロイしたNode-REDフローのURLを設定してください。
(例. ********.herokuapp.com)

```html:index.html
var host = "";  // ホスト名を設定する
```

### 2022/5/6 追記

KatacodaでMQTT over WebSocketをチャットで試せるPlaygroundを作りました。

https://www.katacoda.com/kitazaki/scenarios/mqtt-over-websocket-playground