Broker
Objetivo
A aplicação ira conectar ao WiFi obeter o endereço IP via DHCP, em seguida a mesma ira se increver no topico MQTT e publicar uma mensagem, além de imprimir no monitor serial as mensagens recebidas no mesmo topico.
Código
A execução inicial do código é conduzida pela função wifi_app_start(). Essa função tem a responsabilidade de iniciar o Wi-Fi, estabelecer a conexão com a internet e, adicionalmente, através de uma função de callback configurada para ser acionada após o ESP receber um endereço IP válido, estabelecer a conexão com o MQTT.
static void wifi_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
if (event_id == WIFI_EVENT_STA_START)
{
ESP_LOGI(TAG, "Tentando conexao wifi....\n");
}
else if (event_id == WIFI_EVENT_STA_CONNECTED)
{
ESP_LOGI(TAG, "WiFi conenctado");
}
else if (event_id == WIFI_EVENT_STA_DISCONNECTED)
{
ESP_LOGI(TAG, "WiFi desconectado\n");
if (retry_num < 5) { esp_wifi_connect(); retry_num++; ESP_LOGI(TAG, "Tentando reconexao wifi...\n"); } } else if (event_id== IP_EVENT_STA_GOT_IP) { ESP_LOGI(TAG, "IP recebido"); //Inicia procedimento de conexão ao MQTT mqtt_app_start(); } } esp_err_t wifi_app_start() { //Inicializa o armazenamento flash (requerido pelo driver de wifi) ESP_ERROR_CHECK(nvs_flash_init()); //Inicializa o sistema Wi-fi e a pilha TCP/IP esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_sta(); wifi_init_config_t wifi_initiation=WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&wifi_initiation); //Registra as funçoes de callback para os eventos de wifi e ip esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL); esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL); //Estrutura de incialização wifi_config_t wifi_configuration={ .sta={ .ssid="" , .password="" , } }; //Faz uma cópia das variaveis globais para dentro da estrutura de inicialização strcpy((char*)wifi_configuration.sta.ssid, ssid); strcpy((char*)wifi_configuration.sta.password, passwd); //Atribui os parametros de inicialização esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_configuration); //Inicializa a conexão esp_wifi_start(); esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_connect(); return ESP_OK; }
A função mqtt_app_start() é invocada para configurar o endereço do broker MQTT e definir a função de callback responsável por gerenciar os eventos associados. Após a conexão bem-sucedida com o broker, o ESP se inscreve em um tópico específico e envia uma mensagem correspondente. Adicionalmente, o conteúdo desse tópico é impresso no monitor serial.
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_mqtt_event_handle_t event = event_data;
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
char *topico = "testtopic/238191212838";
char *mensagem = "Olá mundo";
esp_mqtt_client_publish(handler_args, topico, mensagem, 0, 0 ,0 );
esp_mqtt_client_subscribe_single(handler_args, topico, 0);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "Dados recebidos: ");
printf("TOPICO=%.*s\r\n", event->topic_len, event->topic);
printf("DADOS=%.*s\r\n", event->data_len, event->data);
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
}
static void mqtt_app_start(void)
{
esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = "mqtt://broker.emqx.io:1883",
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
esp_mqtt_client_start(client);
}
Resultado
Usando o cliente MQTTX para interagir com o broker:

Mensagem enviada pelo computador:

Mensagem recebida no ESP:

Bônus: Código completo:
#include
#include
#include
#include
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
#include "esp_log.h"
#include "mqtt_client.h"
char *ssid = "Nome canonico da rede wifi";
char *passwd = "senha";
static const char *TAG = "EXEMPLO_MQTT";
int retry_num = 0;
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_mqtt_event_handle_t event = event_data;
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
char *topico = "testtopic/238191212838";
char *mensagem = "Olá mundo";
esp_mqtt_client_publish(handler_args, topico, mensagem, 0, 0 ,0 );
esp_mqtt_client_subscribe_single(handler_args, topico, 0);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "Dados recebidos: ");
printf("TOPICO=%.*s\r\n", event->topic_len, event->topic);
printf("DADOS=%.*s\r\n", event->data_len, event->data);
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
}
static void mqtt_app_start(void)
{
esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = "mqtt://broker.emqx.io:1883",
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
esp_mqtt_client_start(client);
}
static void wifi_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
if (event_id == WIFI_EVENT_STA_START)
{
ESP_LOGI(TAG, "Tentando conexao wifi....\n");
}
else if (event_id == WIFI_EVENT_STA_CONNECTED)
{
ESP_LOGI(TAG, "WiFi conenctado");
}
else if (event_id == WIFI_EVENT_STA_DISCONNECTED)
{
ESP_LOGI(TAG, "WiFi desconectado\n");
if (retry_num < 5) { esp_wifi_connect(); retry_num++; ESP_LOGI(TAG, "Tentando reconexao wifi...\n"); } } else if (event_id== IP_EVENT_STA_GOT_IP) { ESP_LOGI(TAG, "IP recebido"); //Inicia procedimento de conexão ao MQTT mqtt_app_start(); } } esp_err_t wifi_app_start() { //Inicializa o armazenamento flash (requerido pelo driver de wifi) ESP_ERROR_CHECK(nvs_flash_init()); //Inicializa o sistema Wi-fi e a pilha TCP/IP esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_sta(); wifi_init_config_t wifi_initiation=WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&wifi_initiation); //Registra as funçoes de callback para os eventos de wifi e ip esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL); esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL); //Estrutura de incialização wifi_config_t wifi_configuration={ .sta={ .ssid="" , .password="" , } }; //Faz uma cópia das variaveis globais para dentro da estrutura de inicialização strcpy((char*)wifi_configuration.sta.ssid, ssid); strcpy((char*)wifi_configuration.sta.password, passwd); //Atribui os parametros de inicialização esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_configuration); //Inicializa a conexão esp_wifi_start(); esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_connect(); return ESP_OK; } void app_main(void) { esp_log_level_set("*", ESP_LOG_NONE); ESP_ERROR_CHECK(wifi_app_start()); }