ArduinoVN
Đăng nhập Tham gia
Thư viện Code /u/linucat /31/03/2026

Thư viện PubSubClient: subscribe/publish MQTT trên ESP32/Arduino

Thảo luận

PubSubClient của Nick O'Leary là thư viện MQTT phổ biến nhất cho Arduino/ESP32 — gọn nhẹ, ổn định, hỗ trợ MQTT 3.1.1. Bài này liệt kê toàn bộ API kèm pattern cho production.

1. Cài đặt

Library Manager → "PubSubClient" by Nick O'Leary. Cài tự động dependency: không có. Yêu cầu một Client (vd WiFiClient, WiFiClientSecure, EthernetClient).

2. Khởi tạo

#include 
#include 

WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);

void setup() {
  mqtt.setServer("192.168.1.100", 1883);
  mqtt.setCallback(onMessage);
}

3. Connect — có và không auth

mqtt.connect("client-id");
mqtt.connect("client-id", "username", "password");
mqtt.connect("client-id", "user", "pass",
             "home/status", 0, true, "offline");
// Last Will: nếu disconnect bất thường, broker tự publish "offline"

Client ID phải unique trên broker — trùng = thiết bị kia bị đá. Best practice: dùng MAC address:

String cid = "esp-" + String((uint32_t)ESP.getEfuseMac(), HEX);
mqtt.connect(cid.c_str());

4. Publish

mqtt.publish("home/temp", "25.4");
mqtt.publish("home/temp", "25.4", true);  // retain
mqtt.publish("home/raw", payload, length); // raw bytes

Trả về bool — false khi disconnect hoặc payload > buffer (mặc định 256 byte).

5. Subscribe

mqtt.subscribe("home/livingroom/cmd");
mqtt.subscribe("home/+/temp");   // wildcard 1 cấp
mqtt.subscribe("home/#");        // wildcard nhiều cấp
mqtt.subscribe("home/cmd", 1);   // QoS 1
mqtt.unsubscribe("home/cmd");

6. Callback nhận message

void onMessage(char* topic, byte* payload, unsigned int len) {
  String s;
  for (unsigned i = 0; i < len; i++) s += (char)payload[i];
  Serial.printf("[%s] %s\n", topic, s.c_str());

  if (strcmp(topic, "home/cmd") == 0) {
    if (s == "on")  digitalWrite(LED, HIGH);
    if (s == "off") digitalWrite(LED, LOW);
  }
}

Quan trọng: payload KHÔNG null-terminated, chỉ có len byte. Đừng dùng strcmp(payload, "on") trực tiếp — đọc rác.

7. Loop — bắt buộc

void loop() {
  if (!mqtt.connected()) reconnect();
  mqtt.loop();   // xử lý keepalive, callback
  // ... code khác
}

Không gọi mqtt.loop() = không nhận message, disconnect sau 15s.

8. Reconnect with backoff

void reconnect() {
  uint32_t delay_ms = 500;
  while (!mqtt.connected()) {
    String cid = "esp-" + String((uint32_t)ESP.getEfuseMac(), HEX);
    if (mqtt.connect(cid.c_str(), USER, PASS,
                     "home/status", 0, true, "offline")) {
      mqtt.publish("home/status", "online", true);
      mqtt.subscribe("home/cmd");
      return;
    }
    Serial.print("rc="); Serial.println(mqtt.state());
    delay(delay_ms);
    delay_ms = min((uint32_t)10000, delay_ms * 2);   // backoff
  }
}

9. Buffer size — gửi JSON lớn

Mặc định payload tối đa 256 byte (header + topic + data). JSON dài 500 byte sẽ fail. Tăng buffer:

mqtt.setBufferSize(1024);    // gọi trước connect()

Hoặc set qua define MQTT_MAX_PACKET_SIZE khi compile.

10. Keepalive

mqtt.setKeepAlive(60);   // mặc định 15s

Tăng nếu network chậm, giảm nếu cần phát hiện disconnect nhanh.

11. Sockets timeout

mqtt.setSocketTimeout(10);   // giây, mặc định 15

12. State codes — debug fail connect

state()Ý nghĩa
0MQTT_CONNECTED
-1MQTT_DISCONNECTED
-2MQTT_CONNECT_FAILED — TCP fail (broker không reach)
-3MQTT_CONNECTION_LOST
-4MQTT_CONNECTION_TIMEOUT
2MQTT_CONNECT_BAD_PROTOCOL
3MQTT_CONNECT_BAD_CLIENT_ID
4MQTT_CONNECT_BAD_CREDENTIALS
5MQTT_CONNECT_UNAUTHORIZED

13. TLS / mTLS

WiFiClientSecure secureClient;
secureClient.setCACert(rootCA);
// hoặc skip verify (chỉ debug):
// secureClient.setInsecure();
PubSubClient mqtt(secureClient);
mqtt.setServer("broker.hivemq.com", 8883);

14. Async — khi cần hiệu năng cao

PubSubClient là synchronous, block khi gửi. Cần xử lý nhanh và đa connection: chuyển sang AsyncMqttClient (Marvin Roger) — based on AsyncTCP, không block, callback-driven.

Liên quan

Hướng dẫn bối cảnh đầy đủ: ESP32 + MQTT với PubSubClient từ A-Z. Dùng cùng ArduinoJson để truyền JSON. Tham khảo dự án Smart home MQTT + Home Assistant với ESP32.

Thảo luận (0)

Đăng nhập để tham gia thảo luận.
Chưa có bình luận nào. Hãy là người đầu tiên!