feat: upgrade platform and support webdav (#1047)

## Summary
- Upgrade platform from espressif32 6.12.0 (Arduino Core 2.0.17) to
pioarduino 55.03.37 (Arduino Core 3.3.7, ESP-IDF 5.5.2)
- Add WebDAV Class 1 server (RFC 4918) - SD card can be mounted as a
network drive
- I also slightly fixed the SDK and also made a [pull request
](https://github.com/open-x4-epaper/community-sdk/pull/21)

First PR #1030 (was closed because the implementation was based on an
old version of the libraries)
Issue #439

---------

Co-authored-by: Dave Allie <dave@daveallie.com>
This commit is contained in:
Dexif
2026-02-22 20:31:33 +11:00
committed by GitHub
co-authored by Dave Allie
parent d9f114b652
commit a610568f8c
9 changed files with 899 additions and 17 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ extra_configs = platformio.local.ini
version = 1.0.0
[base]
platform = espressif32 @ 6.12.0
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
board = esp32-c3-devkitm-1
framework = arduino
monitor_speed = 115200
+1
View File
@@ -3,6 +3,7 @@
#include <cstddef>
#include <cstdint>
#include <functional>
#include <string>
#include <vector>
class GfxRenderer;
+7 -1
View File
@@ -159,6 +159,12 @@ void CrossPointWebServer::begin() {
server->onNotFound([this] { handleNotFound(); });
LOG_DBG("WEB", "[MEM] Free heap after route setup: %d bytes", ESP.getFreeHeap());
// Collect WebDAV headers and register handler
const char* davHeaders[] = {"Depth", "Destination", "Overwrite", "If", "Lock-Token", "Timeout"};
server->collectHeaders(davHeaders, 6);
server->addHandler(&davHandler);
LOG_DBG("WEB", "WebDAV handler initialized");
server->begin();
// Start WebSocket server for fast binary uploads
@@ -502,7 +508,7 @@ void CrossPointWebServer::handleDownload() const {
server->sendHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
server->send(200, contentType.c_str(), "");
WiFiClient client = server->client();
NetworkClient client = server->client();
client.write(file);
file.close();
}
+5 -2
View File
@@ -1,14 +1,16 @@
#pragma once
#include <HalStorage.h>
#include <NetworkUdp.h>
#include <WebServer.h>
#include <WebSocketsServer.h>
#include <WiFiUdp.h>
#include <memory>
#include <string>
#include <vector>
#include "WebDAVHandler.h"
// Structure to hold file information
struct FileInfo {
String name;
@@ -71,11 +73,12 @@ class CrossPointWebServer {
private:
std::unique_ptr<WebServer> server = nullptr;
std::unique_ptr<WebSocketsServer> wsServer = nullptr;
WebDAVHandler davHandler;
bool running = false;
bool apMode = false; // true when running in AP mode, false for STA mode
uint16_t port = 80;
uint16_t wsPort = 81; // WebSocket port
WiFiUDP udp;
NetworkUDP udp;
bool udpActive = false;
// WebSocket upload state
+11 -11
View File
@@ -2,9 +2,9 @@
#include <HTTPClient.h>
#include <Logging.h>
#include <NetworkClient.h>
#include <NetworkClientSecure.h>
#include <StreamString.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#include <base64.h>
#include <cstring>
@@ -14,14 +14,14 @@
#include "util/UrlUtils.h"
bool HttpDownloader::fetchUrl(const std::string& url, Stream& outContent) {
// Use WiFiClientSecure for HTTPS, regular WiFiClient for HTTP
std::unique_ptr<WiFiClient> client;
// Use NetworkClientSecure for HTTPS, regular NetworkClient for HTTP
std::unique_ptr<NetworkClient> client;
if (UrlUtils::isHttpsUrl(url)) {
auto* secureClient = new WiFiClientSecure();
auto* secureClient = new NetworkClientSecure();
secureClient->setInsecure();
client.reset(secureClient);
} else {
client.reset(new WiFiClient());
client.reset(new NetworkClient());
}
HTTPClient http;
@@ -64,14 +64,14 @@ bool HttpDownloader::fetchUrl(const std::string& url, std::string& outContent) {
HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string& url, const std::string& destPath,
ProgressCallback progress) {
// Use WiFiClientSecure for HTTPS, regular WiFiClient for HTTP
std::unique_ptr<WiFiClient> client;
// Use NetworkClientSecure for HTTPS, regular NetworkClient for HTTP
std::unique_ptr<NetworkClient> client;
if (UrlUtils::isHttpsUrl(url)) {
auto* secureClient = new WiFiClientSecure();
auto* secureClient = new NetworkClientSecure();
secureClient->setInsecure();
client.reset(secureClient);
} else {
client.reset(new WiFiClient());
client.reset(new NetworkClient());
}
HTTPClient http;
@@ -113,7 +113,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
}
// Get the stream for chunked reading
WiFiClient* stream = http.getStreamPtr();
NetworkClient* stream = http.getStreamPtr();
if (!stream) {
LOG_ERR("HTTP", "Failed to get stream");
file.close();
+1 -1
View File
@@ -6,7 +6,7 @@
/**
* HTTP client utility for fetching content and downloading files.
* Wraps WiFiClientSecure and HTTPClient for HTTPS requests.
* Wraps NetworkClientSecure and HTTPClient for HTTPS requests.
*/
class HttpDownloader {
public:
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include <HalStorage.h>
#include <WebServer.h>
class WebDAVHandler : public RequestHandler {
public:
// RequestHandler interface
bool canHandle(WebServer& server, HTTPMethod method, const String& uri) override;
bool canRaw(WebServer& server, const String& uri) override;
void raw(WebServer& server, const String& uri, HTTPRaw& raw) override;
bool handle(WebServer& server, HTTPMethod method, const String& uri) override;
private:
// PUT streaming state (raw() is called in chunks)
FsFile _putFile;
String _putPath;
bool _putOk = false;
bool _putExisted = false;
// WebDAV method handlers
void handleOptions(WebServer& s);
void handlePropfind(WebServer& s);
void handleGet(WebServer& s);
void handleHead(WebServer& s);
void handlePut(WebServer& s);
void handleDelete(WebServer& s);
void handleMkcol(WebServer& s);
void handleMove(WebServer& s);
void handleCopy(WebServer& s);
void handleLock(WebServer& s);
void handleUnlock(WebServer& s);
// Utilities
String getRequestPath(WebServer& s) const;
String getDestinationPath(WebServer& s) const;
void urlEncodePath(const String& path, String& out) const;
bool isProtectedPath(const String& path) const;
int getDepth(WebServer& s) const;
bool getOverwrite(WebServer& s) const;
void clearEpubCacheIfNeeded(const String& path) const;
void sendPropEntry(WebServer& s, const String& href, bool isDir, size_t size, const String& lastModified) const;
String getMimeType(const String& path) const;
};