From 0a882f53baa301229fc3c7379102c772c7eaea06 Mon Sep 17 00:00:00 2001
From: Theo Arends <11044339+arendst@users.noreply.github.com>
Date: Mon, 4 Jan 2021 15:52:32 +0100
Subject: [PATCH] Update xdrv_98_filesystem.ino
---
tasmota/xdrv_98_filesystem.ino | 338 +++++++++++++++++----------------
1 file changed, 174 insertions(+), 164 deletions(-)
diff --git a/tasmota/xdrv_98_filesystem.ino b/tasmota/xdrv_98_filesystem.ino
index 932185c0c..1fadd6427 100644
--- a/tasmota/xdrv_98_filesystem.ino
+++ b/tasmota/xdrv_98_filesystem.ino
@@ -17,17 +17,19 @@
along with this program. If not, see .
*/
-/*
-this driver adds universal file system support for
-ESP8266 (sd card or littlfs on > 1 M devices with special linker file e.g. eagle.flash.4m2m.ld)
-(makes no sense on 1M devices without sd card)
-and
-ESP32 (sd card or little fs or sfatfile system)
-the sd card chip select is the standard SPI_CS or when not found SDCARD_CS_PIN
-initializes the FS System Pointer ufsp which can be used by all standard file system calls
-the only specific call is ufs_fsinfo() which gets the total size (0) and free size (1)
-a button is created in the setup section to show up the file directory to download and upload files
-subdirectories are supported
+#ifdef USE_UFILESYS
+/*********************************************************************************************\
+This driver adds universal file system support for ESP8266 (sd card or littlfs on > 1 M devices
+with special linker file e.g. eagle.flash.4m2m.ld) (makes no sense on 1M devices without sd card)
+and ESP32 (sd card or little fs or sfatfile system).
+
+The sd card chip select is the standard SDCARD_CS or when not found SDCARD_CS_PIN and initializes
+the FS System Pointer ufsp which can be used by all standard file system calls.
+
+The only specific call is ufs_fsinfo() which gets the total size (0) and free size (1).
+
+A button is created in the setup section to show up the file directory to download and upload files
+subdirectories are supported.
console calls :
@@ -36,16 +38,14 @@ ufstype get filesytem type 0=none 1=SD 2=Flashfile
ufssize total size in kB
ufsfree free size in kB
-driver enabled by
+The driver enabled by #define USE_UFILESYS
+\*********************************************************************************************/
-#define USE_UFILESYS
+#define XDRV_98 98
-*/
-
-
-#ifdef USE_UFILESYS
-
-#define XDRV_98 98
+#ifndef SDCARD_CS_PIN
+#define SDCARD_CS_PIN 4
+#endif
#ifdef ESP8266
#include
@@ -53,15 +53,17 @@ driver enabled by
#ifdef USE_SDCARD
#include
#include
-#endif
-#else
+#endif // USE_SDCARD
+#endif // ESP8266
+
+#ifdef ESP32
#include
#ifdef USE_SDCARD
#include
-#endif
+#endif // USE_SDCARD
#include "FFat.h"
#include "FS.h"
-#endif
+#endif // ESP32
#define UFS_FILE_WRITE "w"
#define UFS_FILE_READ "r"
@@ -71,11 +73,6 @@ FS *ufsp;
char ufs_path[48];
File ufs_upload_file;
-
-#ifndef SDCARD_CS_PIN
-#define SDCARD_CS_PIN 4
-#endif
-
// 0 = none, 1 = SD, 2 = ffat, 3 = littlefs
// spiffs should be obsolete
uint8_t ufs_type;
@@ -92,19 +89,20 @@ void UFSInit(void) {
#ifdef USE_SDCARD
-// if (TasmotaGlobal.spi_enabled) {
- if (1) {
+ if (TasmotaGlobal.spi_enabled) {
+// if (1) {
int8_t cs = SDCARD_CS_PIN;
- if (PinUsed(GPIO_SPI_CS)) {
- cs = Pin(GPIO_SPI_CS);
+ if (PinUsed(GPIO_SDCARD_CS)) {
+ cs = Pin(GPIO_SDCARD_CS);
}
if (SD.begin(cs)) {
#ifdef ESP8266
ufsp = (FS*)&SD;
-#else
+#endif // ESP8266
+#ifdef ESP32
ufsp = &SD;
-#endif
+#endif // ESP32
ufs_type = UFS_TSDC;
return;
}
@@ -117,7 +115,8 @@ void UFSInit(void) {
if (!LittleFS.begin()) {
return;
}
-#else
+#endif // ESP8266
+#ifdef ESP32
// try lfs first
ufsp = &LITTLEFS;
if (!LITTLEFS.begin(true)) {
@@ -129,33 +128,35 @@ void UFSInit(void) {
ufs_type = UFS_TFAT;
return;
}
-#endif // ESP8266
+#endif // ESP32
ufs_type = UFS_TLFS;
return;
}
uint32_t ufs_fsinfo(uint32_t sel) {
-uint32_t result = 0;
+ uint32_t result = 0;
+
#ifdef ESP8266
-FSInfo64 fsinfo;
-#endif
+ FSInfo64 fsinfo;
+#endif // ESP8266
switch (ufs_type) {
case UFS_TSDC:
#ifdef USE_SDCARD
-#ifdef ESP32
- if (sel == 0) {
- result = SD.totalBytes();
- } else {
- result = (SD.totalBytes() - SD.usedBytes());
- }
-#else
+#ifdef ESP8266
ufsp->info64(fsinfo);
if (sel == 0) {
result = fsinfo.totalBytes;
} else {
result = (fsinfo.totalBytes - fsinfo.usedBytes);
}
+#endif // ESP8266
+#ifdef ESP32
+ if (sel == 0) {
+ result = SD.totalBytes();
+ } else {
+ result = (SD.totalBytes() - SD.usedBytes());
+ }
#endif
#endif //USE_SDCARD
break;
@@ -168,13 +169,14 @@ FSInfo64 fsinfo;
} else {
result = (fsinfo.totalBytes - fsinfo.usedBytes);
}
-#else
+#endif // ESP8266
+#ifdef ESP32
if (sel == 0) {
result = LITTLEFS.totalBytes();
} else {
result = LITTLEFS.totalBytes() - LITTLEFS.usedBytes();
}
-#endif // ESP8266
+#endif // ESP32
break;
case UFS_TFAT:
@@ -200,21 +202,20 @@ FSInfo64 fsinfo;
#endif
uint8_t ufs_reject(char *name) {
-
char *lcp = strrchr(name,'/');
if (lcp) {
name = lcp + 1;
}
- while (*name=='/') name++;
- if (*name=='_') return 1;
- if (*name=='.') return 1;
+ while (*name=='/') { name++; }
+ if (*name=='_') { return 1; }
+ if (*name=='.') { return 1; }
- if (!strncasecmp(name, "SPOTLI~1", REJCMPL)) return 1;
- if (!strncasecmp(name, "TRASHE~1", REJCMPL)) return 1;
- if (!strncasecmp(name, "FSEVEN~1", REJCMPL)) return 1;
- if (!strncasecmp(name, "SYSTEM~1", REJCMPL)) return 1;
- if (!strncasecmp(name, "System Volume", 13)) return 1;
+ if (!strncasecmp(name, "SPOTLI~1", REJCMPL)) { return 1; }
+ if (!strncasecmp(name, "TRASHE~1", REJCMPL)) { return 1; }
+ if (!strncasecmp(name, "FSEVEN~1", REJCMPL)) { return 1; }
+ if (!strncasecmp(name, "SYSTEM~1", REJCMPL)) { return 1; }
+ if (!strncasecmp(name, "System Volume", 13)) { return 1; }
return 0;
}
@@ -225,35 +226,35 @@ void UFS_form1000(uint32_t number, char *dp, char sc) {
char *sp = str;
uint32_t inum = strlen(sp)/3;
uint32_t fnum = strlen(sp)%3;
- if (!fnum) inum--;
- for (uint32_t count=0; count<=inum; count++) {
- if (fnum){
- memcpy(dp,sp,fnum);
- dp+=fnum;
- sp+=fnum;
- fnum=0;
+ if (!fnum) { inum--; }
+ for (uint32_t count = 0; count <= inum; count++) {
+ if (fnum) {
+ memcpy(dp, sp, fnum);
+ dp += fnum;
+ sp += fnum;
+ fnum = 0;
} else {
- memcpy(dp,sp,3);
- dp+=3;
- sp+=3;
+ memcpy(dp, sp, 3);
+ dp += 3;
+ sp += 3;
}
- if (count!=inum) {
- *dp++=sc;
+ if (count != inum) {
+ *dp++ = sc;
}
}
- *dp=0;
+ *dp = 0;
}
-
-const char kUFSCommands[] PROGMEM = "UFS" "|" // Prefix
- "|" "TYPE" "|" "SIZE" "|" "FREE";
+const char kUFSCommands[] PROGMEM = "Ufs" "|" // Prefix
+ "|" "Type" "|" "Size" "|" "Free";
void (* const kUFSCommand[])(void) PROGMEM = {
&UFS_info, &UFS_type, &UFS_size, &UFS_free};
void UFS_info(void) {
- Response_P(PSTR("{\"UFS\":{\"TYPE\":%d,\"SIZE\":%d,\"FREE\":%d}}"),ufs_type,ufs_fsinfo(0),ufs_fsinfo(1));
+ Response_P(PSTR("{\"Ufs\":{\"Type\":%d,\"Size\":%d,\"Free\":%d}}"), ufs_type, ufs_fsinfo(0), ufs_fsinfo(1));
}
+
void UFS_type(void) {
ResponseCmndNumber(ufs_type);
}
@@ -268,28 +269,28 @@ const char UFS_WEB_DIR[] PROGMEM =
"
";
const char UFS_FILE_UPLOAD[] PROGMEM = D_SDCARD_DIR;
const char UFS_FORM_FILE_UPLOAD[] PROGMEM =
-""
-"
"
+ "
"
+ "" D_UPLOAD_STARTED " ...
";
const char UFS_FORM_SDC_DIRd[] PROGMEM =
-"%s
";
+ "%s
";
const char UFS_FORM_SDC_DIRb[] PROGMEM =
- "%s %s : %8d
";
+ "%s %s : %8d
";
const char UFS_FORM_SDC_HREF[] PROGMEM =
- "http://%s/ufsd?download=%s/%s";
+ "http://%s/ufsd?download=%s/%s";
void UFSdirectory(void) {
uint8_t depth = 0;
@@ -324,7 +325,6 @@ void UFSdirectory(void) {
WSContentSpaceButton(BUTTON_CONFIGURATION);
WSContentStop();
Web.upload_error = 0;
-
}
void UFS_ListDir(char *path, uint8_t depth) {
@@ -337,15 +337,18 @@ void UFS_ListDir(char *path, uint8_t depth) {
if (dir) {
dir.rewindDirectory();
if (strlen(path)>1) {
- snprintf_P(npath, sizeof(npath), PSTR("http://%s/ufsd?download=%s"), WiFi.localIP().toString().c_str(),path);
- for (uint8_t cnt = strlen(npath) - 1; cnt>0; cnt--) {
- if (npath[cnt]=='/') {
- if (npath[cnt - 1]=='=') npath[cnt + 1] = 0;
- else npath[cnt] = 0;
+ snprintf_P(npath, sizeof(npath), PSTR("http://%s/ufsd?download=%s"), WiFi.localIP().toString().c_str(), path);
+ for (uint32_t cnt = strlen(npath) - 1; cnt > 0; cnt--) {
+ if (npath[cnt] == '/') {
+ if (npath[cnt - 1] == '=') {
+ npath[cnt + 1] = 0;
+ } else {
+ npath[cnt] = 0;
+ }
break;
}
}
- WSContentSend_P(UFS_FORM_SDC_DIRd, npath,path, "..");
+ WSContentSend_P(UFS_FORM_SDC_DIRd, npath, path, "..");
}
char *ep;
while (true) {
@@ -355,17 +358,17 @@ void UFS_ListDir(char *path, uint8_t depth) {
}
// esp32 returns path here, shorten to filename
ep = (char*)entry.name();
- if (*ep=='/') ep++;
+ if (*ep == '/') { ep++; }
char *lcp = strrchr(ep,'/');
if (lcp) {
ep = lcp + 1;
}
time_t tm = entry.getLastWrite();
char tstr[24];
- strftime(tstr, 22, "%d-%m-%Y - %H:%M:%S ", localtime(&tm));
+ strftime(tstr, 22, "%d-%m-%Y - %H:%M:%S ", localtime(&tm)); // Theo note to me. Isn't strftime expensive? SHould use ISO Date/Time
char *pp = path;
- if (!*(pp + 1)) pp++;
+ if (!*(pp + 1)) { pp++; }
char *cp = name;
// osx formatted disks contain a lot of stuff we dont want
if (!ufs_reject((char*)ep)) {
@@ -376,17 +379,17 @@ void UFS_ListDir(char *path, uint8_t depth) {
sprintf(cp, format, ep);
if (entry.isDirectory()) {
- snprintf_P(npath, sizeof(npath), UFS_FORM_SDC_HREF, WiFi.localIP().toString().c_str(), pp,ep);
- WSContentSend_P(UFS_FORM_SDC_DIRd, npath,ep,name);
+ snprintf_P(npath, sizeof(npath), UFS_FORM_SDC_HREF, WiFi.localIP().toString().c_str(), pp, ep);
+ WSContentSend_P(UFS_FORM_SDC_DIRd, npath, ep, name);
uint8_t plen = strlen(path);
- if (plen>1) {
+ if (plen > 1) {
strcat(path, "/");
}
strcat(path, ep);
UFS_ListDir(path, depth + 4);
path[plen] = 0;
} else {
- snprintf_P(npath, sizeof(npath), UFS_FORM_SDC_HREF, WiFi.localIP().toString().c_str(), pp,ep);
+ snprintf_P(npath, sizeof(npath), UFS_FORM_SDC_HREF, WiFi.localIP().toString().c_str(), pp, ep);
WSContentSend_P(UFS_FORM_SDC_DIRb, npath, ep, name, tstr, entry.size());
}
}
@@ -400,61 +403,61 @@ uint8_t UFS_DownloadFile(char *file) {
File download_file;
WiFiClient download_Client;
- if (!ufsp->exists(file)) {
- AddLog_P(LOG_LEVEL_INFO, PSTR("file not found"));
- return 0;
- }
-
- download_file = ufsp->open(file, UFS_FILE_READ);
- if (!download_file) {
- AddLog_P(LOG_LEVEL_INFO, PSTR("could not open file"));
- return 0;
- }
-
- if (download_file.isDirectory()) {
- download_file.close();
- return 1;
- }
-
- uint32_t flen = download_file.size();
-
- download_Client = Webserver->client();
- Webserver->setContentLength(flen);
-
- char attachment[100];
- char *cp;
- for (uint8_t cnt = strlen(file); cnt>=0; cnt--) {
- if (file[cnt]=='/') {
- cp = &file[cnt + 1];
- break;
- }
- }
- snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp);
- Webserver->sendHeader(F("Content-Disposition"), attachment);
- WSSend(200, CT_STREAM, "");
-
- uint8_t buff[512];
- uint16_t bread;
-
- // transfer is about 150kb/s
- uint8_t cnt = 0;
- while (download_file.available()) {
- bread = download_file.read(buff, sizeof(buff));
- uint16_t bw = download_Client.write((const char*)buff, bread);
- if (!bw) break;
- cnt++;
- if (cnt>7) {
- cnt = 0;
- //if (glob_script_mem.script_loglevel & 0x80) {
- // this indeed multitasks, but is slower 50 kB/s
- // loop();
- //}
- }
- delay(0);
- }
- download_file.close();
- download_Client.stop();
+ if (!ufsp->exists(file)) {
+ AddLog_P(LOG_LEVEL_INFO, PSTR("UFS: File not found"));
return 0;
+ }
+
+ download_file = ufsp->open(file, UFS_FILE_READ);
+ if (!download_file) {
+ AddLog_P(LOG_LEVEL_INFO, PSTR("UFS: Could not open file"));
+ return 0;
+ }
+
+ if (download_file.isDirectory()) {
+ download_file.close();
+ return 1;
+ }
+
+ uint32_t flen = download_file.size();
+
+ download_Client = Webserver->client();
+ Webserver->setContentLength(flen);
+
+ char attachment[100];
+ char *cp;
+ for (uint32_t cnt = strlen(file); cnt >= 0; cnt--) {
+ if (file[cnt] == '/') {
+ cp = &file[cnt + 1];
+ break;
+ }
+ }
+ snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp);
+ Webserver->sendHeader(F("Content-Disposition"), attachment);
+ WSSend(200, CT_STREAM, "");
+
+ uint8_t buff[512];
+ uint32_t bread;
+
+ // transfer is about 150kb/s
+ uint32_t cnt = 0;
+ while (download_file.available()) {
+ bread = download_file.read(buff, sizeof(buff));
+ uint32_t bw = download_Client.write((const char*)buff, bread);
+ if (!bw) { break; }
+ cnt++;
+ if (cnt > 7) {
+ cnt = 0;
+ //if (glob_script_mem.script_loglevel & 0x80) {
+ // this indeed multitasks, but is slower 50 kB/s
+ // loop();
+ //}
+ }
+ delay(0);
+ }
+ download_file.close();
+ download_Client.stop();
+ return 0;
}
void UFS_Upload(void) {
@@ -464,16 +467,20 @@ void UFS_Upload(void) {
sprintf(npath, "%s/%s", ufs_path, upload.filename.c_str());
ufsp->remove(npath);
ufs_upload_file = ufsp->open(npath, UFS_FILE_WRITE);
- if (!ufs_upload_file) Web.upload_error = 1;
- } else if(upload.status == UPLOAD_FILE_WRITE) {
- if (ufs_upload_file) ufs_upload_file.write(upload.buf, upload.currentSize);
- } else if(upload.status == UPLOAD_FILE_END) {
- if (ufs_upload_file) ufs_upload_file.close();
+ if (!ufs_upload_file) { Web.upload_error = 1; }
+ }
+ else if (upload.status == UPLOAD_FILE_WRITE) {
+ if (ufs_upload_file) {
+ ufs_upload_file.write(upload.buf, upload.currentSize);
+ }
+ }
+ else if (upload.status == UPLOAD_FILE_END) {
+ if (ufs_upload_file) { ufs_upload_file.close(); }
if (Web.upload_error) {
AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload error"));
}
} else {
- Web.upload_error=1;
+ Web.upload_error = 1;
WSSend(500, CT_PLAIN, F("500: couldn't create file"));
}
}
@@ -484,7 +491,7 @@ void UFSFileUploadSuccess(void) {
WSContentSend_P(PSTR("" D_UPLOAD " " D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS));
WSContentSend_P(PSTR("
"));
- WSContentSend_P(PSTR(""),"/ufsd",D_UPL_DONE);
+ WSContentSend_P(PSTR(""), "/ufsd", D_UPL_DONE);
WSContentStop();
}
@@ -513,7 +520,10 @@ bool Xdrv98(uint8_t function) {
case FUNC_WEB_ADD_HANDLER:
Webserver->on("/ufsd", UFSdirectory);
Webserver->on("/ufsu", HTTP_GET, UFSFileUploadSuccess);
- Webserver->on("/ufsu", HTTP_POST,[]() { Webserver->sendHeader("Location","/ufsu");Webserver->send(303);}, UFS_Upload);
+ Webserver->on("/ufsu", HTTP_POST,[]() {
+ Webserver->sendHeader("Location","/ufsu");
+ Webserver->send(303);
+ }, UFS_Upload);
break;
#endif // USE_WEBSERVER
}