次にESP32でMQTTにトライしてみます。
先のESP8266用のMQTTクライアントを改造して動かしてみます。(何箇所か引っかかったところがあり、こちらの記事を参考にさせていただきました)
まず、WiFiのヘッダが違いますので、インクルードするファイルを変更します。
// ESP8266 #include <ESP8266WiFi.h>
を
// ESP32 #include <WiFi.h> #include <WiFiClientSecure.h>
に変更します。
WiFiClientSecure.hを見ると、FingerPrintを検証する方法はESP32版では使えないようなので、ルート証明書を使って検証する形にします。(という表現であっているのか?用語が適切ではないかもしれません)
const char* root_ca = R"( -----BEGIN CERTIFICATE----- ... 証明書の中身 -----END CERTIFICATE----- )";
として、ルート証明書をヒアドキュメントに似た raw string literal の形で貼り付けます。raw string literal についてはこちらが参考になります。ルート証明書は、
$ openssl s_client -connect example.com:443 -showcerts
として、証明書情報を表示させた中にあります。Let’s Encryptを使っている場合、
O = Digital Signature Trust Co., CN = DST Root CA X3
の部分になります。
主要な処理は以下の通りになります。
const char* mqtt_server = "..."; // MQTTサーバーのホスト名 const char* mqtt_user = "..."; // MQTTのユーザー名 const char* mqtt_pass = "..."; // MQTTのパスワード WiFiClientSecure espClient; // 接続にTLSを使う PubSubClient client(espClient); // トピックを設定 #define TOPIC_SIZE (64) char OutTopic[TOPIC_SIZE]; char InTopic[TOPIC_SIZE]; void callback(char* topic, byte* payload, unsigned int length) { // メッセージ受信時のコールバック処理 } void reconnect() { // 再接続に成功するまで繰り返す while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // ランダムなクライアントIDを生成 String clientId = "ESP32Client-"; clientId += String(random(0xffff), HEX); // 接続 if (client.connect(clientId.c_str(),mqtt_user,mqtt_pass)) { Serial.println("connected"); // client.publish(OutTopic, "START"); client.subscribe(InTopic); } else { Serial.print("failed, rc="); Serial.println(client.state()); // 改行追加 char buf[256]; // SSLエラー表示のためのバッファ確保 espClient.lastError(buf,256); // エラーメッセージ取得 Serial.print("SSL error: "); // エラーメッセージ表示 Serial.println(buf); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void setup() { setup_wifi(); setTopic(); // トピックを設定 Serial.println(root_ca); espClient.setCACert(root_ca); client.setServer(mqtt_server, 8883); // 接続先のポートを 1883 ⇒ 8883 に変更する client.setCallback(callback); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); : // 定期的な処理(例:1分間に1回) client.publish(OutTopic, msg); }
あと、ついでですが、MQTTの最大パケットサイズを変更します。
#include <PubSubClient.h> #define MQTT_MAX_PACKET_SIZE 1024
これでMQTTでデータ送信ができるようになりましたが、SmartConfigが上手く行っていません。次はそこを修正します。