ESP8266との接続
本記事では、ESP8266プロジェクトでのPubSubClient
の使用方法について紹介します。クライアントとMQTTブローカー間の接続、サブスクライブ、メッセージングなどの機能の実装方法を解説します。
ESP8266は、高度に統合されたWi-Fi SoCソリューションを提供します。低消費電力、小型設計、高い安定性によりユーザーの要件を満たします。ESP8266は完全かつ独立したWi-Fiネットワーク機能を備えており、単独での利用や他のホストMCUのスレーブとして動作可能です。
本記事では、ESP8266クライアントをTCPポートおよびTLS/SSLポート経由でMQTTブローカーに接続する方法を示します。Serverlessデプロイメントの場合はTLS/SSLポート接続のデモをご参照ください。TCPポート接続とTLS/SSLポート接続では設定が異なりますが、パブリッシュおよびサブスクライブ機能のコードは同じです。
前提条件
接続前に、ブローカーとクライアントの準備が必要です。
MQTTブローカーの準備
EMQXが提供する無料のパブリックMQTTブローカーを利用できます。このサービスはEMQXプラットフォームを基に構築されています。ブローカーアクセス情報は以下の通りです:
- ブローカー:broker.emqx.io
- TCPポート:1883
- SSL/TLSポート:8883
また、デプロイメントを作成することも可能です。デプロイメントの概要で接続情報を確認してください。デプロイメントが稼働中であることを確認し、TCPポートまたはTLS/SSLポートでMQTTサーバーへの接続をテストしてください。
独自のデプロイメントを作成する場合は、アクセス制御 -> 認証を確認し、認証用のユーザー名とパスワードを設定してください。
Arduino IDE
本記事ではコードエディター兼アップローダーとしてArduino IDEを使用します。オープンソースのArduinoソフトウェア(IDE)はコードの作成とボードへのアップロードを容易にします。任意のArduinoボードで使用可能です。
依存関係のインストール
Arduino IDEで以下のインストールを完了してください:
- ESP8266開発ボードのインストール
ツール -> 開発ボード -> 開発ボードマネージャーをクリックし、ESP8266を検索してインストールをクリックします。 - PubSubClientのインストール
スケッチ -> ライブラリをインクルード -> **ライブラリマネージャー...**をクリックし、PubSubClientを検索してNick O’LearyによるPubSubClientをインストールします。
TCPポートでの接続
このセクションでは、Arduino IDEでESP8266クライアントをTCPポート経由でMQTTブローカーに接続する方法を説明します。
- ライブラリESP8266WiFiとPubSubClientをインポートします。
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
- Wi-Fi名とパスワード、接続先アドレスとポートを設定します。
サンプルコードはパブリックMQTTサーバーに接続するため、ユーザー名とパスワードは不要です。デプロイメントを作成した場合は、クライアント認証を参照してユーザー名とパスワードを設定してください。
// WiFi設定
const char *ssid = "WIFI_SSID"; // ご自身のWiFi名に置き換えてください
const char *password = "WIFI_PASSWORD"; // ご自身のWiFiパスワードに置き換えてください
// MQTTブローカー設定
const char *mqtt_broker = "broker.emqx.io"; // EMQXブローカーのエンドポイント
const char *mqtt_topic = "emqx/esp8266"; // MQTTトピック
const char *mqtt_username = "emqx"; // 認証用MQTTユーザー名
const char *mqtt_password = "public"; // 認証用MQTTパスワード
const int mqtt_port = 1883; // MQTTポート(TCP)
- シリアル接続を開き、プログラムの結果を出力し、Wi-Fiネットワークに接続します。
void setup() {
Serial.begin(115200);
connectToWiFi();
mqtt_client.setServer(mqtt_broker, mqtt_port);
mqtt_client.setCallback(mqttCallback);
connectToMQTTBroker();
}
void connectToWiFi() {
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to the WiFi network");
}
- MQTTブローカーを設定し、コールバック関数を記述し、シリアルモニターに接続情報を出力します。
void connectToMQTTBroker() {
while (!mqtt_client.connected()) {
String client_id = "esp8266-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 ESP8266 ^^");
} else {
Serial.print("Failed to connect to MQTT broker, rc=");
Serial.print(mqtt_client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
- MQTTブローカーへの接続に成功すると、ESP8266はトピック
esp8266/test
にメッセージをパブリッシュし、同トピックのメッセージをサブスクライブします。
mqtt_client.subscribe(mqtt_topic);
// 接続成功時にメッセージをパブリッシュ
mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP8266 ^^");
- 受信したメッセージのトピック名をシリアルポートに出力し、メッセージの各バイトを順に表示します。
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();
Serial.println("-----------------------");
}
以下に完全なコードを示します。
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// WiFi設定
const char *ssid = "WIFI_SSID"; // ご自身のWiFi名に置き換えてください
const char *password = "WIFI_PASSWORD"; // ご自身のWiFiパスワードに置き換えてください
// MQTTブローカー設定
const char *mqtt_broker = "broker.emqx.io"; // EMQXブローカーのエンドポイント
const char *mqtt_topic = "emqx/esp8266"; // MQTTトピック
const char *mqtt_username = "emqx"; // 認証用MQTTユーザー名
const char *mqtt_password = "public"; // 認証用MQTTパスワード
const int mqtt_port = 1883; // MQTTポート(TCP)
WiFiClient espClient;
PubSubClient mqtt_client(espClient);
void connectToWiFi();
void connectToMQTTBroker();
void mqttCallback(char *topic, byte *payload, unsigned int length);
void setup() {
Serial.begin(115200);
connectToWiFi();
mqtt_client.setServer(mqtt_broker, mqtt_port);
mqtt_client.setCallback(mqttCallback);
connectToMQTTBroker();
}
void connectToWiFi() {
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to the WiFi network");
}
void connectToMQTTBroker() {
while (!mqtt_client.connected()) {
String client_id = "esp8266-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 ESP8266 ^^");
} else {
Serial.print("Failed to connect to MQTT broker, rc=");
Serial.print(mqtt_client.state());
Serial.println(" try again 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();
Serial.println("-----------------------");
}
void loop() {
if (!mqtt_client.connected()) {
connectToMQTTBroker();
}
mqtt_client.loop();
}
TLS/SSLポートでの接続
このセクションでは、Arduino IDEでESP8266クライアントをTLS/SSLポート経由でMQTTブローカーに接続する方法を説明します。TLS/SSLポート接続の設定はTCPポート接続と異なりますが、パブリッシュおよびサブスクライブ機能のコードは同じです。
- ライブラリESP8266WiFi、PubSubClient、timeをインポートします。
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <time.h>
- Wi-Fi名とパスワード、接続先アドレスとポートを設定します。
サンプルコードはパブリックMQTTサーバーに接続するため、ユーザー名とパスワードは不要です。デプロイメントを作成した場合は、クライアント認証を参照してユーザー名とパスワードを設定してください。
// WiFi認証情報
const char *ssid = "WIFI_SSID"; // ご自身のWiFi名に置き換えてください
const char *password = "WIFI_PASSWORD"; // ご自身のWiFiパスワードに置き換えてください
// MQTTブローカー設定
const int mqtt_port = 8883; // MQTTポート(TLS)
const char *mqtt_broker = "broker.emqx.io"; // EMQXブローカーのエンドポイント
const char *mqtt_topic = "emqx/esp8266"; // MQTTトピック
const char *mqtt_username = "emqx"; // 認証用MQTTユーザー名
const char *mqtt_password = "public"; // 認証用MQTTパスワード
- サーバーとSSL証明書を設定します。
// NTPサーバー設定
const char *ntp_server = "pool.ntp.org"; // デフォルトNTPサーバー
// const char* ntp_server = "cn.pool.ntp.org"; // 中国ユーザー向け推奨NTPサーバー
const long gmt_offset_sec = 0; // GMTオフセット(秒単位、タイムゾーンに応じて調整)
const int daylight_offset_sec = 0; // サマータイムオフセット(秒単位)
// WiFiおよびMQTTクライアント初期化
BearSSL::WiFiClientSecure espClient;
PubSubClient mqtt_client(espClient);
// MQTTブローカー用SSL証明書
// EMQXパブリックブローカー broker.emqx.ioで使用されるDigiCert Global Root G2をロード
static const char ca_cert[]
PROGMEM = 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 Deploymentで使用されるDigiCert Global Root CA ca_certのロード例
/*
static const char ca_cert[] PROGMEM = 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-----
)EOF";
*/
- シリアル接続を開き、プログラムの結果を出力し、Wi-Fiネットワークに接続します。
void setup() {
Serial.begin(115200);
connectToWiFi();
syncTime(); // X.509検証には時刻同期が必要
mqtt_client.setServer(mqtt_broker, mqtt_port);
mqtt_client.setCallback(mqttCallback);
connectToMQTT();
}
void connectToWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
}
- フィンガープリントとMQTTブローカーを設定し、コールバック関数を記述し、シリアルモニターに接続情報を出力します。
void connectToMQTT() {
BearSSL::X509List serverTrustedCA(ca_cert);
espClient.setTrustAnchors(&serverTrustedCA);
while (!mqtt_client.connected()) {
String client_id = "esp8266-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 ESP8266 ^^");
} else {
char err_buf[128];
espClient.getLastSSLError(err_buf, sizeof(err_buf));
Serial.print("Failed to connect to MQTT broker, rc=");
Serial.println(mqtt_client.state());
Serial.print("SSL error: ");
Serial.println(err_buf);
delay(5000);
}
}
}
- MQTTブローカーへの接続に成功すると、ESP8266はメッセージをパブリッシュし、MQTTブローカーをサブスクライブします。
mqtt_client.subscribe(mqtt_topic);
// 接続成功時にメッセージをパブリッシュ
mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP8266 ^^");
- 受信したメッセージのトピック名をシリアルポートに出力し、メッセージの各バイトを順に表示します。
void mqttCallback(char *topic, byte *payload, unsigned int length) {
Serial.print("Message received on topic: ");
Serial.print(topic);
Serial.print("]: ");
for (int i = 0; i < length; i++) {
Serial.print((char) payload[i]);
}
Serial.println();
}
以下に完全なコードを示します。
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <time.h>
// WiFi認証情報
const char *ssid = "WIFI_SSID"; // ご自身のWiFi名に置き換えてください
const char *password = "WIFI_PASSWORD"; // ご自身のWiFiパスワードに置き換えてください
// MQTTブローカー設定
const int mqtt_port = 8883; // MQTTポート(TLS)
const char *mqtt_broker = "broker.emqx.io"; // EMQXブローカーのエンドポイント
const char *mqtt_topic = "emqx/esp8266"; // MQTTトピック
const char *mqtt_username = "emqx"; // 認証用MQTTユーザー名
const char *mqtt_password = "public"; // 認証用MQTTパスワード
// NTPサーバー設定
const char *ntp_server = "pool.ntp.org"; // デフォルトNTPサーバー
// const char* ntp_server = "cn.pool.ntp.org"; // 中国ユーザー向け推奨NTPサーバー
const long gmt_offset_sec = 0; // GMTオフセット(秒単位、タイムゾーンに応じて調整)
const int daylight_offset_sec = 0; // サマータイムオフセット(秒単位)
// WiFiおよびMQTTクライアント初期化
BearSSL::WiFiClientSecure espClient;
PubSubClient mqtt_client(espClient);
// MQTTブローカー用SSL証明書
// EMQXパブリックブローカー broker.emqx.ioで使用されるDigiCert Global Root G2をロード
static const char ca_cert[]
PROGMEM = 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 Deploymentで使用されるDigiCert Global Root CA ca_certのロード例
/*
static const char ca_cert[] PROGMEM = 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-----
)EOF";
*/
// 関数宣言
void connectToWiFi();
void connectToMQTT();
void syncTime();
void mqttCallback(char *topic, byte *payload, unsigned int length);
void setup() {
Serial.begin(115200);
connectToWiFi();
syncTime(); // X.509検証には時刻同期が必要
mqtt_client.setServer(mqtt_broker, mqtt_port);
mqtt_client.setCallback(mqttCallback);
connectToMQTT();
}
void connectToWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
}
void syncTime() {
configTime(gmt_offset_sec, daylight_offset_sec, ntp_server);
Serial.print("Waiting for NTP time sync: ");
while (time(nullptr) < 8 * 3600 * 2) {
delay(1000);
Serial.print(".");
}
Serial.println("Time synchronized");
struct tm timeinfo;
if (getLocalTime(&timeinfo)) {
Serial.print("Current time: ");
Serial.println(asctime(&timeinfo));
} else {
Serial.println("Failed to obtain local time");
}
}
void connectToMQTT() {
BearSSL::X509List serverTrustedCA(ca_cert);
espClient.setTrustAnchors(&serverTrustedCA);
while (!mqtt_client.connected()) {
String client_id = "esp8266-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 ESP8266 ^^");
} else {
char err_buf[128];
espClient.getLastSSLError(err_buf, sizeof(err_buf));
Serial.print("Failed to connect to MQTT broker, rc=");
Serial.println(mqtt_client.state());
Serial.print("SSL error: ");
Serial.println(err_buf);
delay(5000);
}
}
}
void mqttCallback(char *topic, byte *payload, unsigned int length) {
Serial.print("Message received on topic: ");
Serial.print(topic);
Serial.print("]: ");
for (int i = 0; i < length; i++) {
Serial.print((char) payload[i]);
}
Serial.println();
}
void loop() {
if (!mqtt_client.connected()) {
connectToMQTT();
}
mqtt_client.loop();
}
接続のテスト
ESP8266クライアントがMQTTブローカーに正常に接続された後、Arduino IDEとMQTTXを使って接続をテストできます。
- Arduino IDEで完全なコードをESP8266にアップロードし、シリアルモニターを開きます。
- MQTTXクライアントとMQTTブローカー間の接続を確立し、ESP8266にメッセージを送信します。
- シリアルモニターでESP8266が受信したメッセージを確認します。
まとめ
以上で、ESP8266プロジェクトにおけるMQTT接続の作成、クライアントとMQTTブローカー間の接続、サブスクライブ、メッセージ送受信のシミュレーションを実装しました。サンプルコードはこちらからダウンロード可能です。また、他言語のデモ例もGitHubでご覧いただけます。