An ESP32 can send temperature readings to a server, but things become more complicated when several applications need the same information. For example, an environmental monitoring device might need to send readings to a dashboard, a data storage system, and an alert service. The device should not need separate communication logic for every application.

MQTT solves this problem through a publish/subscribe communication model. Instead of sending data directly to each application, the ESP32 publishes messages to a central broker. The broker then distributes those messages to applications that have subscribed to the relevant topics.

MQTT is an application-layer messaging protocol that normally operates over a reliable transport such as TCP. Standard MQTT connections commonly use port 1883, while connections protected by TLS commonly use port 8883. Although MQTT messages are relatively small, building a dependable system still requires careful decisions about message delivery, reconnection, topic organization, authentication, and data handling.

This article explains how MQTT works, how its main features can be used in ESP32 projects, and what should be considered when developing a reliable communication system with ESP-IDF.

Understanding the MQTT Publish/Subscribe Model

A typical MQTT system has three main components.

  • Publisher: A device or application that sends messages to a named topic.
  • Broker: A server that receives published messages and forwards them to clients with matching subscriptions.
  • Subscriber: A client that subscribes to one or more topics to receive the messages it needs.

The publisher does not need to know the identity or address of the subscribers. This separation makes it easier to add new applications without changing the firmware of the device that produces the data.

Consider an industrial monitoring system with an ESP32 identified as esp32-017. The device could publish its readings to plant/line2/esp32-017/telemetry.

An operations dashboard could subscribe to plant/line2/+/telemetry to receive readings from devices on line 2. A historical data collection service could subscribe to plant/line2/# to receive messages from the entire line. A separate control application could publish commands to plant/line2/esp32-017/cmd/setpoint.

MQTT supports two wildcard characters in subscription filters:

  • The plus sign (+) matches exactly one topic level.
  • The hash sign (#) matches the remaining topic levels, including zero levels, and must appear at the end of the filter.

Wildcards are allowed in subscription filters, not in published topic names. Topic names are case-sensitive, so uppercase and lowercase letters must match exactly.

Wildcards also do not match system topics beginning with $, such as $SYS, when the subscription filter begins with a wildcard.

The slash-separated topic structure is an organizational convention. The broker routes messages according to topic names and does not interpret the information contained in the message payload.

Establishing an MQTT Connection

An MQTT connection begins when the client establishes a transport connection and sends a CONNECT packet. The broker responds with CONNACK, which indicates whether the connection has been accepted.

Opening a TCP connection alone does not confirm that the MQTT session has been established successfully.

Clients use SUBSCRIBE and SUBACK packets to establish subscriptions and confirm them. PUBLISH packets carry application messages between clients and the broker. PINGREQ and PINGRESP packets help maintain an otherwise idle connection.

The Keep Alive setting determines the expected interval for communication between the client and broker. If the broker receives no control packet from the client within approximately 1.5 times the negotiated Keep Alive interval, it can treat the connection as lost.

Understanding these connection stages is important when diagnosing communication failures in an ESP32-based application.

Choosing MQTT Instead of...

Read more »