MQTT over WebSocketのクイックスタートガイド

![MQTT over WebSocketのクイックスタートガイド](https://assets.emqx.com/images/404b8c5a346cd6872462d97caa2c1e35.png?imageMogr2/thumbnail/1520x684)

**目次**

- [WebSocketとは？](#what-is-websocket)
- [なぜMQTT over WebSocketを使用するのか？](#why-use-mqtt-over-websocket)
- [MQTTブローカーの準備](#prepare-an-mqtt-broker)
- [MQTT over WebSocketの使用開始](#get-started-with-mqtt-over-websocket)
- [テスト](#test)
- [Q&A](#q-amp-a)
- [まとめ](#summary)
- [リソース](#resources)

近年、Webフロントエンド技術の急速な発展により、新しいブラウザ機能が登場しました。ブラウザレンダリングエンジンを通じて、ブラウザ側で実装できるアプリケーションが増えています。その一つがWebSocketで、Webアプリケーションの即時通信手段として広く使用されています。

WebSocketは、単一のTCP接続上で全二重通信チャネルを提供するコンピュータ通信プロトコルです。IETFは2011年にWebSocketプロトコルをRFC 6455として標準化し、現在、WebSocket API in Web IDLはW3Cによって標準化されています。

[MQTTプロトコル](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718127)では、WebSocket [RFC6455]接続上で[MQTT](https://www.emqx.com/en/blog/the-easiest-guide-to-getting-started-with-mqtt)を転送するために満たすべき条件が規定されています。ここでは詳細には記述しません。

## WebSocketとは？

WebSocketは、単一のTCP接続上で二方向通信チャネルを可能にするネットワーク通信プロトコルです。HTTPとは異なり、WebSocketはクライアントとサーバー間のオープンな接続を維持し、即時かつインタラクティブなデータ交換を可能にします。これにより、オンラインゲーム、チャットアプリケーション、株式取引システムなど、リアルタイムのインタラクティブアプリケーションに最適です。

WebSocketプロトコルには、ハンドシェイクとデータ転送の2部分があります。ハンドシェイクはクライアントとサーバー間の接続を確立し、データ転送はオープンな接続上で情報を交換します。

## なぜMQTT over WebSocketを使用するのか？

IoTインタラクションにおいて、MQTT over WebSocketはますます重要な役割を果たしており、よりアクセスしやすく、効率的で豊かな体験を提供しています。任意のWebブラウザを通じて直接MQTTデータ通信を可能にすることで、IoTの世界を誰もが手軽に利用できるようにします。

MQTT over WebSocketを使用する理由は以下の通りです：

1. **シンプルなインタラクション**: 任意のWebブラウザを通じてIoTデバイスと直接対話できます。異なるプロトコルについて心配する必要はありません。
2. **ユニバーサルアクセシビリティ**: Webブラウザを持っていれば、誰でもIoTデバイスに接続し、対話することができます。
3. **リアルタイムアップデート**: IoTデバイスからのデータをリアルタイムで取得し、最新の洞察を直接ブラウザに提供します。
4. **効率性と広範囲のサポート**: MQTTは軽量プロトコルであり、JavaScriptでのWebSocketの広範囲なサポートと組み合わせることで、ほぼすべてのWebアプリケーションでリアルタイムデータ伝送が可能です。
5. **強化されたデータ視覚化**: Webページは、さまざまなMQTTデータをより良く、速く、豊かに表示できます。これは、WebブラウザがMQTTデータを視覚化するためのデファクトインターフェースになるにつれて特に重要です。

MQTT over WebSocketは、Webブラウザを持つ誰もがリアルタイムでIoTデバイスと対話し、簡単に利用できるようにIoTデバイスへのアクセスを民主化します。

次に、MQTT over WebSocketを使用するための包括的なガイドを提供します。

## MQTTブローカーの準備

進む前に、通信とテストに使用する[MQTTブローカー](https://www.emqx.com/en/blog/the-ultimate-guide-to-mqtt-broker-comparison)があることを確認してください。MQTTブローカーを入手するためのいくつかのオプションがあります。

- **プライベートデプロイメント**

  [EMQX](https://www.emqx.io/)は、IoT、[IIoT](https://www.emqx.com/en/blog/iiot-explained-examples-technologies-benefits-and-challenges)、および接続された車両用の最もスケーラブルなオープンソースMQTTブローカーです。以下のDockerコマンドを実行してEMQXをインストールできます。

  ```
  docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:888 -p 18083:18083 emqx/emqx
  ```

- **完全に管理されたクラウドサービス**

  完全に管理されたクラウドサービスは、MQTTサービスを開始する最も簡単な方法です。[EMQX Cloud](https://www.emqx.com/en/cloud)を使用すると、わずか数分で開始し、AWS、Google Cloud、Microsoft Azureの20以上のリージョンでMQTTサービスを実行できます。

  最新版の[EMQX Cloud Serverless](https://www.emqx.com/en/cloud/serverless-mqtt)では、開発者が数秒でMQTTデプロイメントを簡単に開始できる、毎月1Mセッション分/月の永久無料オファリングを提供しています。

- **無料のパブリッシュMQTTブローカー**

  無料のパブリッシュMQTTブローカーは、MQTTプロトコルを学び、テストするためのものです。セキュリティリスクやダウンタイムの懸念があるため、本番環境での使用は避けてください。

このブログ投稿では、`broker.emqx.io`の無料パブリッシュMQTTブローカーを使用します。

> MQTTブローカー情報：
>
> サーバー：`broker.emqx.io`
>
> TCPポート：`1883`
>
> WebSocketポート：`8083`
>
> SSL/TLSポート：`8883`
>
> セキュアWebSocketポート：`8084`

詳細については、[無料のパブリッシュMQTTブローカー](https://www.emqx.com/en/mqtt/public-mqtt5-broker)をご覧ください。

> EMQXはデフォルトでポート8083を通常の接続、ポート8084をTLS上のWebSocket接続に使用しています

## MQTT over WebSocketの使用開始

### MQTT WebSocketクライアントのインストール

[MQTT.js](https://github.com/mqttjs/MQTT.js)は、MQTTプロトコル用の完全オープンソースのクライアントサイドライブラリで、JavaScriptで記述され、Node.jsとブラウザで利用できます。MQTT/TCP、MQTT/TLS、MQTT/WebSocket接続をサポートしています。

この記事では、WebSocket接続を説明するためにMQTT.jsライブラリを使用します。

Node.jsランタイム環境がある場合は、`npm`コマンドを使用してMQTT.jsをインストールできます。Node.jsでコマンドラインを介してグローバルにインストールし、接続することができます。

**Node.jsプロジェクト用のインストール**

```
# npmを使ってインストール
npm install mqtt --save

# yarnを使ってインストール
yarn add mqtt
```

**CDNリファレンス**

ブラウザで直接作業し、ライブラリをインストールしたくない場合は、CDNを使用することもできます。

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

<script>
   // グローバルにmqtt変数を初期化
   console.log(mqtt)
</script>
```

### ブラウザでWebSocket経由でブローカーに接続

簡単にするために、基本的なHTMLファイルを作成してブラウザで直接実装します。このファイルでは、パブリッシャーとサブスクライバーの両方を設定します。

```javascript
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WebSocket MQTT</title>
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
</head>
<body>
  WebSocketクライアントを使用してMQTTサーバーに接続する
</body>
<script>
    const clientId = 'mqttjs_' + Math.random().toString(16).substr(2, 8)
    const host = 'ws://broker.emqx.io:8083/mqtt'
    const options = {
      keepalive: 60,
      clientId: clientId,
      protocolId: 'MQTT',
      protocolVersion: 4,
      clean: true,
      reconnectPeriod: 1000,
      connectTimeout: 30 * 1000,
      will: {
        topic: 'WillMsg',
        payload: 'Connection Closed abnormally..!',
        qos: 0,
        retain: false
      },
    }
    console.log('Connecting mqtt client')
    const client = mqtt.connect(host, options)
    client.on('error', (err) => {
      console.log('Connection error: ', err)
      client.end()
    })
    client.on('reconnect', () => {
      console.log('Reconnecting...')
    })
</script>
```

### 接続アドレス

例の接続アドレス `ws://broker.emqx.io:8083/mqtt` は `プロトコル` // `ホスト名` . `ドメイン` : `ポート` / `パス` を含んでいます。発生しやすい間違いには以下のものがあります。

- MQTT.jsクライアントに接続する際は、接続アドレスにプロトコルタイプを指定する必要があります。これは、クライアントが複数のプロトコルをサポートしているためです。また、MQTTではWebSocket用のポートが指定されていません。EMQXは8083を非暗号化接続のデフォルトポートとしていますが、暗号化された接続には `8084` をデフォルトとしています。
- 接続アドレスからパスを省略すること：MQTT over WebSocketでは、接続パスとして統一的に `/mqtt` を使用します。接続する際には、このパスを指定する必要があります。
- プロトコルとポートが不一致です。`mqtt://` はMQTT用、`ws://` や `wss://` はWebSocket接続用に使用し、HTTPSの下では暗号化されたWebSocket接続を使用することを確認してください。
- 証明書が接続アドレスと一致していません。

### 接続オプション

前のコードスニペットでの `options` は、クライアントの接続オプションを指します。これらのオプションには、`keepalive`、`clientId`、`username`、`password`、`clean`、`reconnectPeriod`、`connectTimeout`、`will` などのパラメータが含まれています。各オプションの詳細な説明については、[MQTT.jsのドキュメント](https://github.com/mqttjs/MQTT.js#client)を参照してください。

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

成功した接続後にのみサブスクライブが可能で、サブスクライブするトピックはMQTTのサブスクライブトピックルールに準拠している必要があります。JavaScriptの非同期機能により、'connect'イベント後、または`client.connected`を使用して成功した接続が保証されます。

```javascript
client.on('connect', () => {
  console.log(`Client connected: ${clientId}`)
  // トピックをサブスクライブ
  client.subscribe('testtopic', { qos: 0 })
})
// トピックを解除
client.unubscribe('testtopic', () => {
  console.log('Unsubscribed');
})
```

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

特定のトピックにメッセージをパブリッシュできますが、これらのトピックはMQTTのパブリッシュトピックルールに準拠している必要があります。パブリッシュする前にトピックをサブスクライブする必要はありませんが、クライアントは接続されている必要があります。

```javascript
// メッセージをパブリッシュ
client.publish('testtopic', 'ws connection demo...!', { qos: 0, retain: false })
// メッセージを受信
client.on('message', (topic, message, packet) => {
  console.log(`Received Message: ${message.toString()} On topic: ${topic}`)
})
```

より詳細な情報と例については、[JavaScript MQTT Client: A Beginner's Guide to MQTT.js](https://www.emqx.com/en/blog/mqtt-js-tutorial)を参照してください。

### SSL/TLSのWebSocketの使用

WSSプロトコル（WebSocket Secure）を使用して、TLS（以前のSSL）接続上でのセキュアなWebSocket接続を確立できます。TLSは接続上で送信されるデータを暗号化し、データのプライバシーと整合性を保証し、認証を可能にします。

MQTT.jsでTLS上のWebSocketを使用するには、ブローカーアドレスのプロトコルを`ws`から`wss`に変更する必要があります。ただし、接続先のブローカーがWSS接続をサポートしており、WSSのポート番号が正しいことも確認する必要があります。例えば、EMQXはデフォルトでWSS接続にポート`8084`を使用しています。

セキュアな接続を確立する方法の例は以下の通りです：

```javascript
const host = 'wss://broker.emqx.io:8084/mqtt'
const options = {
  // 他のオプションは以前と同様
}

const client = mqtt.connect(host, options)

// その他のコード...
```

HTTPS経由でのWebページからブローカーにWSSで接続する場合は、ブローカーの証明書がクライアントのブラウザによって信頼されていることを確認する必要があります。これは通常、証明書がよく知られた証明機関によって発行され、期限切れ、取り消されていない、または異なるドメインで使用されていないことを意味します。ブローカーに自己署名証明書を使用している場合は、手動でブラウザの信頼ストアに追加する必要があります。

TLS上のWebSocketを使用する際の詳細および関連する問題については、[MQTT.jsのドキュメント](https://github.com/mqttjs/MQTT.js#client)またはMQTTブローカーに関連する適切なチュートリアルを参照してください。

> 注：ブラウザでWebSocket接続を使用する場合、双方向認証接続を確立することはできません。ただし、この機能はほとんどの他のプログラミング言語環境でサポートされています。例えば、Node.jsでは以下のようになります：

```javascript
const mqtt = require('mqtt')
const fs = require('fs')
const path = require('path')

const KEY = fs.readFileSync(path.join(__dirname, '/tls-key.pem'))
const CERT = fs.readFileSync(path.join(__dirname, '/tls-cert.pem'))
const TRUSTED_CA_LIST = fs.readFileSync(path.join(__dirname, '/crt.ca.cg.pem'))

const host = 'wss://broker.emqx.io:8084/mqtt'
const options = {
    ...
  key: KEY,
  cert: CERT,
  rejectUnauthorized: true,
  ca: TRUSTED_CA_LIST,
}

const client = mqtt.connect(host, options)
```

## テスト

Webブラウザで作成したHTMLファイルを開いて、セットアップをテストしてみましょう。[MQTTX](https://mqttx.app/)のようなツールを使用して、MQTTインタラクションに対するGUIを提供します。テスト方法は以下の通りです。

1. ブラウザのコンソールを開くと、成功した接続のメッセージが表示され、サブスクライブしたトピックのメッセージが受信されます。

   ![WebSocket MQTTデモ](https://assets.emqx.com/images/bc98a964995202fdfcf363062ba363fd.png?imageMogr2/thumbnail/1520x)

2. MQTTXで同じアドレスに接続し、サブスクライブしたトピックに「Hello from MQTTX」というメッセージを送信します。

   ![MQTTX](https://assets.emqx.com/images/b87c8ee484061f0be7703458970db92b.png?imageMogr2/thumbnail/1520x)

3. このメッセージがブラウザのコンソールで受信されていることが確認できます。

   ![ブラウザのコンソールでメッセージが受信されています](https://assets.emqx.com/images/03ddd11518fd159650487a897f855fee.png?imageMogr2/thumbnail/1520x)



## Q&A

### MQTTとWebSocketの違いは何ですか？

MQTT（Message Queuing Telemetry Transport）は、パブリッシュ/サブスクライブパターンに基づくメッセージ転送プロトコルです。通常、IoTデバイス間の通信に使用されます。低オーバーヘッドと低帯域幅消費の軽量プロトコルで、リソースに制約のあるデバイスに適しています。

WebSocketは、単一のTCP接続上で永続的な全二重通信チャネルを提供する双方向通信プロトコルです。WebSocketは通常、Webアプリケーションとサーバー間のリアルタイム通信に使用され、クライアントが要求を送信することなく、サーバーからクライアントにデータをプッシュできます。

主な違いはプロトコルの設計と使用例にあります。MQTTはパブリッシュ/サブスクライブ通信用のメッセッセージ転送プロトコルであり、WebSocketはリアルタイム双方向通信用の通信プロトコルです。

### WSSはブラウザで双方向認証接続をサポートしていますか？

いいえ、ブラウザでの接続を確立する際に、JavaScriptコードを使用してクライアント証明書を指定することはできません。OSの証明書ストアやスマートカードにクライアント証明書が設定されていても、MQTT.jsはこれを行うことができません。また、証明機関（CA）も指定できません。これはブラウザによって制御されます。

参考：[How to use TLS/SSL two-way authentication connections in browser? · Issue #1515 · mqttjs/MQTT.js](https://github.com/mqttjs/MQTT.js/issues/1515)

### ブラウザ環境外で使用できますか？

はい、MQTT over WebSocketはブラウザ環境以外でも使用できます。Python、Node.js、Golangなど、さまざまなプログラミング言語には対応する[MQTTクライアントライブラリ](https://www.emqx.com/en/mqtt-client-sdk)があり、選択した環境でMQTTブローカーに接続し、MQTT over WebSocketを使用して通信できます。TLS/SSL接続がサポートされている場合は、相互証明書認証も使用できます。

### EMQXに接続する際にパスを入力する必要があるのはなぜですか？

Webocketを使用して[EMQX](https://www.emqx.io/)に接続する場合、パスを入力する必要があります。これは、EMQXがMQTT-WebSocketの統一されたパス仕様に従っているためです。この仕様では、WebSocket接続で特定のパスを指定する必要があり、これによりMQTT over WebSocketのトラフィックをMQTTブローカーにルーティングし、処理します。

EMQXでは、MQTT over WebSocketのデフォルトパスは`/mqtt`です。この設定は仕様に基づいています。したがって、EMQXに接続する際は、WebSocketアドレスにこのパスを含める必要があり、MQTTブローカーに正しく接続するためには不可欠です。

### MQTT Webアプリケーションを開発する際、Vue.jsやReactを使用していても、WebSocket接続のみを使用する必要がありますか？

ブラウザでアプリケーションを開発している場合、MQTT over WebSocket接続を確立するためにはWebSocket接続のみを使用する必要があります。

## まとめ

このクイックスタートガイドでは、MQTT over WebSocketを使用して、MQTTブローカーとWebブラウザ間のリアルタイム通信を確立する基本をカバーしています。WebSocket接続の確立、[MQTTクライアント](https://www.emqx.com/en/blog/mqtt-client-tools)の初期化、メッセージのサブスクライブとパブリッシュ、接続のテストについての必要なステップを説明しています。

プロジェクトの完全なコードは、このGitHubリンクで見ることができます：[MQTT-Client-Examples/mqtt-client-WebSocket at master · emqx/MQTT-Client-Examples](https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-WebSocket)。

MQTTプロトコルの機能についてさらに学びたい場合、MQTTの高度なアプリケーションを探求したい場合、またはMQTTアプリケーションおよびサービス開発を始めたい場合は、EMQによる[MQTTガイド：初心者から上級者まで](https://www.emqx.com/en/mqtt-guide)の一連の記事をチェックしてください。

## リソース

MQTT over WebSocketについてさらに学ぶための有用なリソースは次のとおりです：

- [MQTTX Web](https://mqttx.app/web)

  MQTTX Webは、オンラインでのデバッグ、開発、およびMQTTアプリケーションのテスト用のユーザーフレンドリーなブラウザベースのツールです。WebSocketクライアントを介してMQTTブローカーに接続し、直感的なインターフェースを提供します。

- [2023年のトップ3 MQTT WebSocketクライアント](https://www.emqx.com/en/blog/top-3-mqtt-websocket-clients-in-2023)

  このブログでは、2023年に強く推奨されるトップ3のMQTT WebSocketクライアントツールについて探ります。

- [JavaScript MQTT Client: MQTT.jsの初心者ガイド](https://www.emqx.com/en/blog/mqtt-js-tutorial)

  このブログは、MQTT.jsのいくつかの一般的なAPIの使用と使用プロセスでの経験について紹介し、ユーザーがJavaScriptプロジェクトでMQTT.jsを迅速に使用できるようにすることを目的としています。

- [VueでのMQTTの使用方法](https://www.emqx.com/en/blog/how-to-use-mqtt-in-vue)

  このブログでは主に、VueプロジェクトでMQTTを使用する方法を紹介し、クライアントとMQTTブローカー間の接続、サブスクライブ、メッセージング、解除などの機能を実装します。

- [ReactでのMQTTの使用方法](https://www.emqx.com/en/blog/how-to-use-mqtt-in-react)

  この記事では、ReactプロジェクトでMQTTを使用する方法を主に紹介し、クライアントとMQTTブローカー間の接続、サブスクライブ、メッセージング、解除などを実装します。