iiOTESP32 Brasil
Contingency mode: public pages and downloads remain available; login, community, and server data may be unavailable.
Back to tutorial catalog
Ilustração: placa ESP32 emitindo Wi-Fi e enviando dados a um servidor compacto com o símbolo de broker MQTT, que repassa os dados a um laptop mostrando gráficos de linha
Imagem ilustrativa gerada por IA
IntermediateMQTTReading: 15 min

ESP32 publishing data to Mosquitto

Step by step to connect an ESP32 to an Eclipse Mosquitto MQTT broker, handling authentication and JSON telemetry format.

Technologies:#ESP32#MQTT#Mosquitto#JSON#PubSubClient

Goal and architecture

This tutorial builds a small, authenticated path for publishing ESP32 telemetry to an Eclipse Mosquitto broker hosted on Ubuntu. The flow is:

code.cpp
cpp
1ESP32 -> Wi-Fi -> Mosquitto -> mosquitto_sub / supervisory application

The example uses MQTT 3.1.1, a device-specific topic, and a small JSON payload. The user names, password, IP address, and SSID below are placeholders: replace them locally and never commit credentials to firmware or the repository.

Install Mosquitto on Ubuntu

On an Ubuntu host under your control, install the broker and test clients:

code.cpp
cpp
1sudo apt update
2sudo apt install mosquitto mosquitto-clients
3sudo systemctl enable --now mosquitto
4sudo systemctl status mosquitto

For a staging installation, confirm that the MQTT port is listening:

code.cpp
cpp
1sudo ss -ltnp | grep 1883

Do not expose an anonymous broker directly to the internet. Even on an industrial network, treat the broker as an authenticated service and restrict the firewall to the required network.

Create a user and require authentication

Create the password file with the official mosquitto_passwd command. The password is entered interactively:

code.cpp
cpp
1sudo mosquitto_passwd -c /etc/mosquitto/passwd esp32-staging
2sudo chown mosquitto:mosquitto /etc/mosquitto/passwd
3sudo chmod 640 /etc/mosquitto/passwd

Create a separate configuration file such as /etc/mosquitto/conf.d/iiot.conf:

code.cpp
cpp
1listener 1883
2allow_anonymous false
3password_file /etc/mosquitto/passwd

Restart the service and inspect its logs:

code.cpp
cpp
1sudo systemctl restart mosquitto
2sudo journalctl -u mosquitto -n 50 --no-pager

For production or untrusted networks, configure TLS and use port 8883 with valid certificates. Port 1883 in this tutorial is for a protected staging network.

Test the broker before the ESP32

Open a subscriber terminal:

code.cpp
cpp
1mosquitto_sub -h 192.168.1.10 -p 1883 \
2 -u esp32-staging -P 'LOCAL_PASSWORD' \
3 -t 'iiot/esp32/esp32-01/telemetry' -v

In another terminal, publish a message:

code.cpp
cpp
1mosquitto_pub -h 192.168.1.10 -p 1883 \
2 -u esp32-staging -P 'LOCAL_PASSWORD' \
3 -t 'iiot/esp32/esp32-01/telemetry' \
4 -m '{"device":"esp32-01","temperature":24.7,"rssi":-61}'

If the message appears in the first terminal, the address, port, authentication, and topic agree. The 192.168.1.10 value is only a local-network example; use the actual broker address.

Configure the PlatformIO project

In platformio.ini, declare PubSubClient:

code.cpp
cpp
1[env:esp32dev]
2platform = espressif32
3board = esp32dev
4framework = arduino
5monitor_speed = 115200
6lib_deps =
7 knolleary/PubSubClient

The following example uses WiFiClient and PubSubClient. It reconnects without trapping the loop in an infinite while loop and publishes a compact JSON payload:

code.cpp
cpp
1#include <Arduino.h>
2#include <WiFi.h>
3#include <PubSubClient.h>
4
5const char* WIFI_SSID = "LOCAL_SSID";
6const char* WIFI_PASSWORD = "WIFI_PASSWORD";
7const char* MQTT_HOST = "192.168.1.10";
8const uint16_t MQTT_PORT = 1883;
9const char* MQTT_USER = "esp32-staging";
10const char* MQTT_PASSWORD = "MQTT_PASSWORD";
11const char* MQTT_TOPIC = "iiot/esp32/esp32-01/telemetry";
12
13WiFiClient network;
14PubSubClient mqtt(network);
15unsigned long lastMqttAttempt = 0;
16unsigned long lastPublish = 0;
17
18void connectWifi() {
19 if (WiFi.status() == WL_CONNECTED) return;
20 WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
21}
22
23void connectMqtt() {
24 if (WiFi.status() != WL_CONNECTED || mqtt.connected()) return;
25 if (millis() - lastMqttAttempt < 5000) return;
26
27 lastMqttAttempt = millis();
28 const char* clientId = "esp32-01";
29 if (mqtt.connect(clientId, MQTT_USER, MQTT_PASSWORD)) {
30 Serial.println("MQTT connected");
31 } else {
32 Serial.printf("MQTT rejected, rc=%d\n", mqtt.state());
33 }
34}
35
36void publishTelemetry() {
37 if (!mqtt.connected()) return;
38
39 char payload[128];
40 const float temperature = 24.7f; // replace with the sensor reading
41 snprintf(payload, sizeof(payload),
42 "{\"device\":\"esp32-01\",\"temperature\":%.2f,\"rssi\":%d}",
43 temperature, WiFi.RSSI());
44
45 if (!mqtt.publish(MQTT_TOPIC, payload)) {
46 Serial.println("Telemetry publish failed");
47 }
48}
49
50void setup() {
51 Serial.begin(115200);
52 mqtt.setServer(MQTT_HOST, MQTT_PORT);
53 connectWifi();
54}
55
56void loop() {
57 connectWifi();
58 connectMqtt();
59 mqtt.loop();
60
61 if (millis() - lastPublish >= 10000) {
62 lastPublish = millis();
63 publishTelemetry();
64 }
65}

Call mqtt.loop() frequently. It processes the protocol and keeps the connection alive; a long delay or blocking operation can make the broker consider the client disconnected. The clientId must also be unique per board.

Quick diagnosis

  • rc=4 usually means an incorrect user name or password.
  • rc=5 means the broker rejected the authorization.
  • rc=-2 points to a host-resolution or connection failure.
  • rc=-4 is commonly a timeout: check the IP, port, route, and firewall.
  • If the subscriber receives nothing, compare the topic character by character.
  • PubSubClient has a small default buffer; for larger JSON payloads, explicitly size it with mqtt.setBufferSize(512) and validate the message size before publishing.

Security and operation

Do not put real passwords in source code, commits, or public examples. On an untrusted network, switch to TLS on port 8883, validate the broker certificate, and configure least-privilege ACLs. In production, monitor disk space, logs, restarts, and client counts; authentication does not replace network segmentation or configuration backups.

Official sources

See more technical tutorialsIIoT ESP32 Brasil — Practical documentation