Merge pull request #4769 from wled/fix-4671

Add mDNS support for MQTT server
This commit is contained in:
Blaž Kristan 2025-08-02 23:15:58 +02:00 committed by GitHub
commit 93e011d403
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -11,6 +11,11 @@
#warning "MQTT topics length > 32 is not recommended for compatibility with usermods!"
#endif
static const char* sTopicFormat PROGMEM = "%.*s/%s";
// parse payload for brightness, ON/OFF or toggle
// briLast is used to remember last brightness value in case of ON/OFF or toggle
// bri is set to 0 if payload is "0" or "OFF" or "false"
static void parseMQTTBriPayload(char* payload)
{
if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; stateUpdated(CALL_MODE_DIRECT_CHANGE);}
@ -30,22 +35,18 @@ static void onMqttConnect(bool sessionPresent)
char subuf[MQTT_MAX_TOPIC_LEN + 9];
if (mqttDeviceTopic[0] != 0) {
strlcpy(subuf, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1);
mqtt->subscribe(mqttDeviceTopic, 0);
snprintf_P(subuf, sizeof(subuf)-1, sTopicFormat, MQTT_MAX_TOPIC_LEN, mqttDeviceTopic, "col");
mqtt->subscribe(subuf, 0);
strcat_P(subuf, PSTR("/col"));
mqtt->subscribe(subuf, 0);
strlcpy(subuf, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1);
strcat_P(subuf, PSTR("/api"));
snprintf_P(subuf, sizeof(subuf)-1, sTopicFormat, MQTT_MAX_TOPIC_LEN, mqttDeviceTopic, "api");
mqtt->subscribe(subuf, 0);
}
if (mqttGroupTopic[0] != 0) {
strlcpy(subuf, mqttGroupTopic, MQTT_MAX_TOPIC_LEN + 1);
mqtt->subscribe(mqttGroupTopic, 0);
snprintf_P(subuf, sizeof(subuf)-1, sTopicFormat, MQTT_MAX_TOPIC_LEN, mqttGroupTopic, "col");
mqtt->subscribe(subuf, 0);
strcat_P(subuf, PSTR("/col"));
mqtt->subscribe(subuf, 0);
strlcpy(subuf, mqttGroupTopic, MQTT_MAX_TOPIC_LEN + 1);
strcat_P(subuf, PSTR("/api"));
snprintf_P(subuf, sizeof(subuf)-1, sTopicFormat, MQTT_MAX_TOPIC_LEN, mqttGroupTopic, "api");
mqtt->subscribe(subuf, 0);
}
@ -54,8 +55,7 @@ static void onMqttConnect(bool sessionPresent)
DEBUG_PRINTLN(F("MQTT ready"));
#ifndef USERMOD_SMARTNEST
strlcpy(subuf, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1);
strcat_P(subuf, PSTR("/status"));
snprintf_P(subuf, sizeof(subuf)-1, sTopicFormat, MQTT_MAX_TOPIC_LEN, mqttDeviceTopic, "status");
mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
#endif
@ -172,21 +172,21 @@ void publishMqtt()
char subuf[MQTT_MAX_TOPIC_LEN + 16];
sprintf_P(s, PSTR("%u"), bri);
strlcpy(subuf, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1);
strcat_P(subuf, PSTR("/g"));
snprintf_P(subuf, sizeof(subuf)-1, sTopicFormat, MQTT_MAX_TOPIC_LEN, mqttDeviceTopic, "g");
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
sprintf_P(s, PSTR("#%06X"), (colPri[3] << 24) | (colPri[0] << 16) | (colPri[1] << 8) | (colPri[2]));
strlcpy(subuf, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1);
strcat_P(subuf, PSTR("/c"));
snprintf_P(subuf, sizeof(subuf)-1, sTopicFormat, MQTT_MAX_TOPIC_LEN, mqttDeviceTopic, "c");
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
snprintf_P(subuf, sizeof(subuf)-1, sTopicFormat, MQTT_MAX_TOPIC_LEN, mqttDeviceTopic, "status");
mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
// TODO: use a DynamicBufferList. Requires a list-read-capable MQTT client API.
DynamicBuffer buf(1024);
bufferPrint pbuf(buf.data(), buf.size());
XML_response(pbuf);
strlcpy(subuf, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1);
strcat_P(subuf, PSTR("/v"));
snprintf_P(subuf, sizeof(subuf)-1, sTopicFormat, MQTT_MAX_TOPIC_LEN, mqttDeviceTopic, "v");
mqtt->publish(subuf, 0, retainMqttMsg, buf.data(), pbuf.size()); // optionally retain message (#2263)
#endif
}
@ -213,14 +213,26 @@ bool initMqtt()
{
mqtt->setServer(mqttIP, mqttPort);
} else {
#ifdef ARDUINO_ARCH_ESP32
String mqttMDNS = mqttServer;
mqttMDNS.toLowerCase(); // make sure we have a lowercase hostname
int pos = mqttMDNS.indexOf(F(".local"));
if (pos > 0) mqttMDNS.remove(pos); // remove .local domain if present (and anything following it)
if (strlen(cmDNS) > 0 && mqttMDNS.length() > 0 && mqttMDNS.indexOf('.') < 0) { // if mDNS is enabled and server does not have domain
mqttIP = MDNS.queryHost(mqttMDNS.c_str());
if (mqttIP != IPAddress()) // if MDNS resolved the hostname
mqtt->setServer(mqttIP, mqttPort);
else
mqtt->setServer(mqttServer, mqttPort);
} else
#endif
mqtt->setServer(mqttServer, mqttPort);
}
mqtt->setClientId(mqttClientID);
if (mqttUser[0] && mqttPass[0]) mqtt->setCredentials(mqttUser, mqttPass);
#ifndef USERMOD_SMARTNEST
strlcpy(mqttStatusTopic, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1);
strcat_P(mqttStatusTopic, PSTR("/status"));
snprintf_P(mqttStatusTopic, sizeof(mqttStatusTopic)-1, sTopicFormat, MQTT_MAX_TOPIC_LEN, mqttDeviceTopic, "status");
mqtt->setWill(mqttStatusTopic, 0, true, "offline"); // LWT message
#endif
mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME);