# React Native から MQTT.js SDK を使ってデプロイメントに接続する方法

本記事では、Expo で構築した React Native アプリケーションで MQTT.js を使用し、クライアントと MQTT ブローカー間の接続、サブスクライブ、メッセージ送受信、サブスクライブ解除などの機能を実装する方法を紹介します。

## 前提条件

### 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)** で設定してください。

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

`Expo` を使って新しい React Native アプリケーションを作成します：

```shell
npx create-expo-app@latest mqtt-test
```

参考リンク：[https://docs.expo.dev/get-started/create-a-project/](https://docs.expo.dev/get-started/create-a-project/)。

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

[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、pnpm でインストール可能です。本例では npm コマンドでインストールします。

1. コマンドラインでインストール：

   ```shell
   npm install mqtt
   # または
   yarn add mqtt
   # または
   pnpm add mqtt
   ```

2. 必要な箇所で MQTT.js をインポート：

   ```js
   import mqtt from "mqtt";
   ```

## WebSocket ポートで接続する

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

```js
const clientId =
  "emqx_react_native_" + 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)を指定します。

```javascript
const doSubscribe = () => {
  setSubBtnText("Subscribing...");
  client?.subscribe(subTopic, { qos: 0 }, (error) => {
    if (error) {
      console.error("トピックのサブスクライブに失敗しました:", subTopic, error);
      setSubBtnText("Subscribe");
    } else {
      setSubBtnText("Subscribed");
      console.log("トピックをサブスクライブしました:", subTopic);
    }
  });
};
```

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

以下のコードで、サブスクライブ解除したいトピックを指定して解除できます。

```javascript
const doUnsubscribe = () => {
  client?.unsubscribe(subTopic, {}, (error) => {
    if (error) {
      console.error("トピックのサブスクライブ解除に失敗しました:", subTopic, error);
      setSubBtnText("Subscribe");
    } else {
      console.log("トピックのサブスクライブを解除しました:", subTopic);
      setSubBtnText("Subscribe");
    }
  });
};
```

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

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

```javascript
const doPublish = () => {
  client?.publish(pubTopic, pubMessage, { qos: 0 }, (error) => {
    if (error) {
      console.error("メッセージのパブリッシュに失敗しました:", error);
    } else {
      console.log("トピックにメッセージをパブリッシュしました:", pubTopic);
    }
  });
};
```

### メッセージの受信

以下のコードはメッセージイベントを監視し、受信したメッセージを保存します。

```js
client.on("message", (topic, payload) => {
  setReceivedMsg((prevMsg) => {
    return prevMsg.concat(`\n${payload.toString()}`);
  });
});
```

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

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

```javascript
const doDisconnect = () => {
  client?.end();
  setClient(null);
  setConnectBtnText("Connect");
};
```

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

## 接続のテスト

React Native を使って、接続作成、トピックのサブスクライブ、メッセージ送受信、サブスクライブ解除、切断ができるシンプルなアプリケーションを作成しました。

<img src="./_assets/react_native_ui.png" alt="React Native UI" style="zoom:67%;" />

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

![mqttx_react_native.png](./_assets/mqttx_react_native.png)

MQTTX が React Native 側からのメッセージを正常に受信できることが確認でき、MQTTX からトピックにメッセージを送信した際にも同様に受信される様子がわかります。

<img src="./_assets/react_native_mqttx.png" alt="React Native と MQTTX のメッセージ送受信" style="zoom:67%;" />

## まとめ

本記事では、React Native プロジェクトで MQTT 接続を作成し、クライアントと MQTT サーバー間でのサブスクライブ、メッセージパブリッシュ、サブスクライブ解除、切断のシナリオを実装しました。

完全なサンプルソースコードは[MQTT Client - React-Native-Expo](https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-React-Native-Expo)からダウンロード可能です。また、[MQTT Client example page](https://github.com/emqx/MQTT-Client-Examples)では他言語のデモ例も多数公開していますので、ぜひご覧ください。
