mirror of
				https://github.com/esp8266/Arduino.git
				synced 2025-10-27 05:56:11 +03:00 
			
		
		
		
	Remove SPIFFS wrapper
This commit is contained in:
		| @@ -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> |  | ||||||
		Reference in New Issue
	
	Block a user