# マルチプロトコルゲートウェイ

EMQX マルチプロトコルゲートウェイは、MQTT以外のすべてのプロトコル接続、認証、およびメッセージの送受信を処理する機能を提供します。さまざまなプロトコルに対して統一された概念モデルを提供します。

EMQX 5.0以前は、MQTT以外のプロトコルアクセスは個別のプロトコルプラグインによって実装されており、これらのプラグインは設計や実装が異なっていたため、利用が難しい面がありました。

5.0以降、EMQXはマルチプロトコルゲートウェイとして統一された概念および運用モデルを定義し、より使いやすくなっています。

マルチプロトコルゲートウェイは、MQTT-SN、STOMP、CoAP、LwM2Mなどのプロトコルをサポートしています。Dashboard上で直接有効化・設定できるほか、REST APIや`base.hocon`を用いて管理することも可能です。これらのゲートウェイの有効化方法や、ビジネスニーズに合わせた設定カスタマイズについては、以下のリンクをご参照ください。

::: warning 重要なお知らせ
ExProto ゲートウェイは EMQX `6.2.0` から非推奨であり、`v7` で削除予定です。
:::

- [MQTT-SN](./mqttsn.md)
- [STOMP](./stomp.md)
- [CoAP](./coap.md)
- [LwM2M](./lwm2m.md)
- [ExProto](./exproto.md)

- [OCPP](./ocpp.md)
- [GB/T 32960](./gbt32960.md)
- [JT/T 808](./jt808.md)
- [NATS](./nats.md)

## マルチプロトコルゲートウェイの仕組み

EMQX マルチプロトコルゲートウェイは、リスナー、コネクション／セッション、パブリッシュ／サブスクライブ、認証、認可など、いくつかの主要コンポーネントに対して統一された概念および運用モデルを定義しています。

<img src="./assets/gateway_struct.png" alt="ゲートウェイ構造" style="zoom:50%;" />

各コンポーネントの概要は以下の通りです：

- **リスナー**：TCP、SSL、UDP、DTLSのリスナータイプをサポートします。各ゲートウェイは複数のリスナーを作成可能です。
- **コネクション／セッション**：ゲートウェイは受け入れたクライアントコネクションごとにセッションを作成し、サブスクリプションリスト、送受信キュー、クライアントメッセージの再送制御を管理します。
- **パブリッシュ／サブスクライブ**：各ゲートウェイタイプは、MQTTプロトコルのPUB/SUBメッセージモデルへの適応方法を定義します。PUB/SUBを持たないプロトコルではメッセージのトピックやペイロードの設定が必要であり、ゲートウェイタイプごとに異なるメッセージフォーマットを使用する場合があります。
- **認証**：各ゲートウェイは認証機能を設定でき、クライアント情報を用いたログイン認可を行います。

## 主な機能

### リスナー

各ゲートウェイは複数のリスナーを有効化でき、プロトコルごとに以下のリスナータイプをサポートしています：

|            | TCP  | UDP  | SSL  | DTLS | Websocket | Websocket over TLS |
| ---------- | ---- | ---- | ---- | ---- | --------- | ------------------ |
| MQTT-SN    |      | ✔︎    |      | ✔︎    |           |                    |
| STOMP      | ✔︎    |      | ✔︎    |      |           |                    |
| CoAP       |      | ✔︎    |      | ✔︎    |           |                    |
| LwM2M      |      | ✔︎    |      | ✔︎    |           |                    |
| ExProto    | ✔︎    | ✔︎    | ✔︎    | ✔︎    |           |                    |
| OCPP       |      |      |      |      | ✔︎         | ✔︎                  |
| GB/T 32960 | ✔︎    |      | ✔︎    |      |           |                    |
| JT/T 808   | ✔︎    |      |      | ✔︎    |           |                    |
| NATS       | ✔︎    |      | ✔︎    |      | ✔︎         | ✔︎                  |

### メッセージフォーマット

PUB/SUBメッセージモデルとの互換性を確保するため、各ゲートウェイタイプは基盤となるプロトコルにPUB/SUBの概念があるかどうかに適応する必要があります。

PUB/SUBの概念を持つプロトコル（[MQTT-SN](./mqttsn.md)、[STOMP](./stomp.md)など）では、クライアントが送信するトピックとペイロードをそのまま使用するため、メッセージフォーマットの変換は不要です。

一方、[CoAP](./coap.md)や[LwM2M](./lwm2m.md)のようにPUB/SUBの概念を持たないプロトコルでは、トピックやパブリッシュ・サブスクライブの定義がなく、ゲートウェイ側でメッセージ内容のフォーマットを設計する必要があります。各ゲートウェイタイプで異なるフォーマットを使用する場合があります。

- **CoAP**：CoAPゲートウェイは、[Publish-Subscribe Broker for the CoAP](https://datatracker.ietf.org/doc/html/draft-ietf-core-coap-pubsub-09)標準で定義されたURIパスとメソッドを使用します。詳細は[メッセージパブリッシュ](./coap.md#message-publish)、[トピックサブスクライブ](./coap.md#topic-subscribe)、[トピックサブスクライブ解除](./coap.md#topic-unsubscribe)をご参照ください。
- **LwM2M**：LwM2Mプロトコルのメッセージモデルは、[Resources Model and Operations](https://technical.openmobilealliance.org/OMNA/LwM2M/LwM2MRegistry.html)に基づいており、MQTTのパブリッシュ／サブスクライブモデルとは全く異なります。詳細は[LwM2Mゲートウェイ - メッセージフォーマット](./lwm2m.md#message-format)をご覧ください。

### 認証

認証は、システムに接続しようとするクライアントの身元を検証するプロセスです。バージョン5.0以降、ゲートウェイはログイン認可のための認証機能をサポートしています。

ゲートウェイによってサポートされる認証タイプは異なりますが、すべてのゲートウェイでHTTPベースの認証が利用可能です。[HTTPベース認証](../access-control/authn/http.md)をご参照ください。以下の表はサポートされる認証タイプの一覧です：

|            | HTTPサーバー | 組み込みデータベース | MySQL | MongoDB | PostgreSQL | Redis | JWT  | LDAP |
| ---------- | ------------ | -------------------- | ----- | ------- | ---------- | ----- | ---- | ---- |
| MQTT-SN    | ✔︎           |                      |       |         |            |       |      |      |
| STOMP      | ✔︎           | ✔︎                    | ✔︎     | ✔︎       | ✔︎          | ✔︎     | ✔︎    | ✔︎    |
| CoAP       | ✔︎           | ✔︎                    | ✔︎     | ✔︎       | ✔︎          | ✔︎     | ✔︎    | ✔︎    |
| LwM2M      | ✔︎           |                      |       |         |            |       |      |      |
| Exproto    | ✔︎           | ✔︎                    | ✔︎     | ✔︎       | ✔︎          | ✔︎     | ✔︎    | ✔︎    |
| OCPP       | ✔︎           | ✔︎                    | ✔︎     | ✔︎       | ✔︎          | ✔︎     | ✔︎    | ✔︎    |
| GB/T 32960 | ✔︎           |                      |       |         |            |       |      |      |
| JT/T 808   | N/A          | N/A                  | N/A   | N/A     | N/A        | N/A   | N/A  |      |
| NATS       | ✔︎           | ✔︎                    | ✔︎     | ✔︎       | ✔︎          | ✔︎     | ✔︎    | ✔︎    |

注：認証機能が設定されていない場合は、どのクライアントもログイン可能です。

#### ゲートウェイにおける認証の仕組み

EMQX マルチプロトコルゲートウェイは、接続してくるクライアントの認証を担当します。これは各コネクションに対して`ClientInfo`を作成することで実現されます。

`ClientInfo`には、認証に一般的に使用される`Username`や`Password`などの汎用フィールドが含まれます。さらに、LwM2Mの`Endpoint Name`のように、各ゲートウェイ固有のクライアント情報フィールドも存在し、これらも認証に利用される場合があります。

認証機能が設定されている場合、ゲートウェイはクライアントのUsernameおよびPasswordを自身のデータベースに保存された情報と照合し、一致すればクライアントを認証しゲートウェイへのアクセスを許可します。

::: tip

異なるゲートウェイ間でクライアントIDは重複しても問題ありませんが、同一ゲートウェイ内でクライアントIDが重複してログインすると、既存のそのクライアントIDに紐づくセッションは切断されます。

:::

## 外部システムとの連携

外部システムとの連携を強化するため、ゲートウェイはEMQXで定義されたフックもサポートしています。

ただし、ゲートウェイ間の意味論の違いにより、コアフックの一部のみが利用可能です。

クライアント接続に関連するフックのサポート状況は以下の通りです：

外部システムとの相互運用性向上のため、ゲートウェイはEMQXで定義されたフックをサポートする設計となっています。

しかし、各ゲートウェイ間の意味論の違いにより、利用可能なコアフックは一部に限られます。以下の表はクライアント接続関連のサポートされるフック一覧です：

| 名前                   | 必須かどうか    | 説明                                                         | 対応プロトコル       |
| ---------------------- | --------------- | ------------------------------------------------------------ | -------------------- |
| `client.connect`       | 任意            | クライアント接続要求の数（成功・失敗を含む）                 | 全ゲートウェイ       |
| `client.connack`       | 任意            | クライアントが受信した`CONNACK`メッセージの数                | 全ゲートウェイ       |
| `client.authenticate`  | 必須            | 認証されたクライアントの数                                    |                      |
| `client.connected`     | 必須            | 正常に接続されたクライアントの数                              | 全ゲートウェイ       |
| `client.disconnected`  | 必須            | クライアントの切断数（正常切断および異常切断を含む）          | 全ゲートウェイ       |
| `client.authorize`     | 必須            | 認可されたクライアントのパブリッシュ／サブスクライブ要求数    | 全ゲートウェイ       |
| `client.subscribe`     | 任意            | クライアントのトピックサブスクライブ試行数                    | MQTT-SN<br />STOMP   |
| `client.unsubscribe`   | 任意            | クライアントのトピックサブスクライブ解除試行数                | MQTT-SN<br/>STOMP    |

セッションおよびメッセージ関連のフックはプロトコル間の意味論の違いがないため、各ゲートウェイタイプで完全にサポートされています。

フックの詳細については[Hooks](../extensions/hooks.md)をご参照ください。
