esp32.diy

ESP32 MQTT Example: Publish & Subscribe Step-by-Step

Oct 13, 2026 · 7 min read · Intermediate

ESP32 MQTT Example: Publish & Subscribe Step-by-Step
TL;DR The ESP32 connects to an MQTT broker using Espressif's ESP-MQTT component, added with `idf.py add-dependency espressif/mqtt`. Once connected, it can publish sensor data or subscribe to topics to trigger actions like controlling a relay.
Protocol versions supportedMQTT v3.1.1 and v5.0
Component install commandidf.py add-dependency espressif/mqtt
Public test broker (TLS)mqtts://test.mosquitto.org:8886
Alternative TLS broker URImqtts://test.mosquitto.org:8883
Transport optionsTCP, TLS, WebSocket, WebSocket Secure, mutual auth
Cloud broker supportAWS IoT Core, Azure IoT Hub

What do you need before you start?

Before writing a single line of code, gather these pieces:

If you plan to control hardware — a relay, LED, or motor — also have the output device wired and ready.

ESP32 development board used in MQTT publish/subscribe examples\2

ESP32 development board used in MQTT publish/subscribe examples Image: Edwiyanto, CC BY-SA 4.0, via Wikimedia Commons

How does the ESP32 MQTT stack actually work?

ESP-MQTT is Espressif's own MQTT client implementation, shipped as part of ESP-IDF. It handles the full MQTT protocol stack so your application code only needs to set a broker URI, register an event handler, and then call publish or subscribe functions.

As of ESP-IDF v6.0, the ESP-MQTT component was moved out of the main ESP-IDF repository and into its own dedicated repository. That means it is now managed as a separate dependency rather than being bundled automatically. The upside is that it can ship updates independently of the core SDK.

The component supports both MQTT v3.1.1 and MQTT v5.0, and it can operate over several transport layers:

Transport Use case
Plain TCP Unencrypted, LAN or trusted networks
TLS Encrypted, certificate-validated connections
WebSocket (WS) Firewalls that block raw TCP 1883
WebSocket Secure (WSS) Encrypted WebSocket
Mutual TLS auth Client certificate required by broker

For most beginner projects, plain TCP to a local broker or TLS to a public broker is the right starting point.

Espressif ESP-WROOM-32 Wi-Fi and Bluetooth module used with MQTT on ESP32\2

Espressif ESP-WROOM-32 Wi-Fi and Bluetooth module used with MQTT on ESP32 Image: Brian Krent, CC BY-SA 4.0, via Wikimedia Commons

How do you add and configure ESP-MQTT in your project?

Step 1 — Add the component

From inside your ESP-IDF project directory, run:

idf.py add-dependency espressif/mqtt

This fetches the component from the Espressif component registry and records it in your project's manifest so it is automatically available at build time.

Step 2 — Choose a broker URI

Decide where your ESP32 will connect. For a first test, use one of the public Mosquitto URIs that Espressif's own examples target:

For a local or private broker, replace the URI with your own hostname and port. For AWS IoT Core or Azure IoT Hub, additional certificate and policy setup is required (see the Common Mistakes section).

Step 3 — Reference the official examples

Two reference projects ship with ESP-IDF:

Example path What it demonstrates
protocols/mqtt MQTT over TLS with certificate bundle validation
protocols/mqtt5 MQTT v5.0 over TLS with certificate bundle

For additional transport modes — plain TCP, WebSocket, WebSocket Secure, and mutual authentication — the espressif/mqtt component repository on the Espressif component registry includes further example projects you can clone and adapt.

ESP32 MQTT subscribe example: controlling a relay

The cleanest way to understand subscribe-driven control is to look at a concrete project. The following is an ESP32 relay controller written for Mongoose OS in JavaScript. The board subscribes to a topic; when a JSON payload arrives, it parses the state field and writes the GPIO accordingly.

Wiring assumption: relay signal wire connected to GPIO 4.

Subscribe and control code:

load('api_config.js');
load('api_gpio.js');
load('api_mqtt.js');

let relaypin = 4;
GPIO.set_mode(relaypin, GPIO.MODE_OUTPUT);
GPIO.write(relaypin, 1);

MQTT.sub('my/rainsensor', function(conn, topic, payload) {
    let test = JSON.parse(payload);
    if (1 === test.state) {
        GPIO.write(relaypin, 0);
    } else if (0 === test.state) {
        GPIO.write(relaypin, 1);
    }
}, null);

Publish payload format to turn the relay ON:

{"actuator": "relay1", "state": 1}

Publish payload format to turn the relay OFF:

{"actuator": "relay1", "state": 0}

Key points from this pattern:

ESP32 MQTT publish example: sending data to the broker

Publishing works in the opposite direction — your ESP32 sends data to a topic, and any subscriber (a dashboard, Home Assistant, Node-RED, or another device) receives it.

In the ESP-IDF / ESP-MQTT model, once the client is connected and the MQTT event handler reports a successful connection, your application calls the publish function with a topic string, a payload, a payload length, a QoS level, and a retain flag.

For integration with smart-home platforms, Tasmota — an alternative open-source firmware that runs on the full ESP32 family including ESP32-S2, S3, C2, C3, C5, C6, and P4 — handles publish and subscribe automatically. It publishes sensor readings and device state to your broker using MQTT v3.1.1 or v5, and plugs directly into Home Assistant, Domoticz, openHAB, and Node-RED without custom code. For projects where you just need a standard sensor or switch talking MQTT, Tasmota removes the need to write publish/subscribe logic at all.

For custom firmware where you need full control, the ESP-MQTT component's publish API is the right tool. The two TLS examples in ESP-IDF (protocols/mqtt and protocols/mqtt5) both demonstrate publish calls after connection.

How do you verify the connection is working?

After flashing your firmware:

  1. Watch the serial monitor for the MQTT connection event. The ESP-MQTT event handler fires a connected event when the broker handshake completes. If you see a publish or subscribe call succeed immediately after, the transport is healthy.
  2. Use the public test broker. Pointing your broker URI at mqtts://test.mosquitto.org:8886 means you do not need any local infrastructure. If the ESP32 connects and publishes, you can verify receipt using any MQTT client (desktop or mobile) subscribed to the same topic on the same broker.
  3. Check QoS and retain flags. If messages are not arriving, confirm the QoS level matches between publisher and subscriber, and that the retain flag is set as expected.
  4. For relay or GPIO control: after publishing a payload, observe the hardware directly — a relay click or an LED state change is the most immediate confirmation that the subscribe callback ran correctly and the GPIO write executed.

What are the most common mistakes with ESP32 MQTT?

1. AWS IoT Core policy misconfiguration

When connecting to AWS IoT, the device policy must explicitly allow every topic operation the firmware attempts. A real-world case reported the error transportStatus=-1 with MQTTRecvFailed after a successful initial connection. The root cause turned out to be the policy not permitting a shadow delete operation the code attempted before the main subscribe calls. Removing or disabling that delete block resolved the issue. If you see a single-byte read failure shortly after connect, audit your IoT policy before changing anything in the firmware.

2. Increasing the network buffer without fixing the real problem

In the same AWS IoT case, the developer tried raising the MQTT network buffer to 4096 bytes — it had no effect because the failure was a permissions error, not a buffer overflow. Reach for policy and credential checks before tuning buffer sizes.

3. Accepting any payload without validation

The initial relay example subscribed to topic/# and toggled the relay on every received message, regardless of content. A stray message or reconnection event would flip the relay unexpectedly. The correct pattern — shown in the resolved version — parses the payload as JSON and checks a specific field value before acting.

4. Wildcard subscriptions in production

Using topic/# (hash wildcard) is fine for debugging but can cause unintended behaviour in a device that processes many topics. Narrow the subscription to the exact topic your device should act on once the design is stable.

5. Missing TLS certificate setup

The two built-in ESP-IDF examples both use TLS. Connecting to mqtts:// endpoints without providing the correct certificate bundle or CA pin will result in a TLS handshake failure before MQTT even starts. Verify your certificate configuration matches the broker's expected chain.

Frequently asked questions

Which MQTT protocol versions does the ESP32 support?

ESP-MQTT supports MQTT v3.1.1 and MQTT v5.0. Tasmota firmware, which also runs on ESP32, supports both MQTT v3.1.1 and v5 as well.

What public broker can I use to test an ESP32 MQTT project?

Espressif's own example projects target mqtts://test.mosquitto.org:8886 (Let's Encrypt chain) and mqtts://test.mosquitto.org:8883 (pinned Mosquitto CA). Both are free public test brokers.

How do I add the ESP-MQTT component to an existing ESP-IDF project?

Run idf.py add-dependency espressif/mqtt from your project directory. The component was separated from the main ESP-IDF repository starting with v6.0.

Can I use ESP32 MQTT with Home Assistant?

Yes. Tasmota firmware on ESP32 integrates directly with Home Assistant via MQTT, publishing sensor readings and device state automatically. Custom ESP-IDF or Mongoose OS firmware can also publish to any broker that Home Assistant monitors.

Why does my ESP32 get transportStatus=-1 when connecting to AWS IoT?

This error typically points to an AWS IoT policy that does not allow one of the topic operations your firmware is attempting — for example, a shadow delete. Review your device policy in the AWS console and ensure every publish and subscribe topic your code uses is explicitly permitted.

Bottom line

ESP32 MQTT is well supported through Espressif's native ESP-MQTT component, which handles TCP, TLS, and WebSocket transports and supports both MQTT v3.1.1 and v5.0. The core skill to develop is matching your subscribe callback logic to a well-defined payload format — parsing JSON and gating on specific field values keeps your device predictable. For projects where writing firmware is unnecessary overhead, Tasmota provides out-of-the-box MQTT integration with major smart-home platforms across the full ESP32 family.

Sources

github.comESP-MQTT (esp-idf docs)stackoverflow.comESP32 AWS IoT transportStatus=-1stackoverflow.comSwitch ON/OFF Relay from MQTT flespi using mongoose (javascript) + ESP32github.comarendst/Tasmota (GitHub README)

This guide summarises the public sources listed above in our own words. Check the original documentation before relying on exact figures.