Zeroconf MQTT set up - JRInge/ha GitHub Wiki

An MQTT client needs to know the address of the message broker to connect to. If using a broker on the local network, we can use a Zeroconf approach to avoid having to hard code the broker's IP address or hostname into the client device's firmware. Instead we can use DNS-SD and Avahi/Bonjour to discover the server hosting the MQTT broker.

For this to work, the MQTT service needs to be advertised. On a Linux host system, Avahi can be configured to do this by including the following in /etc/avahi/services/mqtt.service:

<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
 <name replace-wildcards="yes">MQTT on %h</name>
  <service>
   <type>_mqtt._tcp</type>
   <port>1883</port>
  </service>
</service-group>

On an ESP32 client device, we can use the ESPmDNS library for service discovery:

#include <ESPmDNS.h>

...

const char* clientId = "myhost";
IPAddress mqttServer;
int mqttPort;

Serial.print("Setting up mDNS: ");
if (!MDNS.begin(clientId)) { 
  Serial.println("[Fail]");
} else {
  Serial.println("[OK]");
  Serial.print("Querying MQTT broker: ");

  int n = MDNS.queryService("mqtt", "tcp");

  if (n == 0) {
    // No service found
    Serial.println("[Fail]");
  } else {
    // Found one or more MQTT service - use the first one.
    Serial.println("[OK]");
    mqttServer = MDNS.IP();
    mqttPort = MDNS.port();
}

}

The DNS-SD details from the mDNS object can then be used to subscribe to the broker. Note that while this code deals with automatically locating the broker without any configuration, actually connecting will require a unique ID. Subscription to the broker will fail if multiple devices try to subscribe with the same client ID.

References:

  1. https://forums.balena.io/t/simply-announcing-advertising-an-mqtt-service-via-avahi-mdns/158122/1
  2. http://dagrende.blogspot.com/2017/02/find-mqtt-broker-without-hard-coded-ip.html
⚠️ **GitHub.com Fallback** ⚠️