✨ Refactors filesystem service
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <ESPFS.h>
|
#include <filesystem.h>
|
||||||
#include <EventSocket.h>
|
#include <EventSocket.h>
|
||||||
#include <TaskManager.h>
|
#include <TaskManager.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Camera {
|
|||||||
#include <SettingValue.h>
|
#include <SettingValue.h>
|
||||||
#include <StatefulService.h>
|
#include <StatefulService.h>
|
||||||
#include <esp_camera.h>
|
#include <esp_camera.h>
|
||||||
#include <ESPFS.h>
|
#include <filesystem.h>
|
||||||
|
|
||||||
#define EVENT_CAMERA_SETTINGS "CameraSettings"
|
#define EVENT_CAMERA_SETTINGS "CameraSettings"
|
||||||
#define CAMERA_SETTINGS_PATH "/api/camera/settings"
|
#define CAMERA_SETTINGS_PATH "/api/camera/settings"
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ ESP32SvelteKit::ESP32SvelteKit(PsychicHttpServer *server, unsigned int numberEnd
|
|||||||
_cameraService(server, &_taskManager),
|
_cameraService(server, &_taskManager),
|
||||||
_cameraSettingsService(server, &ESPFS, &_socket),
|
_cameraSettingsService(server, &ESPFS, &_socket),
|
||||||
#endif
|
#endif
|
||||||
_fileExplorer(server),
|
|
||||||
_servoController(server, &ESPFS, &_peripherals, &_socket),
|
_servoController(server, &ESPFS, &_peripherals, &_socket),
|
||||||
#if FT_ENABLED(USE_MOTION)
|
#if FT_ENABLED(USE_MOTION)
|
||||||
_motionService(_server, &_socket, &_servoController, &_taskManager),
|
_motionService(_server, &_socket, &_servoController, &_taskManager),
|
||||||
@@ -112,6 +111,12 @@ void ESP32SvelteKit::setupServer() {
|
|||||||
_server->on("/api/system/status", HTTP_GET, system_service::getStatus);
|
_server->on("/api/system/status", HTTP_GET, system_service::getStatus);
|
||||||
_server->on("/api/system/metrics", HTTP_GET, system_service::getMetrics);
|
_server->on("/api/system/metrics", HTTP_GET, system_service::getMetrics);
|
||||||
|
|
||||||
|
// FILESYSTEM
|
||||||
|
_server->on("/api/files", HTTP_GET, FileSystem::getFiles);
|
||||||
|
_server->on("/api/files/delete", HTTP_POST, FileSystem::handleDelete);
|
||||||
|
_server->on("/api/files/upload/*", HTTP_POST, FileSystem::uploadHandler);
|
||||||
|
_server->on("/api/files/edit", HTTP_POST, FileSystem::handleEdit);
|
||||||
|
|
||||||
// servo
|
// servo
|
||||||
_server->on("/api/servo/config", HTTP_GET,
|
_server->on("/api/servo/config", HTTP_GET,
|
||||||
[this](PsychicRequest *request) { return _servoController.endpoint.getState(request); });
|
[this](PsychicRequest *request) { return _servoController.endpoint.getState(request); });
|
||||||
@@ -202,7 +207,6 @@ void ESP32SvelteKit::startServices() {
|
|||||||
_batteryService.begin();
|
_batteryService.begin();
|
||||||
#endif
|
#endif
|
||||||
_taskManager.begin();
|
_taskManager.begin();
|
||||||
_fileExplorer.begin();
|
|
||||||
_peripherals.begin();
|
_peripherals.begin();
|
||||||
_servoController.begin();
|
_servoController.begin();
|
||||||
#if FT_ENABLED(USE_MOTION)
|
#if FT_ENABLED(USE_MOTION)
|
||||||
|
|||||||
@@ -20,11 +20,10 @@
|
|||||||
|
|
||||||
#include <AnalyticsService.h>
|
#include <AnalyticsService.h>
|
||||||
#include <BatteryService.h>
|
#include <BatteryService.h>
|
||||||
#include <FileExplorerService.h>
|
#include <filesystem.h>
|
||||||
#include <DownloadFirmwareService.h>
|
#include <DownloadFirmwareService.h>
|
||||||
#include <Peripherals.h>
|
#include <Peripherals.h>
|
||||||
#include <ServoController.h>
|
#include <ServoController.h>
|
||||||
#include <ESPFS.h>
|
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include <LEDService.h>
|
#include <LEDService.h>
|
||||||
#include <EventSocket.h>
|
#include <EventSocket.h>
|
||||||
@@ -81,8 +80,6 @@ class ESP32SvelteKit {
|
|||||||
|
|
||||||
TaskManager *getTaskManager() { return &_taskManager; }
|
TaskManager *getTaskManager() { return &_taskManager; }
|
||||||
|
|
||||||
FileExplorer *getFileExplorer() { return &_fileExplorer; }
|
|
||||||
|
|
||||||
#if FT_ENABLED(USE_MOTION)
|
#if FT_ENABLED(USE_MOTION)
|
||||||
MotionService *getMotionService() { return &_motionService; }
|
MotionService *getMotionService() { return &_motionService; }
|
||||||
#endif
|
#endif
|
||||||
@@ -127,7 +124,6 @@ class ESP32SvelteKit {
|
|||||||
AnalyticsService _analyticsService;
|
AnalyticsService _analyticsService;
|
||||||
#endif
|
#endif
|
||||||
TaskManager _taskManager;
|
TaskManager _taskManager;
|
||||||
FileExplorer _fileExplorer;
|
|
||||||
#if FT_ENABLED(USE_MOTION)
|
#if FT_ENABLED(USE_MOTION)
|
||||||
MotionService _motionService;
|
MotionService _motionService;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <LittleFS.h>
|
|
||||||
|
|
||||||
#define ESPFS LittleFS
|
|
||||||
|
|
||||||
#define AP_SETTINGS_FILE "/config/apSettings.json"
|
|
||||||
#define CAMERA_SETTINGS_FILE "/config/cameraSettings.json"
|
|
||||||
#define FS_CONFIG_DIRECTORY "/config"
|
|
||||||
#define NTP_SETTINGS_FILE "/config/ntpSettings.json"
|
|
||||||
#define DEVICE_CONFIG_FILE "/config/peripheral.json"
|
|
||||||
#define WIFI_SETTINGS_FILE "/config/wifiSettings.json"
|
|
||||||
#define SERVO_SETTINGS_FILE "/config/servoSettings.json"
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <StatefulService.h>
|
#include <StatefulService.h>
|
||||||
#include <ESPFS.h>
|
#include <filesystem.h>
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class FSPersistence {
|
class FSPersistence {
|
||||||
@@ -32,6 +32,7 @@ class FSPersistence {
|
|||||||
_filePath(filePath),
|
_filePath(filePath),
|
||||||
_updateHandlerId(0) {
|
_updateHandlerId(0) {
|
||||||
enableUpdateHandler();
|
enableUpdateHandler();
|
||||||
|
readFromFS();
|
||||||
}
|
}
|
||||||
|
|
||||||
void readFromFS() {
|
void readFromFS() {
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
#ifndef FileExplorer_h
|
|
||||||
#define FileExplorer_h
|
|
||||||
|
|
||||||
#include <ESPFS.h>
|
|
||||||
#include <PsychicHttp.h>
|
|
||||||
|
|
||||||
#define FILE_EXPLORER_SERVICE_PATH "/api/files"
|
|
||||||
#define FILE_EXPLORER_DELETE_SERVICE_PATH "/api/files/delete"
|
|
||||||
|
|
||||||
class FileExplorer {
|
|
||||||
public:
|
|
||||||
FileExplorer(PsychicHttpServer *server) : _server(server) {}
|
|
||||||
|
|
||||||
void begin() {
|
|
||||||
_server->on(FILE_EXPLORER_SERVICE_PATH, HTTP_GET, [this](PsychicRequest *request) { return explore(request); });
|
|
||||||
_server->on(FILE_EXPLORER_DELETE_SERVICE_PATH, HTTP_POST,
|
|
||||||
[this](PsychicRequest *request, JsonVariant &json) { return deleteFile(request, json); });
|
|
||||||
|
|
||||||
ESP_LOGV("APStatus", "Registered GET endpoint: %s", FILE_EXPLORER_SERVICE_PATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
PsychicHttpServer *_server;
|
|
||||||
|
|
||||||
esp_err_t explore(PsychicRequest *request) {
|
|
||||||
return request->reply(200, "application/json", listFiles("/").c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t deleteFile(PsychicRequest *request, JsonVariant &json) {
|
|
||||||
if (json.is<JsonObject>()) {
|
|
||||||
String filename = json["file"];
|
|
||||||
ESP_LOGI("FileExplorer", "Deleting file: %s", filename.c_str());
|
|
||||||
return ESPFS.remove(filename.c_str()) ? request->reply(200) : request->reply(500);
|
|
||||||
}
|
|
||||||
return request->reply(400);
|
|
||||||
}
|
|
||||||
|
|
||||||
String listFiles(const String &directory, bool isRoot = true) {
|
|
||||||
File root = ESPFS.open(directory.startsWith("/") ? directory : "/" + directory);
|
|
||||||
if (!root.isDirectory()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
File file = root.openNextFile();
|
|
||||||
String output = isRoot ? "{ \"root\": {" : "{";
|
|
||||||
|
|
||||||
while (file) {
|
|
||||||
if (file.isDirectory()) {
|
|
||||||
output += "\"" + String(file.name()) + "\": " + listFiles(file.name(), false) + ", ";
|
|
||||||
} else {
|
|
||||||
output += "\"" + String(file.name()) + "\": " + String(file.size()) + ", ";
|
|
||||||
}
|
|
||||||
file = root.openNextFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output.endsWith(", ")) {
|
|
||||||
output.remove(output.length() - 2);
|
|
||||||
}
|
|
||||||
output += "}";
|
|
||||||
if (isRoot) {
|
|
||||||
output += "}";
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // end FileExplorer_h
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <StatefulService.h>
|
#include <StatefulService.h>
|
||||||
#include <MathUtils.h>
|
#include <MathUtils.h>
|
||||||
#include <Timing.h>
|
#include <Timing.h>
|
||||||
#include <ESPFS.h>
|
#include <filesystem.h>
|
||||||
#include <Features.h>
|
#include <Features.h>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
#include <filesystem.h>
|
||||||
|
|
||||||
|
static const char *TAG = "FileService";
|
||||||
|
|
||||||
|
namespace FileSystem {
|
||||||
|
|
||||||
|
PsychicUploadHandler *uploadHandler;
|
||||||
|
|
||||||
|
class Initializer {
|
||||||
|
public:
|
||||||
|
Initializer() {
|
||||||
|
uploadHandler = new PsychicUploadHandler();
|
||||||
|
uploadHandler->onUpload(uploadFile);
|
||||||
|
uploadHandler->onRequest([](PsychicRequest *request) { return request->reply(200); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static Initializer initializer;
|
||||||
|
|
||||||
|
esp_err_t getFiles(PsychicRequest *request) { return request->reply(200, "application/json", listFiles("/").c_str()); }
|
||||||
|
|
||||||
|
esp_err_t handleDelete(PsychicRequest *request, JsonVariant &json) {
|
||||||
|
if (json.is<JsonObject>()) {
|
||||||
|
const char *filename = json["file"].as<const char *>();
|
||||||
|
ESP_LOGI(TAG, "Deleting file: %s", filename);
|
||||||
|
return deleteFile(filename) ? request->reply(200) : request->reply(500);
|
||||||
|
}
|
||||||
|
return request->reply(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t handleEdit(PsychicRequest *request, JsonVariant &json) {
|
||||||
|
if (json.is<JsonObject>()) {
|
||||||
|
const char *filename = json["file"].as<const char *>();
|
||||||
|
const char *content = json["content"].as<const char *>();
|
||||||
|
ESP_LOGI(TAG, "Editing file: %s", filename);
|
||||||
|
return editFile(filename, content) ? request->reply(200) : request->reply(500);
|
||||||
|
}
|
||||||
|
return request->reply(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helpers */
|
||||||
|
|
||||||
|
bool deleteFile(const char *filename) { return ESPFS.remove(filename); }
|
||||||
|
|
||||||
|
String listFiles(const String &directory, bool isRoot) {
|
||||||
|
File root = ESPFS.open(directory.startsWith("/") ? directory : "/" + directory);
|
||||||
|
if (!root.isDirectory()) return "";
|
||||||
|
|
||||||
|
File file = root.openNextFile();
|
||||||
|
String output = isRoot ? "{ \"root\": {" : "{";
|
||||||
|
|
||||||
|
while (file) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
output += "\"" + String(file.name()) + "\": " + listFiles(file.name(), false) + ", ";
|
||||||
|
} else {
|
||||||
|
output += "\"" + String(file.name()) + "\": " + String(file.size()) + ", ";
|
||||||
|
}
|
||||||
|
file = root.openNextFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output.endsWith(", ")) {
|
||||||
|
output.remove(output.length() - 2);
|
||||||
|
}
|
||||||
|
output += "}";
|
||||||
|
if (isRoot) output += "}";
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t uploadFile(PsychicRequest *request, const String &filename, uint64_t index, uint8_t *data, size_t len,
|
||||||
|
bool last) {
|
||||||
|
File file;
|
||||||
|
String path = "/www/" + filename;
|
||||||
|
ESP_LOGI(TAG, "Writing %d/%d bytes to: %s\n", (int)index + (int)len, request->contentLength(), path.c_str());
|
||||||
|
|
||||||
|
if (last) ESP_LOGI(TAG, "%s is finished. Total bytes: %d\n", path.c_str(), (int)index + (int)len);
|
||||||
|
|
||||||
|
file = LittleFS.open(path, !index ? FILE_WRITE : FILE_APPEND);
|
||||||
|
if (!file) {
|
||||||
|
ESP_LOGE(TAG, "Failed to open file");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.write(data, len)) {
|
||||||
|
ESP_LOGE(TAG, "Write failed");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool editFile(const char *filename, const char *content) {
|
||||||
|
File file = ESPFS.open(filename, FILE_WRITE);
|
||||||
|
if (!file) return false;
|
||||||
|
|
||||||
|
file.print(content);
|
||||||
|
file.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace FileSystem
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <PsychicHttp.h>
|
||||||
|
|
||||||
|
#include <LittleFS.h>
|
||||||
|
|
||||||
|
#define ESPFS LittleFS
|
||||||
|
|
||||||
|
#define AP_SETTINGS_FILE "/config/apSettings.json"
|
||||||
|
#define CAMERA_SETTINGS_FILE "/config/cameraSettings.json"
|
||||||
|
#define FS_CONFIG_DIRECTORY "/config"
|
||||||
|
#define NTP_SETTINGS_FILE "/config/ntpSettings.json"
|
||||||
|
#define DEVICE_CONFIG_FILE "/config/peripheral.json"
|
||||||
|
#define WIFI_SETTINGS_FILE "/config/wifiSettings.json"
|
||||||
|
#define SERVO_SETTINGS_FILE "/config/servoSettings.json"
|
||||||
|
|
||||||
|
namespace FileSystem {
|
||||||
|
extern PsychicUploadHandler *uploadHandler;
|
||||||
|
|
||||||
|
String listFiles(const String &directory, bool isRoot = true);
|
||||||
|
bool deleteFile(const char *filename);
|
||||||
|
bool editFile(const char *filename, const char *content);
|
||||||
|
esp_err_t uploadFile(PsychicRequest *request, const String &filename, uint64_t index, uint8_t *data, size_t len,
|
||||||
|
bool last);
|
||||||
|
|
||||||
|
esp_err_t getFiles(PsychicRequest *request);
|
||||||
|
esp_err_t handleDelete(PsychicRequest *request, JsonVariant &json);
|
||||||
|
esp_err_t handleEdit(PsychicRequest *request, JsonVariant &json);
|
||||||
|
} // namespace FileSystem
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef NTPService_h
|
#ifndef NTPService_h
|
||||||
#define NTPService_h
|
#define NTPService_h
|
||||||
|
|
||||||
#include <ESPFS.h>
|
#include <filesystem.h>
|
||||||
#include <FSPersistence.h>
|
#include <FSPersistence.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <stateful_service_endpoint.h>
|
#include <stateful_service_endpoint.h>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef SYSTEM_SERVICE_H
|
#ifndef SYSTEM_SERVICE_H
|
||||||
#define SYSTEM_SERVICE_H
|
#define SYSTEM_SERVICE_H
|
||||||
|
|
||||||
#include <ESPFS.h>
|
#include <filesystem.h>
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include <PsychicHttp.h>
|
#include <PsychicHttp.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
|
|
||||||
#include <ESPFS.h>
|
#include <filesystem.h>
|
||||||
#include <Timing.h>
|
#include <Timing.h>
|
||||||
#include <StatefulService.h>
|
#include <StatefulService.h>
|
||||||
#include <FSPersistence.h>
|
#include <FSPersistence.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user