Introdução
Neste artigo, mostraremos como criar uma comunicação MQTT (Message Queuing Telemetry Transport), utilizando a placa de desenvolvimento ESP32-C6 DevKitC-1.
Nosso projeto terá como objetivo o envio e recebimento de mensagens via MQTT para controlar o estado de um LED, além de incluir uma funcionalidade extra: atualizar dinamicamente as credenciais do broker MQTT utilizando WebSocket, sem a necessidade de regravar o firmware.
Para conhecer mais a placa de desenvolvimento consulte nosso artigo Introdução à Placa ESP32-C6-DevKitC-1: Ideal para IoT
Características do MQTT
- Usa o protocolo de mensagens publicador/assinante
- Suporta comunicação assíncrona
- Utiliza padrão de tópicos para organizar mensagem
- Confíavel
A estrutura envolve três componentes:
- Broker MQTT: servidor responsável por gerenciar os tópicos e repassar as mensagens
- Publisher (publicador): dispositivo que envia mensagens
- Subscriber (assinante): dispositivo que recebe mensagem de um tópico
Para saber mais sobre o protocolo MQTT, veja o artigo do professor Marcelo Barros https://embarcados.com.br/mqtt-protocolos-para-iot/
Materiais Necessários
Para desenvolver nossa aplicação os materiais utilizados foram:
- Placa ESP23-C6 DevKitC-1
- Cabo USB-C
- LED
- Resistor 330 ohms
- Botão
- Jumpers
- Arduino IDE
- Broker MQTT (broker.emqx.io e broker.hivemq.com )
- App MQTT Client (MQTT Dashboard Client – Apps no Google Play)
- Cliente de visualização MQTT (MQTTX)
Para configurar o ambiente e instalar o suporte a ESP32-C6 veja o artigo ESP32-C6 na Prática: Seu Primeiro “Hello World”
Circuito
O circuito utilizado para este artigo será a placa ESP32-C6 DevKitC-1 para gerir o Web Server e se conectar ao Broker MQTT como publicador e assinante no tópico, o LED para sinalizar as ações via MQTT e o botão para publicar o estado do LED.
Como o ESP32-C6 possui resistores internos de pull-up, não utilizaremos um resistor externo para o botão.
Código
No projeto proposto, o ESP23-C6 DevKitC-1 é conectado à rede local para gerir o Websocket. Assim, é necessário conectar a placa à rede utilizando as credenciais do Wi-Fi.
Também precisamos instalar as bibliotecas PubSubClient pelo gerenciador de bibliotecas da Arduino IDE por Nick O´Leary
Em seguida, copie o endereço IP apresentado no monitor serial (Figura 2) e cole-o no navegador de sua preferência (Figura 3).
Todo o código desenvolvido está disponível para consulta em download.
Vamos utilizar os seguintes endereços de brokers e WebSocket Port para nossa aplicação Web.
| Nome | Endereço | TCP Port | WebSocket Port |
| EMQX | broker.emqx.io | 1883 | 8084 |
| HiveMQ | broker.hivemq.com | 1883 | 8884 |
Para nosso exemplo, começamos definindo as configurações para se trabalhar com MQTT. Assim, precisamos associar as definições com os tipos que serão constantes no desenvolvimento e as que iremos alterar via WebSocket.
// Definicao de variaveis
#define topic_led "esp32/led/vermelho" // Tópico MQTT para o LED Vermelho
#define broker_default "broker.emqx.io" // Endereço do Broker MQTT - Se desejar utilizar outro, substitua este pelo endereço do seu broker
#define mqtt_tcp_port_default 1883 // Porta do Broker MQTT TCP
#define mqtt_ws_port_default 8084 // Porta do Broker MQTT WebSocket emqx
#define id_mqtt "esp32c6_guilherme" // ID do cliente MQTT - Pode ser alterado, mas deve ser único para cada cliente conectado ao broker
// Definição dos Tópicos MQTT
const char* topic_led_vermelho = topic_led;
// Configuração do Broker MQTT
const int mqtt_port = mqtt_tcp_port_default;
const char* idMqtt = id_mqtt;
String mqtt_server = broker_default;
int mqtt_ws_port = mqtt_ws_port_default;
Depois seguimos com a configuração do WebSocket que já realizamos no artigo {WebScoket}. Agora diferenciando para enviar e receber o endereço e porta do broker.
// Função para lidar com eventos do WebSocket
void onWebSocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
switch (type) {
case WS_EVT_CONNECT:
Serial.printf("WebSocket client #%lu connected from %s\n", client->id(), client->remoteIP().toString().c_str());
client->text("mqtt_server=" + mqtt_server + ";mqtt_port=" + String(mqtt_ws_port) + ";topic_led_vermelho=" + String(topic_led_vermelho));
break;
case WS_EVT_DISCONNECT:
Serial.printf("WebSocket client #%lu disconnected\n", client->id());
break;
case WS_EVT_DATA:
{
String msg = "";
for (size_t i = 0; i < len; i++) {
msg += (char)data[i];
}
Serial.println("Mensagem recebida via WebSocket: " + msg);
mqtt_server = msg.substring(msg.indexOf("mqtt_server=") + 12, msg.indexOf(";mqtt_port="));
mqtt_ws_port = msg.substring(msg.indexOf("mqtt_port=") + 10).toInt();
Serial.println("Novo servidor MQTT: " + mqtt_server);
Serial.println("Nova porta WebSocket MQTT: " + String(mqtt_ws_port));
mqtt.disconnect();
break;
}
default:
break;
}
}
Usamos freeRTOS para ler o estado do botão de forma assíncrona às atividades, assim a task é responsável por publicar a mensagem no tópico para alternar o estado do led.
/*-------------------------------------------------------------------------------
Tarefa para ler o estado do botão e publicar a mensagem no tópico MQTT
*---------------------------------------------------------------------------*/
void taskBotao(void* parameter) {
for (;;) {
button.update(); // Atualiza o estado do botão
if (button.wasPressed()) { // Verifica se o botão foi pressionado
Serial.println("Botão pressionado");
ledState = !ledState; // Inverte o estado do LED
String msg = ledState ? "ON" : "OFF";
mqtt.publish(topic_led_vermelho, msg.c_str(), false); // Publica a mensagem no tópico do LED Vermelho
}
vTaskDelay(pdMS_TO_TICKS(100)); // Aguarda 100 ms antes de verificar novamente
}
}
Também definimos a função para conexão ao Broker MQTT e a função de callback
// Função de conexao ao Broker MQTT
void connectMQTT() {
while (!mqtt.connected()) {
Serial.println("Conectando ao broker: " + mqtt_server + ":" + String(mqtt_port));
mqtt.setServer(mqtt_server.c_str(), mqtt_port);
if (mqtt.connect(idMqtt)) {
Serial.println("Conectado!");
// Assinar os tópicos dos LEDs
mqtt.subscribe(topic_led_vermelho);
// Imprime a mensagem no monitor serial
Serial.println("Assinado nos tópicos: ");
Serial.println(topic_led_vermelho);
} else {
Serial.print("Falha, código: "); // Imprime a mensagem no monitor serial
Serial.println(mqtt.state()); // Imprime o código de erro no monitor serial
delay(5000); // Aguarda 5 segundos e tenta novamente
}
}
}
// Callback para processar mensagens recebidas do MQTT
void callback(char* topic, byte* message, unsigned int length) {
String msg = ""; // Cria uma string para armazenar a mensagem
for (int i = 0; i < length; i++){ // Percorre a mensagem recebida
msg += (char)message[i]; // Concatena os caracteres da mensagem
}
// Imprime a mensagem recebida no monitor serial - Log
Serial.print("Mensagem recebida no tópico: ");
Serial.println(topic);
Serial.print("Conteúdo: ");
Serial.println(msg);
// Verifica se a mensagem é para o LED vermelho
if (strcmp(topic, topic_led_vermelho) == 0){ // Compara o tópico recebido com o tópico do LED Vermelho
if (msg == "ON") {
setLED(true);
} else if (msg == "OFF") {
setLED(false);
}
}
}
O script do websocket para alterar o broker e enviar para o ESP32-C6
function salvarConfiguracoes() {
mqtt_server = document.getElementById("mqtt_server").value;
mqtt_port = document.getElementById("mqtt_port").value;
if (!mqtt_server || !mqtt_port) {
alert("Por favor, preencha o Broker MQTT e a Porta WebSocket MQTT.");
return;
}
if (websocket && websocket.readyState === WebSocket.OPEN) {
websocket.send(`mqtt_server=${mqtt_server};mqtt_port=${mqtt_port}`);
console.log("Configurações salvas via WebSocket");
iniciarClienteMQTT();
} else {
console.warn("WebSocket não conectado");
}
}
Função para se conectar ao broker, ser assinante e publicador
function iniciarClienteMQTT() {
if (mqttClient && mqttClient.connected) {
mqttClient.end(); // desconecta se já estava conectado
}
mqttClient = mqtt.connect(`wss://${mqtt_server}:${mqtt_port}/mqtt`);
mqttClient.on("connect", () => {
document.getElementById("status").textContent = "Conectado!";
mqttClient.subscribe(topic_led_vermelho);
});
mqttClient.on("message", (topic, message) => {
console.log(`Mensagem: ${message.toString()} do tópico: ${topic}`);
if (topic === topic_led_vermelho) {
atualizarEstado(message.toString());
}
});
}
function toggleLed(element) {
const comando = element.checked ? "ON" : "OFF";
mqttClient.publish(topic_led_vermelho, comando);
}
Configuração conexão MQTTX:
Configuração conexão App MQTT Client
Resultados
No exemplo abaixo, utilizamos um servidor web, um botão físico e o MQTTX para publicar valores no tópico esp32/led/vermelho. Além disso, o ESP32 também assina esse tópico para receber atualizações enviadas pelo broker. O monitor serial exibe um log com todas as atividades realizadas.

Atenção: Caso você receba uma falha na conexão MQTT com o status -2, isso indica que a porta TCP 1883 está bloqueada pelo firewall do seu roteador Wi-Fi. Para resolver esse problema, utilize as credenciais do hotspot do celular ou reconfigure seu roteador para liberar a porta 1883.
Conclusão
Neste artigo, mostramos como criar uma comunicação MQTT e um servidor local utilizando a placa ESP32-C6 DevKitC-1 para controlar dispositivos. A interface HTML foi integrada ao firmware, permitindo comunicação em tempo real com o hardware.
Para leitores que não estão familiarizados com HTML e JavaScript, pode haver certa dificuldade inicial, mas existem diversas ferramentas e recursos online que podem auxiliar nesse processo em HTML Basic Examples
Convidamos você a explorar outros projetos com o protocolo MQTT, como transmissão de sensores, gráficos em tempo real, controle múltiplo de dispositivos, e a compartilhar seus resultados com a comunidade por meio de artigos, vídeos ou repositórios abertos.



