mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-07-29 03:02:01 +08:00
add esp8266 littleFS support
add new command to handle files/directories add files creation sketch for each FS fix esplogo compilation if no display remove wifi network starting message if wifi off
This commit is contained in:
parent
bda6c23446
commit
b818022f5e
@ -177,6 +177,10 @@ Get will give type and settings only, not the protected T1/T2
|
|||||||
* List ESP Filesystem
|
* List ESP Filesystem
|
||||||
[ESP720]<Root> pwd=<admin password>
|
[ESP720]<Root> pwd=<admin password>
|
||||||
|
|
||||||
|
* Action on ESP Filesystem
|
||||||
|
rmdir / remove / mkdir / exists
|
||||||
|
[ESP730]<Action>=<path> pwd=<admin password>
|
||||||
|
|
||||||
* FW Informations
|
* FW Informations
|
||||||
[ESP800]<plain> pwd=<admin password>
|
[ESP800]<plain> pwd=<admin password>
|
||||||
|
|
||||||
|
@ -108,8 +108,8 @@
|
|||||||
//FILESYSTEM_FEATURE: to host some files on flash
|
//FILESYSTEM_FEATURE: to host some files on flash
|
||||||
//ESP_SPIFFS_FILESYSTEM 0
|
//ESP_SPIFFS_FILESYSTEM 0
|
||||||
//ESP_FAT_FILESYSTEM 1
|
//ESP_FAT_FILESYSTEM 1
|
||||||
//ESP_LITTLEFS_FILESYSTEM 2 //Not Yet implemented
|
//ESP_LITTLEFS_FILESYSTEM 2
|
||||||
#define FILESYSTEM_FEATURE ESP_SPIFFS_FILESYSTEM
|
#define FILESYSTEM_FEATURE ESP_FAT_FILESYSTEM
|
||||||
|
|
||||||
//DIRECT_PIN_FEATURE: allow to access pin using ESP201 command
|
//DIRECT_PIN_FEATURE: allow to access pin using ESP201 command
|
||||||
#define DIRECT_PIN_FEATURE
|
#define DIRECT_PIN_FEATURE
|
||||||
|
@ -453,6 +453,12 @@ bool Commands::execute_internal_command (int cmd, const char* cmd_params, level_
|
|||||||
case 720:
|
case 720:
|
||||||
response = ESP720(cmd_params, auth_type, output);
|
response = ESP720(cmd_params, auth_type, output);
|
||||||
break;
|
break;
|
||||||
|
//Action on ESP Filesystem
|
||||||
|
//rmdir / remove / mkdir / exists
|
||||||
|
//[ESP730]<Action>=<path> pwd=<admin password>
|
||||||
|
case 730:
|
||||||
|
response = ESP730(cmd_params, auth_type, output);
|
||||||
|
break;
|
||||||
#endif //FILESYSTEM_FEATURE
|
#endif //FILESYSTEM_FEATURE
|
||||||
|
|
||||||
//Get fw version firmare target and fw version
|
//Get fw version firmare target and fw version
|
||||||
|
@ -109,6 +109,7 @@ public:
|
|||||||
#if defined(FILESYSTEM_FEATURE)
|
#if defined(FILESYSTEM_FEATURE)
|
||||||
bool ESP710(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
bool ESP710(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
||||||
bool ESP720(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
bool ESP720(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
||||||
|
bool ESP730(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
||||||
#endif //FILESYSTEM_FEATURE
|
#endif //FILESYSTEM_FEATURE
|
||||||
bool ESP800(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
bool ESP800(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
||||||
bool ESP900(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
bool ESP900(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
|
||||||
|
86
esp3d/src/core/espcmd/ESP730.cpp
Normal file
86
esp3d/src/core/espcmd/ESP730.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
ESP730.cpp - ESP3D command class
|
||||||
|
|
||||||
|
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "../../include/esp3d_config.h"
|
||||||
|
#if defined (FILESYSTEM_FEATURE)
|
||||||
|
#include "../commands.h"
|
||||||
|
#include "../esp3doutput.h"
|
||||||
|
#include "../settings_esp3d.h"
|
||||||
|
#include "../../modules/authentication/authentication_service.h"
|
||||||
|
#include "../../modules/filesystem/esp_filesystem.h"
|
||||||
|
// Action on ESP Filesystem
|
||||||
|
//rmdir / remove / mkdir / exists
|
||||||
|
//[ESP730]<Action>=<path> pwd=<admin password>
|
||||||
|
bool Commands::ESP730(const char* cmd_params, level_authenticate_type auth_type, ESP3DOutput * output)
|
||||||
|
{
|
||||||
|
bool response = true;
|
||||||
|
String parameter;
|
||||||
|
parameter = get_param (cmd_params, "");
|
||||||
|
#ifdef AUTHENTICATION_FEATURE
|
||||||
|
if (auth_type != LEVEL_ADMIN) {
|
||||||
|
output->printERROR("Wrong authentication!", 401);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)auth_type;
|
||||||
|
#endif //AUTHENTICATION_FEATURE
|
||||||
|
parameter = get_param (cmd_params, "mkdir=");
|
||||||
|
if (parameter.length() != 0) {
|
||||||
|
if (ESP_FileSystem::mkdir(parameter.c_str())) {
|
||||||
|
output->printMSG ("ok");
|
||||||
|
} else {
|
||||||
|
output->printERROR ("failed!");
|
||||||
|
response = false;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
parameter = get_param (cmd_params, "rmdir=");
|
||||||
|
if (parameter.length() != 0) {
|
||||||
|
if (ESP_FileSystem::rmdir(parameter.c_str())) {
|
||||||
|
output->printMSG ("ok");
|
||||||
|
} else {
|
||||||
|
output->printERROR ("failed!");
|
||||||
|
response = false;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
parameter = get_param (cmd_params, "remove=");
|
||||||
|
if (parameter.length() != 0) {
|
||||||
|
if (ESP_FileSystem::remove(parameter.c_str())) {
|
||||||
|
output->printMSG ("ok");
|
||||||
|
} else {
|
||||||
|
output->printERROR ("failed!");
|
||||||
|
response = false;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
parameter = get_param (cmd_params, "exists=");
|
||||||
|
if (parameter.length() != 0) {
|
||||||
|
if (ESP_FileSystem::exists(parameter.c_str())) {
|
||||||
|
output->printMSG ("yes");
|
||||||
|
} else {
|
||||||
|
output->printMSG ("no");
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
output->printERROR ("Incorrect command!");
|
||||||
|
response = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //FILESYSTEM_FEATURE
|
@ -88,5 +88,8 @@
|
|||||||
#if FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM && defined( ARDUINO_ARCH_ESP8266)
|
#if FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM && defined( ARDUINO_ARCH_ESP8266)
|
||||||
#error Fat FS is not available in ESP8266
|
#error Fat FS is not available in ESP8266
|
||||||
#endif
|
#endif
|
||||||
|
#if FILESYSTEM_FEATURE == ESP_LITTLEFS_FILESYSTEM && defined( ARDUINO_ARCH_ESP32)
|
||||||
|
#error LittleFS is not available in ESP32
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif //SANITY_ESP3D_H
|
#endif //SANITY_ESP3D_H
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
#include "../../include/esp3d_config.h"
|
||||||
|
#if defined (DISPLAY_DEVICE) && (DISPLAY_UI_TYPE == UI_TYPE_ADVANCED)
|
||||||
|
extern "C" {
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
|
|
||||||
#ifndef LV_ATTRIBUTE_MEM_ALIGN
|
#ifndef LV_ATTRIBUTE_MEM_ALIGN
|
||||||
@ -627,3 +630,7 @@ lv_img_dsc_t esplogo = {
|
|||||||
.header.cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED,
|
.header.cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED,
|
||||||
.data = esplogo_map,
|
.data = esplogo_map,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //defined (DISPLAY_DEVICE) && (DISPLAY_UI_TYPE == UI_TYPE_ADVANCED)
|
@ -25,23 +25,13 @@
|
|||||||
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
#include <SPIFFS.h>
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
#include "FFat.h"
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
#include <esp_ota_ops.h>
|
#include <esp_ota_ops.h>
|
||||||
#endif //ARDUINO_ARCH_ESP32
|
#endif //ARDUINO_ARCH_ESP32
|
||||||
|
|
||||||
#define ESP_MAX_OPENHANDLE 4
|
#define ESP_MAX_OPENHANDLE 4
|
||||||
|
|
||||||
File tFile_handle[ESP_MAX_OPENHANDLE];
|
File tFile_handle[ESP_MAX_OPENHANDLE];
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
bool ESP_FileSystem::_started = false;
|
||||||
Dir tDir_handle[ESP_MAX_OPENHANDLE];
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
|
|
||||||
//constructor
|
//constructor
|
||||||
ESP_FileSystem::ESP_FileSystem()
|
ESP_FileSystem::ESP_FileSystem()
|
||||||
@ -69,76 +59,20 @@ String & ESP_FileSystem::formatBytes (uint64_t bytes)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESP_FileSystem::begin()
|
|
||||||
{
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
|
||||||
return SPIFFS.begin();
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
|
||||||
return SPIFFS.begin(true);
|
|
||||||
#endif //ARDUINO_ARCH_ESP32
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
return FFat.begin();
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
}
|
|
||||||
void ESP_FileSystem::end()
|
|
||||||
{
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
SPIFFS.end();
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
FFat.end();
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ESP_FileSystem::totalBytes()
|
|
||||||
{
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
|
||||||
fs::FSInfo info;
|
|
||||||
SPIFFS.info (info);
|
|
||||||
return info.totalBytes;
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
#if defined (ARDUINO_ARCH_ESP32)
|
|
||||||
return SPIFFS.totalBytes();
|
|
||||||
#endif //ARDUINO_ARCH_ESP32
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
return FFat.totalBytes();
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ESP_FileSystem::usedBytes()
|
|
||||||
{
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
|
||||||
fs::FSInfo info;
|
|
||||||
SPIFFS.info (info);
|
|
||||||
return info.usedBytes;
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
#if defined (ARDUINO_ARCH_ESP32)
|
|
||||||
return SPIFFS.usedBytes();
|
|
||||||
#endif //ARDUINO_ARCH_ESP32
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
return (FFat.totalBytes() - FFat.freeBytes());
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ESP_FileSystem::max_update_size()
|
size_t ESP_FileSystem::max_update_size()
|
||||||
{
|
{
|
||||||
size_t flashsize = 0;
|
size_t flashsize = 0;
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
#if defined (ARDUINO_ARCH_ESP8266)
|
||||||
flashsize = ESP.getFlashChipSize();
|
flashsize = ESP.getFlashChipSize();
|
||||||
//if higher than 1MB take out SPIFFS
|
//if higher than 1MB take out SPIFFS
|
||||||
if (flashsize > 1024 * 1024) {
|
if (flashsize <= 1024 * 1024) {
|
||||||
flashsize = (1024 * 1024)-ESP.getSketchSize()-1024;
|
flashsize = (1024 * 1024)-ESP.getSketchSize()-1024;
|
||||||
} else {
|
} else {
|
||||||
fs::FSInfo info;
|
flashsize = flashsize - ESP.getSketchSize()-totalBytes()-1024;
|
||||||
SPIFFS.info (info);
|
//max OTA partition is 1019Kb
|
||||||
flashsize = flashsize - ESP.getSketchSize()-info.totalBytes-1024;
|
if (flashsize > 1024 * 1024) {
|
||||||
|
flashsize = (1024 * 1024) - 1024;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
#endif //ARDUINO_ARCH_ESP8266
|
||||||
#if defined (ARDUINO_ARCH_ESP32)
|
#if defined (ARDUINO_ARCH_ESP32)
|
||||||
@ -155,252 +89,7 @@ size_t ESP_FileSystem::max_update_size()
|
|||||||
return flashsize;
|
return flashsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * ESP_FileSystem::FilesystemName()
|
ESP_File::ESP_File(const char * name, const char * filename, bool isdir, size_t size)
|
||||||
{
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
return "SPIFFS";
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
return "FAT";
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
return "None";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP_FileSystem::format()
|
|
||||||
{
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
return SPIFFS.format();
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
/* FFat.end();*/
|
|
||||||
return FFat.format();
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_File ESP_FileSystem::open(const char* path, uint8_t mode)
|
|
||||||
{
|
|
||||||
//do some check
|
|
||||||
if(((strcmp(path,"/") == 0) && ((mode == ESP_FILE_WRITE) || (mode == ESP_FILE_APPEND))) || (strlen(path) == 0)) {
|
|
||||||
return ESP_File();
|
|
||||||
}
|
|
||||||
// path must start by '/'
|
|
||||||
if (path[0] != '/') {
|
|
||||||
return ESP_File();
|
|
||||||
}
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
if (mode != ESP_FILE_READ) {
|
|
||||||
//check container exists
|
|
||||||
String p = path;
|
|
||||||
p.remove(p.lastIndexOf('/') +1);
|
|
||||||
if (!exists(p.c_str())) {
|
|
||||||
//log_esp3d("Error opening: %s", path);
|
|
||||||
return ESP_File();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
File ftmp = SPIFFS.open(path, (mode == ESP_FILE_READ)?"r":(mode == ESP_FILE_WRITE)?"w":"a");
|
|
||||||
if(ftmp) {
|
|
||||||
//log_esp3d("Success openening: %s", path);
|
|
||||||
ESP_File esptmp(&ftmp, false,(mode == ESP_FILE_READ)?false:true, path);
|
|
||||||
return esptmp;
|
|
||||||
}
|
|
||||||
(void)mode;
|
|
||||||
Dir dtmp = SPIFFS.openDir(path);
|
|
||||||
ESP_File esptmp(&dtmp, true, false, path);
|
|
||||||
return esptmp;
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
#if defined (ARDUINO_ARCH_ESP32)
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
//TODO add support if path = /DIR1/ <- with last /
|
|
||||||
File tmp = SPIFFS.open(path, (mode == ESP_FILE_READ)?FILE_READ:(mode == ESP_FILE_WRITE)?FILE_WRITE:FILE_APPEND);
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
File tmp = FFat.open(path, (mode == ESP_FILE_READ)?FILE_READ:(mode == ESP_FILE_WRITE)?FILE_WRITE:FILE_APPEND);
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
ESP_File esptmp(&tmp, tmp.isDirectory(),(mode == ESP_FILE_READ)?false:true, path);
|
|
||||||
return esptmp;
|
|
||||||
#endif //ARDUINO_ARCH_ESP32
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP_FileSystem::exists(const char* path)
|
|
||||||
{
|
|
||||||
bool res = false;
|
|
||||||
//log_esp3d("Check %s", path);
|
|
||||||
//root should always be there
|
|
||||||
if (strcmp(path, "/") == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
res = FFat.exists(path);
|
|
||||||
if (!res) {
|
|
||||||
ESP_File root = ESP_FileSystem::open(path, ESP_FILE_READ);
|
|
||||||
if (root) {
|
|
||||||
res = root.isDirectory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
String spath = path;
|
|
||||||
spath.trim();
|
|
||||||
if (spath[spath.length()-1] == '/') {
|
|
||||||
if (spath!="/") {
|
|
||||||
spath.remove(spath.length()-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res = SPIFFS.exists(spath.c_str());
|
|
||||||
if (!res) {
|
|
||||||
String newpath = spath;
|
|
||||||
if (newpath[newpath.length()-1] != '/') {
|
|
||||||
newpath+="/";
|
|
||||||
}
|
|
||||||
newpath+=".";
|
|
||||||
//log_esp3d("Check %s", newpath.c_str());
|
|
||||||
res = SPIFFS.exists(newpath);
|
|
||||||
if (!res) {
|
|
||||||
ESP_File f = ESP_FileSystem::open(path, ESP_FILE_READ);
|
|
||||||
if (f) {
|
|
||||||
//Check directories
|
|
||||||
ESP_File sub = f.openNextFile();
|
|
||||||
if (sub) {
|
|
||||||
sub.close();
|
|
||||||
res = true;
|
|
||||||
}
|
|
||||||
f.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP_FileSystem::remove(const char *path)
|
|
||||||
{
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
return SPIFFS.remove(path);
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
return FFat.remove(path);
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP_FileSystem::mkdir(const char *path)
|
|
||||||
{
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
//Use file named . to simulate directory
|
|
||||||
String p = path;
|
|
||||||
if (p[p.length()-1] != '/') {
|
|
||||||
p+="/";
|
|
||||||
}
|
|
||||||
p+=".";
|
|
||||||
//log_esp3d("Dir create : %s", p.c_str());
|
|
||||||
ESP_File f = open(p.c_str(), ESP_FILE_WRITE);
|
|
||||||
if (f) {
|
|
||||||
f.close();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
return FFat.mkdir(path);
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESP_FileSystem::rmdir(const char *path)
|
|
||||||
{
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
if (!exists(path)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool res = true;
|
|
||||||
GenLinkedList<String > pathlist;
|
|
||||||
String p = path;
|
|
||||||
pathlist.push(p);
|
|
||||||
while (pathlist.count() > 0) {
|
|
||||||
File dir = FFat.open(pathlist.getLast().c_str());
|
|
||||||
File f = dir.openNextFile();
|
|
||||||
bool candelete = true;
|
|
||||||
while (f) {
|
|
||||||
if (f.isDirectory()) {
|
|
||||||
candelete = false;
|
|
||||||
String newdir = f.name();
|
|
||||||
pathlist.push(newdir);
|
|
||||||
f.close();
|
|
||||||
f = File();
|
|
||||||
} else {
|
|
||||||
FFat.remove(f.name());
|
|
||||||
f.close();
|
|
||||||
f = dir.openNextFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (candelete) {
|
|
||||||
if (pathlist.getLast() !="/") {
|
|
||||||
res = FFat.rmdir(pathlist.getLast().c_str());
|
|
||||||
}
|
|
||||||
pathlist.pop();
|
|
||||||
}
|
|
||||||
dir.close();
|
|
||||||
}
|
|
||||||
p = String();
|
|
||||||
log_esp3d("count %d", pathlist.count());
|
|
||||||
return res;
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
|
||||||
Dir dtmp = SPIFFS.openDir(path);
|
|
||||||
while (dtmp.next()) {
|
|
||||||
if (!SPIFFS.remove(dtmp.fileName().c_str())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
#if defined (ARDUINO_ARCH_ESP32)
|
|
||||||
String spath = path;
|
|
||||||
spath.trim();
|
|
||||||
if (spath[spath.length()-1] == '/') {
|
|
||||||
if (spath!="/") {
|
|
||||||
spath.remove(spath.length()-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log_esp3d("Deleting : %s",spath.c_str());
|
|
||||||
File ftmp = SPIFFS.open(spath.c_str());
|
|
||||||
if (ftmp) {
|
|
||||||
File pfile = ftmp.openNextFile();
|
|
||||||
while (pfile) {
|
|
||||||
//log_esp3d("File: %s",pfile.name());
|
|
||||||
if (!SPIFFS.remove(pfile.name())) {
|
|
||||||
pfile.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pfile.close();
|
|
||||||
pfile = ftmp.openNextFile();
|
|
||||||
}
|
|
||||||
ftmp.close();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif //ARDUINO_ARCH_ESP32
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP_FileSystem::closeAll()
|
|
||||||
{
|
|
||||||
for (uint8_t i = 0; i < ESP_MAX_OPENHANDLE; i++) {
|
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
|
||||||
tDir_handle[i] = Dir();
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
tFile_handle[i].close();
|
|
||||||
tFile_handle[i] = File();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_File::ESP_File(const char * name, const char * filename, bool isdir)
|
|
||||||
{
|
{
|
||||||
_isdir = isdir;
|
_isdir = isdir;
|
||||||
_dirlist = "";
|
_dirlist = "";
|
||||||
@ -412,250 +101,7 @@ ESP_File::ESP_File(const char * name, const char * filename, bool isdir)
|
|||||||
memset (&_lastwrite,0,sizeof(time_t));
|
memset (&_lastwrite,0,sizeof(time_t));
|
||||||
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
_iswritemode = false;
|
_iswritemode = false;
|
||||||
_size = 0;
|
_size = size;
|
||||||
}
|
|
||||||
|
|
||||||
ESP_File::ESP_File(void* handle, bool isdir, bool iswritemode, const char * path)
|
|
||||||
{
|
|
||||||
_isdir = isdir;
|
|
||||||
_dirlist = "";
|
|
||||||
_isfakedir = false;
|
|
||||||
_index = -1;
|
|
||||||
_filename = "";
|
|
||||||
_name = "";
|
|
||||||
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
|
||||||
memset (&_lastwrite,0,sizeof(time_t));
|
|
||||||
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
|
||||||
_iswritemode = iswritemode;
|
|
||||||
_size = 0;
|
|
||||||
if (!handle) {
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
bool set =false;
|
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
|
||||||
if (_isdir) {
|
|
||||||
for (uint8_t i=0; (i < ESP_MAX_OPENHANDLE) && !set; i++) {
|
|
||||||
if (tDir_handle[i].fileName().length() == 0) {
|
|
||||||
tDir_handle[i] = *((Dir *)handle);
|
|
||||||
_index = i;
|
|
||||||
//Path = filename
|
|
||||||
if (path) {
|
|
||||||
_filename = path;
|
|
||||||
if (_filename == "/") {
|
|
||||||
_filename = "/.";
|
|
||||||
}
|
|
||||||
if (_filename[_filename.length()-1] != '.') {
|
|
||||||
if (_filename[_filename.length()-2] != '/') {
|
|
||||||
_filename+="/";
|
|
||||||
}
|
|
||||||
_filename+=".";
|
|
||||||
}
|
|
||||||
//log_esp3d("Filename: %s", _filename.c_str());
|
|
||||||
//Name
|
|
||||||
if (_filename == "/.") {
|
|
||||||
_name = "/";
|
|
||||||
} else {
|
|
||||||
_name = _filename;
|
|
||||||
if (_name.length() >=2) {
|
|
||||||
if ((_name[_name.length() - 1] == '.') && (_name[_name.length() - 2] == '/')) {
|
|
||||||
_name.remove( _name.length() - 2,2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_name.remove( 0, _name.lastIndexOf('/')+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//log_esp3d("Name: %s index: %d", _name.c_str(), _index);
|
|
||||||
set = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
|
|
||||||
for (uint8_t i=0; (i < ESP_MAX_OPENHANDLE) && !set; i++) {
|
|
||||||
if (!tFile_handle[i]) {
|
|
||||||
tFile_handle[i] = *((File*)handle);
|
|
||||||
//filename
|
|
||||||
_filename = tFile_handle[i].name();
|
|
||||||
|
|
||||||
//if root
|
|
||||||
if (_filename == "/") {
|
|
||||||
_filename = "/.";
|
|
||||||
}
|
|
||||||
if (_isdir) {
|
|
||||||
if (_filename[_filename.length()-1] != '.') {
|
|
||||||
if (_filename[_filename.length()-2] != '/') {
|
|
||||||
_filename+="/";
|
|
||||||
}
|
|
||||||
_filename+=".";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//name
|
|
||||||
if (_filename == "/.") {
|
|
||||||
_name = "/";
|
|
||||||
} else {
|
|
||||||
_name = _filename;
|
|
||||||
if (_name.endsWith("/.")) {
|
|
||||||
_name.remove( _name.length() - 2,2);
|
|
||||||
_isfakedir = true;
|
|
||||||
_isdir = true;
|
|
||||||
}
|
|
||||||
if (_name[0] == '/') {
|
|
||||||
_name.remove( 0, 1);
|
|
||||||
}
|
|
||||||
int pos = _name.lastIndexOf('/');
|
|
||||||
if (pos != -1) {
|
|
||||||
_name.remove( 0, pos+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//size
|
|
||||||
_size = tFile_handle[i].size();
|
|
||||||
//time
|
|
||||||
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
|
||||||
_lastwrite = tFile_handle[i].getLastWrite();
|
|
||||||
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
|
||||||
_index = i;
|
|
||||||
//log_esp3d("Opening File at index %d",_index);
|
|
||||||
set = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP_File::close()
|
|
||||||
{
|
|
||||||
if (_index != -1) {
|
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
|
||||||
if (_isdir && !_isfakedir) {
|
|
||||||
//log_esp3d("Closing Dir at index %d", _index);
|
|
||||||
tDir_handle[_index] = Dir();
|
|
||||||
_index = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
//log_esp3d("Closing File at index %d", _index);
|
|
||||||
tFile_handle[_index].close();
|
|
||||||
//reopen if mode = write
|
|
||||||
//udate size + date
|
|
||||||
if (_iswritemode && !_isdir) {
|
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
|
||||||
File ftmp = SPIFFS.open(_filename.c_str(), "r");
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
#if defined (ARDUINO_ARCH_ESP32)
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
|
|
||||||
File ftmp = SPIFFS.open(_filename.c_str());
|
|
||||||
#endif //ESP_SPIFFS_FILESYSTEM
|
|
||||||
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
|
||||||
File ftmp = FFat.open(_filename.c_str());
|
|
||||||
#endif //ESP_FAT_FILESYSTEM
|
|
||||||
#endif //ARDUINO_ARCH_ESP32
|
|
||||||
|
|
||||||
if (ftmp) {
|
|
||||||
_size = ftmp.size();
|
|
||||||
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
|
||||||
_lastwrite = ftmp.getLastWrite();
|
|
||||||
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
|
||||||
ftmp.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if defined (ARDUINO_ARCH_ESP32)
|
|
||||||
tFile_handle[_index] = File();
|
|
||||||
#endif //ARDUINO_ARCH_ESP32
|
|
||||||
//log_esp3d("Closing File at index %d",_index);
|
|
||||||
_index = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_File ESP_File::openNextFile()
|
|
||||||
{
|
|
||||||
if ((_index == -1) || !_isdir) {
|
|
||||||
log_esp3d("openNextFile failed");
|
|
||||||
return ESP_File();
|
|
||||||
}
|
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
|
||||||
if(tDir_handle[_index].next()) {
|
|
||||||
//log_esp3d("Getting next file from %s", _filename.c_str());
|
|
||||||
File tmp = tDir_handle[_index].openFile("r");
|
|
||||||
while (tmp) {
|
|
||||||
ESP_File esptmp(&tmp);
|
|
||||||
esptmp.close();
|
|
||||||
String sub = esptmp.filename();
|
|
||||||
sub.remove(0,_filename.length()-1);
|
|
||||||
int pos = sub.indexOf("/");
|
|
||||||
if (pos!=-1) {
|
|
||||||
//is subdir
|
|
||||||
sub = sub.substring(0,pos);
|
|
||||||
//log_esp3d("file name:%s name: %s %s sub:%s root:%s", esptmp.filename(), esptmp.name(), (esptmp.isDirectory())?"isDir":"isFile", sub.c_str(), _filename.c_str());
|
|
||||||
String tag = "*" + sub + "*";
|
|
||||||
//test if already in directory list
|
|
||||||
if (_dirlist.indexOf(tag) == -1) {//not in list so add it and return the info
|
|
||||||
_dirlist+= tag;
|
|
||||||
String fname = _filename.substring(0,_filename.length()-1) + sub + "/.";
|
|
||||||
//log_esp3d("Found dir name: %s filename:%s", sub.c_str(), fname.c_str());
|
|
||||||
esptmp = ESP_File(sub.c_str(), fname.c_str());
|
|
||||||
return esptmp;
|
|
||||||
} else { //already in list so ignore it
|
|
||||||
//log_esp3d("Dir name: %s already in list", sub.c_str());
|
|
||||||
if(!tDir_handle[_index].next()) {
|
|
||||||
return ESP_File();
|
|
||||||
} else {
|
|
||||||
tmp = tDir_handle[_index].openFile("r");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { //is file
|
|
||||||
//log_esp3d("file name:%s name: %s %s sub:%s root:%s", esptmp.filename(), esptmp.name(), (esptmp.isDirectory())?"isDir":"isFile", sub.c_str(), _filename.c_str());
|
|
||||||
if (sub == ".") {
|
|
||||||
//log_esp3d("Dir tag, ignore it");
|
|
||||||
if(!tDir_handle[_index].next()) {
|
|
||||||
return ESP_File();
|
|
||||||
} else {
|
|
||||||
tmp = tDir_handle[_index].openFile("r");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return esptmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ESP_File();
|
|
||||||
#endif //ARDUINO_ARCH_ESP8266
|
|
||||||
#if defined (ARDUINO_ARCH_ESP32)
|
|
||||||
File tmp = tFile_handle[_index].openNextFile();
|
|
||||||
while (tmp) {
|
|
||||||
//log_esp3d("tmp name :%s %s", tmp.name(), (tmp.isDirectory())?"isDir":"isFile");
|
|
||||||
ESP_File esptmp(&tmp, tmp.isDirectory());
|
|
||||||
esptmp.close();
|
|
||||||
String sub = esptmp.filename();
|
|
||||||
sub.remove(0,_filename.length()-1);
|
|
||||||
int pos = sub.indexOf("/");
|
|
||||||
if (pos!=-1) {
|
|
||||||
//is subdir
|
|
||||||
sub = sub.substring(0,pos);
|
|
||||||
//log_esp3d("file name:%s name: %s %s sub:%s root:%s", esptmp.filename(), esptmp.name(), (esptmp.isDirectory())?"isDir":"isFile", sub.c_str(), _filename.c_str());
|
|
||||||
String tag = "*" + sub + "*";
|
|
||||||
//test if already in directory list
|
|
||||||
if (_dirlist.indexOf(tag) == -1) {//not in list so add it and return the info
|
|
||||||
_dirlist+= tag;
|
|
||||||
String fname = _filename.substring(0,_filename.length()-1) + sub + "/.";
|
|
||||||
//log_esp3d("Found dir name: %s filename:%s", sub.c_str(), fname.c_str());
|
|
||||||
esptmp = ESP_File(sub.c_str(), fname.c_str());
|
|
||||||
return esptmp;
|
|
||||||
} else { //already in list so ignore it
|
|
||||||
//log_esp3d("Dir name: %s already in list", sub.c_str());
|
|
||||||
tmp = tFile_handle[_index].openNextFile();
|
|
||||||
}
|
|
||||||
} else { //is file
|
|
||||||
//log_esp3d("file name:%s name: %s %s sub:%s root:%s", esptmp.filename(), esptmp.name(), (esptmp.isDirectory())?"isDir":"isFile", sub.c_str(), _filename.c_str());
|
|
||||||
if (sub == ".") {
|
|
||||||
//log_esp3d("Dir tag, ignore it");
|
|
||||||
tmp = tFile_handle[_index].openNextFile();
|
|
||||||
} else {
|
|
||||||
return esptmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return ESP_File();
|
|
||||||
#endif //ARDUINO_ARCH_ESP32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_File::~ESP_File()
|
ESP_File::~ESP_File()
|
||||||
|
@ -28,11 +28,13 @@
|
|||||||
#define ESP_FILE_WRITE 1
|
#define ESP_FILE_WRITE 1
|
||||||
#define ESP_FILE_APPEND 2
|
#define ESP_FILE_APPEND 2
|
||||||
|
|
||||||
|
#define ESP_MAX_OPENHANDLE 4
|
||||||
|
|
||||||
class ESP_File
|
class ESP_File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ESP_File(void * handle = nullptr, bool isdir =false, bool iswritemode = false, const char * path = nullptr);
|
ESP_File(void * handle = nullptr, bool isdir =false, bool iswritemode = false, const char * path = nullptr);
|
||||||
ESP_File(const char * name, const char * filename, bool isdir = true);
|
ESP_File(const char * name, const char * filename, bool isdir = true, size_t size =0);
|
||||||
~ESP_File();
|
~ESP_File();
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
bool isDirectory();
|
bool isDirectory();
|
||||||
@ -86,6 +88,7 @@ public:
|
|||||||
static bool rmdir(const char *path);
|
static bool rmdir(const char *path);
|
||||||
static void closeAll();
|
static void closeAll();
|
||||||
private:
|
private:
|
||||||
|
static bool _started;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
294
esp3d/src/modules/filesystem/fat_filesystem.cpp
Normal file
294
esp3d/src/modules/filesystem/fat_filesystem.cpp
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
/*
|
||||||
|
fat_filesystem.cpp - ESP3D fat filesystem configuration class
|
||||||
|
|
||||||
|
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "../../include/esp3d_config.h"
|
||||||
|
#if (FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM)
|
||||||
|
#include "esp_filesystem.h"
|
||||||
|
#include "../../core/genLinkedList.h"
|
||||||
|
#include <FS.h>
|
||||||
|
#include "FFat.h"
|
||||||
|
|
||||||
|
extern File tFile_handle[ESP_MAX_OPENHANDLE];
|
||||||
|
|
||||||
|
bool ESP_FileSystem::begin()
|
||||||
|
{
|
||||||
|
_started = FFat.begin();
|
||||||
|
return _started;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP_FileSystem::end()
|
||||||
|
{
|
||||||
|
FFat.end();
|
||||||
|
_started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ESP_FileSystem::totalBytes()
|
||||||
|
{
|
||||||
|
return FFat.totalBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ESP_FileSystem::usedBytes()
|
||||||
|
{
|
||||||
|
return (FFat.totalBytes() - FFat.freeBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * ESP_FileSystem::FilesystemName()
|
||||||
|
{
|
||||||
|
return "FAT";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::format()
|
||||||
|
{
|
||||||
|
return FFat.format();
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File ESP_FileSystem::open(const char* path, uint8_t mode)
|
||||||
|
{
|
||||||
|
//do some check
|
||||||
|
if(((strcmp(path,"/") == 0) && ((mode == ESP_FILE_WRITE) || (mode == ESP_FILE_APPEND))) || (strlen(path) == 0)) {
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
// path must start by '/'
|
||||||
|
if (path[0] != '/') {
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
if (mode != ESP_FILE_READ) {
|
||||||
|
//check container exists
|
||||||
|
String p = path;
|
||||||
|
p.remove(p.lastIndexOf('/') +1);
|
||||||
|
if (!exists(p.c_str())) {
|
||||||
|
log_esp3d("Error opening: %s", path);
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File tmp = FFat.open(path, (mode == ESP_FILE_READ)?FILE_READ:(mode == ESP_FILE_WRITE)?FILE_WRITE:FILE_APPEND);
|
||||||
|
ESP_File esptmp(&tmp, tmp.isDirectory(),(mode == ESP_FILE_READ)?false:true, path);
|
||||||
|
return esptmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::exists(const char* path)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
//root should always be there if started
|
||||||
|
if (strcmp(path, "/") == 0) {
|
||||||
|
return _started;
|
||||||
|
}
|
||||||
|
res = FFat.exists(path);
|
||||||
|
if (!res) {
|
||||||
|
ESP_File root = ESP_FileSystem::open(path, ESP_FILE_READ);
|
||||||
|
if (root) {
|
||||||
|
res = root.isDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::remove(const char *path)
|
||||||
|
{
|
||||||
|
return FFat.remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::mkdir(const char *path)
|
||||||
|
{
|
||||||
|
return FFat.mkdir(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::rmdir(const char *path)
|
||||||
|
{
|
||||||
|
if (!exists(path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool res = true;
|
||||||
|
GenLinkedList<String > pathlist;
|
||||||
|
String p = path;
|
||||||
|
pathlist.push(p);
|
||||||
|
while (pathlist.count() > 0) {
|
||||||
|
File dir = FFat.open(pathlist.getLast().c_str());
|
||||||
|
File f = dir.openNextFile();
|
||||||
|
bool candelete = true;
|
||||||
|
while (f) {
|
||||||
|
if (f.isDirectory()) {
|
||||||
|
candelete = false;
|
||||||
|
String newdir = f.name();
|
||||||
|
pathlist.push(newdir);
|
||||||
|
f.close();
|
||||||
|
f = File();
|
||||||
|
} else {
|
||||||
|
FFat.remove(f.name());
|
||||||
|
f.close();
|
||||||
|
f = dir.openNextFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (candelete) {
|
||||||
|
if (pathlist.getLast() !="/") {
|
||||||
|
res = FFat.rmdir(pathlist.getLast().c_str());
|
||||||
|
}
|
||||||
|
pathlist.pop();
|
||||||
|
}
|
||||||
|
dir.close();
|
||||||
|
}
|
||||||
|
p = String();
|
||||||
|
log_esp3d("count %d", pathlist.count());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP_FileSystem::closeAll()
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < ESP_MAX_OPENHANDLE; i++) {
|
||||||
|
tFile_handle[i].close();
|
||||||
|
tFile_handle[i] = File();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File::ESP_File(void* handle, bool isdir, bool iswritemode, const char * path)
|
||||||
|
{
|
||||||
|
_isdir = isdir;
|
||||||
|
_dirlist = "";
|
||||||
|
_isfakedir = false;
|
||||||
|
_index = -1;
|
||||||
|
_filename = "";
|
||||||
|
_name = "";
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
memset (&_lastwrite,0,sizeof(time_t));
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_iswritemode = iswritemode;
|
||||||
|
_size = 0;
|
||||||
|
if (!handle) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
bool set =false;
|
||||||
|
for (uint8_t i=0; (i < ESP_MAX_OPENHANDLE) && !set; i++) {
|
||||||
|
if (!tFile_handle[i]) {
|
||||||
|
tFile_handle[i] = *((File*)handle);
|
||||||
|
//filename
|
||||||
|
_filename = tFile_handle[i].name();
|
||||||
|
|
||||||
|
//if root
|
||||||
|
if (_filename == "/") {
|
||||||
|
_filename = "/.";
|
||||||
|
}
|
||||||
|
if (_isdir) {
|
||||||
|
if (_filename[_filename.length()-1] != '.') {
|
||||||
|
if (_filename[_filename.length()-2] != '/') {
|
||||||
|
_filename+="/";
|
||||||
|
}
|
||||||
|
_filename+=".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//name
|
||||||
|
if (_filename == "/.") {
|
||||||
|
_name = "/";
|
||||||
|
} else {
|
||||||
|
_name = _filename;
|
||||||
|
if (_name.endsWith("/.")) {
|
||||||
|
_name.remove( _name.length() - 2,2);
|
||||||
|
_isfakedir = true;
|
||||||
|
_isdir = true;
|
||||||
|
}
|
||||||
|
if (_name[0] == '/') {
|
||||||
|
_name.remove( 0, 1);
|
||||||
|
}
|
||||||
|
int pos = _name.lastIndexOf('/');
|
||||||
|
if (pos != -1) {
|
||||||
|
_name.remove( 0, pos+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//size
|
||||||
|
_size = tFile_handle[i].size();
|
||||||
|
//time
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_lastwrite = tFile_handle[i].getLastWrite();
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_index = i;
|
||||||
|
//log_esp3d("Opening File at index %d",_index);
|
||||||
|
set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP_File::close()
|
||||||
|
{
|
||||||
|
if (_index != -1) {
|
||||||
|
//log_esp3d("Closing File at index %d", _index);
|
||||||
|
tFile_handle[_index].close();
|
||||||
|
//reopen if mode = write
|
||||||
|
//udate size + date
|
||||||
|
if (_iswritemode && !_isdir) {
|
||||||
|
File ftmp = FFat.open(_filename.c_str());
|
||||||
|
if (ftmp) {
|
||||||
|
_size = ftmp.size();
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_lastwrite = ftmp.getLastWrite();
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
ftmp.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tFile_handle[_index] = File();
|
||||||
|
//log_esp3d("Closing File at index %d",_index);
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File ESP_File::openNextFile()
|
||||||
|
{
|
||||||
|
if ((_index == -1) || !_isdir) {
|
||||||
|
log_esp3d("openNextFile failed");
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
File tmp = tFile_handle[_index].openNextFile();
|
||||||
|
while (tmp) {
|
||||||
|
log_esp3d("tmp name :%s %s", tmp.name(), (tmp.isDirectory())?"isDir":"isFile");
|
||||||
|
ESP_File esptmp(&tmp, tmp.isDirectory());
|
||||||
|
esptmp.close();
|
||||||
|
String sub = esptmp.filename();
|
||||||
|
sub.remove(0,_filename.length()-1);
|
||||||
|
int pos = sub.indexOf("/");
|
||||||
|
if (pos!=-1) {
|
||||||
|
//is subdir
|
||||||
|
sub = sub.substring(0,pos);
|
||||||
|
//log_esp3d("file name:%s name: %s %s sub:%s root:%s", esptmp.filename(), esptmp.name(), (esptmp.isDirectory())?"isDir":"isFile", sub.c_str(), _filename.c_str());
|
||||||
|
String tag = "*" + sub + "*";
|
||||||
|
//test if already in directory list
|
||||||
|
if (_dirlist.indexOf(tag) == -1) {//not in list so add it and return the info
|
||||||
|
_dirlist+= tag;
|
||||||
|
String fname = _filename.substring(0,_filename.length()-1) + sub + "/.";
|
||||||
|
//log_esp3d("Found dir name: %s filename:%s", sub.c_str(), fname.c_str());
|
||||||
|
esptmp = ESP_File(sub.c_str(), fname.c_str());
|
||||||
|
return esptmp;
|
||||||
|
} else { //already in list so ignore it
|
||||||
|
//log_esp3d("Dir name: %s already in list", sub.c_str());
|
||||||
|
tmp = tFile_handle[_index].openNextFile();
|
||||||
|
}
|
||||||
|
} else { //is file
|
||||||
|
//log_esp3d("file name:%s name: %s %s sub:%s root:%s", esptmp.filename(), esptmp.name(), (esptmp.isDirectory())?"isDir":"isFile", sub.c_str(), _filename.c_str());
|
||||||
|
if (sub == ".") {
|
||||||
|
//log_esp3d("Dir tag, ignore it");
|
||||||
|
tmp = tFile_handle[_index].openNextFile();
|
||||||
|
} else {
|
||||||
|
return esptmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ESP_FAT_FILESYSTEM
|
320
esp3d/src/modules/filesystem/littlefs_filesystem .cpp
Normal file
320
esp3d/src/modules/filesystem/littlefs_filesystem .cpp
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
/*
|
||||||
|
littlefs_filesystem.cpp - ESP3D littlefs filesystem configuration class
|
||||||
|
|
||||||
|
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "../../include/esp3d_config.h"
|
||||||
|
#if (FILESYSTEM_FEATURE == ESP_LITTLEFS_FILESYSTEM)
|
||||||
|
#include "esp_filesystem.h"
|
||||||
|
#include "../../core/genLinkedList.h"
|
||||||
|
#include <FS.h>
|
||||||
|
#include <LittleFS.h>
|
||||||
|
|
||||||
|
Dir tDir_handle[ESP_MAX_OPENHANDLE];
|
||||||
|
extern File tFile_handle[ESP_MAX_OPENHANDLE];
|
||||||
|
|
||||||
|
bool ESP_FileSystem::begin()
|
||||||
|
{
|
||||||
|
_started = LittleFS.begin();
|
||||||
|
return _started;
|
||||||
|
}
|
||||||
|
void ESP_FileSystem::end()
|
||||||
|
{
|
||||||
|
_started = false;
|
||||||
|
LittleFS.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ESP_FileSystem::totalBytes()
|
||||||
|
{
|
||||||
|
fs::FSInfo info;
|
||||||
|
LittleFS.info (info);
|
||||||
|
return info.totalBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ESP_FileSystem::usedBytes()
|
||||||
|
{
|
||||||
|
fs::FSInfo info;
|
||||||
|
LittleFS.info (info);
|
||||||
|
return info.usedBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * ESP_FileSystem::FilesystemName()
|
||||||
|
{
|
||||||
|
return "LittleFS";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::format()
|
||||||
|
{
|
||||||
|
return LittleFS.format();
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File ESP_FileSystem::open(const char* path, uint8_t mode)
|
||||||
|
{
|
||||||
|
//do some check
|
||||||
|
if(((strcmp(path,"/") == 0) && ((mode == ESP_FILE_WRITE) || (mode == ESP_FILE_APPEND))) || (strlen(path) == 0)) {
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
// path must start by '/'
|
||||||
|
if (path[0] != '/') {
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
File ftmp = LittleFS.open(path, (mode == ESP_FILE_READ)?"r":(mode == ESP_FILE_WRITE)?"w":"a");
|
||||||
|
if(ftmp) {
|
||||||
|
log_esp3d("Success openening: %s", path);
|
||||||
|
if (ftmp.isFile()){
|
||||||
|
log_esp3d("It is a file");
|
||||||
|
ESP_File esptmp(&ftmp, false,(mode == ESP_FILE_READ)?false:true, path);
|
||||||
|
return esptmp;
|
||||||
|
}
|
||||||
|
if (ftmp.isDirectory()){
|
||||||
|
log_esp3d("It is a Directory");
|
||||||
|
}
|
||||||
|
ftmp.close();
|
||||||
|
}
|
||||||
|
log_esp3d("Opening as Directory");
|
||||||
|
Dir dtmp = LittleFS.openDir(path);
|
||||||
|
ESP_File esptmp(&dtmp, true, false, path);
|
||||||
|
return esptmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::exists(const char* path)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
//root should always be there if started
|
||||||
|
if (strcmp(path, "/") == 0) {
|
||||||
|
return _started;
|
||||||
|
}
|
||||||
|
String spath = path;
|
||||||
|
spath.trim();
|
||||||
|
if (spath[spath.length()-1] == '/') {
|
||||||
|
if (spath!="/") {
|
||||||
|
spath.remove(spath.length()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LittleFS.exists(spath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::remove(const char *path)
|
||||||
|
{
|
||||||
|
return LittleFS.remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::mkdir(const char *path)
|
||||||
|
{
|
||||||
|
String spath = path;
|
||||||
|
spath.trim();
|
||||||
|
if (spath[spath.length()-1] == '/') {
|
||||||
|
if (spath!="/") {
|
||||||
|
spath.remove(spath.length()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LittleFS.mkdir(spath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::rmdir(const char *path)
|
||||||
|
{
|
||||||
|
if (!exists(path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool res = true;
|
||||||
|
GenLinkedList<String > pathlist;
|
||||||
|
String spath = path;
|
||||||
|
spath.trim();
|
||||||
|
if (spath[spath.length()-1] != '/') {
|
||||||
|
spath+="/";
|
||||||
|
}if (spath[0] != '/') {
|
||||||
|
spath ="/" + spath;
|
||||||
|
}
|
||||||
|
pathlist.push(spath);
|
||||||
|
while (pathlist.count() > 0) {
|
||||||
|
spath=pathlist.getLast();
|
||||||
|
bool candelete = true;
|
||||||
|
if (LittleFS.exists(spath.c_str())) {
|
||||||
|
Dir dir = LittleFS.openDir(pathlist.getLast().c_str());
|
||||||
|
while (dir.next()) {
|
||||||
|
if (dir.isDirectory()) {
|
||||||
|
candelete = false;
|
||||||
|
String newdir = pathlist.getLast() + dir.fileName() + "/";
|
||||||
|
pathlist.push(newdir);
|
||||||
|
} else {
|
||||||
|
log_esp3d("remove %s", dir.fileName().c_str());
|
||||||
|
String s = spath + dir.fileName();
|
||||||
|
LittleFS.remove(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (candelete) {
|
||||||
|
if (spath !="/") {
|
||||||
|
if (spath[spath.length()-1] == '/') {
|
||||||
|
spath.remove(spath.length()-1);
|
||||||
|
}
|
||||||
|
if (LittleFS.exists(spath.c_str())) {
|
||||||
|
res = LittleFS.rmdir(spath.c_str());
|
||||||
|
}
|
||||||
|
log_esp3d("rmdir %s %d", spath.c_str(), res);
|
||||||
|
}
|
||||||
|
pathlist.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP_FileSystem::closeAll()
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < ESP_MAX_OPENHANDLE; i++) {
|
||||||
|
tDir_handle[i] = Dir();
|
||||||
|
tFile_handle[i].close();
|
||||||
|
tFile_handle[i] = File();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File::ESP_File(void* handle, bool isdir, bool iswritemode, const char * path)
|
||||||
|
{
|
||||||
|
_isdir = isdir;
|
||||||
|
_dirlist = "";
|
||||||
|
_isfakedir = false;
|
||||||
|
_index = -1;
|
||||||
|
_filename = "";
|
||||||
|
_name = "";
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
memset (&_lastwrite,0,sizeof(time_t));
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_iswritemode = iswritemode;
|
||||||
|
_size = 0;
|
||||||
|
if (!handle) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
bool set =false;
|
||||||
|
if (_isdir) {
|
||||||
|
for (uint8_t i=0; (i < ESP_MAX_OPENHANDLE) && !set; i++) {
|
||||||
|
if (tDir_handle[i].fileName().length() == 0) {
|
||||||
|
tDir_handle[i] = *((Dir *)handle);
|
||||||
|
_index = i;
|
||||||
|
//Path = filename
|
||||||
|
if (path) {
|
||||||
|
_filename = path;
|
||||||
|
_filename.trim();
|
||||||
|
if (!((_filename[_filename.length()-1] == '/') || (_filename == "/"))) {
|
||||||
|
_filename+="/";
|
||||||
|
}
|
||||||
|
//log_esp3d("Filename: %s", _filename.c_str());
|
||||||
|
//Name
|
||||||
|
if (_filename == "/") {
|
||||||
|
_name = "/";
|
||||||
|
} else {
|
||||||
|
_name.remove( 0, _name.lastIndexOf('/')+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//log_esp3d("Name: %s index: %d", _name.c_str(), _index);
|
||||||
|
set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i=0; (i < ESP_MAX_OPENHANDLE) && !set; i++) {
|
||||||
|
if (!tFile_handle[i]) {
|
||||||
|
tFile_handle[i] = *((File*)handle);
|
||||||
|
//filename
|
||||||
|
_filename = tFile_handle[i].name();
|
||||||
|
if (_isdir) {
|
||||||
|
if (!((_filename[_filename.length()-1] == '/') || (_filename == "/"))) {
|
||||||
|
_filename+="/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//name
|
||||||
|
if (_filename == "/") {
|
||||||
|
_name = "/";
|
||||||
|
} else {
|
||||||
|
_name = _filename;
|
||||||
|
if (_name[0] == '/') {
|
||||||
|
_name.remove( 0, 1);
|
||||||
|
}
|
||||||
|
int pos = _name.lastIndexOf('/');
|
||||||
|
if (pos != -1) {
|
||||||
|
_name.remove( 0, pos+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//size
|
||||||
|
_size = tFile_handle[i].size();
|
||||||
|
//time
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_lastwrite = tFile_handle[i].getLastWrite();
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_index = i;
|
||||||
|
//log_esp3d("Opening File at index %d",_index);
|
||||||
|
set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP_File::close()
|
||||||
|
{
|
||||||
|
if (_index != -1) {
|
||||||
|
if (_isdir) {
|
||||||
|
//log_esp3d("Closing Dir at index %d", _index);
|
||||||
|
tDir_handle[_index] = Dir();
|
||||||
|
_index = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//log_esp3d("Closing File at index %d", _index);
|
||||||
|
tFile_handle[_index].close();
|
||||||
|
//reopen if mode = write
|
||||||
|
//udate size + date
|
||||||
|
if (_iswritemode && !_isdir) {
|
||||||
|
File ftmp = LittleFS.open(_filename.c_str(), "r");
|
||||||
|
if (ftmp) {
|
||||||
|
_size = ftmp.size();
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_lastwrite = ftmp.getLastWrite();
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
ftmp.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//log_esp3d("Closing File at index %d",_index);
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File ESP_File::openNextFile()
|
||||||
|
{
|
||||||
|
if ((_index == -1) || !_isdir) {
|
||||||
|
log_esp3d("openNextFile failed");
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
if(tDir_handle[_index].next()) {
|
||||||
|
String name = tDir_handle[_index].fileName();
|
||||||
|
log_esp3d("Getting next file from %s", _filename.c_str());
|
||||||
|
log_esp3d("name :%s %s", name.c_str(), (tDir_handle[_index].isDirectory())?"isDir":"isFile");
|
||||||
|
String s = _filename;
|
||||||
|
if(s[s.length()-1]!='/')s+="/";
|
||||||
|
s+=name.c_str();
|
||||||
|
if (tDir_handle[_index].isFile()) {
|
||||||
|
ESP_File esptmp(name.c_str(), s.c_str(), false, tDir_handle[_index].fileSize()) ;
|
||||||
|
return esptmp;
|
||||||
|
} else {
|
||||||
|
log_esp3d("Found dir name: %s filename:%s",name.c_str(), s.c_str());
|
||||||
|
ESP_File esptmp = ESP_File(name.c_str(), s.c_str());
|
||||||
|
return esptmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //ESP_LITTLEFS_FILESYSTEM
|
308
esp3d/src/modules/filesystem/spiffs_esp32_filesystem.cpp
Normal file
308
esp3d/src/modules/filesystem/spiffs_esp32_filesystem.cpp
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
/*
|
||||||
|
spiffs_esp32_filesystem.cpp - ESP3D filesystem configuration class
|
||||||
|
|
||||||
|
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "../../include/esp3d_config.h"
|
||||||
|
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM) && defined(ARDUINO_ARCH_ESP32)
|
||||||
|
#include "esp_filesystem.h"
|
||||||
|
#include "../../core/genLinkedList.h"
|
||||||
|
#include <FS.h>
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
extern File tFile_handle[ESP_MAX_OPENHANDLE];
|
||||||
|
|
||||||
|
bool ESP_FileSystem::begin()
|
||||||
|
{
|
||||||
|
_started = SPIFFS.begin(true);
|
||||||
|
return _started;
|
||||||
|
}
|
||||||
|
void ESP_FileSystem::end()
|
||||||
|
{
|
||||||
|
_started = false;
|
||||||
|
SPIFFS.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ESP_FileSystem::totalBytes()
|
||||||
|
{
|
||||||
|
return SPIFFS.totalBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ESP_FileSystem::usedBytes()
|
||||||
|
{
|
||||||
|
return SPIFFS.usedBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * ESP_FileSystem::FilesystemName()
|
||||||
|
{
|
||||||
|
return "SPIFFS";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::format()
|
||||||
|
{
|
||||||
|
return SPIFFS.format();
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File ESP_FileSystem::open(const char* path, uint8_t mode)
|
||||||
|
{
|
||||||
|
//do some check
|
||||||
|
if(((strcmp(path,"/") == 0) && ((mode == ESP_FILE_WRITE) || (mode == ESP_FILE_APPEND))) || (strlen(path) == 0)) {
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
// path must start by '/'
|
||||||
|
if (path[0] != '/') {
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
//TODO add support if path = /DIR1/ <- with last /
|
||||||
|
File tmp = SPIFFS.open(path, (mode == ESP_FILE_READ)?FILE_READ:(mode == ESP_FILE_WRITE)?FILE_WRITE:FILE_APPEND);
|
||||||
|
ESP_File esptmp(&tmp, tmp.isDirectory(),(mode == ESP_FILE_READ)?false:true, path);
|
||||||
|
return esptmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::exists(const char* path)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
//root should always be there if started
|
||||||
|
if (strcmp(path, "/") == 0) {
|
||||||
|
return _started;
|
||||||
|
}
|
||||||
|
String spath = path;
|
||||||
|
spath.trim();
|
||||||
|
if (spath[spath.length()-1] == '/') {
|
||||||
|
if (spath!="/") {
|
||||||
|
spath.remove(spath.length()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = SPIFFS.exists(spath.c_str());
|
||||||
|
if (!res) {
|
||||||
|
String newpath = spath;
|
||||||
|
if (newpath[newpath.length()-1] != '/') {
|
||||||
|
newpath+="/";
|
||||||
|
}
|
||||||
|
newpath+=".";
|
||||||
|
//log_esp3d("Check %s", newpath.c_str());
|
||||||
|
res = SPIFFS.exists(newpath);
|
||||||
|
if (!res) {
|
||||||
|
ESP_File f = ESP_FileSystem::open(path, ESP_FILE_READ);
|
||||||
|
if (f) {
|
||||||
|
//Check directories
|
||||||
|
ESP_File sub = f.openNextFile();
|
||||||
|
if (sub) {
|
||||||
|
sub.close();
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::remove(const char *path)
|
||||||
|
{
|
||||||
|
return SPIFFS.remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::mkdir(const char *path)
|
||||||
|
{
|
||||||
|
//Use file named . to simulate directory
|
||||||
|
String p = path;
|
||||||
|
if (p[p.length()-1] != '/') {
|
||||||
|
p+="/";
|
||||||
|
}
|
||||||
|
p+=".";
|
||||||
|
//log_esp3d("Dir create : %s", p.c_str());
|
||||||
|
ESP_File f = open(p.c_str(), ESP_FILE_WRITE);
|
||||||
|
if (f) {
|
||||||
|
f.close();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::rmdir(const char *path)
|
||||||
|
{
|
||||||
|
String spath = path;
|
||||||
|
spath.trim();
|
||||||
|
if (spath[spath.length()-1] == '/') {
|
||||||
|
if (spath!="/") {
|
||||||
|
spath.remove(spath.length()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log_esp3d("Deleting : %s",spath.c_str());
|
||||||
|
File ftmp = SPIFFS.open(spath.c_str());
|
||||||
|
if (ftmp) {
|
||||||
|
File pfile = ftmp.openNextFile();
|
||||||
|
while (pfile) {
|
||||||
|
//log_esp3d("File: %s",pfile.name());
|
||||||
|
if (!SPIFFS.remove(pfile.name())) {
|
||||||
|
pfile.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pfile.close();
|
||||||
|
pfile = ftmp.openNextFile();
|
||||||
|
}
|
||||||
|
ftmp.close();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP_FileSystem::closeAll()
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < ESP_MAX_OPENHANDLE; i++) {
|
||||||
|
tFile_handle[i].close();
|
||||||
|
tFile_handle[i] = File();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File::ESP_File(void* handle, bool isdir, bool iswritemode, const char * path)
|
||||||
|
{
|
||||||
|
_isdir = isdir;
|
||||||
|
_dirlist = "";
|
||||||
|
_isfakedir = false;
|
||||||
|
_index = -1;
|
||||||
|
_filename = "";
|
||||||
|
_name = "";
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
memset (&_lastwrite,0,sizeof(time_t));
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_iswritemode = iswritemode;
|
||||||
|
_size = 0;
|
||||||
|
if (!handle) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
bool set =false;
|
||||||
|
for (uint8_t i=0; (i < ESP_MAX_OPENHANDLE) && !set; i++) {
|
||||||
|
if (!tFile_handle[i]) {
|
||||||
|
tFile_handle[i] = *((File*)handle);
|
||||||
|
//filename
|
||||||
|
_filename = tFile_handle[i].name();
|
||||||
|
|
||||||
|
//if root
|
||||||
|
if (_filename == "/") {
|
||||||
|
_filename = "/.";
|
||||||
|
}
|
||||||
|
if (_isdir) {
|
||||||
|
if (_filename[_filename.length()-1] != '.') {
|
||||||
|
if (_filename[_filename.length()-2] != '/') {
|
||||||
|
_filename+="/";
|
||||||
|
}
|
||||||
|
_filename+=".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//name
|
||||||
|
if (_filename == "/.") {
|
||||||
|
_name = "/";
|
||||||
|
} else {
|
||||||
|
_name = _filename;
|
||||||
|
if (_name.endsWith("/.")) {
|
||||||
|
_name.remove( _name.length() - 2,2);
|
||||||
|
_isfakedir = true;
|
||||||
|
_isdir = true;
|
||||||
|
}
|
||||||
|
if (_name[0] == '/') {
|
||||||
|
_name.remove( 0, 1);
|
||||||
|
}
|
||||||
|
int pos = _name.lastIndexOf('/');
|
||||||
|
if (pos != -1) {
|
||||||
|
_name.remove( 0, pos+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//size
|
||||||
|
_size = tFile_handle[i].size();
|
||||||
|
//time
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_lastwrite = tFile_handle[i].getLastWrite();
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_index = i;
|
||||||
|
//log_esp3d("Opening File at index %d",_index);
|
||||||
|
set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP_File::close()
|
||||||
|
{
|
||||||
|
if (_index != -1) {
|
||||||
|
//log_esp3d("Closing File at index %d", _index);
|
||||||
|
tFile_handle[_index].close();
|
||||||
|
//reopen if mode = write
|
||||||
|
//udate size + date
|
||||||
|
if (_iswritemode && !_isdir) {
|
||||||
|
File ftmp = SPIFFS.open(_filename.c_str());
|
||||||
|
if (ftmp) {
|
||||||
|
_size = ftmp.size();
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_lastwrite = ftmp.getLastWrite();
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
ftmp.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tFile_handle[_index] = File();
|
||||||
|
//log_esp3d("Closing File at index %d",_index);
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File ESP_File::openNextFile()
|
||||||
|
{
|
||||||
|
if ((_index == -1) || !_isdir) {
|
||||||
|
log_esp3d("openNextFile failed");
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
File tmp = tFile_handle[_index].openNextFile();
|
||||||
|
while (tmp) {
|
||||||
|
//log_esp3d("tmp name :%s %s", tmp.name(), (tmp.isDirectory())?"isDir":"isFile");
|
||||||
|
ESP_File esptmp(&tmp, tmp.isDirectory());
|
||||||
|
esptmp.close();
|
||||||
|
String sub = esptmp.filename();
|
||||||
|
sub.remove(0,_filename.length()-1);
|
||||||
|
int pos = sub.indexOf("/");
|
||||||
|
if (pos!=-1) {
|
||||||
|
//is subdir
|
||||||
|
sub = sub.substring(0,pos);
|
||||||
|
//log_esp3d("file name:%s name: %s %s sub:%s root:%s", esptmp.filename(), esptmp.name(), (esptmp.isDirectory())?"isDir":"isFile", sub.c_str(), _filename.c_str());
|
||||||
|
String tag = "*" + sub + "*";
|
||||||
|
//test if already in directory list
|
||||||
|
if (_dirlist.indexOf(tag) == -1) {//not in list so add it and return the info
|
||||||
|
_dirlist+= tag;
|
||||||
|
String fname = _filename.substring(0,_filename.length()-1) + sub + "/.";
|
||||||
|
//log_esp3d("Found dir name: %s filename:%s", sub.c_str(), fname.c_str());
|
||||||
|
esptmp = ESP_File(sub.c_str(), fname.c_str());
|
||||||
|
return esptmp;
|
||||||
|
} else { //already in list so ignore it
|
||||||
|
//log_esp3d("Dir name: %s already in list", sub.c_str());
|
||||||
|
tmp = tFile_handle[_index].openNextFile();
|
||||||
|
}
|
||||||
|
} else { //is file
|
||||||
|
//log_esp3d("file name:%s name: %s %s sub:%s root:%s", esptmp.filename(), esptmp.name(), (esptmp.isDirectory())?"isDir":"isFile", sub.c_str(), _filename.c_str());
|
||||||
|
if (sub == ".") {
|
||||||
|
//log_esp3d("Dir tag, ignore it");
|
||||||
|
tmp = tFile_handle[_index].openNextFile();
|
||||||
|
} else {
|
||||||
|
return esptmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ESP_SPIFFS_FILESYSTEM
|
353
esp3d/src/modules/filesystem/spiffs_esp8266_filesystem.cpp
Normal file
353
esp3d/src/modules/filesystem/spiffs_esp8266_filesystem.cpp
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
/*
|
||||||
|
spiffs_8266_filesystem.cpp - ESP3D filesystem configuration class
|
||||||
|
|
||||||
|
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "../../include/esp3d_config.h"
|
||||||
|
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM) && defined (ARDUINO_ARCH_ESP8266)
|
||||||
|
#include "esp_filesystem.h"
|
||||||
|
#include "../../core/genLinkedList.h"
|
||||||
|
#include <FS.h>
|
||||||
|
Dir tDir_handle[ESP_MAX_OPENHANDLE];
|
||||||
|
extern File tFile_handle[ESP_MAX_OPENHANDLE];
|
||||||
|
|
||||||
|
bool ESP_FileSystem::begin()
|
||||||
|
{
|
||||||
|
_started = SPIFFS.begin();
|
||||||
|
return _started;
|
||||||
|
}
|
||||||
|
void ESP_FileSystem::end()
|
||||||
|
{
|
||||||
|
_started = false;
|
||||||
|
SPIFFS.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ESP_FileSystem::totalBytes()
|
||||||
|
{
|
||||||
|
fs::FSInfo info;
|
||||||
|
SPIFFS.info (info);
|
||||||
|
return info.totalBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ESP_FileSystem::usedBytes()
|
||||||
|
{
|
||||||
|
fs::FSInfo info;
|
||||||
|
SPIFFS.info (info);
|
||||||
|
return info.usedBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * ESP_FileSystem::FilesystemName()
|
||||||
|
{
|
||||||
|
return "SPIFFS";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::format()
|
||||||
|
{
|
||||||
|
return SPIFFS.format();
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File ESP_FileSystem::open(const char* path, uint8_t mode)
|
||||||
|
{
|
||||||
|
//do some check
|
||||||
|
if(((strcmp(path,"/") == 0) && ((mode == ESP_FILE_WRITE) || (mode == ESP_FILE_APPEND))) || (strlen(path) == 0)) {
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
// path must start by '/'
|
||||||
|
if (path[0] != '/') {
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
File ftmp = SPIFFS.open(path, (mode == ESP_FILE_READ)?"r":(mode == ESP_FILE_WRITE)?"w":"a");
|
||||||
|
if(ftmp) {
|
||||||
|
//log_esp3d("Success openening: %s", path);
|
||||||
|
ESP_File esptmp(&ftmp, false,(mode == ESP_FILE_READ)?false:true, path);
|
||||||
|
return esptmp;
|
||||||
|
}
|
||||||
|
(void)mode;
|
||||||
|
Dir dtmp = SPIFFS.openDir(path);
|
||||||
|
ESP_File esptmp(&dtmp, true, false, path);
|
||||||
|
return esptmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::exists(const char* path)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
//root should always be there if started
|
||||||
|
if (strcmp(path, "/") == 0) {
|
||||||
|
return _started;
|
||||||
|
}
|
||||||
|
String spath = path;
|
||||||
|
spath.trim();
|
||||||
|
if (spath[spath.length()-1] == '/') {
|
||||||
|
if (spath!="/") {
|
||||||
|
spath.remove(spath.length()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = SPIFFS.exists(spath.c_str());
|
||||||
|
if (!res) {
|
||||||
|
String newpath = spath;
|
||||||
|
if (newpath[newpath.length()-1] != '/') {
|
||||||
|
newpath+="/";
|
||||||
|
}
|
||||||
|
newpath+=".";
|
||||||
|
//log_esp3d("Check %s", newpath.c_str());
|
||||||
|
res = SPIFFS.exists(newpath);
|
||||||
|
if (!res) {
|
||||||
|
ESP_File f = ESP_FileSystem::open(path, ESP_FILE_READ);
|
||||||
|
if (f) {
|
||||||
|
//Check directories
|
||||||
|
ESP_File sub = f.openNextFile();
|
||||||
|
if (sub) {
|
||||||
|
sub.close();
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::remove(const char *path)
|
||||||
|
{
|
||||||
|
return SPIFFS.remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::mkdir(const char *path)
|
||||||
|
{
|
||||||
|
//Use file named . to simulate directory
|
||||||
|
String p = path;
|
||||||
|
if (p[p.length()-1] != '/') {
|
||||||
|
p+="/";
|
||||||
|
}
|
||||||
|
p+=".";
|
||||||
|
//log_esp3d("Dir create : %s", p.c_str());
|
||||||
|
ESP_File f = open(p.c_str(), ESP_FILE_WRITE);
|
||||||
|
if (f) {
|
||||||
|
f.close();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP_FileSystem::rmdir(const char *path)
|
||||||
|
{
|
||||||
|
Dir dtmp = SPIFFS.openDir(path);
|
||||||
|
while (dtmp.next()) {
|
||||||
|
if (!SPIFFS.remove(dtmp.fileName().c_str())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP_FileSystem::closeAll()
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < ESP_MAX_OPENHANDLE; i++) {
|
||||||
|
tDir_handle[i] = Dir();
|
||||||
|
tFile_handle[i].close();
|
||||||
|
tFile_handle[i] = File();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File::ESP_File(void* handle, bool isdir, bool iswritemode, const char * path)
|
||||||
|
{
|
||||||
|
_isdir = isdir;
|
||||||
|
_dirlist = "";
|
||||||
|
_isfakedir = false;
|
||||||
|
_index = -1;
|
||||||
|
_filename = "";
|
||||||
|
_name = "";
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
memset (&_lastwrite,0,sizeof(time_t));
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_iswritemode = iswritemode;
|
||||||
|
_size = 0;
|
||||||
|
if (!handle) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
bool set =false;
|
||||||
|
if (_isdir) {
|
||||||
|
for (uint8_t i=0; (i < ESP_MAX_OPENHANDLE) && !set; i++) {
|
||||||
|
if (tDir_handle[i].fileName().length() == 0) {
|
||||||
|
tDir_handle[i] = *((Dir *)handle);
|
||||||
|
_index = i;
|
||||||
|
//Path = filename
|
||||||
|
if (path) {
|
||||||
|
_filename = path;
|
||||||
|
if (_filename == "/") {
|
||||||
|
_filename = "/.";
|
||||||
|
}
|
||||||
|
if (_filename[_filename.length()-1] != '.') {
|
||||||
|
if (_filename[_filename.length()-2] != '/') {
|
||||||
|
_filename+="/";
|
||||||
|
}
|
||||||
|
_filename+=".";
|
||||||
|
}
|
||||||
|
//log_esp3d("Filename: %s", _filename.c_str());
|
||||||
|
//Name
|
||||||
|
if (_filename == "/.") {
|
||||||
|
_name = "/";
|
||||||
|
} else {
|
||||||
|
_name = _filename;
|
||||||
|
if (_name.length() >=2) {
|
||||||
|
if ((_name[_name.length() - 1] == '.') && (_name[_name.length() - 2] == '/')) {
|
||||||
|
_name.remove( _name.length() - 2,2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_name.remove( 0, _name.lastIndexOf('/')+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//log_esp3d("Name: %s index: %d", _name.c_str(), _index);
|
||||||
|
set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (uint8_t i=0; (i < ESP_MAX_OPENHANDLE) && !set; i++) {
|
||||||
|
if (!tFile_handle[i]) {
|
||||||
|
tFile_handle[i] = *((File*)handle);
|
||||||
|
//filename
|
||||||
|
_filename = tFile_handle[i].name();
|
||||||
|
|
||||||
|
//if root
|
||||||
|
if (_filename == "/") {
|
||||||
|
_filename = "/.";
|
||||||
|
}
|
||||||
|
if (_isdir) {
|
||||||
|
if (_filename[_filename.length()-1] != '.') {
|
||||||
|
if (_filename[_filename.length()-2] != '/') {
|
||||||
|
_filename+="/";
|
||||||
|
}
|
||||||
|
_filename+=".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//name
|
||||||
|
if (_filename == "/.") {
|
||||||
|
_name = "/";
|
||||||
|
} else {
|
||||||
|
_name = _filename;
|
||||||
|
if (_name.endsWith("/.")) {
|
||||||
|
_name.remove( _name.length() - 2,2);
|
||||||
|
_isfakedir = true;
|
||||||
|
_isdir = true;
|
||||||
|
}
|
||||||
|
if (_name[0] == '/') {
|
||||||
|
_name.remove( 0, 1);
|
||||||
|
}
|
||||||
|
int pos = _name.lastIndexOf('/');
|
||||||
|
if (pos != -1) {
|
||||||
|
_name.remove( 0, pos+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//size
|
||||||
|
_size = tFile_handle[i].size();
|
||||||
|
//time
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_lastwrite = tFile_handle[i].getLastWrite();
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_index = i;
|
||||||
|
//log_esp3d("Opening File at index %d",_index);
|
||||||
|
set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP_File::close()
|
||||||
|
{
|
||||||
|
if (_index != -1) {
|
||||||
|
if (_isdir && !_isfakedir) {
|
||||||
|
//log_esp3d("Closing Dir at index %d", _index);
|
||||||
|
tDir_handle[_index] = Dir();
|
||||||
|
_index = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//log_esp3d("Closing File at index %d", _index);
|
||||||
|
tFile_handle[_index].close();
|
||||||
|
//reopen if mode = write
|
||||||
|
//udate size + date
|
||||||
|
if (_iswritemode && !_isdir) {
|
||||||
|
File ftmp = SPIFFS.open(_filename.c_str(), "r");
|
||||||
|
if (ftmp) {
|
||||||
|
_size = ftmp.size();
|
||||||
|
#ifdef FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
_lastwrite = ftmp.getLastWrite();
|
||||||
|
#endif //FILESYSTEM_TIMESTAMP_FEATURE
|
||||||
|
ftmp.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//log_esp3d("Closing File at index %d",_index);
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_File ESP_File::openNextFile()
|
||||||
|
{
|
||||||
|
if ((_index == -1) || !_isdir) {
|
||||||
|
log_esp3d("openNextFile failed");
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
if(tDir_handle[_index].next()) {
|
||||||
|
//log_esp3d("Getting next file from %s", _filename.c_str());
|
||||||
|
File tmp = tDir_handle[_index].openFile("r");
|
||||||
|
while (tmp) {
|
||||||
|
ESP_File esptmp(&tmp);
|
||||||
|
esptmp.close();
|
||||||
|
String sub = esptmp.filename();
|
||||||
|
sub.remove(0,_filename.length()-1);
|
||||||
|
int pos = sub.indexOf("/");
|
||||||
|
if (pos!=-1) {
|
||||||
|
//is subdir
|
||||||
|
sub = sub.substring(0,pos);
|
||||||
|
//log_esp3d("file name:%s name: %s %s sub:%s root:%s", esptmp.filename(), esptmp.name(), (esptmp.isDirectory())?"isDir":"isFile", sub.c_str(), _filename.c_str());
|
||||||
|
String tag = "*" + sub + "*";
|
||||||
|
//test if already in directory list
|
||||||
|
if (_dirlist.indexOf(tag) == -1) {//not in list so add it and return the info
|
||||||
|
_dirlist+= tag;
|
||||||
|
String fname = _filename.substring(0,_filename.length()-1) + sub + "/.";
|
||||||
|
//log_esp3d("Found dir name: %s filename:%s", sub.c_str(), fname.c_str());
|
||||||
|
esptmp = ESP_File(sub.c_str(), fname.c_str());
|
||||||
|
return esptmp;
|
||||||
|
} else { //already in list so ignore it
|
||||||
|
//log_esp3d("Dir name: %s already in list", sub.c_str());
|
||||||
|
if(!tDir_handle[_index].next()) {
|
||||||
|
return ESP_File();
|
||||||
|
} else {
|
||||||
|
tmp = tDir_handle[_index].openFile("r");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { //is file
|
||||||
|
//log_esp3d("file name:%s name: %s %s sub:%s root:%s", esptmp.filename(), esptmp.name(), (esptmp.isDirectory())?"isDir":"isFile", sub.c_str(), _filename.c_str());
|
||||||
|
if (sub == ".") {
|
||||||
|
//log_esp3d("Dir tag, ignore it");
|
||||||
|
if(!tDir_handle[_index].next()) {
|
||||||
|
return ESP_File();
|
||||||
|
} else {
|
||||||
|
tmp = tDir_handle[_index].openFile("r");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return esptmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_File();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ESP_SPIFFS_FILESYSTEM
|
@ -217,8 +217,9 @@ bool NetConfig::begin()
|
|||||||
bool res = false;
|
bool res = false;
|
||||||
//clear everything
|
//clear everything
|
||||||
end();
|
end();
|
||||||
|
int8_t espMode =Settings_ESP3D::read_byte(ESP_RADIO_MODE);
|
||||||
ESP3DOutput output(ESP_ALL_CLIENTS);
|
ESP3DOutput output(ESP_ALL_CLIENTS);
|
||||||
output.printMSG("Starting Network");
|
if (espMode != NO_NETWORK)output.printMSG("Starting Network");
|
||||||
//setup events
|
//setup events
|
||||||
if(!_events_registered) {
|
if(!_events_registered) {
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
@ -235,7 +236,6 @@ bool NetConfig::begin()
|
|||||||
}
|
}
|
||||||
//Get hostname
|
//Get hostname
|
||||||
_hostname = Settings_ESP3D::read_string(ESP_HOSTNAME);
|
_hostname = Settings_ESP3D::read_string(ESP_HOSTNAME);
|
||||||
int8_t espMode =Settings_ESP3D::read_byte(ESP_RADIO_MODE);
|
|
||||||
_mode = espMode;
|
_mode = espMode;
|
||||||
if (espMode == NO_NETWORK) {
|
if (espMode == NO_NETWORK) {
|
||||||
ESP3DGlobalOutput::display_IP();
|
ESP3DGlobalOutput::display_IP();
|
||||||
|
75
test/fatwrite/fatwrite.ino
Normal file
75
test/fatwrite/fatwrite.ino
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* full system / not flat fs
|
||||||
|
* directory mode supported
|
||||||
|
* parsing only File variables
|
||||||
|
* directory creation: yes
|
||||||
|
* parsing: one level at once
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <FS.h>
|
||||||
|
#include "FFat.h"
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(5000);
|
||||||
|
Serial.printf("Format()\n");
|
||||||
|
if (!FFat.format()) {
|
||||||
|
Serial.printf("Unable to format(), aborting\n");
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
Serial.printf("begin()\n");
|
||||||
|
if (!FFat.begin()) {
|
||||||
|
Serial.printf("Unable to begin(), aborting\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File f = FFat.open("/test.txt","w");
|
||||||
|
if (f){
|
||||||
|
Serial.printf("/test.txt created\n");
|
||||||
|
f.print("hello world");
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("/test.txt creation failed\n");
|
||||||
|
}
|
||||||
|
if (FFat.mkdir("/myDir")){
|
||||||
|
Serial.printf("/myDir/ created\n");
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir directory creation failed\n");
|
||||||
|
}
|
||||||
|
if (FFat.mkdir("/myDir2")){
|
||||||
|
Serial.printf("/myDir2/ created\n");
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir2 directory creation failed\n");
|
||||||
|
}
|
||||||
|
f = FFat.open("/myDir/test2.txt","w");
|
||||||
|
if (f){
|
||||||
|
Serial.printf("/myDir/test2.txt created\n");
|
||||||
|
f.print("hello world");
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir/test.txt creation failed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
File root = FFat.open("/");
|
||||||
|
uint8_t nbf = 0;
|
||||||
|
uint8_t nbd = 0;
|
||||||
|
File dir = root.openNextFile();
|
||||||
|
while (dir) {
|
||||||
|
String filename = dir.name();
|
||||||
|
size_t fileSize = dir.size();
|
||||||
|
if (dir.isDirectory())
|
||||||
|
{
|
||||||
|
Serial.printf("Dir %s\n",filename.c_str() );
|
||||||
|
nbd++;
|
||||||
|
}
|
||||||
|
if (!dir.isDirectory())
|
||||||
|
{
|
||||||
|
Serial.printf("File %s %d\n",filename.c_str(), fileSize );
|
||||||
|
nbf++;
|
||||||
|
}
|
||||||
|
dir = root.openNextFile();
|
||||||
|
}
|
||||||
|
Serial.printf("NB Dir: %d, NB File: %d\n",nbd, nbf);
|
||||||
|
delay(5000);
|
||||||
|
}
|
67
test/littlefswrite/littlefswrite.ino
Normal file
67
test/littlefswrite/littlefswrite.ino
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include <LittleFS.h>
|
||||||
|
/*
|
||||||
|
* full system / not flat
|
||||||
|
* directory mode supported
|
||||||
|
* parsing need Dir and File variables
|
||||||
|
* directory creation / query no `/` at the end
|
||||||
|
* parsing: one level at once
|
||||||
|
*/
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(5000);
|
||||||
|
if (!LittleFS.format()) {
|
||||||
|
Serial.printf("Unable to format(), aborting\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!LittleFS.begin()) {
|
||||||
|
Serial.printf("Unable to begin(), aborting\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File f = LittleFS.open("/test.txt","w");
|
||||||
|
if (f){
|
||||||
|
Serial.printf("/test.txt created\n");
|
||||||
|
f.write("hello world", strlen("hello world"));
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("/test.txt creation failed\n");
|
||||||
|
}
|
||||||
|
if (LittleFS.mkdir("/myDir")){
|
||||||
|
if (LittleFS.mkdir("/myDir/mysubDir")){}
|
||||||
|
f = LittleFS.open("/myDir/test2.txt","w");
|
||||||
|
if (f){
|
||||||
|
Serial.printf("/myDir/test2.txt created\n");
|
||||||
|
f.write("hello world", strlen("hello world"));
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir/test.txt creation failed\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir directory creation failed\n");
|
||||||
|
}
|
||||||
|
if (!LittleFS.mkdir("/myDir/mysubDir/mysubdir2")){
|
||||||
|
Serial.printf("/myDir/mysubDir/mysubdir2 directory creation failed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
Dir dir = LittleFS.openDir("/");
|
||||||
|
uint8_t nbf = 0;
|
||||||
|
uint8_t nbd = 0;
|
||||||
|
while (dir.next()) {
|
||||||
|
String fileName = dir.fileName();
|
||||||
|
size_t fileSize = dir.fileSize();
|
||||||
|
if (dir.isDirectory())
|
||||||
|
{
|
||||||
|
Serial.printf("Dir %s\n",fileName.c_str() );
|
||||||
|
nbd++;
|
||||||
|
}
|
||||||
|
if (dir.isFile())
|
||||||
|
{
|
||||||
|
Serial.printf("File %s %d\n",fileName.c_str(), fileSize );
|
||||||
|
nbf++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.printf("NB Dir: %d, NB File: %d\n",nbd, nbf);
|
||||||
|
delay(5000);
|
||||||
|
}
|
84
test/spiffs32write/spiffs32write.ino
Normal file
84
test/spiffs32write/spiffs32write.ino
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* full system / flat fs
|
||||||
|
* directory mode not supported
|
||||||
|
* parsing only File variable
|
||||||
|
* directory creation: no, need fake dir using . file
|
||||||
|
* parsing: all levels at once
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <FS.h>
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(5000);
|
||||||
|
Serial.printf("Format()\n");
|
||||||
|
if (!SPIFFS.format()) {
|
||||||
|
Serial.printf("Unable to format(), aborting\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Serial.printf("begin()\n");
|
||||||
|
if (!SPIFFS.begin()) {
|
||||||
|
Serial.printf("Unable to begin(), aborting\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File f = SPIFFS.open("/test.txt","w");
|
||||||
|
if (f){
|
||||||
|
Serial.printf("/test.txt created\n");
|
||||||
|
f.print("hello world");
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("/test.txt creation failed\n");
|
||||||
|
}
|
||||||
|
if (SPIFFS.mkdir("/myDir")){
|
||||||
|
Serial.printf("/myDir/ created\n");
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir directory creation failed\n");
|
||||||
|
}
|
||||||
|
if (SPIFFS.mkdir("/myDir2")){
|
||||||
|
Serial.printf("/myDir2/ created\n");
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir2 directory creation failed\n");
|
||||||
|
}
|
||||||
|
f = SPIFFS.open("/myDir/test2.txt","w");
|
||||||
|
if (f){
|
||||||
|
Serial.printf("/myDir/test2.txt created\n");
|
||||||
|
f.print("hello world");
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir/test.txt creation failed\n");
|
||||||
|
}
|
||||||
|
f = SPIFFS.open("/myDir/mysubdir/.","w");
|
||||||
|
if (f) {
|
||||||
|
Serial.printf("/myDir/mysubdir/. created\n");
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir/mysubdir/. creation failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
File root = SPIFFS.open("/");
|
||||||
|
uint8_t nbf = 0;
|
||||||
|
uint8_t nbd = 0;
|
||||||
|
File dir = root.openNextFile();
|
||||||
|
while (dir) {
|
||||||
|
String filename = dir.name();
|
||||||
|
size_t fileSize = dir.size();
|
||||||
|
if (dir.isDirectory())
|
||||||
|
{
|
||||||
|
Serial.printf("Dir %s\n",filename.c_str() );
|
||||||
|
nbd++;
|
||||||
|
}
|
||||||
|
if (!dir.isDirectory())
|
||||||
|
{
|
||||||
|
Serial.printf("File %s %d\n",filename.c_str(), fileSize );
|
||||||
|
nbf++;
|
||||||
|
}
|
||||||
|
dir = root.openNextFile();
|
||||||
|
}
|
||||||
|
Serial.printf("NB Dir: %d, NB File: %d\n",nbd, nbf);
|
||||||
|
delay(5000);
|
||||||
|
}
|
76
test/spiffs8266write/spiffs8266write.ino
Normal file
76
test/spiffs8266write/spiffs8266write.ino
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* full system / flat fs
|
||||||
|
* directory mode not supported ?
|
||||||
|
* parsing need Dir and File variables
|
||||||
|
* directory creation: no, need fake dir using . file
|
||||||
|
* parsing: all levels at once
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <FS.h>
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(5000);
|
||||||
|
Serial.printf("Format()\n");
|
||||||
|
// if (!SPIFFS.format()) {
|
||||||
|
// Serial.printf("Unable to format(), aborting\n");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
Serial.printf("begin()\n");
|
||||||
|
if (!SPIFFS.begin()) {
|
||||||
|
Serial.printf("Unable to begin(), aborting\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File f = SPIFFS.open("/test.txt","w");
|
||||||
|
if (f){
|
||||||
|
Serial.printf("/test.txt created\n");
|
||||||
|
f.write("hello world", strlen("hello world"));
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("/test.txt creation failed\n");
|
||||||
|
}
|
||||||
|
if (SPIFFS.mkdir("/myDir")){
|
||||||
|
Serial.printf("/myDir/ created\n");
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir directory creation failed\n");
|
||||||
|
}
|
||||||
|
f = SPIFFS.open("/myDir/test2.txt","w");
|
||||||
|
if (f){
|
||||||
|
Serial.printf("/myDir/test2.txt created\n");
|
||||||
|
f.write("hello world", strlen("hello world"));
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir/test.txt creation failed\n");
|
||||||
|
}
|
||||||
|
f = SPIFFS.open("/myDir/mysubdir/.","w");
|
||||||
|
if (f) {
|
||||||
|
Serial.printf("/myDir/mysubdir/. created\n");
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("/myDir/mysubdir/. creation failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
Dir dir = SPIFFS.openDir("/");
|
||||||
|
uint8_t nbf = 0;
|
||||||
|
uint8_t nbd = 0;
|
||||||
|
while (dir.next()) {
|
||||||
|
String fileName = dir.fileName();
|
||||||
|
size_t fileSize = dir.fileSize();
|
||||||
|
if (dir.isDirectory())
|
||||||
|
{
|
||||||
|
Serial.printf("Dir %s\n",fileName.c_str() );
|
||||||
|
nbd++;
|
||||||
|
}
|
||||||
|
if (dir.isFile())
|
||||||
|
{
|
||||||
|
Serial.printf("File %s %d\n",fileName.c_str(), fileSize );
|
||||||
|
nbf++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.printf("NB Dir: %d, NB File: %d\n",nbd, nbf);
|
||||||
|
delay(5000);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user