Skip to content

A thread-safe MQTT client for Arduino ESP32xx, based on ESP-IDF MQTT component. Work with the latest ESP32 Arduino Core 3.x and ESP-IDF 5.x.

License

cyijun/ESP32MQTTClient

Repository files navigation

ESP32MQTTClient

Arduino CI ESP-IDF CI Ask DeepWiki

A thread-safe MQTT client for native ESP-IDF or Arduino ESP32. This library is compatible with arduino-esp32 v2/v3+ and ESP-IDF v4.x/v5.x C++.

Table of Contents

Features

  • Non-blocking operation - MQTT runs in background FreeRTOS task, no loop() calls needed
  • Thread-safe MQTT client based on the official esp-mqtt component
  • TLS/SSL support for secure MQTT connections (port 8883)
  • Uses standard C++ std::string instead of Arduino String
  • Logging is performed using the standard ESP-IDF ESP_LOGX macros
  • Provides both specific topic subscriptions and a global "catch-all" message callback
  • Interfaces inspired by EspMQTTClient
  • CA cert support by dwolshin
  • Arduino-esp32 v3+ support by dzungpv

Non-Blocking Architecture

Unlike blocking MQTT libraries, loopStart() returns immediately and MQTT operations run in a background FreeRTOS task. This means:

  • No watchdog timeouts during connection
  • Safe for single-core devices (e.g., ESP32-C3)
  • Main loop stays responsive
  • Connection typically completes in ~1 second vs 8+ seconds with blocking clients

Quick Start

Arduino Setup

#include <WiFi.h>
#include "ESP32MQTTClient.h"

ESP32MQTTClient mqttClient;

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "PASSWORD");
  
  mqttClient.setURI("mqtt://broker.hivemq.com:1883");
  mqttClient.setMqttClientName("ESP32_Client");
  mqttClient.loopStart(); // Non-blocking!
}

void loop() {
  // Your code here - no need for mqttClient.loop()
  delay(1000);
}

TLS/SSL Example

// For TLS brokers like HiveMQ Cloud
const char* caCert = "-----BEGIN CERTIFICATE-----\n...";

void setup() {
  // ... WiFi setup ...
  
  mqttClient.setURL("broker.hivemq.cloud", 8883, "username", "password");
  mqttClient.setCaCert(caCert);  // Enable TLS verification
  mqttClient.loopStart();
}

String Handling

This library uses std::string instead of Arduino String. Here's how to handle conversions:

// ✅ Correct - use std::string directly
std::string topic = "mytopic";
std::string payload = "Hello World";
mqttClient.publish(topic, payload, 0, false);

// ✅ Convert from Arduino String
String arduinoTopic = "mytopic";
String arduinoPayload = "Hello World";
mqttClient.publish(arduinoTopic.c_str(), arduinoPayload.c_str(), 0, false);

// ❌ This will cause compilation error
// String arduinoTopic = "mytopic";
// mqttClient.publish(arduinoTopic, payload, 0, false);

Required Global Callbacks

Important: These callback functions must be global (not class methods, not lambdas):

// Required global callback for connection events
void onMqttConnect(esp_mqtt_client_handle_t client) {
  if (mqttClient.isMyTurn(client)) {
    // Subscribe to topics here
    mqttClient.subscribe("test/topic", [](const std::string &payload) {
      Serial.printf("Received: %s\n", payload.c_str());
    });
  }
}

// Required global event handler - ESP-IDF version dependent
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
esp_err_t handleMQTT(esp_mqtt_event_handle_t event) {
  mqttClient.onEventCallback(event);
  return ESP_OK;
}
#else
void handleMQTT(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
  auto *event = static_cast<esp_mqtt_event_handle_t>(event_data);
  mqttClient.onEventCallback(event);
}
#endif

Migration Guide from PubSubClient

If you're migrating from the popular PubSubClient library:

PubSubClient ESP32MQTTClient Notes
client.connect() mqttClient.loopStart() Non-blocking, returns immediately
client.loop() Not needed Runs automatically in background
client.connected() mqttClient.isConnected() Check connection status
client.setServer() + setCallback() mqttClient.setURL() + callbacks Similar setup pattern
client.setBufferSize() mqttClient.setMaxPacketSize() Adjust packet size limits
Arduino String std::string Use .c_str() for conversion

Example Migration

Before (PubSubClient):

PubSubClient client;

void setup() {
  client.setServer("broker", 1883);
  client.setCallback(messageCallback);
}

void loop() {
  if (!client.connected()) {
    client.connect("client"); // Blocks for 8+ seconds!
  }
  client.loop(); // Required in every loop
}

After (ESP32MQTTClient):

ESP32MQTTClient mqttClient;

void setup() {
  mqttClient.setURI("mqtt://broker:1883");
  mqttClient.loopStart(); // Returns immediately!
}

void loop() {
  // No mqttClient.loop() needed!
}

API Reference

Configuration Methods

  • setURL(url, port, username, password) - Set broker connection details
  • setURI(uri, username, password) - Set complete MQTT URI
  • setMqttClientName(name) - Set client ID
  • setCaCert(caCert) - Enable TLS with CA certificate
  • setClientCert(clientCert) - Set client certificate
  • setKey(clientKey) - Set client private key
  • setMaxPacketSize(size) - Set maximum packet size (default: 1024)
  • setKeepAlive(seconds) - Change keepalive interval (default: 15s)
  • enableLastWillMessage(topic, message, retain) - Set last will message
  • setAutoReconnect(choice) - Enable/disable auto-reconnect
  • disableAutoReconnect() - Disable auto-reconnect
  • enableDebuggingMessages(enabled) - Enable debug logging

Lifecycle Methods

  • loopStart() - Start non-blocking MQTT connection
  • isConnected() - Check connection status
  • isMyTurn(client) - Check if event is for this client

Pub/Sub Methods

  • publish(topic, payload, qos, retain)bool - Publish message
  • subscribe(topic, callback, qos)bool - Subscribe with payload callback
  • subscribe(topic, callbackWithTopic, qos)bool - Subscribe with topic+payload callback
  • unsubscribe(topic)bool - Unsubscribe from topic
  • setOnMessageCallback(callback) - Set global message handler

New Functions

setOnMessageCallback(MessageReceivedCallbackWithTopic callback)

Sets a global callback function that is invoked for any incoming message, regardless of the topic. This is useful for centralized logging or handling all messages in one place.

Example:

mqttClient.setOnMessageCallback([](const std::string &topic, const std::string &payload) {
    ESP_LOGI("MAIN", "Global handler: %s: %s", topic.c_str(), payload.c_str());
});

setAutoReconnect(bool choice)

Enables or disables the automatic reconnection feature of the underlying ESP-IDF MQTT client. By default, auto-reconnect is enabled.

Example:

// Disable automatic reconnection
mqttClient.setAutoReconnect(false);

Building the ESP-IDF Example

The library includes a native ESP-IDF example in the examples/CppEspIdf directory. To build it:

  1. Set up ESP-IDF: Ensure you have the ESP-IDF environment installed and configured.
  2. Configure Wi-Fi: Open examples/CppEspIdf/main/main.cpp and set your Wi-Fi SSID and password.
  3. Build the project:
    cd examples/CppEspIdf
    idf.py build

About

A thread-safe MQTT client for Arduino ESP32xx, based on ESP-IDF MQTT component. Work with the latest ESP32 Arduino Core 3.x and ESP-IDF 5.x.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published