From 571ab674c3be3078b73e869d808acbb3aa65c571 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 22 Nov 2025 12:22:05 +0000 Subject: [PATCH 1/8] Update to use deviceId --- wled00/data/index.js | 189 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) diff --git a/wled00/data/index.js b/wled00/data/index.js index 2d49a26400..d5e7f7d466 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -3304,6 +3304,195 @@ function simplifyUI() { gId("btns").style.display = "none"; } +// Version reporting feature +var versionCheckDone = false; + +function checkVersionUpgrade(info) { + // Only check once per page load + if (versionCheckDone) return; + versionCheckDone = true; + + // Suppress feature if in AP mode (no internet connection available) + if (info.wifi && info.wifi.ap) return; + + // Fetch version-info.json using existing /edit endpoint + fetch(getURL('/edit?func=edit&path=/version-info.json'), { + method: 'get' + }) + .then(res => { + if (res.status === 404) { + // File doesn't exist - first install, show install prompt + showVersionUpgradePrompt(info, null, info.ver); + return null; + } + if (!res.ok) { + throw new Error('Failed to fetch version-info.json'); + } + return res.json(); + }) + .then(versionInfo => { + if (!versionInfo) return; // 404 case already handled + + // Check if user opted out + if (versionInfo.neverAsk) return; + + // Check if version has changed + const currentVersion = info.ver; + const storedVersion = versionInfo.version || ''; + + if (storedVersion && storedVersion !== currentVersion) { + // Version has changed, show upgrade prompt + showVersionUpgradePrompt(info, storedVersion, currentVersion); + } else if (!storedVersion) { + // Empty version in file, show install prompt + showVersionUpgradePrompt(info, null, currentVersion); + } + }) + .catch(e => { + console.log('Failed to load version-info.json', e); + // On error, save current version for next time + if (info && info.ver) { + updateVersionInfo(info.ver, false); + } + }); +} + +function showVersionUpgradePrompt(info, oldVersion, newVersion) { + // Determine if this is an install or upgrade + const isInstall = !oldVersion; + + // Create overlay and dialog + const overlay = d.createElement('div'); + overlay.id = 'versionUpgradeOverlay'; + overlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:10000;display:flex;align-items:center;justify-content:center;'; + + const dialog = d.createElement('div'); + dialog.style.cssText = 'background:var(--c-1);border-radius:10px;padding:25px;max-width:500px;margin:20px;box-shadow:0 4px 6px rgba(0,0,0,0.3);'; + + // Build contextual message based on install vs upgrade + const title = isInstall + ? '🎉 Thank you for installing WLED!' + : '🎉 WLED Upgrade Detected!'; + + const description = isInstall + ? `You are now running WLED ${newVersion}.` + : `Your WLED has been upgraded from ${oldVersion} to ${newVersion}.`; + + const question = 'Would you like to help the WLED development team by reporting your installation? This helps us understand what hardware and versions are being used.' + + dialog.innerHTML = ` +

${title}

+

${description}

+

${question}

+

+ Learn more about what data is collected and why +

+
+ + + +
+ `; + + overlay.appendChild(dialog); + d.body.appendChild(overlay); + + // Add event listeners + gId('versionReportYes').addEventListener('click', () => { + reportUpgradeEvent(info, oldVersion, newVersion); + d.body.removeChild(overlay); + }); + + gId('versionReportNo').addEventListener('click', () => { + // Don't update version, will ask again on next load + d.body.removeChild(overlay); + }); + + gId('versionReportNever').addEventListener('click', () => { + updateVersionInfo(newVersion, true); + d.body.removeChild(overlay); + showToast('You will not be asked again.'); + }); +} + +function reportUpgradeEvent(info, oldVersion, newVersion) { + showToast('Reporting upgrade...'); + + // Fetch fresh data from /json/info endpoint as requested + fetch(getURL('/json/info'), { + method: 'get' + }) + .then(res => res.json()) + .then(infoData => { + // Map to UpgradeEventRequest structure per OpenAPI spec + // Required fields: deviceId, version, previousVersion, releaseName, chip, ledCount, isMatrix, bootloaderSHA256 + const upgradeData = { + deviceId: infoData.deviceid, // Use anonymous unique device ID + version: infoData.ver || '', // Current version string + previousVersion: oldVersion || '', // Previous version from version-info.json + releaseName: infoData.release || '', // Release name (e.g., "WLED 0.15.0") + chip: infoData.arch || '', // Chip architecture (esp32, esp8266, etc) + ledCount: infoData.leds ? infoData.leds.count : 0, // Number of LEDs + isMatrix: !!(infoData.leds && infoData.leds.matrix), // Whether it's a 2D matrix setup + bootloaderSHA256: infoData.bootloaderSHA256 || '', // Bootloader SHA256 hash + brand: infoData.brand, // Device brand (always present) + product: infoData.product, // Product name (always present) + flashSize: infoData.flash + 'MB' // Flash size (always present) + }; + + // Add optional fields if available + if (infoData.psram !== undefined) upgradeData.psramSize = infoData.psram + 'B'; + // Note: partitionSizes not currently available in /json/info endpoint + + // Make AJAX call to postUpgradeEvent API + return fetch('https://usage.wled.me/api/usage/upgrade', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(upgradeData) + }); + }) + .then(res => { + if (res.ok) { + showToast('Thank you for reporting!'); + updateVersionInfo(newVersion, false); + } else { + showToast('Report failed. Please try again later.', true); + // Do NOT update version info on failure - user will be prompted again + } + }) + .catch(e => { + console.log('Failed to report upgrade', e); + showToast('Report failed. Please try again later.', true); + // Do NOT update version info on error - user will be prompted again + }); +} + +function updateVersionInfo(version, neverAsk) { + const versionInfo = { + version: version, + neverAsk: neverAsk + }; + + // Create a Blob with JSON content and use /upload endpoint + const blob = new Blob([JSON.stringify(versionInfo)], { type: 'application/json' }); + const formData = new FormData(); + formData.append('data', blob, 'version-info.json'); + + fetch(getURL('/upload'), { + method: 'POST', + body: formData + }) + .then(res => res.text()) + .then(data => { + console.log('Version info updated', data); + }) + .catch(e => { + console.log('Failed to update version-info.json', e); + }); +} + size(); _C.style.setProperty('--n', N); From b6f3cb63942cc41f2785f991554d759668950b8e Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 22 Nov 2025 12:32:23 +0000 Subject: [PATCH 2/8] Use deviceId not mac --- wled00/data/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index d5e7f7d466..8832fc716e 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -3427,7 +3427,7 @@ function reportUpgradeEvent(info, oldVersion, newVersion) { // Map to UpgradeEventRequest structure per OpenAPI spec // Required fields: deviceId, version, previousVersion, releaseName, chip, ledCount, isMatrix, bootloaderSHA256 const upgradeData = { - deviceId: infoData.deviceid, // Use anonymous unique device ID + deviceId: infoData.deviceId, // Use anonymous unique device ID version: infoData.ver || '', // Current version string previousVersion: oldVersion || '', // Previous version from version-info.json releaseName: infoData.release || '', // Release name (e.g., "WLED 0.15.0") From 49a25af1f23e0eeb2c8d18b662d4b95b3cf15337 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 22 Nov 2025 12:51:23 +0000 Subject: [PATCH 3/8] Fix styling issues --- wled00/data/index.css | 2 +- wled00/data/index.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/data/index.css b/wled00/data/index.css index c92c884abb..75ea796902 100644 --- a/wled00/data/index.css +++ b/wled00/data/index.css @@ -794,7 +794,7 @@ input[type=range]::-moz-range-thumb { /* buttons */ .btn { padding: 8px; - /*margin: 10px 4px;*/ + margin: 10px 4px; width: 230px; font-size: 19px; color: var(--c-d); diff --git a/wled00/data/index.js b/wled00/data/index.js index 8832fc716e..f09bf0f149 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -3375,8 +3375,8 @@ function showVersionUpgradePrompt(info, oldVersion, newVersion) { : '🎉 WLED Upgrade Detected!'; const description = isInstall - ? `You are now running WLED ${newVersion}.` - : `Your WLED has been upgraded from ${oldVersion} to ${newVersion}.`; + ? `You are now running WLED ${newVersion}.` + : `Your WLED has been upgraded from ${oldVersion} to ${newVersion}.`; const question = 'Would you like to help the WLED development team by reporting your installation? This helps us understand what hardware and versions are being used.' From 61f5737df2f35792e8b533a44afe1e747b58b8d1 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 22 Nov 2025 12:58:07 +0000 Subject: [PATCH 4/8] Remove MB suffix --- wled00/data/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index f09bf0f149..c77f1bfb01 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -3437,7 +3437,7 @@ function reportUpgradeEvent(info, oldVersion, newVersion) { bootloaderSHA256: infoData.bootloaderSHA256 || '', // Bootloader SHA256 hash brand: infoData.brand, // Device brand (always present) product: infoData.product, // Product name (always present) - flashSize: infoData.flash + 'MB' // Flash size (always present) + flashSize: infoData.flash // Flash size (always present) }; // Add optional fields if available From 17e91a7d2a48a27d94fa0f97f10beadedd65c36d Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 22 Nov 2025 13:02:06 +0000 Subject: [PATCH 5/8] Remove K suffix --- wled00/data/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index c77f1bfb01..4b399bda72 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -3441,7 +3441,7 @@ function reportUpgradeEvent(info, oldVersion, newVersion) { }; // Add optional fields if available - if (infoData.psram !== undefined) upgradeData.psramSize = infoData.psram + 'B'; + if (infoData.psram !== undefined) upgradeData.psramSize = infoData.psram; // Note: partitionSizes not currently available in /json/info endpoint // Make AJAX call to postUpgradeEvent API From 579021f5fc5c607a276b000eaf5aa39c6665036f Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 26 Nov 2025 22:41:45 +0000 Subject: [PATCH 6/8] trigger reportUpgradeEvent --- wled00/data/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index 4b399bda72..93ffe80100 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -693,6 +693,8 @@ function parseInfo(i) { // gId("filterVol").classList.add("hide"); hideModes(" ♪"); // hide volume reactive effects // gId("filterFreq").classList.add("hide"); hideModes(" ♫"); // hide frequency reactive effects // } + // Check for version upgrades on page load + checkVersionUpgrade(i); } //https://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml @@ -3399,7 +3401,7 @@ function showVersionUpgradePrompt(info, oldVersion, newVersion) { // Add event listeners gId('versionReportYes').addEventListener('click', () => { - reportUpgradeEvent(info, oldVersion, newVersion); + reportUpgradeEvent(info, oldVersion); d.body.removeChild(overlay); }); @@ -3415,7 +3417,7 @@ function showVersionUpgradePrompt(info, oldVersion, newVersion) { }); } -function reportUpgradeEvent(info, oldVersion, newVersion) { +function reportUpgradeEvent(info, oldVersion) { showToast('Reporting upgrade...'); // Fetch fresh data from /json/info endpoint as requested @@ -3456,7 +3458,7 @@ function reportUpgradeEvent(info, oldVersion, newVersion) { .then(res => { if (res.ok) { showToast('Thank you for reporting!'); - updateVersionInfo(newVersion, false); + updateVersionInfo(info.ver, false); } else { showToast('Report failed. Please try again later.', true); // Do NOT update version info on failure - user will be prompted again From 8bc434b6143ee433f8bbcaa6316316e1ab775e4f Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 27 Nov 2025 13:36:04 +0000 Subject: [PATCH 7/8] Update working to Aircoookie's suggestion --- wled00/data/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index 93ffe80100..ea297595bd 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -3380,7 +3380,7 @@ function showVersionUpgradePrompt(info, oldVersion, newVersion) { ? `You are now running WLED ${newVersion}.` : `Your WLED has been upgraded from ${oldVersion} to ${newVersion}.`; - const question = 'Would you like to help the WLED development team by reporting your installation? This helps us understand what hardware and versions are being used.' + const question = 'Help make WLED better with a one-time hardware report? It includes only device details like chip type, LED count, etc. — never personal data or your activities.' dialog.innerHTML = `

${title}

From 33411f0300424db1b005cd2d37d00596bca2451d Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 27 Nov 2025 13:43:24 +0000 Subject: [PATCH 8/8] Reformat to tabs --- wled00/data/index.js | 204 +++++++++++++++++++++---------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index ea297595bd..fe011dce37 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -3321,65 +3321,65 @@ function checkVersionUpgrade(info) { fetch(getURL('/edit?func=edit&path=/version-info.json'), { method: 'get' }) - .then(res => { - if (res.status === 404) { - // File doesn't exist - first install, show install prompt - showVersionUpgradePrompt(info, null, info.ver); - return null; - } - if (!res.ok) { - throw new Error('Failed to fetch version-info.json'); - } - return res.json(); - }) - .then(versionInfo => { - if (!versionInfo) return; // 404 case already handled - - // Check if user opted out - if (versionInfo.neverAsk) return; - - // Check if version has changed - const currentVersion = info.ver; - const storedVersion = versionInfo.version || ''; - - if (storedVersion && storedVersion !== currentVersion) { - // Version has changed, show upgrade prompt - showVersionUpgradePrompt(info, storedVersion, currentVersion); - } else if (!storedVersion) { - // Empty version in file, show install prompt - showVersionUpgradePrompt(info, null, currentVersion); - } - }) - .catch(e => { - console.log('Failed to load version-info.json', e); - // On error, save current version for next time - if (info && info.ver) { - updateVersionInfo(info.ver, false); - } - }); + .then(res => { + if (res.status === 404) { + // File doesn't exist - first install, show install prompt + showVersionUpgradePrompt(info, null, info.ver); + return null; + } + if (!res.ok) { + throw new Error('Failed to fetch version-info.json'); + } + return res.json(); + }) + .then(versionInfo => { + if (!versionInfo) return; // 404 case already handled + + // Check if user opted out + if (versionInfo.neverAsk) return; + + // Check if version has changed + const currentVersion = info.ver; + const storedVersion = versionInfo.version || ''; + + if (storedVersion && storedVersion !== currentVersion) { + // Version has changed, show upgrade prompt + showVersionUpgradePrompt(info, storedVersion, currentVersion); + } else if (!storedVersion) { + // Empty version in file, show install prompt + showVersionUpgradePrompt(info, null, currentVersion); + } + }) + .catch(e => { + console.log('Failed to load version-info.json', e); + // On error, save current version for next time + if (info && info.ver) { + updateVersionInfo(info.ver, false); + } + }); } function showVersionUpgradePrompt(info, oldVersion, newVersion) { // Determine if this is an install or upgrade const isInstall = !oldVersion; - + // Create overlay and dialog const overlay = d.createElement('div'); overlay.id = 'versionUpgradeOverlay'; overlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:10000;display:flex;align-items:center;justify-content:center;'; - + const dialog = d.createElement('div'); dialog.style.cssText = 'background:var(--c-1);border-radius:10px;padding:25px;max-width:500px;margin:20px;box-shadow:0 4px 6px rgba(0,0,0,0.3);'; - + // Build contextual message based on install vs upgrade - const title = isInstall - ? '🎉 Thank you for installing WLED!' + const title = isInstall + ? '🎉 Thank you for installing WLED!' : '🎉 WLED Upgrade Detected!'; - + const description = isInstall ? `You are now running WLED ${newVersion}.` : `Your WLED has been upgraded from ${oldVersion} to ${newVersion}.`; - + const question = 'Help make WLED better with a one-time hardware report? It includes only device details like chip type, LED count, etc. — never personal data or your activities.' dialog.innerHTML = ` @@ -3395,21 +3395,21 @@ function showVersionUpgradePrompt(info, oldVersion, newVersion) { `; - + overlay.appendChild(dialog); d.body.appendChild(overlay); - + // Add event listeners gId('versionReportYes').addEventListener('click', () => { reportUpgradeEvent(info, oldVersion); d.body.removeChild(overlay); }); - + gId('versionReportNo').addEventListener('click', () => { // Don't update version, will ask again on next load d.body.removeChild(overlay); }); - + gId('versionReportNever').addEventListener('click', () => { updateVersionInfo(newVersion, true); d.body.removeChild(overlay); @@ -3419,56 +3419,56 @@ function showVersionUpgradePrompt(info, oldVersion, newVersion) { function reportUpgradeEvent(info, oldVersion) { showToast('Reporting upgrade...'); - + // Fetch fresh data from /json/info endpoint as requested fetch(getURL('/json/info'), { method: 'get' }) - .then(res => res.json()) - .then(infoData => { - // Map to UpgradeEventRequest structure per OpenAPI spec - // Required fields: deviceId, version, previousVersion, releaseName, chip, ledCount, isMatrix, bootloaderSHA256 - const upgradeData = { - deviceId: infoData.deviceId, // Use anonymous unique device ID - version: infoData.ver || '', // Current version string - previousVersion: oldVersion || '', // Previous version from version-info.json - releaseName: infoData.release || '', // Release name (e.g., "WLED 0.15.0") - chip: infoData.arch || '', // Chip architecture (esp32, esp8266, etc) - ledCount: infoData.leds ? infoData.leds.count : 0, // Number of LEDs - isMatrix: !!(infoData.leds && infoData.leds.matrix), // Whether it's a 2D matrix setup - bootloaderSHA256: infoData.bootloaderSHA256 || '', // Bootloader SHA256 hash - brand: infoData.brand, // Device brand (always present) - product: infoData.product, // Product name (always present) - flashSize: infoData.flash // Flash size (always present) - }; - - // Add optional fields if available - if (infoData.psram !== undefined) upgradeData.psramSize = infoData.psram; - // Note: partitionSizes not currently available in /json/info endpoint - - // Make AJAX call to postUpgradeEvent API - return fetch('https://usage.wled.me/api/usage/upgrade', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(upgradeData) - }); - }) - .then(res => { - if (res.ok) { - showToast('Thank you for reporting!'); - updateVersionInfo(info.ver, false); - } else { + .then(res => res.json()) + .then(infoData => { + // Map to UpgradeEventRequest structure per OpenAPI spec + // Required fields: deviceId, version, previousVersion, releaseName, chip, ledCount, isMatrix, bootloaderSHA256 + const upgradeData = { + deviceId: infoData.deviceId, // Use anonymous unique device ID + version: infoData.ver || '', // Current version string + previousVersion: oldVersion || '', // Previous version from version-info.json + releaseName: infoData.release || '', // Release name (e.g., "WLED 0.15.0") + chip: infoData.arch || '', // Chip architecture (esp32, esp8266, etc) + ledCount: infoData.leds ? infoData.leds.count : 0, // Number of LEDs + isMatrix: !!(infoData.leds && infoData.leds.matrix), // Whether it's a 2D matrix setup + bootloaderSHA256: infoData.bootloaderSHA256 || '', // Bootloader SHA256 hash + brand: infoData.brand, // Device brand (always present) + product: infoData.product, // Product name (always present) + flashSize: infoData.flash // Flash size (always present) + }; + + // Add optional fields if available + if (infoData.psram !== undefined) upgradeData.psramSize = infoData.psram; + // Note: partitionSizes not currently available in /json/info endpoint + + // Make AJAX call to postUpgradeEvent API + return fetch('https://usage.wled.me/api/usage/upgrade', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(upgradeData) + }); + }) + .then(res => { + if (res.ok) { + showToast('Thank you for reporting!'); + updateVersionInfo(info.ver, false); + } else { + showToast('Report failed. Please try again later.', true); + // Do NOT update version info on failure - user will be prompted again + } + }) + .catch(e => { + console.log('Failed to report upgrade', e); showToast('Report failed. Please try again later.', true); - // Do NOT update version info on failure - user will be prompted again - } - }) - .catch(e => { - console.log('Failed to report upgrade', e); - showToast('Report failed. Please try again later.', true); - // Do NOT update version info on error - user will be prompted again - }); + // Do NOT update version info on error - user will be prompted again + }); } function updateVersionInfo(version, neverAsk) { @@ -3476,23 +3476,23 @@ function updateVersionInfo(version, neverAsk) { version: version, neverAsk: neverAsk }; - + // Create a Blob with JSON content and use /upload endpoint - const blob = new Blob([JSON.stringify(versionInfo)], { type: 'application/json' }); + const blob = new Blob([JSON.stringify(versionInfo)], {type: 'application/json'}); const formData = new FormData(); formData.append('data', blob, 'version-info.json'); - + fetch(getURL('/upload'), { method: 'POST', body: formData }) - .then(res => res.text()) - .then(data => { - console.log('Version info updated', data); - }) - .catch(e => { - console.log('Failed to update version-info.json', e); - }); + .then(res => res.text()) + .then(data => { + console.log('Version info updated', data); + }) + .catch(e => { + console.log('Failed to update version-info.json', e); + }); } size();