Closed rakeshpai closed 5 years ago
I am interested in this too. I resorted to a static IP address for my MQTT broker.
I have a feeling that it's not so simple to get an IP address from mDNS.
There is a standard library for mDNS for ESP8266. So it's fairly easy to get an IP for a responding broker.
For the integration: I guess you just want to enter the hostname into the config.json and let Homie do the thinking?
@bertmelis I'm pretty sure it's not as simple as just putting the mDNS host name in config.json. It's what I tried and looks like it's what @rakeshpai tried. But certainly that's how it should work.
I think that the ESP8266mDNS library (https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266mDNS) only allows you to advertise your own IP address and respond to requests for it (as is already used by Homie) but I don't think it allows you to request the IP address for a given .local
name.
@bertmelis Sorry for the late reply. Missed this thread somehow.
For the integration: I guess you just want to enter the hostname into the config.json and let Homie do the thinking?
I'm not sure there can be any other way, considering that the config.json is the only way to set the mqtt server, unless I'm missing something. I don't mind resolving the IP externally (though I don't know how yet) and passing it to Homie, but I don't think it's possible to programatically pass the IP to Homie. Also, it will be very convenient if Homie does the IP resolution internally, of course. :)
@Nzbuu I even believe there are 2 options:
int n = MDNS.queryService("esp", "tcp"); // Send out query for esp tcp services
(change service to mqtt or something. I should wireshark for the correct query.)However, the real question lies in the integration. You should query for the service on every connect and for easy of use also the setup firmware packages should be updated (uibundle etc).
Hi,
This feature existed in Homie v1.x. With Homie v2, we're using an asynchronous Wi-Fi stack, which means we cannot use the standard MDNS.queryService function, which is a synchronous implementation. So this is unfortunately impossible until an asynchronous MDNS client is available.
The following code works OK for mi using current Homie v2. Feel free to use it.
//---------------------------------------------------------------------------------------
void BootNormal::set_mqtt_broker_ip()
{
//Use mDNS server for finding an MQTT broker in the LAN. If any found,
//configure MQTT client for connecting to that broker. Otherwise,
//use static configuration parameters, as defined in config.h
AsyncMqttClient& client = Interface::get().getMqttClient();
Config& cfg = Interface::get().getConfig();
int n = find_service("mqtt","tcp");
if (n > 0)
{
//use the first broker found
IPAddress ip = MDNS.IP(0);
uint16_t port = MDNS.port(0);
Interface::get().getLogger() << F("Using discovered MQTT broker at ") << ip
<< F(":") << port << endl;
client.setServer(ip, port);
}
else
{
//use fallback data in config
client.setServer(cfg.get().mqtt.server.host,
cfg.get().mqtt.server.port);
Interface::get().getLogger() << F("Using fallback MQTT data. host: ")
<< cfg.get().mqtt.server.host << F(", port: ")
<< cfg.get().mqtt.server.port << endl;
}
}
//---------------------------------------------------------------------------------------
int BootNormal::find_service(const char* service, const char* protocol)
{
Interface::get().getLogger() << F("Sending mDNS query. Service=") << service
<< F(", protocol=") << protocol << endl;
int n = MDNS.queryService(service, protocol);
if (n == 0)
{
Interface::get().getLogger() << F("no services found") << endl;
}
else
{
Interface::get().getLogger() << n << F(" service(s) found") << endl;
for (int i = 0; i < n; ++i)
{
// Print details for each service found
Interface::get().getLogger() << (i + 1)
<< F(": ") << MDNS.hostname(i)
<< F(" (") << MDNS.IP(i)
<< F(":") << MDNS.port(i)
<< F(")") << endl;
}
}
return n;
}
@marvinroger you mentioned MDNS.queryService()
is problematic because it's synchronous.
Do you think it's ok in this context - before MQTT is connected, or is there another issue that would cause the above solution to be unstable?
@lorenwest for example, I use a shutters library (https://github.com/marvinroger/arduino-shutters) that is time sensitive and that must be called regularly every few ms. If MDNS.queryService
was used in the homie-esp8266 code, it might delay the loop()
function for a few seconds, which would basically unsync my shutters.
There's a lot of other use cases where some code has to be called every few ms, even if the device is not yet connected to MQTT.
I don't want the framework to behave that way. As long as there's no async implementation of MDNS, it is, I believe, better to do it directly in the sketch. That way, the developer is responsible for the blocking code.
Gotcha - that makes sense. Keep the library clear of any sync code, and have that be the decision of the sketch author based on their needs. Thanks for the explanation.
I will close this issue as there seems to be conses.
Homie connects correctly to my MQTT broker if I use the following in my config.json
However, Homie fails to connect if I use the following:
I just get a series of the following in my serial monitor:
I know that my mDNS is working fine on my mqtt server. (It's avahi on Linux)
I'd like to use mDNS to address my MQTT server from Homie, so that I don't have to set up static IPs in my router. It appears from the above that this isn't currently supported? Or am I doing something wrong?