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:
Luc 2019-09-17 13:53:53 +08:00
parent bda6c23446
commit b818022f5e
18 changed files with 1702 additions and 569 deletions

View File

@ -177,6 +177,10 @@ Get will give type and settings only, not the protected T1/T2
* List ESP Filesystem
[ESP720]<Root> pwd=<admin password>
* Action on ESP Filesystem
rmdir / remove / mkdir / exists
[ESP730]<Action>=<path> pwd=<admin password>
* FW Informations
[ESP800]<plain> pwd=<admin password>

View File

@ -108,8 +108,8 @@
//FILESYSTEM_FEATURE: to host some files on flash
//ESP_SPIFFS_FILESYSTEM 0
//ESP_FAT_FILESYSTEM 1
//ESP_LITTLEFS_FILESYSTEM 2 //Not Yet implemented
#define FILESYSTEM_FEATURE ESP_SPIFFS_FILESYSTEM
//ESP_LITTLEFS_FILESYSTEM 2
#define FILESYSTEM_FEATURE ESP_FAT_FILESYSTEM
//DIRECT_PIN_FEATURE: allow to access pin using ESP201 command
#define DIRECT_PIN_FEATURE

View File

@ -453,6 +453,12 @@ bool Commands::execute_internal_command (int cmd, const char* cmd_params, level_
case 720:
response = ESP720(cmd_params, auth_type, output);
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
//Get fw version firmare target and fw version

View File

@ -109,6 +109,7 @@ public:
#if defined(FILESYSTEM_FEATURE)
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 ESP730(const char* cmd_params, level_authenticate_type auth_level, ESP3DOutput * output);
#endif //FILESYSTEM_FEATURE
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);

View 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

View File

@ -88,5 +88,8 @@
#if FILESYSTEM_FEATURE == ESP_FAT_FILESYSTEM && defined( ARDUINO_ARCH_ESP8266)
#error Fat FS is not available in ESP8266
#endif
#if FILESYSTEM_FEATURE == ESP_LITTLEFS_FILESYSTEM && defined( ARDUINO_ARCH_ESP32)
#error LittleFS is not available in ESP32
#endif
#endif //SANITY_ESP3D_H

View File

@ -1,3 +1,6 @@
#include "../../include/esp3d_config.h"
#if defined (DISPLAY_DEVICE) && (DISPLAY_UI_TYPE == UI_TYPE_ADVANCED)
extern "C" {
#include "lvgl.h"
#ifndef LV_ATTRIBUTE_MEM_ALIGN
@ -627,3 +630,7 @@ lv_img_dsc_t esplogo = {
.header.cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED,
.data = esplogo_map,
};
};
#endif //defined (DISPLAY_DEVICE) && (DISPLAY_UI_TYPE == UI_TYPE_ADVANCED)

View File

@ -25,23 +25,13 @@
#endif //FILESYSTEM_TIMESTAMP_FEATURE
#include <FS.h>
#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>
#endif //ARDUINO_ARCH_ESP32
#define ESP_MAX_OPENHANDLE 4
File tFile_handle[ESP_MAX_OPENHANDLE];
#ifdef ARDUINO_ARCH_ESP8266
#if (FILESYSTEM_FEATURE == ESP_SPIFFS_FILESYSTEM)
Dir tDir_handle[ESP_MAX_OPENHANDLE];
#endif //ESP_SPIFFS_FILESYSTEM
#endif //ARDUINO_ARCH_ESP8266
bool ESP_FileSystem::_started = false;
//constructor
ESP_FileSystem::ESP_FileSystem()
@ -69,76 +59,20 @@ String & ESP_FileSystem::formatBytes (uint64_t bytes)
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 flashsize = 0;
#if defined (ARDUINO_ARCH_ESP8266)
flashsize = ESP.getFlashChipSize();
//if higher than 1MB take out SPIFFS
if (flashsize > 1024 * 1024) {
if (flashsize <= 1024 * 1024) {
flashsize = (1024 * 1024)-ESP.getSketchSize()-1024;
} else {
fs::FSInfo info;
SPIFFS.info (info);
flashsize = flashsize - ESP.getSketchSize()-info.totalBytes-1024;
flashsize = flashsize - ESP.getSketchSize()-totalBytes()-1024;
//max OTA partition is 1019Kb
if (flashsize > 1024 * 1024) {
flashsize = (1024 * 1024) - 1024;
}
}
#endif //ARDUINO_ARCH_ESP8266
#if defined (ARDUINO_ARCH_ESP32)
@ -155,252 +89,7 @@ size_t ESP_FileSystem::max_update_size()
return flashsize;
}
const char * ESP_FileSystem::FilesystemName()
{
#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)
ESP_File::ESP_File(const char * name, const char * filename, bool isdir, size_t size)
{
_isdir = isdir;
_dirlist = "";
@ -412,250 +101,7 @@ ESP_File::ESP_File(const char * name, const char * filename, bool isdir)
memset (&_lastwrite,0,sizeof(time_t));
#endif //FILESYSTEM_TIMESTAMP_FEATURE
_iswritemode = false;
_size = 0;
}
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
_size = size;
}
ESP_File::~ESP_File()

View File

@ -28,11 +28,13 @@
#define ESP_FILE_WRITE 1
#define ESP_FILE_APPEND 2
#define ESP_MAX_OPENHANDLE 4
class ESP_File
{
public:
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();
operator bool() const;
bool isDirectory();
@ -86,6 +88,7 @@ public:
static bool rmdir(const char *path);
static void closeAll();
private:
static bool _started;
};

View 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

View 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

View 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

View 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

View File

@ -217,8 +217,9 @@ bool NetConfig::begin()
bool res = false;
//clear everything
end();
int8_t espMode =Settings_ESP3D::read_byte(ESP_RADIO_MODE);
ESP3DOutput output(ESP_ALL_CLIENTS);
output.printMSG("Starting Network");
if (espMode != NO_NETWORK)output.printMSG("Starting Network");
//setup events
if(!_events_registered) {
#ifdef ARDUINO_ARCH_ESP8266
@ -235,7 +236,6 @@ bool NetConfig::begin()
}
//Get hostname
_hostname = Settings_ESP3D::read_string(ESP_HOSTNAME);
int8_t espMode =Settings_ESP3D::read_byte(ESP_RADIO_MODE);
_mode = espMode;
if (espMode == NO_NETWORK) {
ESP3DGlobalOutput::display_IP();

View 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);
}

View 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);
}

View 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);
}

View 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);
}