1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Remove SPIFFS wrapper

This commit is contained in:
Ivan Grokhotkov 2015-05-23 10:13:59 +03:00
parent 8bd0ad4653
commit db1e033186
15 changed files with 0 additions and 1997 deletions

View File

@ -209,7 +209,6 @@ void loop(void);
#include "WString.h"
#include "HardwareSerial.h"
#include "FileSystem.h"
#include "Esp.h"
#include "debug.h"

View File

@ -1,388 +0,0 @@
/*
FileSystem.cpp - SPIFS implementation for esp8266
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
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 "FileSystem.h"
#include "Arduino.h"
#include "spiffs/spiffs_esp8266.h"
// These addresses and sizes are defined in the linker script.
// For each flash memory size there is a linker script variant
// which sets spiffs location and size.
extern "C" uint32_t _SPIFFS_start;
extern "C" uint32_t _SPIFFS_end;
extern "C" uint32_t _SPIFFS_page;
extern "C" uint32_t _SPIFFS_block;
static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst);
static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src);
static s32_t api_spiffs_erase(u32_t addr, u32_t size);
FSClass FS((uint32_t) &_SPIFFS_start, (uint32_t) &_SPIFFS_end, (uint32_t) &_SPIFFS_page, (uint32_t) &_SPIFFS_block, 4);
FSClass::FSClass(uint32_t beginAddress, uint32_t endAddress, uint32_t pageSize, uint32_t blockSize, uint32_t maxOpenFiles)
: _beginAddress(beginAddress)
, _endAddress(endAddress)
, _pageSize(pageSize)
, _blockSize(blockSize)
, _maxOpenFiles(maxOpenFiles)
, _fs({0})
{
}
int FSClass::_mountInternal(){
if (_beginAddress == 0 || _beginAddress >= _endAddress){
SPIFFS_API_DBG_E("Can't start file system, wrong address\r\n");
return SPIFFS_ERR_NOT_CONFIGURED;
}
if(_pageSize == 0) _pageSize = 256;
if(_blockSize == 0) _blockSize = 4096;
spiffs_config cfg = {0};
cfg.phys_addr = _beginAddress;
cfg.phys_size = _endAddress - _beginAddress;
cfg.phys_erase_block = INTERNAL_FLASH_SECTOR_SIZE;
cfg.log_block_size = _blockSize;
cfg.log_page_size = _pageSize;
cfg.hal_read_f = api_spiffs_read;
cfg.hal_write_f = api_spiffs_write;
cfg.hal_erase_f = api_spiffs_erase;
SPIFFS_API_DBG_V("FSClass::_mountInternal: start:%x, size:%d Kb\n", cfg.phys_addr, cfg.phys_size / 1024);
_work.reset(new uint8_t[2*_pageSize]);
_fdsSize = 32 * _maxOpenFiles;
_fds.reset(new uint8_t[_fdsSize]);
_cacheSize = (32 + _pageSize) * _maxOpenFiles;
_cache.reset(new uint8_t[_cacheSize]);
s32_t res = SPIFFS_mount(&_fs,
&cfg,
_work.get(),
_fds.get(),
_fdsSize,
_cache.get(),
_cacheSize,
NULL);
SPIFFS_API_DBG_V("FSClass::_mountInternal: %d\n", res);
return res;
}
bool FSClass::mount() {
if(SPIFFS_mounted(&_fs))
return true;
int res = _mountInternal();
if(res != SPIFFS_OK){
int formated = SPIFFS_format(&_fs);
if(formated != SPIFFS_OK)
return false;
res = _mountInternal();
}
return (res == SPIFFS_OK);
}
// TODO: need to invalidate open file objects
void FSClass::unmount() {
if(SPIFFS_mounted(&_fs))
SPIFFS_unmount(&_fs);
}
bool FSClass::format() {
if(!SPIFFS_mounted(&_fs)){
_mountInternal();
}
SPIFFS_unmount(&_fs);
int formated = SPIFFS_format(&_fs);
if(formated != SPIFFS_OK)
return false;
return (_mountInternal() == SPIFFS_OK);
}
bool FSClass::check() {
return SPIFFS_check(&_fs) == SPIFFS_OK;
}
bool FSClass::exists(char *filename) {
spiffs_stat stat = {0};
if (SPIFFS_stat(&_fs, filename, &stat) < 0)
return false;
return stat.name[0] != '\0';
}
bool FSClass::create(char *filepath){
return SPIFFS_creat(&_fs, filepath, 0) == SPIFFS_OK;
}
bool FSClass::remove(char *filepath){
return SPIFFS_remove(&_fs, filepath) == SPIFFS_OK;
}
bool FSClass::rename(char *filename, char *newname) {
return SPIFFS_rename(&_fs, filename, newname) == SPIFFS_OK;
}
size_t FSClass::totalBytes(){
u32_t totalBytes;
u32_t usedBytes;
if(SPIFFS_info(&_fs, &totalBytes, &usedBytes) == SPIFFS_OK)
return totalBytes;
return 0;
}
size_t FSClass::usedBytes(){
u32_t totalBytes;
u32_t usedBytes;
if(SPIFFS_info(&_fs, &totalBytes, &usedBytes) == SPIFFS_OK)
return usedBytes;
return 0;
}
FSFile FSClass::open(char *filename, uint8_t mode) {
if(strcmp(filename, "") == 0 ||
strcmp(filename, "/") == 0)
return FSFile(&_fs, "/");
int repeats = 0;
bool notExist;
bool canRecreate = (mode & SPIFFS_CREAT) == SPIFFS_CREAT;
int res;
do{
notExist = false;
res = SPIFFS_open(&_fs, filename, (spiffs_flags)mode, 0);
int code = SPIFFS_errno(&_fs);
if (res < 0){
SPIFFS_API_DBG_E("open errno %d\n", code);
notExist = (code == SPIFFS_ERR_NOT_FOUND || code == SPIFFS_ERR_DELETED || code == SPIFFS_ERR_FILE_DELETED || code == SPIFFS_ERR_IS_FREE);
if (notExist && canRecreate)
remove(filename); // fix for deleted files
}
} while (notExist && canRecreate && repeats++ < 3);
if(res){
return FSFile(&_fs, res);
}
return FSFile();
}
FSFile FSClass::open(spiffs_dirent* entry, uint8_t mode){
int res = SPIFFS_open_by_dirent(&_fs, entry, (spiffs_flags)mode, 0);
if (res){
return FSFile(&_fs, res);
}
return FSFile();
}
FSFile::FSFile()
: _file(0)
, _stats({0})
, _fs(0)
{
}
FSFile::FSFile(spiffs* fs, String path)
: _fs(fs)
{
if(path == "/"){
_file = 0x1;
os_sprintf((char*)_stats.name, "%s", (char*)path.c_str());
_stats.size = 0;
_stats.type = SPIFFS_TYPE_DIR;
SPIFFS_opendir(_fs, (char*)_stats.name, &_dir);
} else {
_file = SPIFFS_open(_fs, (char *)path.c_str(), (spiffs_flags)FSFILE_READ, 0);
if(SPIFFS_fstat(_fs, _file, &_stats) != 0){
SPIFFS_API_DBG_E("fstat errno %d\n", SPIFFS_errno(_fs));
}
//debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type);
if(_stats.type == SPIFFS_TYPE_DIR){
SPIFFS_opendir(_fs, (char*)_stats.name, &_dir);
}
}
}
FSFile::FSFile(spiffs* fs, file_t f)
: _file(f)
, _fs(fs)
{
if(SPIFFS_fstat(_fs, _file, &_stats) != 0){
SPIFFS_API_DBG_E("fstat errno %d\n", SPIFFS_errno(_fs));
}
//debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type);
if(_stats.type == SPIFFS_TYPE_DIR){
SPIFFS_opendir(_fs, (char*)_stats.name, &_dir);
}
}
void FSFile::close() {
if (!_file)
return;
if(_stats.type == SPIFFS_TYPE_DIR){
SPIFFS_closedir(&_dir);
}
if(os_strlen((char*)_stats.name) > 1)
SPIFFS_close(_fs, _file);
_file = 0;
}
char * FSFile::name(){
return (char*)_stats.name;
}
bool FSFile::isDirectory(void) {
return _stats.type == SPIFFS_TYPE_DIR;
}
void FSFile::rewindDirectory() {
if (!_file || !isDirectory())
return;
SPIFFS_closedir(&_dir);
SPIFFS_opendir(_fs, (char*)_stats.name, &_dir);
}
FSFile FSFile::openNextFile(){
if (!_file || !isDirectory())
return FSFile();
struct spiffs_dirent e;
struct spiffs_dirent *pe = &e;
if ((pe = SPIFFS_readdir(&_dir, pe))){
// TODO: store actual FS pointer
return FS.open((char *)pe->name);
}
return FSFile();
}
uint32_t FSFile::size() {
if(!_file)
return 0;
if(_stats.size)
return _stats.size;
uint32_t pos = SPIFFS_tell(_fs, _file);
SPIFFS_lseek(_fs, _file, 0, SPIFFS_SEEK_END);
_stats.size = SPIFFS_tell(_fs, _file);
SPIFFS_lseek(_fs, _file, pos, SPIFFS_SEEK_SET);
return _stats.size;
}
int FSFile::available() {
if (!_file)
return 0;
uint32_t pos = SPIFFS_tell(_fs, _file);
return size() - pos;
}
uint32_t FSFile::seek(uint32_t pos) {
if (!_file)
return 0;
return SPIFFS_lseek(_fs, _file, pos, SPIFFS_SEEK_SET);
}
uint32_t FSFile::position() {
if (!_file)
return 0;
return SPIFFS_tell(_fs, _file);
}
bool FSFile::eof() {
if (!_file)
return 0;
return SPIFFS_eof(_fs, _file);
}
int FSFile::read(void *buf, uint16_t nbyte) {
if (!_file || isDirectory())
return -1;
return SPIFFS_read(_fs, _file, buf, nbyte);
}
int FSFile::read() {
if (! _file || isDirectory())
return -1;
int val;
if(SPIFFS_read(_fs, _file, &val, 1) != 1) return -1;
return val;
}
int FSFile::peek() {
if (!_file || isDirectory())
return 0;
int c = read();
SPIFFS_lseek(_fs, _file, -1, SPIFFS_SEEK_CUR);
return c;
}
size_t FSFile::write(const uint8_t *buf, size_t size){
if (!_file || isDirectory())
return 0;
int res = SPIFFS_write(_fs, _file, (uint8_t *)buf, size);
return (res > 0)?(size_t)res:0;
}
size_t FSFile::write(uint8_t val) {
if (!_file || isDirectory())
return 0;
return write(&val, 1);
}
void FSFile::flush(){
if (!_file || isDirectory())
return;
SPIFFS_fflush(_fs, _file);
}
bool FSFile::remove(){
if (!_file)
return 0;
close();
return SPIFFS_remove(_fs, (char *)_stats.name) == 0;
}
int FSFile::lastError(){
return SPIFFS_errno(_fs);
}
void FSFile::clearError(){
_fs->err_code = SPIFFS_OK;
}
static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst){
SPIFFS_API_DBG_V("api_spiffs_read: 0x%08x len: %u\n", addr, size);
flashmem_read(dst, addr, size);
return SPIFFS_OK;
}
static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src){
SPIFFS_API_DBG_V("api_spiffs_write: 0x%08x len: %u\n", addr, size);
flashmem_write(src, addr, size);
return SPIFFS_OK;
}
static s32_t api_spiffs_erase(u32_t addr, u32_t size){
SPIFFS_API_DBG_V("api_spiffs_erase: 0x%08x len: %u\n", addr, size);
u32_t sect_first = flashmem_get_sector_of_address(addr);
u32_t sect_last = flashmem_get_sector_of_address(addr+size);
while( sect_first <= sect_last )
if( !flashmem_erase_sector( sect_first ++ ) )
return SPIFFS_ERR_INTERNAL;
return SPIFFS_OK;
}

View File

@ -1,132 +0,0 @@
/*
FileSystem.h - SPIFS implementation for esp8266
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
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
*/
#ifndef _SPIFFS_CORE_FILESYSTEM_H_
#define _SPIFFS_CORE_FILESYSTEM_H_
#include <memory>
#include "spiffs/spiffs.h"
#include "Arduino.h"
#define FSFILE_READ SPIFFS_RDONLY
#define FSFILE_WRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND )
#define FSFILE_OVERWRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC )
class FSFile : public Stream {
private:
spiffs_stat _stats;
file_t _file;
spiffs_DIR _dir;
spiffs * _fs;
public:
FSFile(spiffs* fs, String path);
FSFile(spiffs* fs, file_t f);
FSFile(void);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
virtual int read();
virtual int peek();
virtual int available();
virtual void flush();
int read(void *buf, uint16_t nbyte);
uint32_t seek(uint32_t pos);
uint32_t position();
uint32_t size();
bool eof();
void close();
bool remove();
int lastError();
void clearError();
operator bool() { return _file > 0; }
char * name();
bool isDirectory(void);
void rewindDirectory(void);
FSFile openNextFile(void);
template<typename T> size_t write(T &src){
const size_t bufferSize = 64;
uint8_t obuf[bufferSize];
size_t bytesWritten = 0;
while (true){
size_t available = src.available();
if(!available)
return bytesWritten;
size_t willWrite = (available < bufferSize) ? available : bufferSize;
src.read(obuf, willWrite);
size_t cb = write(obuf, willWrite);
if (cb != willWrite) {
return bytesWritten;
}
bytesWritten += cb;
}
return bytesWritten;
}
using Print::write;
};
class FSClass {
public:
FSClass(uint32_t beginAddress, uint32_t endAddress, uint32_t pageSize, uint32_t blockSize, uint32_t maxOpenFiles);
bool mount();
void unmount();
bool format();
bool check();
bool exists(char *filename);
bool create(char *filepath);
bool remove(char *filepath);
bool rename(char *filename, char *newname);
size_t totalBytes();
size_t usedBytes();
size_t size(){ return _fs.cfg.phys_size; }
size_t blockSize(){ return _fs.cfg.log_block_size; }
size_t totalBlocks(){ return _fs.block_count; }
size_t freeBlocks(){ return _fs.free_blocks; }
size_t pageSize(){ return _fs.cfg.log_page_size; }
size_t allocatedPages(){ return _fs.stats_p_allocated; }
size_t deletedPages(){ return _fs.stats_p_deleted; }
FSFile open(char *filename, uint8_t mode = FSFILE_READ);
FSFile open(spiffs_dirent* entry, uint8_t mode = FSFILE_READ);
protected:
int _mountInternal();
std::unique_ptr<uint8_t[]> _work;
std::unique_ptr<uint8_t[]> _fds;
size_t _fdsSize;
std::unique_ptr<uint8_t[]> _cache;
size_t _cacheSize;
uint32_t _beginAddress;
uint32_t _endAddress;
uint32_t _pageSize;
uint32_t _blockSize;
uint32_t _maxOpenFiles;
spiffs _fs;
private:
friend class FSFile;
};
extern FSClass FS;
#endif

View File

@ -1,164 +0,0 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/anakod/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
****/
#include "spiffs_esp8266.h"
#include "spi_flash.h"
#include "esp8266_peri.h"
#include "Arduino.h"
/*
FLASH ACCESS FUNCTIONS
*/
//lowest level sector erase method
bool flashmem_erase_sector( uint32_t sector_id ){
WDT_RESET();
noInterrupts();
uint32_t chip_size = flashchip->chip_size;
flashchip->chip_size = 0x01000000;
bool erased = spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK;
flashchip->chip_size = chip_size;
interrupts();
return erased;
}
//lowest level data write method
uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t size ){
toaddr -= INTERNAL_FLASH_START_ADDRESS;
SpiFlashOpResult r;
const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
uint32_t *apbuf = NULL;
if(((uint32_t)from) & blkmask){
apbuf = (uint32_t *)os_malloc(size);
if(!apbuf)
return 0;
os_memcpy(apbuf, from, size);
}
WDT_RESET();
noInterrupts();
uint32_t chip_size = flashchip->chip_size;
flashchip->chip_size = 0x01000000;
r = spi_flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size);
flashchip->chip_size = chip_size;
interrupts();
if(apbuf)
os_free(apbuf);
if(SPI_FLASH_RESULT_OK == r)
return size;
else{
SPIFFS_API_DBG_E( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr+INTERNAL_FLASH_START_ADDRESS );
return 0;
}
}
//lowest level data read method
uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size ){
fromaddr -= INTERNAL_FLASH_START_ADDRESS;
SpiFlashOpResult r;
WDT_RESET();
noInterrupts();
uint32_t chip_size = flashchip->chip_size;
flashchip->chip_size = 0x01000000;
r = spi_flash_read(fromaddr, (uint32 *)to, size);
flashchip->chip_size = chip_size;
interrupts();
if(SPI_FLASH_RESULT_OK == r)
return size;
else{
SPIFFS_API_DBG_E( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr+INTERNAL_FLASH_START_ADDRESS );
return 0;
}
}
//mid level data write method
uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size ){
uint32_t temp, rest, ssize = size;
unsigned i;
char tmpdata[ INTERNAL_FLASH_WRITE_UNIT_SIZE ];
const uint8_t *pfrom = ( const uint8_t* )from;
const uint32_t blksize = INTERNAL_FLASH_WRITE_UNIT_SIZE;
const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
// Align the start
if(toaddr & blkmask){
rest = toaddr & blkmask;
temp = toaddr & ~blkmask; // this is the actual aligned address
// c_memcpy( tmpdata, ( const void* )temp, blksize );
flashmem_read_internal( tmpdata, temp, blksize );
for( i = rest; size && ( i < blksize ); i ++, size --, pfrom ++ )
tmpdata[ i ] = *pfrom;
flashmem_write_internal( tmpdata, temp, blksize );
if( size == 0 )
return ssize;
toaddr = temp + blksize;
}
// The start address is now a multiple of blksize
// Compute how many bytes we can write as multiples of blksize
rest = size & blkmask;
temp = size & ~blkmask;
// Program the blocks now
if(temp){
flashmem_write_internal( pfrom, toaddr, temp );
toaddr += temp;
pfrom += temp;
}
// And the final part of a block if needed
if(rest){
// c_memcpy( tmpdata, ( const void* )toaddr, blksize );
flashmem_read_internal( tmpdata, toaddr, blksize );
for( i = 0; size && ( i < rest ); i ++, size --, pfrom ++ )
tmpdata[ i ] = *pfrom;
flashmem_write_internal( tmpdata, toaddr, blksize );
}
return ssize;
}
//mid level data write method
uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ){
uint32_t temp, rest, ssize = size;
unsigned i;
char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ];
uint8_t *pto = ( uint8_t* )to;
const uint32_t blksize = INTERNAL_FLASH_READ_UNIT_SIZE;
const uint32_t blkmask = INTERNAL_FLASH_READ_UNIT_SIZE - 1;
// Align the start
if(fromaddr & blkmask){
rest = fromaddr & blkmask;
temp = fromaddr & ~blkmask; // this is the actual aligned address
flashmem_read_internal( tmpdata, temp, blksize );
for( i = rest; size && ( i < blksize ); i ++, size --, pto ++ )
*pto = tmpdata[ i ];
if( size == 0 )
return ssize;
fromaddr = temp + blksize;
}
// The start address is now a multiple of blksize
// Compute how many bytes we can read as multiples of blksize
rest = size & blkmask;
temp = size & ~blkmask;
// Program the blocks now
if(temp){
flashmem_read_internal( pto, fromaddr, temp );
fromaddr += temp;
pto += temp;
}
// And the final part of a block if needed
if(rest){
flashmem_read_internal( tmpdata, fromaddr, blksize );
for( i = 0; size && ( i < rest ); i ++, size --, pto ++ )
*pto = tmpdata[ i ];
}
return ssize;
}
//shorthand when start and end addresses of the sector are not needed
uint32_t flashmem_get_sector_of_address( uint32_t addr ){
return (addr - INTERNAL_FLASH_START_ADDRESS) / INTERNAL_FLASH_SECTOR_SIZE;
}

View File

@ -1,42 +0,0 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/anakod/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
****/
#ifndef SYSTEM_FLASHMEM_H_
#define SYSTEM_FLASHMEM_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "spiffs.h"
/*******************
The W25Q32BV array is organized into 16,384 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time.
Pages can be erased in groups of 16 (4KB sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or
the entire chip (chip erase). The W25Q32BV has 1,024 erasable sectors and 64 erasable blocks respectively.
The small 4KB sectors allow for greater flexibility in applications that require data and parameter storage.
********************/
#define SPIFFS_API_DBG_V(fmt, ...) //os_printf(fmt, ##__VA_ARGS__)
#define SPIFFS_API_DBG_E(fmt, ...) //os_printf("ERROR: " fmt , ##__VA_ARGS__)
#define INTERNAL_FLASH_SECTOR_SIZE 4096
#define INTERNAL_FLASH_START_ADDRESS 0x40200000
#define INTERNAL_FLASH_WRITE_UNIT_SIZE 4
#define INTERNAL_FLASH_READ_UNIT_SIZE 4
extern uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size );
extern uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size );
extern bool flashmem_erase_sector( uint32_t sector_id );
uint32_t flashmem_get_sector_of_address( uint32_t addr );
#ifdef __cplusplus
}
#endif
#endif /* SYSTEM_FLASHMEM_H_ */

View File

@ -1,273 +0,0 @@
/*
FSWebServer - Example WebServer with SPIFFS backend for esp8266
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the ESP8266WebServer library for Arduino environment.
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
upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
!!! This will erase any previous SPIFFS data you may have!
!!! Make Backups First !!!
if you do not have it, get it at : <<<FILL THIS
access the sample web page at http://esp8266fs.local
edit the page by going to http://esp8266fs.local/edit
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <FileSystem.h>
#define DBG_OUTPUT_PORT Serial
const char* ssid = "**********";
const char* password = "**********";
const char* hostname = "esp8266fs";
MDNSResponder mdns;
ESP8266WebServer server(80);
//holds the current upload
FSFile fsUploadFile;
//format bytes
char *formatBytes(size_t bytes){
if (bytes < 1024){
return (char *)String(String(bytes)+"B").c_str();
} else if(bytes < (1024 * 1024)){
return (char *)String(String(bytes/1024.0)+"KB").c_str();
} else if(bytes < (1024 * 1024 * 1024)){
return (char *)String(String(bytes/1024.0/1024.0)+"MB").c_str();
} else {
return (char *)String(String(bytes/1024.0/1024.0/1024.0)+"GB").c_str();
}
}
String getContentType(String filename){
if(server.hasArg("download")) return "application/octet-stream";
else if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
bool handleFileRead(String path){
if(path.endsWith("/")) path += "index.htm";
String contentType = getContentType(path);
if(FS.exists((char *)(path+".gz").c_str()) || FS.exists((char *)path.c_str())){
if(FS.exists((char *)(path+".gz").c_str()))
path += ".gz";
FSFile file = FS.open((char *)path.c_str());
server.streamFile(file, contentType);
file.close();
return true;
}
return false;
}
void handleFileUpdate(){
if(server.uri() != "/edit") return;
HTTPUpload& upload = server.upload();
if(upload.status == UPLOAD_FILE_START){
String filename = upload.filename;
DBG_OUTPUT_PORT.print("Upload Name: "); DBG_OUTPUT_PORT.println(filename);
fsUploadFile = FS.open((char *)filename.c_str(), FSFILE_OVERWRITE);
filename = String();
} else if(upload.status == UPLOAD_FILE_WRITE){
//DBG_OUTPUT_PORT.print("Upload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize);
if(fsUploadFile)
fsUploadFile.write(upload.buf, upload.currentSize);
} else if(upload.status == UPLOAD_FILE_END){
if(fsUploadFile)
fsUploadFile.close();
DBG_OUTPUT_PORT.print("Upload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
}
}
void handleFileDelete(){
if(server.args() == 0) {
server.send(500, "text/plain", "BAD ARGS");
return;
}
String path = server.arg(0);
if(path == "/") {
server.send(500, "text/plain", "BAD PATH");
return;
}
if(!FS.exists((char *)(path.c_str()))) {
server.send(404, "text/plain", "FileNotFound");
return;
}
FS.remove((char *)path.c_str());
server.send(200, "text/plain", "");
path = String();
}
void handleFileCreate(){
if(server.args() == 0) {
server.send(500, "text/plain", "BAD ARGS");
return;
}
String path = server.arg(0);
if(path == "/") {
server.send(500, "text/plain", "BAD PATH");
return;
}
if(FS.exists((char *)path.c_str())) {
server.send(500, "text/plain", "FILE EXISTS");
return;
}
FSFile file = FS.open((char *)path.c_str(), FSFILE_OVERWRITE);
if(file)
file.close();
else {
server.send(500, "text/plain", "CREATE FAILED");
return;
}
server.send(200, "text/plain", "");
path = String();
}
void handleFileList() {
if(!server.hasArg("dir")) {
server.send(500, "text/plain", "BAD ARGS");
return;
}
String path = server.arg("dir");
FSFile entry;
FSFile dir = FS.open((char *)path.c_str());
path = String();
if(!dir.isDirectory()){
dir.close();
server.send(500, "text/plain", "NOT DIR");
return;
}
dir.rewindDirectory();
String output = "[";
while(true){
entry = dir.openNextFile();
if (!entry)
break;
if(!FS.exists(entry.name())){
os_printf("Entry[%s] Not Exists!\n", entry.name());
entry.remove();
entry.close();
continue;
}
if(output != "[")
output += ',';
output += "{\"type\":\"";
output += (entry.isDirectory())?"dir":"file";
output += "\",\"name\":\"";
output += String(entry.name()).substring(1);
output += "\"}";
entry.close();
}
dir.close();
output += "]";
server.send(200, "text/json", output);
}
void setup(void){
DBG_OUTPUT_PORT.begin(115200);
DBG_OUTPUT_PORT.print("\n");
//SPIFFS INIT
DBG_OUTPUT_PORT.printf("\n==== SPIFFS Info ====\n");
DBG_OUTPUT_PORT.printf("FS Mount: %d\n", FS.mount());
DBG_OUTPUT_PORT.printf("FS Size: %s\n", formatBytes(FS.size()));
DBG_OUTPUT_PORT.printf("FS Bytes: total: %s, used: %s\n", formatBytes(FS.totalBytes()), formatBytes(FS.usedBytes()));
DBG_OUTPUT_PORT.printf("FS Blocks: total: %d, free: %d, size: %s\n", FS.totalBlocks(), FS.freeBlocks(), formatBytes(FS.blockSize()));
DBG_OUTPUT_PORT.printf("FS Pages: allocated: %d, deleted: %d, size: %s\n", FS.allocatedPages(), FS.deletedPages(), formatBytes(FS.pageSize()));
FSFile entry;
FSFile dir = FS.open((char *)"/");
while(true){
entry = dir.openNextFile();
if (!entry) break;
DBG_OUTPUT_PORT.printf("FS File: %s, type: %s, size: %s\n", entry.name(), (entry.isDirectory())?"dir":"file", formatBytes(entry.size()));
entry.close();
}
dir.close();
DBG_OUTPUT_PORT.printf("\n");
//WIFI INIT
DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid);
WiFi.begin(ssid, password);
if(WiFi.waitForConnectResult() != WL_CONNECTED){
DBG_OUTPUT_PORT.printf("Could not connect to %s\n", ssid);
while(1) delay(500);
}
DBG_OUTPUT_PORT.print("Connected! IP address: ");
DBG_OUTPUT_PORT.println(WiFi.localIP());
//mDNS INIT
if (mdns.begin(hostname, WiFi.localIP()))
DBG_OUTPUT_PORT.printf("mDNS responder started for %s.local\n", hostname);
//SERVER INIT
//list directory
server.on("/list", HTTP_GET, handleFileList);
//load editor
server.on("/edit", HTTP_GET, [](){
if(!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound");
});
//create file
server.on("/edit", HTTP_PUT, handleFileCreate);
//delete file
server.on("/edit", HTTP_DELETE, handleFileDelete);
//called after file upload
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); });
//called when a file is received inside POST data
server.onFileUpload(handleFileUpdate);
//called when the url is not defined here
//use it to load content from SPIFFS
server.onNotFound([](){
if(!handleFileRead(server.uri()))
server.send(404, "text/plain", "FileNotFound");
});
//get heap status, analog input value and all GPIO statuses in one json call
server.on("/all", HTTP_GET, [](){
String json = "{";
json += "\"heap\":"+String(ESP.getFreeHeap());
json += ", \"analog\":"+String(analogRead(A0));
json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
json += "}";
server.send(200, "text/json", json);
json = String();
});
server.begin();
DBG_OUTPUT_PORT.println("HTTP server started");
}
void loop(void){
server.handleClient();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,100 +0,0 @@
<!--
FSWebServer - Example Index Page
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the ESP8266WebServer library for Arduino environment.
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
-->
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>ESP Monitor</title>
<script type="text/javascript" src="graphs.js"></script>
<script type="text/javascript">
var heap,temp,digi;
var reloadPeriod = 1000;
var running = false;
function loadValues(){
if(!running) return;
var xh = new XMLHttpRequest();
xh.onreadystatechange = function(){
if (xh.readyState == 4){
if(xh.status == 200) {
var res = JSON.parse(xh.responseText);
heap.add(res.heap);
temp.add(res.analog);
digi.add(res.gpio);
if(running) setTimeout(loadValues, reloadPeriod);
} else running = false;
}
};
xh.open("GET", "/all", true);
xh.send(null);
};
function run(){
if(!running){
running = true;
loadValues();
}
}
function onBodyLoad(){
var refreshInput = document.getElementById("refresh-rate");
refreshInput.value = reloadPeriod;
refreshInput.onchange = function(e){
var value = parseInt(e.target.value);
reloadPeriod = (value > 0)?value:0;
e.target.value = reloadPeriod;
}
var stopButton = document.getElementById("stop-button");
stopButton.onclick = function(e){
running = false;
}
var startButton = document.getElementById("start-button");
startButton.onclick = function(e){
run();
}
// Example with 10K thermistor
//function calcThermistor(v) {
// var t = Math.log(((10230000 / v) - 10000));
// t = (1/(0.001129148+(0.000234125*t)+(0.0000000876741*t*t*t)))-273.15;
// return (t>120)?0:Math.round(t*10)/10;
//}
//temp = createGraph(document.getElementById("analog"), "Temperature", 100, 128, 10, 40, false, "cyan", calcThermistor);
temp = createGraph(document.getElementById("analog"), "Analog Input", 100, 128, 0, 1023, false, "cyan");
heap = createGraph(document.getElementById("heap"), "Current Heap", 100, 125, 0, 30000, true, "orange");
digi = createDigiGraph(document.getElementById("digital"), "GPIO", 100, 146, [0, 4, 5, 16], "gold");
run();
}
</script>
</head>
<body id="index" style="margin:0; padding:0;" onload="onBodyLoad()">
<div id="controls" style="display: block; border: 1px solid rgb(68, 68, 68); padding: 5px; margin: 5px; width: 362px; background-color: rgb(238, 238, 238);">
<label>Period (ms):</label>
<input type="number" id="refresh-rate"/>
<input type="button" id="start-button" value="Start"/>
<input type="button" id="stop-button" value="Stop"/>
</div>
<div id="heap"></div>
<div id="analog"></div>
<div id="digital"></div>
</body>
</html>

View File

@ -1,512 +0,0 @@
<!--
FSWebServer - SPIFFS Editor/Manager
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the ESP8266WebServer library for Arduino environment.
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
-->
<!DOCTYPE html>
<html lang="en">
<head>
<title>ESP Editor</title>
<style type="text/css" media="screen">
.cm {
z-index: 300;
position: absolute;
left: 5px;
border: 1px solid #444;
background-color: #F5F5F5;
display: none;
box-shadow: 0 0 10px rgba( 0, 0, 0, .4 );
font-size: 12px;
font-family: sans-serif;
font-weight:bold;
}
.cm ul {
list-style: none;
top: 0;
left: 0;
margin: 0;
padding: 0;
}
.cm li {
position: relative;
min-width: 60px;
cursor: pointer;
}
.cm span {
color: #444;
display: inline-block;
padding: 6px;
}
.cm li:hover { background: #444; }
.cm li:hover span { color: #EEE; }
.tvu ul, .tvu li {
padding: 0;
margin: 0;
list-style: none;
}
.tvu input {
position: absolute;
opacity: 0;
}
.tvu {
font: normal 12px Verdana, Arial, Sans-serif;
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
color: #444;
line-height: 16px;
}
.tvu span {
margin-bottom:5px;
padding: 0 0 0 18px;
cursor: pointer;
display: inline-block;
height: 16px;
vertical-align: middle;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADoSURBVBgZBcExblNBGAbA2ceegTRBuIKOgiihSZNTcC5LUHAihNJR0kGKCDcYJY6D3/77MdOinTvzAgCw8ysThIvn/VojIyMjIyPP+bS1sUQIV2s95pBDDvmbP/mdkft83tpYguZq5Jh/OeaYh+yzy8hTHvNlaxNNczm+la9OTlar1UdA/+C2A4trRCnD3jS8BB1obq2Gk6GU6QbQAS4BUaYSQAf4bhhKKTFdAzrAOwAxEUAH+KEM01SY3gM6wBsEAQB0gJ+maZoC3gI6iPYaAIBJsiRmHU0AALOeFC3aK2cWAACUXe7+AwO0lc9eTHYTAAAAAElFTkSuQmCC') no-repeat;
background-position: 0px 0px;
}
.tvu span:hover {
text-decoration: underline;
}
@media screen and (-webkit-min-device-pixel-ratio:0){
.tvu{
-webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
}
@-webkit-keyframes webkit-adjacent-element-selector-bugfix {
from {
padding: 0;
}
to {
padding: 0;
}
}
}
#uploader {
position: absolute;
top: 0;
right: 0;
left: 0;
height:28px;
line-height: 24px;
padding-left: 10px;
background-color: #444;
color:#EEE;
}
#tree {
position: absolute;
top: 28px;
bottom: 0;
left: 0;
width:160px;
padding: 8px;
}
#editor, #preview {
position: absolute;
top: 28px;
right: 0;
bottom: 0;
left: 160px;
border-left:1px solid #EEE;
}
#preview {
background-color: #EEE;
padding:5px;
}
</style>
<script>
function createFileUploader(element, tree, editor){
var xmlHttp;
var input = document.createElement("input");
input.type = "file";
input.multiple = false;
input.name = "data";
document.getElementById(element).appendChild(input);
var path = document.createElement("input");
path.id = "upload-path";
path.type = "text";
path.name = "path";
path.defaultValue = "/";
document.getElementById(element).appendChild(path);
var button = document.createElement("button");
button.innerHTML = 'Upload';
document.getElementById(element).appendChild(button);
var mkfile = document.createElement("button");
mkfile.innerHTML = 'MkDir';
document.getElementById(element).appendChild(mkfile);
function httpPostProcessRequest(){
if (xmlHttp.readyState == 4){
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
else {
tree.refreshPath(path.value);
}
}
}
function createPath(p){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpPostProcessRequest;
var formData = new FormData();
formData.append("path", p);
xmlHttp.open("PUT", "/edit");
xmlHttp.send(formData);
}
mkfile.onclick = function(e){
if(path.value.indexOf(".") === -1) return;
createPath(path.value);
editor.loadUrl(path.value);
};
button.onclick = function(e){
if(input.files.length === 0){
return;
}
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpPostProcessRequest;
var formData = new FormData();
formData.append("data", input.files[0], path.value);
xmlHttp.open("POST", "/edit");
xmlHttp.send(formData);
};
input.onchange = function(e){
if(input.files.length === 0) return;
var filename = input.files[0].name;
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
var name = /(.*)\.[^.]+$/.exec(filename)[1];
if(typeof name !== undefined){
filename = name;
}
if(typeof ext !== undefined){
if(ext === "html") ext = "htm";
else if(ext === "jpeg") ext = "jpg";
filename = filename + "." + ext;
}
if(path.value === "/" || path.value.lastIndexOf("/") === 0){
path.value = "/"+filename;
} else {
path.value = path.value.substring(0, path.value.lastIndexOf("/")+1)+filename;
}
};
}
function createTree(element, editor){
var preview = document.getElementById("preview");
var treeRoot = document.createElement("div");
treeRoot.className = "tvu";
document.getElementById(element).appendChild(treeRoot);
function loadDownload(path){
document.getElementById('download-frame').src = path+"?download=true";
}
function loadPreview(path){
document.getElementById("editor").style.display = "none";
preview.style.display = "block";
preview.innerHTML = '<img src="'+path+'?_cb='+Date.now()+'" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
}
function fillFileMenu(el, path){
var list = document.createElement("ul");
el.appendChild(list);
var action = document.createElement("li");
list.appendChild(action);
if(isTextFile(path)){
action.innerHTML = "<span>Edit</span>";
action.onclick = function(e){
editor.loadUrl(path);
if(document.body.getElementsByClassName('cm').length > 0) document.body.removeChild(el);
};
} else if(isImageFile(path)){
action.innerHTML = "<span>Preview</span>";
action.onclick = function(e){
loadPreview(path);
if(document.body.getElementsByClassName('cm').length > 0) document.body.removeChild(el);
};
}
var download = document.createElement("li");
list.appendChild(download);
download.innerHTML = "<span>Download</span>";
download.onclick = function(e){
loadDownload(path);
if(document.body.getElementsByClassName('cm').length > 0) document.body.removeChild(el);
};
var delFile = document.createElement("li");
list.appendChild(delFile);
delFile.innerHTML = "<span>Delete</span>";
delFile.onclick = function(e){
httpDelete(path);
if(document.body.getElementsByClassName('cm').length > 0) document.body.removeChild(el);
};
}
function showContextMenu(e, path, isfile){
var divContext = document.createElement("div");
var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
var left = event.clientX + scrollLeft;
var top = event.clientY + scrollTop;
divContext.className = 'cm';
divContext.style.display = 'block';
divContext.style.left = left + 'px';
divContext.style.top = top + 'px';
fillFileMenu(divContext, path);
document.body.appendChild(divContext);
var width = divContext.offsetWidth;
var height = divContext.offsetHeight;
divContext.onmouseout = function(e){
if(e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)){
if(document.body.getElementsByClassName('cm').length > 0) document.body.removeChild(divContext);
}
};
}
function createTreeLeaf(path, name, size){
var leaf = document.createElement("li");
leaf.id = (((path == "/")?"":path)+"/"+name);
var label = document.createElement("span");
label.innerText = name;
leaf.appendChild(label);
leaf.onclick = function(e){
if(isTextFile(leaf.id.toLowerCase())){
editor.loadUrl(leaf.id);
} else if(isImageFile(leaf.id.toLowerCase())){
loadPreview(leaf.id);
}
};
leaf.oncontextmenu = function(e){
e.preventDefault();
e.stopPropagation();
showContextMenu(e, leaf.id, true);
};
return leaf;
}
function addList(parent, path, items){
var list = document.createElement("ul");
parent.appendChild(list);
var ll = items.length;
for(var i = 0; i < ll; i++){
if(items[i].type === "file")
list.appendChild(createTreeLeaf(path, items[i].name, items[i].size));
}
}
function isTextFile(path){
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
if(typeof ext !== undefined){
switch(ext){
case "txt":
case "htm":
case "js":
case "c":
case "cpp":
case "css":
case "xml":
return true;
}
}
return false;
}
function isImageFile(path){
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
if(typeof ext !== undefined){
switch(ext){
case "png":
case "jpg":
case "gif":
return true;
}
}
return false;
}
this.refreshPath = function(path){
treeRoot.removeChild(treeRoot.childNodes[0]);
httpGet(treeRoot, "/");
};
function delCb(path){
return function(){
if (xmlHttp.readyState == 4){
if(xmlHttp.status != 200){
alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
} else {
treeRoot.removeChild(treeRoot.childNodes[0]);
httpGet(treeRoot, "/");
}
}
}
}
function httpDelete(filename){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = delCb(filename);
var formData = new FormData();
formData.append("path", filename);
xmlHttp.open("DELETE", "/edit");
xmlHttp.send(formData);
}
function getCb(parent, path){
return function(){
if (xmlHttp.readyState == 4){
if(xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
}
}
}
function httpGet(parent, path){
xmlHttp = new XMLHttpRequest(parent, path);
xmlHttp.onreadystatechange = getCb(parent, path);
xmlHttp.open("GET", "/list?dir="+path, true);
xmlHttp.send(null);
}
httpGet(treeRoot, "/");
return this;
}
function createEditor(element, file, lang, theme, type){
function getLangFromFilename(filename){
var lang = "plain";
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
if(typeof ext !== undefined){
switch(ext){
case "txt": lang = "plain"; break;
case "htm": lang = "html"; break;
case "js": lang = "javascript"; break;
case "c": lang = "c_cpp"; break;
case "cpp": lang = "c_cpp"; break;
case "css":
case "scss":
case "php":
case "html":
case "json":
case "xml":
lang = ext;
}
}
return lang;
}
if(typeof file === "undefined") file = "/index.htm";
if(typeof lang === "undefined"){
lang = getLangFromFilename(file);
}
if(typeof theme === "undefined") theme = "textmate";
if(typeof type === "undefined"){
type = "text/"+lang;
if(lang === "c_cpp") type = "text/plain";
}
var xmlHttp = null;
var editor = ace.edit(element);
function httpPostProcessRequest(){
if (xmlHttp.readyState == 4){
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
}
}
function httpPost(filename, data, type){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpPostProcessRequest;
var formData = new FormData();
formData.append("data", new Blob([data], { type: type }), filename);
xmlHttp.open("POST", "/edit");
xmlHttp.send(formData);
}
function httpGetProcessRequest(){
if (xmlHttp.readyState == 4){
document.getElementById("preview").style.display = "none";
document.getElementById("editor").style.display = "block";
if(xmlHttp.status == 200) editor.setValue(xmlHttp.responseText);
else editor.setValue("");
editor.clearSelection();
}
}
function httpGet(theUrl){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpGetProcessRequest;
xmlHttp.open("GET", theUrl, true);
xmlHttp.send(null);
}
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
editor.setTheme("ace/theme/"+theme);
editor.$blockScrolling = Infinity;
editor.getSession().setUseSoftTabs(true);
editor.getSession().setTabSize(2);
editor.setHighlightActiveLine(true);
editor.setShowPrintMargin(false);
editor.commands.addCommand({
name: 'saveCommand',
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
exec: function(editor) {
httpPost(file, editor.getValue()+"", type);
},
readOnly: false
});
editor.commands.addCommand({
name: 'undoCommand',
bindKey: {win: 'Ctrl-Z', mac: 'Command-Z'},
exec: function(editor) {
editor.getSession().getUndoManager().undo(false);
},
readOnly: false
});
editor.commands.addCommand({
name: 'redoCommand',
bindKey: {win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z'},
exec: function(editor) {
editor.getSession().getUndoManager().redo(false);
},
readOnly: false
});
httpGet(file);
editor.loadUrl = function(filename){
file = filename;
lang = getLangFromFilename(file);
type = "text/"+lang;
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
httpGet(file);
};
return editor;
}
function onBodyLoad(){
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
var tree = createTree("tree", editor);
createFileUploader("uploader", tree, editor);
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript" charset="utf-8"></script>
</head>
<body onload="onBodyLoad();">
<div id="uploader"></div>
<div id="tree"></div>
<div id="editor"></div>
<div id="preview" style="display:none;"></div>
<iframe id=download-frame style='display:none;'></iframe>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1,281 +0,0 @@
/*
FSWebServer - Sample Graphing Library
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the ESP8266WebServer library for Arduino environment.
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
*/
function ce(t){ return document.createElement(t); }
function ac(a,b){ a.appendChild(b); }
function createGraph(el, t, w, h, l, m, ib, tc, cb){
if(typeof el === "undefined" || !el) return null;
if(typeof ib === "undefined" || !ib) ib = false;
w = (w>360)?w:360;
h = (h<100)?100:h;
var vs = new Array();
var bgc = "black";
var lc = (typeof tc === "undefined" && tc)?"yellow":tc;
var bc = "#444";
var vcb = (typeof cb === "undefined" && cb)?null:cb;
var minV = m;
var maxV = 0;
var sv = 1;
var ov = l;
var gh = h+20;
el.style.display = "block";
el.style.backgroundColor = "#eee";
el.style.border = "1px solid "+bc;
el.style.padding = "5px";
el.style.margin = "5px";
el.style.width = (w+2)+"px";
var g = ce("canvas");
g.style.border = "1px solid "+bc;
g.style.marginTop = "5px";
g.width = w;
g.height = gh;
var c = g.getContext("2d");
var sl = ce("span");
sl.innerText = "Scale: ";
sl.style.paddingLeft = "5px";
var st = ce("input");
st.type = "text";
st.size = 3;
st.value = sv;
st.onchange = function(e){ sv = st.value; };
var sm = ce("button");
sm.innerText = "-";
sm.onclick = function(e){ if(sv > 1) sv--; st.value = sv; };
var sp = ce("button");
sp.innerText = "+";
sp.onclick = function(e){ sv++; st.value = parseInt(sv); };
var ol = ce("span");
ol.innerText = "Offset: ";
ol.style.paddingLeft = "5px";
var ot = ce("input");
ot.type = "text";
ot.size = 5;
ot.value = ov;
ot.onchange = function(e){ ov = parseInt(ot.value); };
var om = ce("button");
om.innerText = "-";
om.onclick = function(e){ if(ov > l) ov--; ot.value = ov; };
var op = ce("button");
op.innerText = "+";
op.onclick = function(e){ if(ov < m) ov++; ot.value = ov; };
ac(el,sl);
ac(el,sm);
ac(el,st);
ac(el,sp);
ac(el,ol);
ac(el,om);
ac(el,ot);
ac(el,op);
ac(el,ce("br"));
ac(el,g);
function scv(v){
if(v <= ov) return 0;
if(v > (((m - l) / sv) + ov)) return h;
return Math.round((v - ov) * (h / ((m - l) / sv)));
}
g.add = function(v){
if(vcb) v = vcb(v);
vs.push(v);
if(v < minV) minV = v;
if(v > maxV) maxV = v;
if(vs.length > w) vs.shift();
c.canvas.width = w;
c.lineWidth = 1;
c.shadowBlur=2;
c.shadowColor="black";
c.fillStyle = bc;
c.fillRect(0, 0, w, 20);
c.fillStyle = lc;
c.font = "14px Verdana";
var header = t+": "+(vs[vs.length - 1])+" | Min: "+minV+" | Max: "+maxV;
c.fillText(header,5,15);
c.fillStyle = bgc;
c.fillRect(0, 20, w, gh);
c.strokeStyle = lc;
for(var i = 0; i < vs.length; i++){
if(ib){
c.moveTo(i, gh);
c.lineTo(i, gh - scv(vs[i]));
c.stroke();
continue;
}
if(i === 0){
c.moveTo(0, gh - scv(vs[0]));
c.lineTo(0, gh - scv(vs[0]));
c.stroke();
} else {
c.moveTo((i - 1), gh - scv(vs[i - 1]));
c.lineTo(i, gh - scv(vs[i]));
c.stroke();
}
}
c.fillStyle = lc;
c.font = "10px Verdana";
c.fillText(ov, 2, gh - 5);
c.fillText(Math.round((((m - l) / sv) + ov) * 10) / 10, 2, 30);
};
return g;
}
function createDigiGraph(el, t, w, h, m, tc){
if(typeof el === "undefined" || !el) return null;
w = (w>360)?w:360;
h = (h<20)?20:h;
var vs = new Array();
var bgc = "black";
var lc = (typeof tc === "undefined" && tc)?"pink":tc;
var bc = "#444";
var sv = 1;
var gh = h+20;
el.style.display = "block";
el.style.backgroundColor = "#eee";
el.style.border = "1px solid "+bc;
el.style.padding = "5px";
el.style.margin = "5px";
el.style.width = (w+2)+"px";
var g = ce("canvas");
g.style.border = "1px solid "+bc;
g.style.marginTop = "5px";
g.width = w;
g.height = gh;
var c = g.getContext("2d");
var sl = ce("span");
sl.innerText = "Scale: ";
sl.style.paddingLeft = "5px";
var st = ce("input");
st.type = "text";
st.size = 3;
st.value = sv;
st.onchange = function(e){ sv = st.value; };
var sm = ce("button");
sm.innerText = "-";
sm.onclick = function(e){ if(sv > 1) sv--; st.value = sv; };
var sp = ce("button");
sp.innerText = "+";
sp.onclick = function(e){ sv++; st.value = parseInt(sv); };
ac(el,sl);
ac(el,sm);
ac(el,st);
ac(el,sp);
ac(el,ce("br"));
ac(el,g);
function gpos(p){
var each = Math.floor(((h - ((m.length - 1)*2))/m.length));
var s = (p * 2) + (p * each);
return [s, s + each];
}
function gact(i,p){
return ((vs[i] & (1 << m[p])) !== 0);;
}
var vc = ["aqua","yellow","#FF4500","#00FF7F","orange","cyan","magenta","#7FFF00","#FAF0E6","#00CED1","#FFD700","#EE82EE","#00FF00","#00BFFF","#FF4500","#EEE8AA","#FF1493"];
g.add = function(v){
vs.push(v);
if(vs.length > w) vs.shift();
c.canvas.width = w;
c.lineWidth=1;
c.shadowBlur=2;
c.shadowColor="black";
c.fillStyle = bc;
c.fillRect(0, 0, w, 20);
c.fillStyle = lc;
c.font = "14px Verdana";
c.fillText(t,5,15);
c.fillStyle = bgc;
c.fillRect(0, 20, w, gh);
c.strokeStyle = bc;
c.lineWidth = 1;
c.shadowBlur=0;
c.shadowColor="";
for(var p=0;p<m.length;p++){
var pos = gpos(p);
c.moveTo(0, 20 + pos[1] + 1);
c.lineTo(w, 20 + pos[1] + 1);
c.stroke();
}
c.shadowBlur=2;
c.font = "14px Verdana";
var pn = Math.round(w / sv);
var stv = w - pn - (w - vs.length);
if(stv < 0) stv = 0;
for(var i = stv; i < vs.length; i++){
for(var p=0;p<m.length;p++){
var pos = gpos(p);
var act = gact(i, p);
c.fillStyle = vc[p];
c.shadowColor="black";
c.font = "12px Verdana";
c.fillText(""+m[p], 2, pos[0] + 32);
c.shadowColor=vc[p];
var x1 = ((i-stv)*sv) - (sv / 2);
var wa = gact(i - 1, p);
if(i && act != wa){
if(!wa){
c.fillRect(x1, 20 + (pos[1] - 2), sv/2, 2);
c.fillRect(x1+(sv/2), 20 + pos[0], 2, pos[1] - pos[0]);
c.fillRect(x1+(sv/2), 20 + pos[0], sv/2, 2);
} else {
c.fillRect(x1, 20 + pos[0], sv/2, 2);
c.fillRect(x1+(sv/2), 20 + pos[0], 2, pos[1] - pos[0]);
c.fillRect(x1+(sv/2), 20 + (pos[1] - 2), sv/2, 2);
}
} else if(act){
c.fillRect(x1, 20 + pos[0], sv, 2);
} else {
c.fillRect(x1, 20 + (pos[1] - 2), sv, 2);
}
}
}
};
return g;
}

View File

@ -1 +0,0 @@
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('8 H(t){K 21.1Y(t)}8 9(a,b){a.1S(b)}8 1O(b,t,w,h,l,m,d,f,j){6(Q b==="S"||!b)K 1f;6(Q d==="S"||!d)d=1P;w=(w>1b)?w:1b;h=(h<1N)?1N:h;4 k=1M 1L();4 n="V";4 o=(Q f==="S"&&f)?"1J":f;4 p="#1I";4 q=(Q j==="S"&&j)?1f:j;4 r=m;4 s=0;4 u=1;4 x=l;4 y=h+20;b.7.1H="1G";b.7.1F="#1s";b.7.1c="12 11 "+p;b.7.1D="N";b.7.1C="N";b.7.P=(w+2)+"1B";4 g=H("1a");g.7.1c="12 11 "+p;g.7.1z="N";g.P=w;g.1w=y;4 c=g.1v("2d");4 z=H("1j");z.M="1u: ";z.7.1m="N";4 A=H("1p");A.1i="1r";A.1e=3;A.I=u;A.1h=8(e){u=A.I};4 B=H("T");B.M="-";B.U=8(e){6(u>1)u--;A.I=u};4 C=H("T");C.M="+";C.U=8(e){u++;A.I=1n(u)};4 D=H("1j");D.M="1Q: ";D.7.1m="N";4 E=H("1p");E.1i="1r";E.1e=5;E.I=x;E.1h=8(e){x=1n(E.I)};4 F=H("T");F.M="-";F.U=8(e){6(x>l)x--;E.I=x};4 G=H("T");G.M="+";G.U=8(e){6(x<m)x++;E.I=x};9(b,z);9(b,B);9(b,A);9(b,C);9(b,D);9(b,F);9(b,E);9(b,G);9(b,H("1E"));9(b,g);8 R(v){6(v<=x)K 0;6(v>(((m-l)/u)+x))K h;K 1d.1o((v-x)*(h/((m-l)/u)))}g.1x=8(v){6(q)v=q(v);k.1y(v);6(v<r)r=v;6(v>s)s=v;6(k.L>w)k.1A();c.1a.P=w;c.1g=1;c.17=2;c.Y="V";c.O=p;c.J(0,0,w,20);c.O=o;c.X="1q Z";4 a=t+": "+(k[k.L-1])+" | 1U: "+r+" | 23: "+s;c.W(a,5,15);c.O=n;c.J(0,20,w,y);c.1K=o;18(4 i=0;i<k.L;i++){6(d){c.13(i,y);c.14(i,y-R(k[i]));c.16();1R}6(i===0){c.13(0,y-R(k[0]));c.14(0,y-R(k[0]));c.16()}19{c.13((i-1),y-R(k[i-1]));c.14(i,y-R(k[i]));c.16()}}c.O=o;c.X="1T Z";c.W(x,2,y-5);c.W(1d.1o((((m-l)/u)+x)*10)/10,2,1V)};K g}8 1W(j,t,w,h,m,k){6(Q j==="S"||!j)K 1f;w=(w>1b)?w:1b;h=(h<20)?20:h;4 l=1M 1L();4 n="V";4 o=(Q k==="S"&&k)?"1X":k;4 q="#1I";4 r=1;4 u=h+20;j.7.1H="1G";j.7.1F="#1s";j.7.1c="12 11 "+q;j.7.1D="N";j.7.1C="N";j.7.P=(w+2)+"1B";4 g=H("1a");g.7.1c="12 11 "+q;g.7.1z="N";g.P=w;g.1w=u;4 c=g.1v("2d");4 x=H("1j");x.M="1u: ";x.7.1m="N";4 y=H("1p");y.1i="1r";y.1e=3;y.I=r;y.1h=8(e){r=y.I};4 z=H("T");z.M="-";z.U=8(e){6(r>1)r--;y.I=r};4 A=H("T");A.M="+";A.U=8(e){r++;y.I=1n(r)};9(j,x);9(j,z);9(j,y);9(j,A);9(j,H("1E"));9(j,g);8 1l(p){4 a=1d.1Z(((h-((m.L-1)*2))/m.L));4 s=(p*2)+(p*a);K[s,s+a]}8 1k(i,p){K((l[i]&(1<<m[p]))!==0)}4 B=["22","1J","#1t","#24","25","26","27","#28","#29","#2a","#2b","#2c","#2e","#2f","#1t","#2g","#2h"];g.1x=8(v){l.1y(v);6(l.L>w)l.1A();c.1a.P=w;c.1g=1;c.17=2;c.Y="V";c.O=q;c.J(0,0,w,20);c.O=o;c.X="1q Z";c.W(t,5,15);c.O=n;c.J(0,20,w,u);c.1K=q;c.1g=1;c.17=0;c.Y="";18(4 p=0;p<m.L;p++){4 a=1l(p);c.13(0,20+a[1]+1);c.14(w,20+a[1]+1);c.16()}c.17=2;c.X="1q Z";4 b=1d.1o(w/r);4 d=w-b-(w-l.L);6(d<0)d=0;18(4 i=d;i<l.L;i++){18(4 p=0;p<m.L;p++){4 a=1l(p);4 e=1k(i,p);c.O=B[p];c.Y="V";c.X="2i Z";c.W(""+m[p],2,a[0]+2j);c.Y=B[p];4 f=((i-d)*r)-(r/2);4 g=1k(i-1,p);6(i&&e!=g){6(!g){c.J(f,20+(a[1]-2),r/2,2);c.J(f+(r/2),20+a[0],2,a[1]-a[0]);c.J(f+(r/2),20+a[0],r/2,2)}19{c.J(f,20+a[0],r/2,2);c.J(f+(r/2),20+a[0],2,a[1]-a[0]);c.J(f+(r/2),20+(a[1]-2),r/2,2)}}19 6(e){c.J(f,20+a[0],r,2)}19{c.J(f,20+(a[1]-2),r,2)}}}};K g}',62,144,'||||var||if|style|function|ac||||||||||||||||||||||||||||||||||ce|value|fillRect|return|length|innerText|5px|fillStyle|width|typeof|scv|undefined|button|onclick|black|fillText|font|shadowColor|Verdana||solid|1px|moveTo|lineTo||stroke|shadowBlur|for|else|canvas|360|border|Math|size|null|lineWidth|onchange|type|span|gact|gpos|paddingLeft|parseInt|round|input|14px|text|eee|FF4500|Scale|getContext|height|add|push|marginTop|shift|px|margin|padding|br|backgroundColor|block|display|444|yellow|strokeStyle|Array|new|100|createGraph|false|Offset|continue|appendChild|10px|Min|30|createDigiGraph|pink|createElement|floor||document|aqua|Max|00FF7F|orange|cyan|magenta|7FFF00|FAF0E6|00CED1|FFD700|EE82EE||00FF00|00BFFF|EEE8AA|FF1493|12px|32'.split('|'),0,{}))

View File

@ -1,100 +0,0 @@
<!--
FSWebServer - Sample Index Page
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the ESP8266WebServer library for Arduino environment.
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
-->
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>ESP Monitor</title>
<script type="text/javascript" src="graphs.js"></script>
<script type="text/javascript">
var heap,temp,digi;
var reloadPeriod = 1000;
var running = false;
function loadValues(){
if(!running) return;
var xh = new XMLHttpRequest();
xh.onreadystatechange = function(){
if (xh.readyState == 4){
if(xh.status == 200) {
var res = JSON.parse(xh.responseText);
heap.add(res.heap);
temp.add(res.analog);
digi.add(res.gpio);
if(running) setTimeout(loadValues, reloadPeriod);
} else running = false;
}
};
xh.open("GET", "/all", true);
xh.send(null);
};
function run(){
if(!running){
running = true;
loadValues();
}
}
function onBodyLoad(){
var refreshInput = document.getElementById("refresh-rate");
refreshInput.value = reloadPeriod;
refreshInput.onchange = function(e){
var value = parseInt(e.target.value);
reloadPeriod = (value > 0)?value:0;
e.target.value = reloadPeriod;
}
var stopButton = document.getElementById("stop-button");
stopButton.onclick = function(e){
running = false;
}
var startButton = document.getElementById("start-button");
startButton.onclick = function(e){
run();
}
// Example with 10K thermistor
//function calcThermistor(v) {
// var t = Math.log(((10230000 / v) - 10000));
// t = (1/(0.001129148+(0.000234125*t)+(0.0000000876741*t*t*t)))-273.15;
// return (t>120)?0:Math.round(t*10)/10;
//}
//temp = createGraph(document.getElementById("analog"), "Temperature", 100, 128, 10, 40, false, "cyan", calcThermistor);
temp = createGraph(document.getElementById("analog"), "Analog Input", 100, 128, 0, 1023, false, "cyan");
heap = createGraph(document.getElementById("heap"), "Current Heap", 100, 125, 22000, 25000, true, "orange");
digi = createDigiGraph(document.getElementById("digital"), "GPIO", 100, 146, [0, 4, 5, 16], "gold");
run();
}
</script>
</head>
<body id="index" style="margin:0; padding:0;" onload="onBodyLoad()">
<div id="controls" style="display: block; border: 1px solid rgb(68, 68, 68); padding: 5px; margin: 5px; width: 362px; background-color: rgb(238, 238, 238);">
<label>Period (ms):</label>
<input type="number" id="refresh-rate"/>
<input type="button" id="start-button" value="Start"/>
<input type="button" id="stop-button" value="Stop"/>
</div>
<div id="heap"></div>
<div id="analog"></div>
<div id="digital"></div>
</body>
</html>