Seção 6 — Consultando serviços mDNS a partir do próprio ESP32
Até aqui usamos o ESP32 como um dispositivo que anuncia sua presença na rede. Mas o mDNS também pode ser usado no sentido inverso: o próprio ESP32 pode procurar outros dispositivos ou serviços dentro da rede local. Isso é muito útil quando estamos construindo sistemas distribuídos, nos quais um nó precisa descobrir automaticamente outro nó sem configuração manual de IP.
Imagine uma rede com três ESP32. Um deles funciona como gateway, outro como sensor ambiental e outro como atuador. Em vez de gravar no firmware do gateway o IP fixo de cada dispositivo, podemos fazer com que cada nó anuncie seus serviços via mDNS. O gateway, então, consulta a rede procurando por serviços específicos, como _http._tcp, _mqtt._tcp ou um serviço próprio, como _sensor._tcp.
A documentação da Espressif informa que o mDNS fornece métodos para procurar serviços e resolver endereços IPv4 ou IPv6 de hosts, retornando os resultados como uma lista encadeada de estruturas mdns_result_t. (Espressif Systems) Isso significa que, em vez de receber apenas uma resposta simples, o ESP32 pode receber uma lista de dispositivos encontrados, cada um com hostname, porta, endereço IP e informações adicionais.
A consulta mais comum é feita por tipo de serviço. Por exemplo, para procurar servidores HTTP anunciados na rede local, podemos consultar:
_http._tcp
Em código, a lógica geral fica assim:
#include "esp_log.h"
#include "mdns.h"
static const char *TAG = "MDNS_QUERY";
/**
* @brief Procura serviços HTTP anunciados via mDNS na rede local.
*
* Esta função faz uma consulta por serviços do tipo _http._tcp,
* aguarda respostas por um tempo limitado e imprime os resultados
* encontrados no log serial.
*/
static void app_mdns_query_http_services(void)
{
mdns_result_t *results = NULL;
esp_err_t err = mdns_query_ptr(
"_http",
"_tcp",
3000,
20,
&results
);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Erro ao consultar serviços mDNS: %s", esp_err_to_name(err));
return;
}
if (results == NULL) {
ESP_LOGW(TAG, "Nenhum serviço HTTP encontrado via mDNS");
return;
}
ESP_LOGI(TAG, "Serviços HTTP encontrados:");
mdns_result_t *r = results;
while (r != NULL) {
ESP_LOGI(TAG, "Instância: %s", r->instance_name ? r->instance_name : "sem nome");
ESP_LOGI(TAG, "Hostname: %s", r->hostname ? r->hostname : "sem hostname");
ESP_LOGI(TAG, "Porta: %u", r->port);
r = r->next;
}
mdns_query_results_free(results);
}
A função central neste exemplo é:
mdns_query_ptr("_http", "_tcp", 3000, 20, &results);
O primeiro argumento indica o tipo do serviço. O segundo indica o protocolo. O terceiro define o tempo máximo de espera em milissegundos. O quarto define o número máximo de resultados. O último argumento recebe o ponteiro para a lista de resultados.
Em uma rede onde existam vários ESP32 anunciando servidores HTTP, essa função pode retornar mais de um resultado. Por isso, o código percorre a lista usando:
mdns_result_t *r = results;
while (r != NULL) {
/*
* Processa cada resultado encontrado.
*/
r = r->next;
}
Esse detalhe é importante porque, em sistemas IoT, raramente devemos assumir que existe apenas um dispositivo. Uma rede de sensores pode ter dezenas de nós. Um laboratório pode ter várias placas com o mesmo firmware. Um produto comercial pode trabalhar com múltiplas unidades instaladas no mesmo ambiente.
Depois de usar os resultados, chamamos:
mdns_query_results_free(results);
Essa chamada libera a memória alocada pela consulta. Em microcontroladores, esse cuidado não é opcional. Se fizermos consultas repetidas sem liberar os resultados, podemos introduzir vazamento de memória e reduzir a estabilidade do sistema.
Também podemos procurar um host específico pelo nome. Por exemplo, se sabemos que existe um dispositivo chamado:
esp32-sensor.local
podemos resolver seu endereço IP usando uma consulta de host. A documentação da Espressif descreve esse tipo de consulta como resolução de endereço do host, além da navegação por serviços. (Espressif Systems) Conceitualmente, isso é útil quando já sabemos o nome do dispositivo, mas não seu IP atual.
No entanto, para arquiteturas mais flexíveis, a descoberta por serviço costuma ser mais interessante do que a descoberta por hostname. Quando consultamos _http._tcp, não estamos procurando “um dispositivo específico”; estamos procurando “qualquer dispositivo que ofereça HTTP”. Essa diferença reduz acoplamento entre os nós do sistema.
Um exemplo mais próximo de uma aplicação real seria criar um serviço próprio:
_sensor._tcp
Nesse caso, cada ESP32 sensor poderia anunciar:
mdns_service_add(
"Sensor de Temperatura",
"_sensor",
"_tcp",
8080,
service_txt_data,
sizeof(service_txt_data) / sizeof(service_txt_data[0])
);
E o gateway poderia procurar:
mdns_query_ptr("_sensor", "_tcp", 3000, 20, &results);
Esse modelo permite criar redes locais autoconfiguráveis. O gateway liga, conecta ao Wi-Fi, consulta a rede, descobre sensores compatíveis e começa a se comunicar com eles. Se um sensor for substituído e receber outro IP, o sistema continua funcionando porque a descoberta não depende do endereço fixo.
O mDNS, porém, não elimina a necessidade de validação. Em uma aplicação robusta, o gateway deve verificar se o dispositivo encontrado realmente oferece a API esperada. O registro TXT pode ajudar nessa triagem, mas a confirmação deve ocorrer na camada da aplicação, por exemplo consultando uma rota como:
http://esp32-sensor.local/api/v1/info
ou acessando diretamente o IP e a porta descobertos pela consulta mDNS.
Essa distinção é fundamental: o mDNS ajuda a encontrar candidatos, mas não garante compatibilidade, autorização ou segurança. Ele responde à pergunta “quem oferece este serviço na rede local?”. A aplicação ainda precisa responder “esse dispositivo é confiável?”, “fala a versão correta do protocolo?” e “está autorizado a participar do sistema?”.
Portanto, consultar mDNS a partir do próprio ESP32 transforma o microcontrolador em um participante mais ativo da rede. Ele deixa de depender de configuração estática e passa a descobrir serviços dinamicamente. Para projetos IoT, isso abre espaço para topologias mais flexíveis, instalação mais simples e manutenção mais inteligente.