Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions wled00/bus_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "bus_wrapper.h"
#include <bits/unique_ptr.h>

extern char cmDNS[];
extern bool mDNSenabled;
extern bool cctICused;
extern bool useParallelI2S;

Expand Down Expand Up @@ -730,7 +730,7 @@ void BusNetwork::resolveHostname() {
if (Network.isConnected() && millis() > nextResolve && _hostname.length() > 0) {
nextResolve = millis() + 600000; // resolve only every 10 minutes
IPAddress clnt;
if (strlen(cmDNS) > 0) clnt = MDNS.queryHost(_hostname);
if (mDNSenabled) clnt = MDNS.queryHost(_hostname);
else WiFi.hostByName(_hostname.c_str(), clnt);
if (clnt != IPAddress()) _client = clnt;
}
Expand Down
34 changes: 27 additions & 7 deletions wled00/cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,22 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
#endif

JsonObject id = doc["id"];
getStringFromJson(cmDNS, id[F("mdns")], 33);
getStringFromJson(serverDescription, id[F("name")], 33);
getStringFromJson(serverDescription, id["name"], sizeof(serverDescription));
// legacy behaviour
getStringFromJson(hostName, id[F("mdns")], sizeof(hostName));
if (strlen(hostName) == 0) {
mDNSenabled = false; // if no host name is set, disable mDNS
prepareHostname(hostName, sizeof(hostName)-1);
}

Comment on lines +60 to +67
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential issue with legacy hostname migration logic

The current implementation reads from id["mdns"] into hostName for legacy compatibility, but if that field is empty, it disables mDNS and generates a new hostname. This could unexpectedly disable mDNS for users who had it enabled but didn't have an explicit hostname set in their legacy configuration.

Consider preserving the existing mDNS enabled state when migrating legacy configurations:

-  // legacy behaviour
-  getStringFromJson(hostName, id[F("mdns")], sizeof(hostName));
-  if (strlen(hostName) == 0) {
-    mDNSenabled = false; // if no host name is set, disable mDNS
-    prepareHostname(hostName, sizeof(hostName)-1);
-  }
+  // legacy behaviour - preserve existing mDNS state
+  const char* legacyHostname = id[F("mdns")];
+  if (legacyHostname != nullptr) {
+    getStringFromJson(hostName, legacyHostname, sizeof(hostName));
+  }
+  // Generate hostname if empty (from either legacy or new location)
+  if (strlen(hostName) == 0) {
+    prepareHostname(hostName, sizeof(hostName)-1);
+  }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In wled00/cfg.cpp around lines 60 to 67, the legacy migration currently zeroes
mDNSenabled when id["mdns"] yields an empty hostName; instead, preserve the
existing mDNSenabled flag and only change it if the legacy config explicitly
indicates mDNS should be disabled. Update the logic to: read hostName from
id["mdns"], if hostName is empty call prepareHostname(...) to generate a
hostname but do not set mDNSenabled = false; only set mDNSenabled = false when
the legacy field explicitly signals mDNS should be disabled (or when another
explicit legacy flag indicates disablement).

#ifndef WLED_DISABLE_ALEXA
getStringFromJson(alexaInvocationName, id[F("inv")], 33);
getStringFromJson(alexaInvocationName, id[F("inv")], sizeof(alexaInvocationName));
#endif
CJSON(simplifiedUI, id[F("sui")]);

JsonObject nw = doc["nw"];
CJSON(mDNSenabled, nw[F("mdns")]);
getStringFromJson(hostName, nw["name"], sizeof(hostName));
Comment on lines +74 to +75
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Order of operations issue: mDNS flag might be overwritten

The mDNS enabled flag is set on line 74 from the new location nw["mdns"], but the legacy code on lines 62-66 might have already set it to false. This could cause the new value to override the legacy migration logic unexpectedly.

Consider reordering to handle legacy migration after reading the new values:

   JsonObject nw = doc["nw"];
-  CJSON(mDNSenabled, nw[F("mdns")]);
-  getStringFromJson(hostName, nw["name"], sizeof(hostName));
+  // Read new format first
+  bool hasNewHostname = nw["name"] != nullptr;
+  if (hasNewHostname) {
+    getStringFromJson(hostName, nw["name"], sizeof(hostName));
+    CJSON(mDNSenabled, nw[F("mdns")]);
+  }
+  // Only apply legacy if new format not present
+  else if (id[F("mdns")] != nullptr) {
+    getStringFromJson(hostName, id[F("mdns")], sizeof(hostName));
+    // Don't force mDNS disabled for legacy configs
+  }
+  // Generate hostname if still empty
+  if (strlen(hostName) == 0) {
+    prepareHostname(hostName, sizeof(hostName)-1);
+  }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In wled00/cfg.cpp around lines 62-75, the new mDNS flag is read from nw["mdns"]
on line 74 which can be unintentionally overridden by the earlier legacy
migration block (lines 62-66); move the legacy migration logic to run after you
read the new values (i.e., after the CJSON/getStringFromJson lines) or,
alternatively, keep reading nw["mdns"] first and then apply the legacy check to
explicitly override mDNSenabled when legacy storage indicates it should be
disabled; update the surrounding comment to clarify the order and ensure the
final mDNSenabled value reflects legacy migration when applicable.

#ifndef WLED_DISABLE_ESPNOW
CJSON(enableESPNow, nw[F("espnow")]);
linked_remotes.clear();
Expand Down Expand Up @@ -143,13 +151,23 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {

JsonObject wifi = doc[F("wifi")];
noWifiSleep = !(wifi[F("sleep")] | !noWifiSleep); // inverted
//noWifiSleep = !noWifiSleep;
CJSON(force802_3g, wifi[F("phy")]); //force phy mode g?
#ifdef ARDUINO_ARCH_ESP32
CJSON(txPower, wifi[F("txpwr")]);
txPower = min(max((int)txPower, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm);
#endif

// apply WiFi options from above (regardless of fromFS or not)
#ifdef ARDUINO_ARCH_ESP32
WiFi.setSleep(!noWifiSleep);
WiFi.setHostname(hostName);
WiFi.setTxPower(wifi_power_t(txPower));
#else
WiFi.setPhyMode(force802_3g ? WIFI_PHY_MODE_11G : WIFI_PHY_MODE_11N);
wifi_set_sleep_type((noWifiSleep) ? NONE_SLEEP_T : MODEM_SLEEP_T);
WiFi.hostname(hostName);
#endif

JsonObject hw = doc[F("hw")];

// initialize LED pins and lengths prior to other HW (except for ethernet)
Expand Down Expand Up @@ -637,8 +655,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
Expand Down Expand Up @@ -849,14 +868,15 @@ void serializeConfig(JsonObject root) {
root[F("vid")] = VERSION;

JsonObject id = root.createNestedObject("id");
id[F("mdns")] = cmDNS;
id[F("name")] = serverDescription;
id["name"] = serverDescription;
#ifndef WLED_DISABLE_ALEXA
id[F("inv")] = alexaInvocationName;
#endif
id[F("sui")] = simplifiedUI;

JsonObject nw = root.createNestedObject("nw");
nw["name"] = hostName;
nw[F("mdns")] = mDNSenabled;
#ifndef WLED_DISABLE_ESPNOW
nw[F("espnow")] = enableESPNow;
JsonArray lrem = nw.createNestedArray(F("linked_remote"));
Expand Down
6 changes: 3 additions & 3 deletions wled00/data/settings.htm
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@
</head>
<body onload="S()">
<button type=submit id="b" onclick="window.location=getURL('/')">Back</button>
<button type="submit" onclick="window.location=getURL('/settings/wifi')">WiFi Setup</button>
<button type="submit" onclick="window.location=getURL('/settings/leds')">LED Preferences</button>
<button type="submit" onclick="window.location=getURL('/settings/wifi')">Network Setup</button>
<button type="submit" onclick="window.location=getURL('/settings/leds')">Hardware Setup</button>
<button id="2dbtn" type="submit" onclick="window.location=getURL('/settings/2D')">2D Configuration</button>
<button type="submit" onclick="window.location=getURL('/settings/ui')">User Interface</button>
<button id="dmxbtn" style="display:none;" type="submit" onclick="window.location=getURL('/settings/dmx')">DMX Output</button>
<button type="submit" onclick="window.location=getURL('/settings/sync')">Sync Interfaces</button>
<button type="submit" onclick="window.location=getURL('/settings/time')">Time & Macros</button>
<button type="submit" onclick="window.location=getURL('/settings/time')">Time & Scheduler</button>
<button type="submit" onclick="window.location=getURL('/settings/um')">Usermods</button>
<button type="submit" onclick="window.location=getURL('/settings/sec')">Security & Updates</button>
</body>
Expand Down
8 changes: 3 additions & 5 deletions wled00/data/settings_ui.htm
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,13 @@

function Save() {
SetLS();
if (d.Sf.DS.value != initial_ds || /*d.Sf.ST.checked != initial_st ||*/ d.Sf.SU.checked != initial_su) d.Sf.submit();
if (d.Sf.DS.value != initial_ds || d.Sf.SU.checked != initial_su) d.Sf.submit();
}

function S() {
getLoc();
loadJS(getURL('/settings/s.js?p=3'), false, undefined, ()=>{
initial_ds = d.Sf.DS.value;
//initial_st = d.Sf.ST.checked;
initial_su = d.Sf.SU.checked;
GetLS();
}); // If we set async false, file is loaded and executed, then next statement is processed
Expand Down Expand Up @@ -219,10 +218,9 @@
<span id="lserr" style="color:red; display:none">&#9888; Could not access local storage. Make sure it is enabled in your browser.</span><hr>
</div>
<h2>Web Setup</h2>
Server description: <input type="text" name="DS" maxlength="32"><br>
<!-- Sync button toggles both send and receive: <input type="checkbox" name="ST"><br> -->
Device name: <input type="text" name="DS" minlength="2" maxlength="32"><br>
Enable simplified UI: <input type="checkbox" name="SU"><br>
<i>The following UI customization settings are unique both to the WLED device and this browser.<br>
<i class="warn">The following UI customization settings are unique both to the WLED device and this browser.<br>
You will need to set them again if using a different browser, device or WLED IP address.<br>
Refresh the main UI to apply changes.</i><br>

Expand Down
113 changes: 60 additions & 53 deletions wled00/data/settings_wifi.htm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
<title>WiFi Settings</title>
<title>Network Settings</title>
<script src="common.js" async type="text/javascript"></script>
<script>
var scanLoops = 0, preScanSSID = "";
Expand Down Expand Up @@ -134,7 +134,7 @@
}
function S() {
getLoc();
loadJS(getURL('/settings/s.js?p=1'), false); // If we set async false, file is loaded and executed, then next statement is processed
loadJS(getURL('/settings/s.js?p=1'), false, undefined, genUrl); // If we set async false, file is loaded and executed, then next statement is processed
if (loc) d.Sf.action = getURL('/settings/wifi');
setTimeout(tE, 500); // wait for DOM to load before calling tE()
}
Expand All @@ -144,6 +144,7 @@
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() {
Expand Down Expand Up @@ -176,7 +177,10 @@
rC++;
gId('+').style.display = gId("rml").childElementCount < 10 ? 'inline' : 'none'; // can't append to list anymore, hide button
}

function genUrl() {
gId("ml").textContent = d.Sf.CM.value;
gId('mi').style.display = d.Sf.MD.checked?'inline':'none'
}
</script>
<style>@import url("style.css");</style>
</head>
Expand All @@ -186,36 +190,75 @@
<div class="helpB"><button type="button" onclick="H('features/settings/#wifi-settings')">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save & Connect</button><hr>
</div>
<h2>WiFi setup</h2>
<h3>Connect to existing network</h3>
<h2>Network setup</h2>
Hostname<br>
<input type="text" name="CM" minlength="2" maxlength="32" pattern="[a-zA-Z0-9_\-]*" oninput="genUrl()"><br>
Enable mDNS: <input type="checkbox" name="MD" checked onchange="genUrl()"><br>
<div id="mi"><i>http://<span id="ml">wled</span>.local</i><br></div>
Client IP: <span class="sip"> Not connected </span><br>
<h3>WiFi</h3>
<button type="button" id="scan" onclick="N()">Scan</button><br>
<div id="wifi">
Wireless networks
<div id="wifi_entries"></div>
<hr class="sml">
<button type="button" id="wifi_add" onclick="addWiFi()">+</button>
<button type="button" id="wifi_rem" onclick="remWiFi()">-</button><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>
<hr class="sml">
<h3>Access Point</h3>
AP SSID (empty for no AP):<br><input type="text" name="AS" maxlength="32" pattern="[a-zA-Z0-9_\-]*"><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:
AP opens:<br>
<select name="AB">
<option value="0">No connection after boot</option>
<option value="1">Disconnected</option>
<option value="2">Always</option>
<option value="3">Never (not recommended)</option>
<option value="4">Temporary (no connection after boot)</option>
<option value="3">Never (use button!)</option>
<option value="4">Temporary</option>
</select><br>
AP IP: <span class="sip"> Not active </span><br>
AP IP: <span class="sip">Not active</span><br>
<hr class="sml">
<div id="ethd">
<h3>Ethernet Type</h3>
<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>
<option value="11">ESP32-POE-WROVER</option>
<option value="6">ESP32Deux/RGB2Go</option>
<option value="7">KIT-VE</option>
<option value="12">LILYGO T-POE Pro</option>
<option value="8">QuinLED-Dig-Octa & T-ETH-POE</option>
<option value="4">QuinLED-ESP32</option>
<option value="10">Serg74-ETH32</option>
<option value="5">TwilightLord-ESP32</option>
<option value="3">WESP32</option>
<option value="1">WT32-ETH01</option>
</select><br>
<i class="warn">ESP-NOW is incompatible with Ethernet.</i>
</div>
<hr class="sml">
<h3>ESP-NOW Wireless</h3>
<div id="NoESPNOW" class="hide">
<i class="warn">This firmware build does not include ESP-NOW support.<br></i>
</div>
<div id="ESPNOW">
Enable ESP-NOW: <input type="checkbox" name="RE" onchange="tE()"><br>
<i>Listen for events over ESP-NOW<br>
Keep disabled if not using a remote or wireless sync, increases power consumption.<br></i>
<div id="rlc">
Last device seen: <span class="rlid" id="ld"></span>
<button type="button" class="sml" id="+" onclick="aR(gId('ld').textContent)">+</button><br>
Linked MACs:<br>
<div id="rml"></div>
</div>
<input type="hidden" name="RMAC" id="rmacs">
</div>
<hr class="sml">
<h3>Experimental</h3>
Force 802.11g mode (ESP8266 only): <input type="checkbox" name="FG"><br>
Disable WiFi sleep: <input type="checkbox" name="WS"><br>
Expand All @@ -236,42 +279,6 @@ <h3>Experimental</h3>
</select><br>
<i class="warn">WARNING: Modifying TX power may render device unreachable.</i>
</div>

<h3>ESP-NOW Wireless</h3>
<div id="NoESPNOW" class="hide">
<i class="warn">This firmware build does not include ESP-NOW support.<br></i>
</div>
<div id="ESPNOW">
Enable ESP-NOW: <input type="checkbox" name="RE" onchange="tE()"><br>
<i>Listen for events over ESP-NOW<br>
Keep disabled if not using a remote or ESP-NOW sync, increases power consumption.<br></i>
<div id="rlc">
Last device seen: <span class="rlid" id="ld">None</span>
<button type="button" class="sml" id="+" onclick="aR('RM'+rC,gId('ld').textContent)">+</button><br>
Linked MACs (10 max):<br>
<div id="rml">
</div>
</div>
</div>

<div id="ethd">
<h3>Ethernet Type</h3>
<select name="ETH">
<option value="0">None</option>
<option value="9">ABC! WLED V43 & compatible</option>
<option value="2">ESP32-POE</option>
<option value="11">ESP32-POE-WROVER</option>
<option value="6">ESP32Deux/RGB2Go</option>
<option value="7">KIT-VE</option>
<option value="12">LILYGO T-POE Pro</option>
<option value="8">QuinLED-Dig-Octa & T-ETH-POE</option>
<option value="4">QuinLED-ESP32</option>
<option value="10">Serg74-ETH32</option>
<option value="5">TwilightLord-ESP32</option>
<option value="3">WESP32</option>
<option value="1">WT32-ETH01</option>
</select><br><br>
</div>
<hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save & Connect</button>
</form>
Expand Down
2 changes: 1 addition & 1 deletion wled00/data/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ button.sml {
.hide {
display: none;
}
.err {
.err, input:invalid {
color: #f00;
}
.warn {
Expand Down
3 changes: 2 additions & 1 deletion wled00/fcn_declare.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ void espNowReceiveCB(uint8_t* address, uint8_t* data, uint8_t len, signed int rs
//network.cpp
bool initEthernet(); // result is informational
int getSignalQuality(int rssi);
IPAddress resolveHostname(const String &hostname, bool useMDNS = true);
void fillMAC2Str(char *str, const uint8_t *mac);
void fillStr2MAC(uint8_t *mac, const char *str);
int findWiFi(bool doScan = false);
Expand Down Expand Up @@ -388,7 +389,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();
Expand Down
9 changes: 4 additions & 5 deletions wled00/improv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,10 @@ void sendImprovInfoResponse() {
#endif
strlwr(bString);
#endif
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
char vString[32];
sprintf_P(vString, PSTR("%s/%i"), versionString, VERSION);
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
char vString[33];
snprintf_P(vString, sizeof(vString)-1, PSTR("%s/%i"), versionString, VERSION);
//Use serverDescription if it has been changed from the default "WLED", else host name
const char *str[4] = {"WLED", vString, bString, strcmp(serverDescription, "WLED") == 0 ? hostName : serverDescription};

sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);
}
Expand Down
2 changes: 1 addition & 1 deletion wled00/mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ bool initMqtt()
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
if (mDNSenabled && 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);
Expand Down
Loading