# Vue.js と MQTT.js SDK を使ったデプロイメントへの接続

本記事では、Vue 3 フレームワーク上で構築されたウェブアプリケーションにおいて MQTT.js を使用し、クライアントと MQTT ブローカー間の接続、サブスクライブ、メッセージ送受信、サブスクライブ解除などの機能を実装する方法を紹介します。

本記事のコードは Vue 3 を使用しています。Vue 2 をご利用の場合は、[Vue 2 MQTT 接続デモ](https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-Vue.js)をご参照ください。

## 前提条件

### MQTT ブローカーのデプロイ

- EMQX が提供する[無料のパブリック MQTT ブローカー](https://www.emqx.com/en/mqtt/public-mqtt5-broker)を利用できます。このサービスは[EMQX プラットフォーム](https://www.emqx.com/en)をベースに構築されています。ブローカーへのアクセス情報は以下の通りです：

  - アドレス：**broker.emqx.io**
  - WebSocket ポート：**8083**
  - TLS/SSL 対応 WebSocket ポート：**8084**

- また、[独自の MQTT ブローカーを作成](../create/overview.md)することも可能です。デプロイメントが稼働状態になった後、接続情報はデプロイメントの概要ページで確認できます。後のクライアント接続時に必要なユーザー名とパスワードは、**アクセス制御** -> **[認証](../deployments/default_auth.md)** で設定してください。

### Vue アプリケーションの作成

Vue アプリケーションの作成方法は、Vue ドキュメントの[Vue アプリケーションの作成](https://vuejs.org/guide/quick-start.html#creating-a-vue-application)をご参照ください。本例では Node 16.16.0 を使用しています。

## 依存関係のインストール

[MQTT.js](https://github.com/mqttjs/MQTT.js)は、JavaScript で書かれた完全オープンソースの MQTT プロトコル用クライアントライブラリで、Node.js とブラウザの両方で利用可能です。`MQTT.js` の詳細や使い方は、[MQTT.js GitHub](https://github.com/mqttjs/MQTT.js#table-of-contents)をご参照ください。

MQTT.js は NPM や Yarn でインストールできるほか、CDN や相対パスからのインポートも可能です。本例では NPM コマンドでのインストール方法を示します。CDN 経由で Vue を利用するプロジェクトには、直接ファイルをインポートする方法が適しています。

- NPM または Yarn を使う場合：

  MQTT.js をインストールします。

  ```shell
  # NPM
  npm install mqtt
  # または Yarn
  yarn add mqtt
  ```

  インストール後、MQTT.js をインポートする必要があります。詳細は [Vite Support](https://github.com/mqttjs/MQTT.js/issues/1269)をご参照ください。

  ```js
  import * as mqtt from "mqtt/dist/mqtt.min";
  ```

- CDN から MQTT.js を使用する場合：

  ```html
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
  ```

- プロジェクトにダウンロードして相対パスでインポートする場合：

  ```html
  <script src="/your/path/to/mqtt.min.js"></script>
  ```

## WebSocket ポートでの接続

クライアント ID、ユーザー名、パスワードを以下のコードで設定できます。クライアント ID は一意である必要があります。

```js
const clientId = "emqx_vue3_" + Math.random().toString(16).substring(2, 8);
const username = "emqx_test";
const password = "emqx_test";
```

以下のコードでクライアントと MQTT ブローカー間の接続を確立できます。

```js
const client = mqtt.connect("ws://broker.emqx.io:8083/mqtt", {
  clientId,
  username,
  password,
  // ...その他のオプション
});
```

## WebSocket セキュアポートでの接続

TLS/SSL 暗号化が有効な場合、接続の[パラメーターオプション](https://github.com/mqttjs/MQTT.js#mqttclientstreambuilder-options)は WebSocket ポート経由の接続と同じですが、プロトコルを `wss` に変更し、適切なポート番号を指定する点に注意してください。

以下のコードでクライアントと MQTT ブローカー間の接続を確立できます。

```js
const client = mqtt.connect("wss://broker.emqx.io:8084/mqtt", {
  clientId,
  username,
  password,
  // ...その他のオプション
});
```

## サブスクライブとパブリッシュ

### トピックのサブスクライブ

サブスクライブするトピックと対応する[QoS（サービス品質）レベル](https://www.emqx.com/zh/blog/introduction-to-mqtt-qos)を指定します。

```js
// トピックと QoS
const subscription = ref({
  topic: "topic/mqttx",
  qos: 0 as mqtt.QoS,
});

const doSubscribe = () => {
  const { topic, qos } = subscription.value;
  client.subscribe(
    topic,
    { qos },
    (error: Error, granted: mqtt.ISubscriptionGrant[]) => {
      if (error) {
        console.log("subscribe error:", error);
        return;
      }
      console.log("subscribe successfully:", granted);
    }
  );
};
```

### トピックのサブスクライブ解除

以下のコードで、指定したトピックと対応する QoS レベルのサブスクライブを解除できます。

```js
const doUnSubscribe = () => {
  const { topic, qos } = subscription.value;
  client.unsubscribe(topic, { qos }, (error) => {
    if (error) {
      console.log("unsubscribe error:", error);
      return;
    }
    console.log(`unsubscribed topic: ${topic}`);
  });
};
```

### メッセージのパブリッシュ

メッセージをパブリッシュする際は、MQTT ブローカーに対して対象のトピックとメッセージ内容を指定する必要があります。

```js
const publish = ref({
  topic: "topic/browser",
  payload: '{ "msg": "Hello, I am browser." }',
  qos: 0 as mqtt.QoS,
});

const doPublish = () => {
  const { topic, qos, payload } = publish.value;
  client.publish(topic, payload, { qos }, (error) => {
    if (error) {
      console.log("publish error:", error);
      return;
    }
    console.log(`published message: ${payload}`);
  });
};
```

### メッセージの受信

以下のコードはメッセージイベントを監視し、メッセージ受信時に受信したメッセージとトピックをコンソールに出力します。

```js
client.on("message", (topic: string, message) => {
  console.log(`received message: ${message} from topic: ${topic}`);
});
```

### MQTT ブローカーからの切断

クライアントをブローカーから切断するには、以下のコードを使用します。

```js
const destroyConnection = () => {
  if (client.connected) {
    try {
      client.end(false, () => {
        console.log("disconnected successfully");
      });
    } catch (error) {
      console.log("disconnect error:", error);
    }
  }
};
```

上記は主要なコードスニペットのみを示しています。完全なプロジェクトコードは [MQTT Client - Vue3](https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-Vue3.js) をご参照ください。ダウンロードして実際に試すことが可能です。

## 接続のテスト

Vue 3 を使って作成したシンプルな MQTT クライアントには、接続作成、トピックのサブスクライブ、メッセージの送受信、サブスクライブ解除、切断などの機能が含まれています。完全なコードは [MQTT Client Vue3](https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-Vue3.js) で確認できます。

![vueui.png](https://assets.emqx.com/images/b6563b0eb66eb51a2a02776889016a18.png)

別のクライアントとして [MQTT 5.0 クライアントツール - MQTTX](https://mqttx.app/) を使い、メッセージングをテストできます。

![vuemqttx.png](https://assets.emqx.com/images/2013cbab1bdffcae69b817bfebb4a33f.png)

ブラウザ側でサブスクライブ解除を行うと、MQTTX が2回目のメッセージを送信する前に、ブラウザは以降の MQTTX からのメッセージを受信しなくなります。

## FAQ

1. 自己署名証明書の使い方は？双方向 TLS/SSL 認証は使えますか？

   ブラウザの制限により、現時点ではサポートされていません。詳細は MQTT.js の issue をご参照ください：[ブラウザでの TLS/SSL 双方向認証接続の使い方](https://github.com/mqttjs/MQTT.js/issues/1515) および [Node.js では双方向認証可能だがブラウザでは未対応](https://github.com/mqttjs/mqtt.js/issues/741)。

## まとめ

本記事では、Vue 3 プロジェクトでの MQTT 接続作成と、クライアントと MQTT サーバー間のサブスクライブ、メッセージパブリッシュ、サブスクライブ解除、切断のシナリオを実装しました。完全なサンプルソースコードは[MQTT Client - Vue3 ページ](https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-Vue3.js)からダウンロード可能です。また、[MQTT Client example ページ](https://github.com/emqx/MQTT-Client-Examples)では他言語のデモ例も多数公開していますので、ぜひご覧ください。
