【JavaScript 2020】PubNub を使ったリアルタイム通信を試してみる（JavaScript を利用）

この記事は、リアルタイムな通信に利用可能な [PubNub](https://www.pubnub.com/) を試してみた話の記事です。
また、ちょうど今日の枠が空いている [JavaScript のアドベントカレンダー](https://qiita.com/advent-calendar/2020/javascript2)があったので、急遽、そちらへの登録も行ってみました。

無料プランもあるサービスで、記事執筆時点（2020年12月19日現在）では、以下の範囲は無料で利用できるようです。

> This plan is free up to 1 million transactions or 200 monthly active users. 

![Simple_pricing_for_realtime_communication_and_chat_applications___PubNub.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/37736021-f2e9-1262-1be7-00a6ef1a4299.jpeg)

また、 [公式のドキュメントの SDK に関するページ](https://www.pubnub.com/docs/platform/sdks) を見ると、以下の複数の言語・環境で利用できるようです。

![Our_SDKs_·_PubNub_Docs.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/52f24eef-1545-dec4-4c8c-53c0f02d1a60.jpeg)

上記の画像の下には、「Client SDKs」・「IoT SDKs」・「Server SDKs」といった項目ごとに対応言語等が書かれていました。個人的に気になったのはこのあたりです。

- [JavaScript V4 SDK for Realtime Apps | PubNub](https://www.pubnub.com/docs/web-javascript/pubnub-javascript-sdk)
- [Node.js V4 SDK for Realtime Apps | PubNub](https://www.pubnub.com/docs/nodejs-javascript/pubnub-javascript-sdk)
- [PubNub REST API Documentation | PubNub](https://www.pubnub.com/docs/pubnub-rest-api-documentation)

サクッと試すには、クイックスタートのほうを見た方が良いかもしれません。

- [JavaScript Quickstart · PubNub Docs](https://www.pubnub.com/docs/platform/quickstarts/javascript)
- [MQTT PubNub bridge | PubNub](https://www.pubnub.com/docs/mqtt-pubnub-bridge/getting-started#introduction)

また、HTML＋JavaScript で pubnub.js 使う場合・mosquitto のコマンドを利用して使う場合の話は、 @n0bisuke さんが記事を書かれていたりします。

●PubNubで5分でリアルタイムWebこと初め + MQTTでデバイス連携も #protoout #iotlt #ヒーローズリーグ - Qiita
　https://qiita.com/n0bisuke/items/36e4b334d17174446df7

自分は今回は、[MQTT.js](https://github.com/mqttjs/MQTT.js) を使ったパターンを試してみます。普段、ブラウザ上や Node.js のプログラムで MQTT を使う際、自分がよく利用しているものになります。

## MQTT.js ＋ PubNub
それでは、Node.js のプログラムで試したパターンと、ブラウザ上で試したパターン（HTML＋JavaScript）の話を、それぞれ書いていきます。

PubNub を MQTT と組み合わせて使う場合、「MQTTブローカーに `mqtt.pndsn.com` を指定」して、クライアントID の指定を PubNub の 2つのキーを使った「`<publish_key>/<subscribe_key>/<actual device ID>`」という形にすれば良いようです。

![MQTT_PubNub_bridge___PubNub1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/677a981c-214c-57e5-d5f1-8bef62f39d2d.jpeg)

Python の MQTTクライアントの例で、Publish を行う場合のサンプルを公式から引用してみます。

```Python
import paho.mqtt.client as mqtt

publish_key = "<your publish key>"
subscribe_key = "<your subscribe key>"
client_id = "<your unique client identifier>"


client = mqtt.Client(client_id=publish_key + "/" + subscribe_key + "/" + client_id)
client.connect("mqtt.pndsn.com", 1883, 60)
client.publish("<topic to publish>", json.dumps({ "hi": 10 }))
```

こちらも参考にしつつ、以下で JavaScript でのお試しの話を書いていきます。

## Node.js で MQTT.js を使って試す
上記の Python のプログラムの設定内容を参考にしつつ、JavaScript での実装を試しました。そして、以下のプログラムで PubNub を介した MQTT の Pub/Sub を行うことができました。

```JavaScript
const mqtt = require('mqtt')

const publish_key = "【PubNub の publish key】";
const subscribe_key = "【PubNub の subscribe key】";
const client_id_org = "【任意のID】";
const topic = "test"; // とりあえず適当に設定
const client_id = publish_key + '/' + subscribe_key + '/' + client_id_org;

let client = mqtt.connect({
  host: 'mqtt.pndsn.com',
  port: 1883,
  clientId: client_id
});

client.on('connect', function () {
  console.log("connecting");
  client.subscribe(topic, function (err) {
    if (!err) {
      console.log("sub");
    }
  })
})

client.on('message', function (topic, message) {
  console.log("Sub: " + message.toString())
})

setInterval(function(){
  let message = "メッセージのテスト";
  console.log("Pub: " + message);
  client.publish(topic, message);
}, 2000);
```

上記のプログラムの動作確認には、前に以下の記事などでも登場させていた「MQTT.fx」を使いました。

●GUIベースのMQTTクライアントアプ「MQTT.fx」の使い方メモ - Qiita
　https://qiita.com/youtoy/items/1086cb1c9518a34968be

## ブラウザ上で MQTT.js を使って試す
HTML＋JavaScript でも試そうとしたのですが、上記の Node.js と同じようなプログラムを作っても、MQTTブローカーへのアクセスのところがうまく動いていませんでした。

プログラムに誤りがあるか、もしくは PubNub が MQTT over WebSocket に対応してない、とかかな（詳細は未調査）。

## まとめ
今回、初めて PubNub を使ってみました。

とあるサービスのとある機能を利用しようとして、その準備として PubNub を使ってみた話だったのですが、こちらを活用する話も記事にできればと思っています。