اتصال ESP32 به بروکر MQTT با TLS (PubSubClient)
آموزش

اتصال ESP32 به بروکر MQTT با TLS (PubSubClient)

۷ آبان ۱۴۰۵۷ دقیقه مطالعه

یک نمونه کامل و قابل اجرا برای اتصال امن ESP32 به بروکر روی پورت 8883، همراه با اتصال مجدد خودکار و نکاتی که معمولاً در اولین تلاش مشکل‌ساز می‌شوند.

پیش‌نیازها#

  • برد ESP32 و Arduino IDE (یا PlatformIO) با پشتیبانی ESP32
  • کتابخانه PubSubClient نوشته Nick O'Leary از Library Manager
  • یک اکانت MQTT و یک دستگاه ثبت‌شده در داشبورد (مثلاً شناسه esp32-01)

گواهی ریشه برای TLS#

گواهی بروکر توسط Let's Encrypt صادر شده و زنجیره آن به گواهی ریشه ISRG Root X1 می‌رسد. ESP32 مجموعه گواهی‌های سیستم را ندارد، پس باید همین گواهی ریشه را در کد قرار دهید. متن PEM آن را از صفحه رسمی گواهی‌های Let's Encrypt (letsencrypt.org/certificates) بردارید و در ثابت ROOT_CA بگذارید.

استفاده از setInsecure() بررسی گواهی را کاملاً خاموش می‌کند؛ فقط برای آزمایش اولیه مناسب است و نباید روی دستگاه نهایی بماند.

کد کامل#

cpp
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>

const char* WIFI_SSID = "your-wifi";
const char* WIFI_PASS = "your-wifi-password";

const char* MQTT_HOST = "mqtt.mqttcloud.ir";
const int   MQTT_PORT = 8883;
const char* MQTT_USER = "alice";          // your MQTT username
const char* MQTT_PASS = "YOUR_PASSWORD";
const char* CLIENT_ID = "esp32-01";       // registered in the dashboard

// ISRG Root X1, PEM from letsencrypt.org/certificates
const char* ROOT_CA = R"EOF(
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
)EOF";

WiFiClientSecure net;
PubSubClient client(net);

void onMessage(char* topic, byte* payload, unsigned int length) {
  Serial.printf("%s: %.*s\n", topic, length, (char*)payload);
}

void connectMqtt() {
  while (!client.connected()) {
    if (client.connect(CLIENT_ID, MQTT_USER, MQTT_PASS)) {
      client.subscribe("alice/esp32-01/cmd");
    } else {
      Serial.printf("MQTT connect failed, state=%d\n", client.state());
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);

  net.setCACert(ROOT_CA);
  client.setServer(MQTT_HOST, MQTT_PORT);
  client.setCallback(onMessage);
  client.setBufferSize(512);  // default is 256 bytes
}

unsigned long lastSend = 0;

void loop() {
  if (!client.connected()) connectMqtt();
  client.loop();

  if (millis() - lastSend > 10000) {
    lastSend = millis();
    client.publish("alice/esp32-01/temp", "{\"c\":24.8}");
  }
}

نکات مهم#

  • همه تاپیک‌ها باید با نام کاربری اکانت و یک / شروع شوند. انتشار روی تاپیک خارج از این فضا باعث قطع اتصال دستگاه می‌شود.
  • CLIENT_ID باید دقیقاً همان شناسه ثبت‌شده در داشبورد باشد.
  • PubSubClient پیام‌ها را فقط با QoS 0 منتشر می‌کند؛ اشتراک با QoS 0 یا 1 ممکن است.
  • اندازه بافر پیش‌فرض PubSubClient ۲۵۶ بایت است؛ پیام بزرگ‌تر بی‌صدا ارسال نمی‌شود. با setBufferSize آن را بزرگ کنید.
  • اگر client.state() عدد ۵ برگرداند، بروکر اتصال را «غیرمجاز» دانسته است؛ مقاله عیب‌یابی اتصال MQTT دلیل‌های رایج آن را توضیح می‌دهد.
#ESP32#Arduino#PubSubClient#TLS