Skip to content

Commit 45b340a

Browse files
fhirschmannclaude
andcommitted
feat: show SD card capacity in web interface
Expose SD card size and free space via /info and render a usage gauge in the files tab (refreshed after uploads) plus a line in the system info dialog. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 6ea4020 commit 45b340a

5 files changed

Lines changed: 59 additions & 0 deletions

File tree

‎html/locales/de.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@
146146
"files": {
147147
"title": "Dateien",
148148
"loading": "Wird geladen...",
149+
"storage": {
150+
"title": "Speicherplatz",
151+
"info": "{{free}} GB frei von {{total}} GB ({{percent}} % belegt)"
152+
},
149153
"context": {
150154
"newFolder": "Neuer Ordner",
151155
"play": "Abspielen",
@@ -511,6 +515,7 @@
511515
"arduinoversion": "Arduino Version: {{arduinoversion}} (ESP-IDF {{idfversion}})",
512516
"hardware": "Hardware: {{hwmodel}}, Revision {{hwrevision}}, CPU: {{hwfreq}} MHZ",
513517
"freeheap": "Freier Heap: {{freeheap}} Bytes",
518+
"sdcard": "SD-Karte: {{free}} GB frei von {{total}} GB",
514519
"largestfreeblock": "Größter freier Heap-Block: {{largestfreeblock}} Bytes",
515520
"freepsram": "Freier PS-RAM: {{freepsram}} Bytes",
516521
"currentip": "Aktuelle IP-Adresse: {{currentip}}",

‎html/locales/en.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@
147147
"files": {
148148
"title": "Files",
149149
"loading": "Please wait...",
150+
"storage": {
151+
"title": "Storage",
152+
"info": "{{free}} GB free of {{total}} GB ({{percent}} % used)"
153+
},
150154
"context": {
151155
"newFolder": "New Folder",
152156
"play": "Play",
@@ -513,6 +517,7 @@
513517
"arduinoversion": "Arduino Version: {{arduinoversion}} (ESP-IDF {{idfversion}})",
514518
"hardware": "Hardware: {{hwmodel}}, Revision {{hwrevision}}, CPU: {{hwfreq}} MHZ",
515519
"freeheap": "Free heap: {{freeheap}} Bytes",
520+
"sdcard": "SD card: {{free}} GB free of {{total}} GB",
516521
"largestfreeblock": "Largest free heap-block: {{largestfreeblock}} Bytes",
517522
"freepsram": "Free PS-RAM: {{freepsram}} Bytes",
518523
"currentip": "Current IP-Address: {{currentip}}",

‎html/locales/fr.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@
139139
"files": {
140140
"title": "Fichiers",
141141
"loading": "Veuillez patienter...",
142+
"storage": {
143+
"title": "Stockage",
144+
"info": "{{free}} Go libres sur {{total}} Go ({{percent}} % utilisés)"
145+
},
142146
"context": {
143147
"newFolder": "Nouveau dossier",
144148
"play": "Lire",
@@ -500,6 +504,7 @@
500504
"arduinoversion": "Version Arduino : {{arduinoversion}} (ESP-IDF {{idfversion}})",
501505
"hardware": "Matériel : {{hwmodel}}, Révision {{hwrevision}}, CPU : {{hwfreq}} MHZ",
502506
"freeheap": "Mémoire libre : {{freeheap}} octets",
507+
"sdcard": "Carte SD : {{free}} Go libres sur {{total}} Go",
503508
"largestfreeblock": "Plus grand bloc de mémoire libre : {{largestfreeblock}} octets",
504509
"freepsram": "PS-RAM libre : {{freepsram}} octets",
505510
"currentip": "Adresse IP actuelle : {{currentip}}",

‎html/management.html‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,14 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
14551455
class="label d-flex position-absolute flex-column align-self-center text-center w-100 text-nowrap text-light">
14561456
</div>
14571457
</div>
1458+
<div id="sdCapacity" class="mt-3" data-visible="false">
1459+
<small><span data-i18n="files.storage.title"></span>: <span
1460+
id="sdCapacityText"></span></small>
1461+
<div class="progress progress-sm">
1462+
<div id="sdCapacityBar" class="progress-bar" role="progressbar" aria-valuemin="0"
1463+
aria-valuemax="100"></div>
1464+
</div>
1465+
</div>
14581466
</div>
14591467
</div>
14601468
</fieldset>
@@ -2388,6 +2396,7 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
23882396
});
23892397
i18next.on('languageChanged', (lng) => {
23902398
document.querySelector('#langSel').value = lng;
2399+
refreshSdCapacity();
23912400
if (localize) {
23922401
localize('body');
23932402
// (re)initialize all popover buttons to get correct translations in the popovers
@@ -2771,6 +2780,7 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
27712780
addFileDirectory(sel, data);
27722781
ref.open_node(sel);
27732782
});
2783+
refreshSdCapacity();
27742784
},
27752785
error: function (request, status, error) {
27762786
console.log("Upload ERROR!", request);
@@ -4250,6 +4260,28 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
42504260
}
42514261
return dDisplay + hDisplay + mDisplay;
42524262
}
4263+
async function refreshSdCapacity() {
4264+
try {
4265+
const info = await (await fetch("http://" + host + "/info?section=sdcard")).json();
4266+
const sd = info.sdcard;
4267+
if (!sd || !sd.size) {
4268+
return;
4269+
}
4270+
const usedPercent = Math.round((sd.size - sd.free) * 100 / sd.size);
4271+
const bar = document.getElementById('sdCapacityBar');
4272+
bar.style.width = usedPercent + "%";
4273+
bar.setAttribute('aria-valuenow', usedPercent);
4274+
document.getElementById('sdCapacityText').textContent = i18next.t("files.storage.info", {
4275+
free: (sd.free / 1024).toFixed(1),
4276+
total: (sd.size / 1024).toFixed(1),
4277+
percent: usedPercent
4278+
});
4279+
document.getElementById('sdCapacity').setAttribute('data-visible', true);
4280+
} catch (e) {
4281+
console.log("failed to fetch sd capacity", e);
4282+
}
4283+
}
4284+
42534285
async function fetchInfo() {
42544286
let info = await (await fetch("http://" + host + "/info")).json();
42554287
console.log(info);
@@ -4297,6 +4329,12 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
42974329
audiotimesincestart: timestampToDuration(info.audio.playtimeSinceStart, true)
42984330
}) + "<br>";
42994331
}
4332+
if (info.sdcard && info.sdcard.size) {
4333+
content += i18next.t("systeminfo.sdcard", {
4334+
free: (info.sdcard.free / 1024).toFixed(1),
4335+
total: (info.sdcard.size / 1024).toFixed(1)
4336+
}) + "<br>";
4337+
}
43004338
if (info.battery) {
43014339
content += i18next.t("systeminfo.currvoltage", {
43024340
currvoltage: info.battery.currVoltage.toFixed(2)

‎src/Web.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,12 @@ void handleGetInfo(AsyncWebServerRequest *request) {
14011401
audioObj["playtimeSinceStart"] = AudioPlayer_GetPlayTimeSinceStart();
14021402
audioObj["firstStart"] = gPrefsSettings.getULong("firstStart", 0);
14031403
}
1404+
// sd card
1405+
if ((section == "") || (section == "sdcard")) {
1406+
JsonObject sdObj = infoObj["sdcard"].to<JsonObject>();
1407+
sdObj["size"] = SdCard_GetSize() / (1024 * 1024); // MiB
1408+
sdObj["free"] = SdCard_GetFreeSize() / (1024 * 1024); // MiB
1409+
}
14041410
#ifdef BATTERY_MEASURE_ENABLE
14051411
// battery
14061412
if ((section == "") || (section == "battery")) {

0 commit comments

Comments
 (0)