mirror of
https://github.com/wled/WLED.git
synced 2025-07-14 14:26:33 +00:00
Hostname unification
- fixes #1242 - fixes empty MQTT topic - fixes missing hostname on change #4586
This commit is contained in:
parent
66869f8341
commit
e2edd38de5
@ -57,10 +57,21 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
#endif
|
||||
|
||||
JsonObject id = doc["id"];
|
||||
getStringFromJson(cmDNS, id[F("mdns")], 33);
|
||||
getStringFromJson(serverDescription, id[F("name")], 33);
|
||||
getStringFromJson(cmDNS, id[F("mdns")], sizeof(cmDNS));
|
||||
// fill in unique mDNS name if not set (cmDNS can be empty meaning no mDNS is used)
|
||||
if (strcmp(cmDNS, DEFAULT_MDNS_NAME) == 0) sprintf_P(cmDNS, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6);
|
||||
getStringFromJson(serverDescription, id[F("name")], sizeof(serverDescription));
|
||||
if (!fromFS) {
|
||||
char hostname[25];
|
||||
prepareHostname(hostname, sizeof(hostname)-1);
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WiFi.setHostname(hostname);
|
||||
#else
|
||||
WiFi.hostname(hostname);
|
||||
#endif
|
||||
}
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
getStringFromJson(alexaInvocationName, id[F("inv")], 33);
|
||||
getStringFromJson(alexaInvocationName, id[F("inv")], sizeof(alexaInvocationName));
|
||||
#endif
|
||||
CJSON(simplifiedUI, id[F("sui")]);
|
||||
|
||||
@ -637,8 +648,9 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
getStringFromJson(mqttUser, if_mqtt[F("user")], 41);
|
||||
getStringFromJson(mqttPass, if_mqtt["psk"], 65); //normally not present due to security
|
||||
getStringFromJson(mqttClientID, if_mqtt[F("cid")], 41);
|
||||
|
||||
if (mqttClientID[0] == 0) sprintf_P(mqttClientID, PSTR("WLED-%*s"), 6, escapedMac.c_str() + 6);
|
||||
getStringFromJson(mqttDeviceTopic, if_mqtt[F("topics")][F("device")], MQTT_MAX_TOPIC_LEN+1); // "wled/test"
|
||||
if (mqttDeviceTopic[0] == 0) sprintf_P(mqttDeviceTopic, PSTR("wled/%*s"), 6, escapedMac.c_str() + 6);
|
||||
getStringFromJson(mqttGroupTopic, if_mqtt[F("topics")][F("group")], MQTT_MAX_TOPIC_LEN+1); // ""
|
||||
CJSON(retainMqttMsg, if_mqtt[F("rtn")]);
|
||||
#endif
|
||||
|
@ -144,6 +144,7 @@ Static subnet mask:<br>
|
||||
function tE() {
|
||||
// keep the hidden input with MAC addresses, only toggle visibility of the list UI
|
||||
gId('rlc').style.display = d.Sf.RE.checked ? 'block' : 'none';
|
||||
if (d.Sf.RE.checked) d.Sf.ETH.selectedIndex = 0; // disable Ethernet if ESPNOW is enabled
|
||||
}
|
||||
// reset remotes: initialize empty list (called from xml.cpp)
|
||||
function rstR() {
|
||||
@ -176,7 +177,9 @@ Static subnet mask:<br>
|
||||
rC++;
|
||||
gId('+').style.display = gId("rml").childElementCount < 10 ? 'inline' : 'none'; // can't append to list anymore, hide button
|
||||
}
|
||||
|
||||
function vI(i) {
|
||||
i.style.color = (i.value.match(/^[a-zA-Z0-9_\-]*$/)) ? 'white' : 'red';
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
@ -187,6 +190,9 @@ Static subnet mask:<br>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save & Connect</button><hr>
|
||||
</div>
|
||||
<h2>WiFi setup</h2>
|
||||
Hostname/mDNS address (empty for no mDNS):<br>
|
||||
http://<input type="text" name="CM" maxlength="32" pattern="[a-zA-Z0-9_\-]*" oninput="vI(this)">.local<br>
|
||||
Client IP: <span class="sip"> Not connected </span><br>
|
||||
<h3>Connect to existing network</h3>
|
||||
<button type="button" id="scan" onclick="N()">Scan</button><br>
|
||||
<div id="wifi">
|
||||
@ -198,14 +204,10 @@ Static subnet mask:<br>
|
||||
</div>
|
||||
DNS server address:<br>
|
||||
<input name="D0" type="number" class="s" min="0" max="255" required>.<input name="D1" type="number" class="s" min="0" max="255" required>.<input name="D2" type="number" class="s" min="0" max="255" required>.<input name="D3" type="number" class="s" min="0" max="255" required><br>
|
||||
<br>
|
||||
mDNS address (leave empty for no mDNS):<br>
|
||||
http:// <input type="text" name="CM" maxlength="32"> .local<br>
|
||||
Client IP: <span class="sip"> Not connected </span> <br>
|
||||
<h3>Configure Access Point</h3>
|
||||
AP SSID (leave empty for no AP):<br> <input type="text" name="AS" maxlength="32"><br>
|
||||
AP SSID (empty for no AP):<br> <input type="text" name="AS" maxlength="32" pattern="[a-zA-Z0-9_\-]*" oninput="vI(this)"><br>
|
||||
Hide AP name: <input type="checkbox" name="AH"><br>
|
||||
AP password (leave empty for open):<br> <input type="password" name="AP" maxlength="63" pattern="(.{8,63})|()" title="Empty or min. 8 characters"><br>
|
||||
AP password (empty for open):<br> <input type="password" name="AP" maxlength="63" pattern="(.{8,63})|()" title="Empty or min. 8 characters"><br>
|
||||
Access Point WiFi channel: <input name="AC" type="number" class="xs" min="1" max="13" required><br>
|
||||
AP opens:
|
||||
<select name="AB">
|
||||
@ -256,7 +258,7 @@ Static subnet mask:<br>
|
||||
|
||||
<div id="ethd">
|
||||
<h3>Ethernet Type</h3>
|
||||
<select name="ETH">
|
||||
<select name="ETH" onchange="if(this.selectedIndex!=0)d.Sf.RE.checked=false;">
|
||||
<option value="0">None</option>
|
||||
<option value="9">ABC! WLED V43 & compatible</option>
|
||||
<option value="2">ESP32-POE</option>
|
||||
@ -270,7 +272,8 @@ Static subnet mask:<br>
|
||||
<option value="5">TwilightLord-ESP32</option>
|
||||
<option value="3">WESP32</option>
|
||||
<option value="1">WT32-ETH01</option>
|
||||
</select><br><br>
|
||||
</select><br>
|
||||
<i class="warn">ESP-NOW is incompatible with Ethernet.</i>
|
||||
</div>
|
||||
<hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save & Connect</button>
|
||||
|
@ -505,7 +505,7 @@ size_t printSetFormValue(Print& settingsScript, const char* key, int val);
|
||||
size_t printSetFormValue(Print& settingsScript, const char* key, const char* val);
|
||||
size_t printSetFormIndex(Print& settingsScript, const char* key, int index);
|
||||
size_t printSetClassElementHTML(Print& settingsScript, const char* key, const int index, const char* val);
|
||||
void prepareHostname(char* hostname);
|
||||
void prepareHostname(char* hostname, size_t maxLen = 32);
|
||||
[[gnu::pure]] bool isAsterisksOnly(const char* str, byte maxLen);
|
||||
bool requestJSONBufferLock(uint8_t moduleID=255);
|
||||
void releaseJSONBufferLock();
|
||||
|
@ -386,7 +386,7 @@ void WiFiEvent(WiFiEvent_t event)
|
||||
case ARDUINO_EVENT_WIFI_AP_STOP:
|
||||
DEBUG_PRINTLN(F("WiFi-E: AP Stopped"));
|
||||
break;
|
||||
#if defined(WLED_USE_ETHERNET)
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
DEBUG_PRINTLN(F("ETH-E: Started"));
|
||||
break;
|
||||
@ -402,8 +402,8 @@ void WiFiEvent(WiFiEvent_t event)
|
||||
ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
}
|
||||
// convert the "serverDescription" into a valid DNS hostname (alphanumeric)
|
||||
char hostname[64];
|
||||
prepareHostname(hostname);
|
||||
char hostname[33];
|
||||
prepareHostname(hostname, sizeof(hostname)-1);
|
||||
ETH.setHostname(hostname);
|
||||
showWelcomePage = false;
|
||||
break;
|
||||
|
@ -63,16 +63,23 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
dnsAddress = IPAddress(request->arg(F("D0")).toInt(),request->arg(F("D1")).toInt(),request->arg(F("D2")).toInt(),request->arg(F("D3")).toInt());
|
||||
}
|
||||
|
||||
strlcpy(cmDNS, request->arg(F("CM")).c_str(), 33);
|
||||
strlcpy(cmDNS, request->arg(F("CM")).c_str(), sizeof(cmDNS));
|
||||
char hostname[25];
|
||||
prepareHostname(hostname, sizeof(hostname)-1);
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WiFi.setHostname(hostname);
|
||||
#else
|
||||
WiFi.hostname(hostname);
|
||||
#endif
|
||||
|
||||
apBehavior = request->arg(F("AB")).toInt();
|
||||
char oldSSID[33]; strcpy(oldSSID, apSSID);
|
||||
strlcpy(apSSID, request->arg(F("AS")).c_str(), 33);
|
||||
strlcpy(apSSID, request->arg(F("AS")).c_str(), sizeof(apSSID));
|
||||
if (!strcmp(oldSSID, apSSID) && apActive) forceReconnect = true;
|
||||
apHide = request->hasArg(F("AH"));
|
||||
int passlen = request->arg(F("AP")).length();
|
||||
if (passlen == 0 || (passlen > 7 && !isAsterisksOnly(request->arg(F("AP")).c_str(), 65))) {
|
||||
strlcpy(apPass, request->arg(F("AP")).c_str(), 65);
|
||||
if (passlen == 0 || (passlen > 7 && !isAsterisksOnly(request->arg(F("AP")).c_str(), sizeof(apPass)))) {
|
||||
strlcpy(apPass, request->arg(F("AP")).c_str(), sizeof(apPass));
|
||||
forceReconnect = true;
|
||||
}
|
||||
int t = request->arg(F("AC")).toInt();
|
||||
@ -368,6 +375,13 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (subPage == SUBPAGE_UI)
|
||||
{
|
||||
strlcpy(serverDescription, request->arg(F("DS")).c_str(), 33);
|
||||
char hostname[25];
|
||||
prepareHostname(hostname, sizeof(hostname)-1);
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WiFi.setHostname(hostname);
|
||||
#else
|
||||
WiFi.hostname(hostname);
|
||||
#endif
|
||||
//syncToggleReceive = request->hasArg(F("ST"));
|
||||
simplifiedUI = request->hasArg(F("SU"));
|
||||
DEBUG_PRINTLN(F("Enumerating ledmaps"));
|
||||
|
@ -114,29 +114,31 @@ size_t printSetClassElementHTML(Print& settingsScript, const char* key, const in
|
||||
}
|
||||
|
||||
|
||||
|
||||
void prepareHostname(char* hostname)
|
||||
// prepare a unique hostname based on the last 6 digits of the MAC address
|
||||
// if no mDNS name or serverDescription is set, otherwise use cmDNS or serverDescription
|
||||
// the hostname will be at most 24 characters long, starting with "wled-"
|
||||
// and containing only alphanumeric characters and hyphens
|
||||
// the hostname will not end with a hyphen and will be null-terminated
|
||||
void prepareHostname(char* hostname, size_t maxLen)
|
||||
{
|
||||
// create a unique hostname based on the last 6 digits of the MAC address if no mDNS name or serverDescription is set
|
||||
sprintf_P(hostname, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6);
|
||||
const char *pC = serverDescription;
|
||||
unsigned pos = 5; // keep "wled-"
|
||||
while (*pC && pos < 24) { // while !null and not over length
|
||||
const char *pC = cmDNS; // use cmDNS as hostname if set
|
||||
if (strlen(pC) == 0) pC = serverDescription; // else use serverDescription
|
||||
unsigned pos = 5; // keep "wled-" from unique name
|
||||
while (*pC && pos < maxLen) { // while !null and not over length
|
||||
if (isalnum(*pC)) { // if the current char is alpha-numeric append it to the hostname
|
||||
hostname[pos] = *pC;
|
||||
pos++;
|
||||
hostname[pos++] = *pC;
|
||||
} else if (*pC == ' ' || *pC == '_' || *pC == '-' || *pC == '+' || *pC == '!' || *pC == '?' || *pC == '*') {
|
||||
hostname[pos] = '-';
|
||||
pos++;
|
||||
hostname[pos++] = '-';
|
||||
}
|
||||
// else do nothing - no leading hyphens and do not include hyphens for all other characters.
|
||||
pC++;
|
||||
}
|
||||
// last character must not be hyphen
|
||||
if (pos > 5) {
|
||||
while (pos > 4 && hostname[pos-1] == '-') pos--;
|
||||
hostname[pos] = '\0'; // terminate string (leave at least "wled")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool isAsterisksOnly(const char* str, byte maxLen)
|
||||
|
Loading…
x
Reference in New Issue
Block a user