# ESP32との接続

本記事では、ESP32プロジェクトでの`PubSubClient`の使用方法を主に紹介します。クライアントとMQTTブローカー間の接続、サブスクライブ、メッセージ送受信などの機能の実装方法を解説します。

ESP8266のアップグレード版である[ESP32](https://www.espressif.com/en/products/socs/esp32)は、IoTプロジェクトに最適な選択肢です。Wi-Fiモジュールに加え、Bluetooth 4.0モジュールも搭載しています。デュアルコアCPUは80〜240 MHzの周波数で動作し、2つのWi-FiおよびBluetoothモジュールと多様な入出力ピンを備えています。

本記事では、ESP32クライアントをTCPポートおよびTLS/SSLポート経由でMQTTブローカーに接続する方法を示します。Serverlessデプロイメントの場合はTLS/SSLポート接続のデモをご参照ください。TCPポートとTLS/SSLポートの接続設定は異なりますが、パブリッシュおよびサブスクライブのコードは共通です。

## 前提条件

接続前に、ブローカーとクライアントの準備を行ってください。

### MQTTブローカーの準備

EMQXが提供する[無料のパブリックMQTTブローカー](https://www.emqx.com/en/mqtt/public-mqtt5-broker)を利用できます。このサービスは[EMQX Platform](https://www.emqx.com/en)を基に構築されています。ブローカーアクセス情報は以下の通りです：
- ブローカー：**broker.emqx.io**
- TCPポート：**1883**
- SSL/TLSポート：**8883**

[デプロイメントを作成](../create/overview.md)することも可能です。デプロイメント概要で接続情報を確認し、デプロイメントが稼働中であることを確認してください。MQTTサーバーへの接続テストにはTCPポートまたはTLS/SSLポートを使用します。

独自にデプロイメントを作成する場合は、[認証](../deployments/auth_overview.md)を確認し、**アクセス制御** -> **認証**でユーザー名とパスワードを設定してください。

### Arduino IDE
本記事ではコードエディター兼アップローダーとして[Arduino IDE](https://www.arduino.cc/en/software)を使用します。オープンソースのArduinoソフトウェア（IDE）はコードの記述とボードへのアップロードを容易にします。任意のArduinoボードで使用可能です。

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

Arduino IDEで以下をインストールしてください：

1. ESP32開発ボードをインストール  
   **ツール** -> **開発ボード** -> **開発ボードマネージャー**をクリックし、ESP32を検索して**インストール**をクリックします。
2. PubSubClientをインストール  
   **スケッチ** -> **ライブラリをインクルード** -> **ライブラリマネージャー...**をクリックし、PubSubClientを検索してNick O’LearyによるPubSubClientをインストールします。

## TCPポート経由で接続する

このセクションでは、Arduino IDEでESP32クライアントをTCPポート経由でMQTTブローカーに接続する方法を説明します。

1. WiFiとPubSubClientライブラリをインポートします。

```c
#include <WiFi.h>
#include <PubSubClient.h>
```

2. Wi-FiのSSIDとパスワード、MQTTサーバーの接続アドレスとポートを設定し、トピックを`esp32/test`に設定します。

> サンプルコードはパブリックMQTTサーバーに接続するため、ユーザー名とパスワードは不要です。デプロイメントを作成した場合は、[デフォルト認証](../deployments/default_auth.md)を参照し、ユーザー名とパスワードを設定してください。

```c
// WiFi Credentials
const char *ssid = "WIFI_SSID";            // ご自身のWiFi名に置き換えてください
const char *password = "WIFI_PASSWORD";  // ご自身のWiFiパスワードに置き換えてください

// MQTT Broker Settings
const char *mqtt_broker = "broker.emqx.io";
const char *mqtt_topic = "emqx/esp32";
const char *mqtt_username = "emqx";
const char *mqtt_password = "public";
const int mqtt_port = 1883;
```

3. シリアル接続を開き、プログラムの結果を出力し、Wi-Fiネットワークに接続します。

```c
void setup() {
    Serial.begin(115200);
    connectToWiFi();
    mqtt_client.setServer(mqtt_broker, mqtt_port);
    mqtt_client.setKeepAlive(60);
    mqtt_client.setCallback(mqttCallback); // コールバック関数名を修正済み
    connectToMQTT();
}

void connectToWiFi() {
    WiFi.begin(ssid, password);
    Serial.print("Connecting to WiFi");
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("\nConnected to WiFi");
}
```

4. PubSubClientを使ってパブリックMQTTブローカーに接続します。

```c
void connectToMQTT() {
    while (!mqtt_client.connected()) {
        String client_id = "esp32-client-" + String(WiFi.macAddress());
        Serial.printf("Connecting to MQTT Broker as %s.....\n", client_id.c_str());
        if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
            Serial.println("Connected to MQTT broker");
            mqtt_client.subscribe(mqtt_topic);
            mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 ^^"); // 接続成功時にメッセージをパブリッシュ
        } else {
            Serial.print("Failed, rc=");
            Serial.print(mqtt_client.state());
            Serial.println(" try again in 5 seconds");
            delay(5000);
        }
    }
}
```

5. MQTTサーバーへの接続が成功すると、ESP32はトピック`esp32/test`にメッセージをパブリッシュし、同トピックのメッセージをサブスクライブします。

```c
// パブリッシュとサブスクライブ
mqtt_client.subscribe(mqtt_topic);
mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 ^^"); // 接続成功時にメッセージをパブリッシュ
```

6. コールバック関数を設定し、トピック名をシリアルポートに出力し、`esp32/test`トピックから受信したメッセージを表示します。

```c
void mqttCallback(char *mqtt_topic, byte *payload, unsigned int length) {
    Serial.print("Message received on mqtt_topic: ");
    Serial.println(mqtt_topic);
    Serial.print("Message: ");
    for (unsigned int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
    }
    Serial.println("\n-----------------------");
}
```

以下に完全なコードを示します：

```c
#include <WiFi.h>
#include <PubSubClient.h>

// WiFi Credentials
const char *ssid = "WIFI_SSID";            // ご自身のWiFi名に置き換えてください
const char *password = "WIFI_PASSWORD";  // ご自身のWiFiパスワードに置き換えてください

// MQTT Broker Settings
const char *mqtt_broker = "broker.emqx.io";
const char *mqtt_topic = "emqx/esp32";
const char *mqtt_username = "emqx";
const char *mqtt_password = "public";
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient mqtt_client(espClient);

// 関数宣言
void connectToWiFi();

void connectToMQTT();

void mqttCallback(char *mqtt_topic, byte *payload, unsigned int length);

void setup() {
    Serial.begin(115200);
    connectToWiFi();
    mqtt_client.setServer(mqtt_broker, mqtt_port);
    mqtt_client.setKeepAlive(60);
    mqtt_client.setCallback(mqttCallback); // コールバック関数名を修正済み
    connectToMQTT();
}

void connectToWiFi() {
    WiFi.begin(ssid, password);
    Serial.print("Connecting to WiFi");
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("\nConnected to WiFi");
}

void connectToMQTT() {
    while (!mqtt_client.connected()) {
        String client_id = "esp32-client-" + String(WiFi.macAddress());
        Serial.printf("Connecting to MQTT Broker as %s.....\n", client_id.c_str());
        if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
            Serial.println("Connected to MQTT broker");
            mqtt_client.subscribe(mqtt_topic);
            mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 ^^"); // 接続成功時にメッセージをパブリッシュ
        } else {
            Serial.print("Failed, rc=");
            Serial.print(mqtt_client.state());
            Serial.println(" try again in 5 seconds");
            delay(5000);
        }
    }
}

void mqttCallback(char *mqtt_topic, byte *payload, unsigned int length) {
    Serial.print("Message received on mqtt_topic: ");
    Serial.println(mqtt_topic);
    Serial.print("Message: ");
    for (unsigned int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
    }
    Serial.println("\n-----------------------");
}

void loop() {
    if (!mqtt_client.connected()) {
        connectToMQTT();
    }
    mqtt_client.loop();
}
```

## TLS/SSLポート経由で接続する

このセクションでは、Arduino IDEでESP32クライアントをTLS/SSLポート経由でMQTTブローカーに接続する方法を説明します。TLS/SSLポートの接続設定はTCPポートと異なりますが、パブリッシュおよびサブスクライブのコードは共通です。

1. ESP32WiFi、PubSubClient、WiFiClientSecureライブラリをインポートします。

```c
#include <WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>
```

2. Wi-FiのSSIDとパスワード、接続先アドレスとポートを設定します。

> サンプルコードはパブリックMQTTサーバーに接続するため、ユーザー名とパスワードは不要です。デプロイメントを作成した場合は、[デフォルト認証](../deployments/default_auth.md)を参照し、ユーザー名とパスワードを設定してください。

```c
// WiFi credentials
const char *ssid = "WIFI_SSID";             // ご自身のWiFi名に置き換えてください
const char *password = "WIFI_PASSWORD";   // ご自身のWiFiパスワードに置き換えてください

// MQTT Broker settings
const char *mqtt_broker = "broker.emqx.io";
const char *mqtt_topic = "emqx/esp32";
const char *mqtt_username = "emqx";
const char *mqtt_password = "public";
const int mqtt_port = 8883;
```

3. サーバー側証明書を設定します。

   パブリックMQTTブローカーを使用する場合は、[CA証明書をダウンロード](https://assets.emqx.com/data/emqxsl-ca.crt)し、ServerlessデプロイメントのTLS/SSLポート接続に使用してください。Dedicatedデプロイメントの場合は独自のサーバー証明書を使用します。

```c
// ルートCA証明書
// EMQXパブリックブローカー broker.emqx.ioで使用されるDigiCert Global Root G2をロード
const char *ca_cert = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----
)EOF";

// EMQX Serverlessデプロイメントで使用されるDigiCert Global Root CA ca_certの例
/*
const char* ca_cert = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----
*/
```

4. シリアル接続を開き、プログラムの結果を出力し、Wi-Fiネットワークに接続します。

```c
void setup() {
    Serial.begin(115200);
    connectToWiFi();

    // ルートCA証明書を設定
    esp_client.setCACert(ca_cert);

    mqtt_client.setServer(mqtt_broker, mqtt_port);
    mqtt_client.setKeepAlive(60);
    mqtt_client.setCallback(mqttCallback);
    connectToMQTT();
}

void connectToWiFi() {
    WiFi.begin(ssid, password);
    Serial.print("Connecting to WiFi");
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("\nConnected to WiFi");
}
```

5. 証明書とMQTTブローカーを設定し、コールバック関数を書き、接続情報をシリアルモニターに表示します。

```c
void connectToMQTT() {
    while (!mqtt_client.connected()) {
        String client_id = "esp32-client-" + String(WiFi.macAddress());
        Serial.printf("Connecting to MQTT Broker as %s...\n", client_id.c_str());
        if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
            Serial.println("Connected to MQTT broker");
            mqtt_client.subscribe(mqtt_topic);
            mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 ^^");  // 接続成功時にメッセージをパブリッシュ
        } else {
            Serial.print("Failed to connect to MQTT broker, rc=");
            Serial.print(mqtt_client.state());
            Serial.println(" Retrying in 5 seconds.");
            delay(5000);
        }
    }
}
```

6. MQTTブローカーへの接続が成功すると、ESP32はメッセージをパブリッシュし、サブスクライブします。

```c
// パブリッシュとサブスクライブ
mqtt_client.subscribe(mqtt_topic);
mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 ^^");  // 接続成功時にメッセージをパブリッシュ
```

7. トピック名をシリアルポートに出力し、受信したメッセージの各バイトを表示します。

```c
void callback(char *topic, byte *payload, unsigned int length) {
    Serial.print("Message arrived in topic: ");
    Serial.println(topic);
    Serial.print("Message:");
    for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
    }
    Serial.println();
    Serial.println("-----------------------");
}
```

8. 再接続用関数

```c
void mqttCallback(char *topic, byte *payload, unsigned int length) {
    Serial.print("Message received on topic: ");
    Serial.println(topic);
    Serial.print("Message: ");
    for (unsigned int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
    }
    Serial.println("\n-----------------------");
}
```

以下に完全なコードを示します：

```c
#include <WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>

// WiFi credentials
const char *ssid = "WIFI_SSID";             // ご自身のWiFi名に置き換えてください
const char *password = "WIFI_PASSWORD";   // ご自身のWiFiパスワードに置き換えてください

// MQTT Broker settings
const char *mqtt_broker = "broker.emqx.io";
const char *mqtt_topic = "emqx/esp32";
const char *mqtt_username = "emqx";
const char *mqtt_password = "public";
const int mqtt_port = 8883;

// WiFiとMQTTクライアントの初期化
WiFiClientSecure esp_client;
PubSubClient mqtt_client(esp_client);

// ルートCA証明書
// EMQXパブリックブローカー broker.emqx.ioで使用されるDigiCert Global Root G2をロード
const char *ca_cert = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----
)EOF";

// 関数宣言
void connectToWiFi();

void connectToMQTT();

void mqttCallback(char *topic, byte *payload, unsigned int length);

void setup() {
    Serial.begin(115200);
    connectToWiFi();

    // ルートCA証明書を設定
    esp_client.setCACert(ca_cert);

    mqtt_client.setServer(mqtt_broker, mqtt_port);
    mqtt_client.setKeepAlive(60);
    mqtt_client.setCallback(mqttCallback);
    connectToMQTT();
}

void connectToWiFi() {
    WiFi.begin(ssid, password);
    Serial.print("Connecting to WiFi");
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("\nConnected to WiFi");
}

void connectToMQTT() {
    while (!mqtt_client.connected()) {
        String client_id = "esp32-client-" + String(WiFi.macAddress());
        Serial.printf("Connecting to MQTT Broker as %s...\n", client_id.c_str());
        if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
            Serial.println("Connected to MQTT broker");
            mqtt_client.subscribe(mqtt_topic);
            mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 ^^");  // 接続成功時にメッセージをパブリッシュ
        } else {
            Serial.print("Failed to connect to MQTT broker, rc=");
            Serial.print(mqtt_client.state());
            Serial.println(" Retrying in 5 seconds.");
            delay(5000);
        }
    }
}

void mqttCallback(char *topic, byte *payload, unsigned int length) {
    Serial.print("Message received on topic: ");
    Serial.println(topic);
    Serial.print("Message: ");
    for (unsigned int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
    }
    Serial.println("\n-----------------------");
}

void loop() {
    if (!mqtt_client.connected()) {
        connectToMQTT();
    }
    mqtt_client.loop();
}
```

## 接続テスト

ESP32クライアントがMQTTブローカーに正常に接続された後、Arduino IDEおよびMQTTXを使用して接続をテストできます。

1. シリアルモニターを開き、ボーレートを115200に設定し、ESP32の接続状態を確認します。  
   ![esp32_connection](./_assets/esp32_connection.png)
2. MQTTXクライアントとMQTTブローカー間の接続を確立し、ESP32にメッセージを送信します。  
   ![esp32_mqttx](./_assets/esp32_mqttx.png)

## まとめ

本記事では、ESP32プロジェクトにおいてMQTT接続を作成し、クライアントとMQTTブローカー間の接続、サブスクライブ、メッセージ送受信をシミュレートしました。サンプルコードは[こちら](https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-ESP32)からダウンロード可能です。また、他言語のデモ例も[GitHub](https://github.com/emqx/MQTT-Client-Examples)でご覧いただけます。
