Skip to content

Commit d949d6f

Browse files
author
Luc
committed
Add ESP32 support (POC)
1 parent d5979c8 commit d949d6f

10 files changed

+581
-45
lines changed

ESPWebDAV.cpp

+143-41
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,36 @@
2727
2828
*/
2929

30-
#include <ESP8266WiFi.h>
3130
#include <FS.h>
32-
#include <time.h>
31+
#if defined(ARDUINO_ARCH_ESP8266)
32+
#include <ESP8266WiFi.h>
3333
#include <coredecls.h> // crc32()
3434
#include <PolledTimeout.h>
35+
#define FILENAME(f) f.fileName().c_str()
36+
#define FILEFULLNAME(f) f.fullName()
37+
#define FILESIZE(f) f.fileSize()
38+
#define FILETIME(f) f.fileTime()
39+
#define GETCREATIONTIME(f) f.getCreationTime()
40+
#define FILECREATIONTIME(f) f.fileCreationTime()
41+
#define ISFILE(f) f.isFile()
42+
#endif //ARDUINO_ARCH_ESP8266
43+
#if defined(ARDUINO_ARCH_ESP32)
44+
#include <WiFi.h>
45+
#include "crc32.h"
46+
#include "PolledTimeout.h"
47+
#define FILENAME(f) f.name()
48+
#define FILEFULLNAME(f) f.name()
49+
#define FILESIZE(f) f.size()
50+
#define FILETIME(f) f.getLastWrite()
51+
#define GETCREATIONTIME(f) f.getLastWrite()
52+
#define FILECREATIONTIME(f) f.getLastWrite()
53+
#define ISFILE(f) !f.isDirectory()
54+
extern uint64_t TotalBytes();
55+
extern uint64_t UsedBytes();
56+
#endif //ARDUINO_ARCH_ESP32
57+
58+
#include <time.h>
59+
3560

3661
#include <ESPWebDAV.h>
3762

@@ -211,13 +236,13 @@ void ESPWebDAVCore::dir(const String& path, Print* out)
211236
for (int i = 0; i < depth; i++)
212237
out->print(" ");
213238
if (entry.isDirectory())
214-
out->printf("[%s]\n", entry.fileName().c_str());
239+
out->printf("[%s]\n", FILENAME(entry));
215240
else
216241
out->printf("%-40s%4dMiB %6dKiB %d\n",
217-
entry.fileName().c_str(),
218-
((int)entry.fileSize() + (1 << 19)) >> 20,
219-
((int)entry.fileSize() + (1 << 9)) >> 10,
220-
(int)entry.fileSize());
242+
FILENAME(entry),
243+
((int)FILESIZE(entry) + (1 << 19)) >> 20,
244+
((int)FILESIZE(entry) + (1 << 9)) >> 10,
245+
(int)FILESIZE(entry));
221246
return true;
222247
}, /*false=subdir first*/false);
223248
}
@@ -227,7 +252,13 @@ size_t ESPWebDAVCore::makeVirtual(virt_e v, String& internal)
227252
{
228253
if (v == VIRT_PROC)
229254
{
255+
#if defined(ARDUINO_ARCH_ESP8266)
230256
internal = ESP.getFullVersion();
257+
#endif //ARDUINO_ARCH_ESP8266
258+
#if defined(ARDUINO_ARCH_ESP32)
259+
internal = "SDK:";
260+
internal += ESP.getSdkVersion();
261+
#endif //ARDUINO_ARCH_ESP32
231262
internal += '\n';
232263
}
233264
return internal.length();
@@ -252,7 +283,13 @@ bool ESPWebDAVCore::getPayload(StreamString& payload)
252283
if (contentLengthHeader > 0)
253284
{
254285
payload.reserve(contentLengthHeader);
286+
#if defined(ARDUINO_ARCH_ESP8266)
255287
esp8266::polledTimeout::oneShotFastMs timeout(HTTP_MAX_POST_WAIT);
288+
#endif //ARDUINO_ARCH_ESP8266
289+
#if defined(ARDUINO_ARCH_ESP32)
290+
PolledTimeout timeout(HTTP_MAX_POST_WAIT);
291+
#endif //ARDUINO_ARCH_ESP32
292+
256293
while (payload.length() < (size_t)contentLengthHeader)
257294
{
258295
uint8_t buf[16];
@@ -284,12 +321,19 @@ bool ESPWebDAVCore::dirAction(const String& path,
284321
int depth)
285322
{
286323
//DBG_PRINTF("diraction: scanning dir '%s'\n", path.c_str());
324+
#if defined(ARDUINO_ARCH_ESP8266)
287325
Dir entry = gfs->openDir(path);
288-
289-
while (entry.next())
326+
while (entry.next())
327+
#endif //ARDUINO_ARCH_ESP8266
328+
#if defined(ARDUINO_ARCH_ESP32)
329+
File root = gfs->open(path);
330+
File entry = root.openNextFile();
331+
while(entry)
332+
#endif //ARDUINO_ARCH_ESP32
333+
{
290334
if (!entry.isDirectory())
291335
{
292-
//DBG_PRINTF("diraction: %s/%s (%d B): ", path.c_str(), entry.fileName().c_str(), (int)entry.fileSize());
336+
//DBG_PRINTF("diraction: %s/%s (%d B): ", path.c_str(), FILENAME(entry), (int)entry.fileSize());
293337
if (cb(depth, path, entry))
294338
{
295339
//DBG_PRINTF("(file-OK)\n");
@@ -300,16 +344,27 @@ bool ESPWebDAVCore::dirAction(const String& path,
300344
return false;
301345
}
302346
}
303-
347+
#if defined(ARDUINO_ARCH_ESP32)
348+
entry = root.openNextFile();
349+
#endif //ARDUINO_ARCH_ESP32
350+
}
304351
if (recursive)
305352
{
353+
#if defined(ARDUINO_ARCH_ESP32)
354+
root = gfs->open(path);
355+
entry = root.openNextFile();
356+
while(entry)
357+
#endif //ARDUINO_ARCH_ESP32
358+
#if defined(ARDUINO_ARCH_ESP8266)
306359
entry = gfs->openDir(path);
307360
while (entry.next())
361+
#endif //ARDUINO_ARCH_ESP8266
362+
{
308363
if (entry.isDirectory())
309364
{
310-
//DBG_PRINTF("diraction: -------- %s/%s/\n", path.c_str(), entry.fileName().c_str());
365+
//DBG_PRINTF("diraction: -------- %s/%s/\n", path.c_str(), FILENAME(entry));
311366
if ((callAfter || cb(depth, path, entry))
312-
&& dirAction(path + '/' + entry.fileName(), recursive, cb, callAfter, depth + 1)
367+
&& dirAction(path + '/' + FILENAME(entry), recursive, cb, callAfter, depth + 1)
313368
&& (!callAfter || cb(depth, path, entry)))
314369
{
315370
//DBG_PRINTF("(dir-OK)\n");
@@ -320,6 +375,10 @@ bool ESPWebDAVCore::dirAction(const String& path,
320375
return false;
321376
}
322377
}
378+
#if defined(ARDUINO_ARCH_ESP32)
379+
entry = root.openNextFile();
380+
#endif //ARDUINO_ARCH_ESP32
381+
}
323382
}
324383

325384
return true;
@@ -367,17 +426,20 @@ void ESPWebDAVCore::handleRequest()
367426
depth = DEPTH_ALL;
368427
DBG_PRINT("Depth: "); DBG_PRINTLN(depth);
369428
}
370-
371-
// does uri refer to a file or directory or a null?
372-
File file = gfs->open(uri, "r");
373-
if (file)
374-
{
375-
resource = file.isDirectory() ? RESOURCE_DIR : RESOURCE_FILE;
376-
DBG_PRINTF("resource: '%s' is %s\n", uri.c_str(), resource == RESOURCE_DIR ? "dir" : "file");
429+
File file;
430+
if (gfs->exists(uri) || (uri=="/")){
431+
// does uri refer to a file or directory or a null?
432+
file = gfs->open(uri, "r");
433+
if (file)
434+
{
435+
resource = file.isDirectory() ? RESOURCE_DIR : RESOURCE_FILE;
436+
DBG_PRINTF("resource: '%s' is %s\n", uri.c_str(), resource == RESOURCE_DIR ? "dir" : "file");
437+
}
438+
else
439+
DBG_PRINTF("resource: '%s': no file nor dir\n", uri.c_str());
440+
} else {
441+
DBG_PRINTF("resource: '%s': not exists\n", uri.c_str());
377442
}
378-
else
379-
DBG_PRINTF("resource: '%s': no file nor dir\n", uri.c_str());
380-
381443

382444
DBG_PRINT("\r\nm: "); DBG_PRINT(method);
383445
DBG_PRINT(" r: "); DBG_PRINT(resource);
@@ -635,10 +697,10 @@ void ESPWebDAVCore::handleProp(ResourceType resource, File& file)
635697
// virtual file
636698
sendPropResponse(false, uri.c_str(), 1024, time(nullptr), 0);
637699
}
638-
else if (file.isFile() || depth == DEPTH_NONE)
700+
else if (ISFILE(file) || depth == DEPTH_NONE)
639701
{
640702
DBG_PRINTF("----- PROP FILE '%s':\n", uri.c_str());
641-
sendPropResponse(file.isDirectory(), uri.c_str(), file.size(), file.getLastWrite(), file.getCreationTime());
703+
sendPropResponse(file.isDirectory(), uri.c_str(), file.size(), file.getLastWrite(), GETCREATIONTIME(file));
642704
}
643705
else
644706
{
@@ -650,30 +712,51 @@ void ESPWebDAVCore::handleProp(ResourceType resource, File& file)
650712
///XXX fixme: more generic way to list virtual file list
651713
sendPropResponse(false, PROC, 1024, time(nullptr), 0);
652714
}
653-
715+
#if defined(ARDUINO_ARCH_ESP32)
716+
File root = gfs->open(uri);
717+
File entry = root.openNextFile();
718+
while(entry)
719+
#endif //ARDUINO_ARCH_ESP32
720+
#if defined(ARDUINO_ARCH_ESP8266)
654721
Dir entry = gfs->openDir(uri);
655-
while (entry.next())
722+
while (entry.next())
723+
#endif //ARDUINO_ARCH_ESP8266
656724
{
657725
yield();
658726
String path;
659-
path.reserve(uri.length() + 1 + entry.fileName().length());
727+
path.reserve(uri.length() + 1 + strlen(FILENAME(entry)));
660728
path += uri;
661729
path += '/';
662-
path += entry.fileName();
730+
path += FILENAME(entry);
663731
stripSlashes(path);
664-
sendPropResponse(entry.isDirectory(), path.c_str(), entry.fileSize(), entry.fileTime(), entry.fileCreationTime());
732+
sendPropResponse(entry.isDirectory(), path.c_str(), FILESIZE(entry), FILETIME(entry), FILECREATIONTIME(entry));
733+
#if defined(ARDUINO_ARCH_ESP32)
734+
entry = root.openNextFile();
735+
#endif //ARDUINO_ARCH_ESP32
665736
}
666737
}
667738

668739
if (payload.indexOf(F("quota-available-bytes")) >= 0 ||
669740
payload.indexOf(F("quota-used-bytes")) >= 0)
670741
{
742+
#if defined(ARDUINO_ARCH_ESP8266)
671743
fs::FSInfo64 info;
672744
if (gfs->info64(info))
673745
{
674746
sendContentProp(F("quota-available-bytes"), String(1.0 * (info.totalBytes - info.usedBytes), 0));
675747
sendContentProp(F("quota-used-bytes"), String(1.0 * info.usedBytes, 0));
676748
}
749+
#endif //ARDUINO_ARCH_ESP8266
750+
#if defined(ARDUINO_ARCH_ESP32)
751+
//NEED TO BE not related to SPIFFS
752+
//use external functions
753+
//but SPIFFS/FAT size_t because in MB
754+
//and SD uint64_t because in GB
755+
//so use uint64_t
756+
sendContentProp(F("quota-available-bytes"), String(1.0 * (TotalBytes() - UsedBytes()), 0));
757+
sendContentProp(F("quota-used-bytes"), String(1.0 * UsedBytes(), 0));
758+
#endif //ARDUINO_ARCH_ESP32
759+
677760
}
678761

679762
sendContent(F("</D:multistatus>"));
@@ -883,8 +966,18 @@ void ESPWebDAVCore::handlePut(ResourceType resource)
883966
File file;
884967
stripName(uri);
885968
DBG_PRINTF("create file '%s'\n", uri.c_str());
969+
#if defined(ARDUINO_ARCH_ESP8266)
886970
if (!(file = gfs->open(uri, "w")))
971+
#endif //ARDUINO_ARCH_ESP8266
972+
#if defined(ARDUINO_ARCH_ESP32)
973+
String s = uri;
974+
if (uri[0]!='/')s = "/" + uri;
975+
DBG_PRINTF("Create file %s\n", s.c_str());
976+
if (!(file = gfs->open(s, "w")))
977+
#endif //ARDUINO_ARCH_ESP32
978+
{
887979
return handleWriteError("Unable to create a new file", file);
980+
}
888981

889982
// file is created/open for writing at this point
890983
// did server send any data in put
@@ -1033,7 +1126,7 @@ void ESPWebDAVCore::handleMove(ResourceType resource, File& src)
10331126
return handleIssue(code, "Locked");
10341127

10351128
File destFile = gfs->open(dest, "r");
1036-
if (destFile && !destFile.isFile())
1129+
if (destFile && !ISFILE(destFile))
10371130
{
10381131
dest += '/';
10391132
dest += src.name();
@@ -1100,10 +1193,10 @@ bool ESPWebDAVCore::deleteDir(const String& dir)
11001193
{
11011194
(void)depth;
11021195
String toRemove;
1103-
toRemove.reserve(parent.length() + entry.fileName().length() + 2);
1196+
toRemove.reserve(parent.length() + strlen(FILENAME(entry)) + 2);
11041197
toRemove += parent;
11051198
toRemove += '/';
1106-
toRemove += entry.fileName();
1199+
toRemove += FILENAME(entry);
11071200
bool ok = !!(entry.isDirectory() ? gfs->rmdir(toRemove) : gfs->remove(toRemove));
11081201
DBG_PRINTF("DELETE %s %s: %s\n", entry.isDirectory() ? "[ dir]" : "[file]", toRemove.c_str(), ok ? "ok" : "bad");
11091202
return ok;
@@ -1170,9 +1263,17 @@ bool ESPWebDAVCore::copyFile(File srcFile, const String& destName)
11701263
return false;
11711264
}
11721265
}
1266+
#if defined(ARDUINO_ARCH_ESP8266)
11731267
dest = gfs->open(destName, "w");
1268+
#endif //ARDUINO_ARCH_ESP8266
1269+
#if defined(ARDUINO_ARCH_ESP32)
1270+
String s = destName;
1271+
if (destName[0]!='/')s = "/" + destName;
1272+
dest = gfs->open(s, "w");
1273+
DBG_PRINTF("Create file %s\n", s.c_str());
1274+
#endif //ARDUINO_ARCH_ESP32
11741275
if (!dest)
1175-
{
1276+
{
11761277
handleIssue(413, "Request Entity Too Large");
11771278
return false;
11781279
}
@@ -1188,7 +1289,7 @@ bool ESPWebDAVCore::copyFile(File srcFile, const String& destName)
11881289
handleIssue(500, "Internal Server Error");
11891290
return false;
11901291
}
1191-
int wr = dest.write(cp, nb);
1292+
int wr = dest.write((const uint8_t*)cp, nb);
11921293
if (wr != nb)
11931294
{
11941295
DBG_PRINTF("copy: short write wr=%d != rd=%d\n", (int)wr, (int)nb);
@@ -1240,7 +1341,7 @@ void ESPWebDAVCore::handleCopy(ResourceType resource, File& src)
12401341
}
12411342

12421343
DBG_PRINTF("copy: src='%s'=>'%s' dest='%s'=>'%s' parent:'%s'\n",
1243-
uri.c_str(), src.fullName(),
1344+
uri.c_str(), FILEFULLNAME(src),
12441345
destinationHeader.c_str(), destPath.c_str(),
12451346
destParentPath.c_str());
12461347
File destParent = gfs->open(destParentPath, "r");
@@ -1254,20 +1355,21 @@ void ESPWebDAVCore::handleCopy(ResourceType resource, File& src)
12541355
if (src.isDirectory())
12551356
{
12561357
DBG_PRINTF("Source is directory\n");
1257-
if (destParent.isFile())
1358+
if (ISFILE(destParent))
12581359
{
12591360
DBG_PRINTF("'%s' is not a directory\n", destParentPath.c_str());
12601361
return handleIssue(409, "Conflict");
12611362
}
12621363

1263-
if (!dirAction(src.fullName(), depth == DEPTH_ALL, [this, destParentPath](int depth, const String & parent, Dir & source)->bool
1364+
if (!dirAction(FILEFULLNAME(src), depth == DEPTH_ALL, [this, destParentPath](int depth, const String & parent, Dir & source)->bool
12641365
{
12651366
(void)depth;
12661367
(void)parent;
1267-
String destNameX = destParentPath + '/' + source.fileName();
1368+
String destNameX = destParentPath + '/';
1369+
destNameX += FILENAME(source);
12681370
stripName(destNameX);
1269-
DBG_PRINTF("COPY: '%s' -> '%s'\n", source.fileName().c_str(), destNameX.c_str());
1270-
return copyFile(gfs->open(source.fileName(), "r"), destNameX);
1371+
DBG_PRINTF("COPY: '%s' -> '%s'\n", FILENAME(source), destNameX.c_str());
1372+
return copyFile(gfs->open(FILENAME(source), "r"), destNameX);
12711373
}))
12721374
{
12731375
return; // handleIssue already called by failed copyFile() handleIssue(409, "Conflict");

ESPWebDAV.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#define WEBDAV_LOCK_SUPPORT 2
4343

4444
//#define DBG_WEBDAV 1
45+
//#define DEBUG_ESP_PORT Serial
4546

4647
#if CORE_MOCK && !defined(DBG_WEBDAV)
4748
#define DBG_WEBDAV 1
@@ -76,7 +77,14 @@
7677
#include <map>
7778
#endif
7879
#include <functional>
80+
#if defined(ARDUINO_ARCH_ESP8266)
7981
#include <ESP8266WiFi.h>
82+
#endif //ARDUINO_ARCH_ESP8266
83+
#if defined(ARDUINO_ARCH_ESP32)
84+
#include <WiFi.h>
85+
#include <FS.h>
86+
#define Dir File
87+
#endif //ARDUINO_ARCH_ESP32
8088
#include <StreamString.h>
8189

8290
class ESPWebDAVCore
@@ -92,12 +100,17 @@ class ESPWebDAVCore
92100
void begin(FS* gfs)
93101
{
94102
this->gfs = gfs;
95-
103+
#if defined(ARDUINO_ARCH_ESP8266)
96104
fs::FSInfo64 info;
97105
if (gfs->info64(info))
98106
_maxPathLength = info.maxPathLength;
99107
else
100108
_maxPathLength = 16;
109+
#endif //ARDUINO_ARCH_ESP8266
110+
#if defined(ARDUINO_ARCH_ESP32)
111+
_maxPathLength = 32;
112+
#endif //ARDUINO_ARCH_ESP32
113+
101114
}
102115

103116
bool dirAction(

0 commit comments

Comments
 (0)