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:
parent
8bd0ad4653
commit
db1e033186
@ -209,7 +209,6 @@ void loop(void);
|
|||||||
#include "WString.h"
|
#include "WString.h"
|
||||||
|
|
||||||
#include "HardwareSerial.h"
|
#include "HardwareSerial.h"
|
||||||
#include "FileSystem.h"
|
|
||||||
#include "Esp.h"
|
#include "Esp.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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_ */
|
|
@ -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.
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
@ -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>
|
|
@ -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
@ -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;
|
|
||||||
}
|
|
@ -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,{}))
|
|
@ -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>
|
|
Loading…
x
Reference in New Issue
Block a user