kopia lustrzana https://github.com/Aircoookie/WLED
				
				
				
			Merge branch 'filesystem' into master-to-fs
						commit
						b6789e0011
					
				|  | @ -27,11 +27,11 @@ default_envs = travis_esp8266, travis_esp32 | |||
| ; default_envs = esp01_1m_ota | ||||
| ; default_envs = esp01_1m_full | ||||
| ; default_envs = esp07 | ||||
| ; default_envs = d1_mini | ||||
| default_envs = d1_mini | ||||
| ; default_envs = heltec_wifi_kit_8 | ||||
| ; default_envs = h803wf | ||||
| ; default_envs = d1_mini_debug | ||||
| ; default_envs = d1_mini_ota | ||||
| ;default_envs = d1_mini_ota | ||||
| ; default_envs = esp32dev | ||||
| ; default_envs = esp8285_4CH_MagicHome | ||||
| ; default_envs = esp8285_4CH_H801 | ||||
|  |  | |||
|  | @ -46,6 +46,11 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet); | |||
| 
 | ||||
| //file.cpp
 | ||||
| bool handleFileRead(AsyncWebServerRequest*, String path); | ||||
| bool writeObjectToFileUsingId(const char* file, uint16_t id, JsonDocument* content); | ||||
| bool writeObjectToFile(const char* file, const char* key, JsonDocument* content); | ||||
| bool appendObjectToFile(const char* file, const char* key, JsonDocument* content, File input); | ||||
| bool readObjectFromFileUsingId(const char* file, uint16_t id, JsonDocument* dest); | ||||
| bool readObjectFromFile(const char* file, const char* key, JsonDocument* dest); | ||||
| 
 | ||||
| //hue.cpp
 | ||||
| void handleHue(); | ||||
|  |  | |||
							
								
								
									
										190
									
								
								wled00/file.cpp
								
								
								
								
							
							
						
						
									
										190
									
								
								wled00/file.cpp
								
								
								
								
							|  | @ -13,6 +13,192 @@ | |||
| #include "SPIFFSEditor.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifndef WLED_DISABLE_FILESYSTEM | ||||
| 
 | ||||
| //find() that reads and buffers data from file stream in 256-byte blocks.
 | ||||
| //Significantly faster, f.find(key) can take SECONDS for multi-kB files
 | ||||
| bool bufferedFind(const char *target, File f) { | ||||
|   size_t targetLen = strlen(target); | ||||
|   Serial.println(target); | ||||
|   //Serial.println(f.position());
 | ||||
|   size_t index = 0; | ||||
|   byte c; | ||||
|   uint16_t bufsize = 0, count = 0; | ||||
|   byte buf[256]; | ||||
| 
 | ||||
|   while (f.position() < f.size() -1) { | ||||
|     //c = f.read();
 | ||||
|     //Serial.println(f.position());
 | ||||
|     bufsize = f.read(buf, 256); | ||||
|     count = 0; | ||||
|     while (count < bufsize) { | ||||
|       if(buf[count] != target[index]) | ||||
|       index = 0; // reset index if any char does not match
 | ||||
| 
 | ||||
|       if(buf[count] == target[index]) { | ||||
|         if(++index >= targetLen) { // return true if all chars in the target match
 | ||||
|           f.seek((f.position() - bufsize) + count +1); | ||||
|           return true; | ||||
|         } | ||||
|       } | ||||
|       count++; | ||||
|     } | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| //find empty spots in file stream in 256-byte blocks.
 | ||||
| bool bufferedFindSpace(uint16_t targetLen, File f) { | ||||
|   size_t index = 0; | ||||
|   byte c; | ||||
|   uint16_t bufsize = 0, count = 0; | ||||
|   byte buf[256]; | ||||
| 
 | ||||
|   while (f.position() < f.size() -1) { | ||||
|     bufsize = f.read(buf, 256); | ||||
|     count = 0; | ||||
|     while (count < bufsize) { | ||||
|       if(buf[count] != ' ') | ||||
|       index = 0; // reset index if not space
 | ||||
| 
 | ||||
|       if(buf[count] == ' ') { | ||||
|         if(++index >= targetLen) { // return true if space long enough
 | ||||
|           f.seek(f.position() - targetLen); | ||||
|           return true; | ||||
|         } | ||||
|       } | ||||
|       count++; | ||||
|     } | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| bool writeObjectToFileUsingId(const char* file, uint16_t id, JsonDocument* content) | ||||
| { | ||||
|   char objKey[10]; | ||||
|   sprintf(objKey, "\"%ld\":", id); | ||||
|   writeObjectToFile(file, objKey, content); | ||||
| } | ||||
| 
 | ||||
| bool writeObjectToFile(const char* file, const char* key, JsonDocument* content) | ||||
| { | ||||
|   uint32_t pos = 0; | ||||
|   File f = SPIFFS.open(file, "r+"); | ||||
|   if (!f) f = SPIFFS.open(file,"w"); | ||||
|   if (!f) return false; | ||||
|   //f.setTimeout(1);
 | ||||
|   f.seek(0, SeekSet); | ||||
|    | ||||
|   if (!bufferedFind(key, f)) //key does not exist in file
 | ||||
|   { | ||||
|     return appendObjectToFile(file, key, content, f); | ||||
|   }  | ||||
|    | ||||
|   //exists
 | ||||
|   pos = f.position(); | ||||
|   //measure out end of old object
 | ||||
|   StaticJsonDocument<512> doc; | ||||
|   deserializeJson(doc, f); | ||||
|   uint32_t pos2 = f.position(); | ||||
|   uint32_t oldLen = pos2 - pos; | ||||
|    | ||||
|   if (!content->isNull() && measureJson(*content) <= oldLen)  //replace
 | ||||
|   { | ||||
|     serializeJson(*content, f); | ||||
|     //pad rest
 | ||||
|     for (uint32_t i = f.position(); i < pos2; i++) { | ||||
|       f.write(' '); | ||||
|     } | ||||
|   } else { //delete
 | ||||
|     pos -+ strlen(key); | ||||
|     oldLen = pos2 - pos; | ||||
|     f.seek(pos, SeekSet); | ||||
|     for (uint32_t i = pos; i < pos2; i++) { | ||||
|       f.write(' '); | ||||
|     } | ||||
|     if (!content->isNull()) return appendObjectToFile(file, key, content, f); | ||||
|   } | ||||
|   f.close(); | ||||
| } | ||||
| 
 | ||||
| bool appendObjectToFile(const char* file, const char* key, JsonDocument* content, File input) | ||||
| { | ||||
|   Serial.println("Append"); | ||||
|   uint32_t pos = 0; | ||||
|   File f = (input) ? input : SPIFFS.open(file, "r+"); | ||||
|   if (!f) f = SPIFFS.open(file,"w"); | ||||
|   if (!f) return false; | ||||
|   if (f.size() < 3) f.print("{}"); | ||||
|    | ||||
|   //if there is enough empty space in file, insert there instead of appending
 | ||||
|   uint32_t contentLen = measureJson(*content); | ||||
|   Serial.print("clen"); Serial.println(contentLen); | ||||
|   if (bufferedFindSpace(contentLen, f)) { | ||||
|     Serial.println("space"); | ||||
|     serializeJson(*content, f); | ||||
|     return true; | ||||
|   } | ||||
|    | ||||
|   //check if last character in file is '}' (typical)
 | ||||
|   f.seek(1, SeekEnd); | ||||
|   if (f.read() == '}') pos = f.size() -1; | ||||
|    | ||||
|   if (pos == 0) //not found
 | ||||
|   { | ||||
|     Serial.println("not}"); | ||||
|     while (bufferedFind("}",f)) //find last closing bracket in JSON if not last char
 | ||||
|     { | ||||
|       pos = f.position(); | ||||
|     } | ||||
|   } | ||||
|   Serial.print("pos"); Serial.println(pos); | ||||
|   if (pos < 3) | ||||
|   { | ||||
|     f.seek(pos -1, SeekSet); | ||||
|     f.write(','); | ||||
|   } else { //file content is not valid JSON object
 | ||||
|     f.seek(0, SeekSet); | ||||
|     f.write('{'); //start JSON
 | ||||
|   } | ||||
| 
 | ||||
|   //f.print("\"");
 | ||||
|   f.print(key); | ||||
|   //f.print("\":");
 | ||||
|   //Append object
 | ||||
|   serializeJson(*content, f); | ||||
|    | ||||
|   f.write('}'); | ||||
|   f.close(); | ||||
| } | ||||
| 
 | ||||
| bool readObjectFromFileUsingId(const char* file, uint16_t id, JsonDocument* dest) | ||||
| { | ||||
|   char objKey[10]; | ||||
|   sprintf(objKey, "\"%ld\":", id); | ||||
|   readObjectFromFile(file, objKey, dest); | ||||
| } | ||||
| 
 | ||||
| bool readObjectFromFile(const char* file, const char* key, JsonDocument* dest) | ||||
| { | ||||
|   //if (id == playlistId) return true;
 | ||||
|   //playlist is already loaded, but we can't be sure that file hasn't changed since loading
 | ||||
|    | ||||
|   File f = SPIFFS.open(file, "r"); | ||||
|   if (!f) return false; | ||||
|   //f.setTimeout(0);
 | ||||
|   //Serial.println(key);
 | ||||
|   if (!bufferedFind(key, f)) //key does not exist in file
 | ||||
|   { | ||||
|     f.close(); | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   deserializeJson(*dest, f); | ||||
| 
 | ||||
|   f.close(); | ||||
|   return true; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #if !defined WLED_DISABLE_FILESYSTEM && defined WLED_ENABLE_FS_SERVING | ||||
| //Un-comment any file types you need
 | ||||
|  | @ -38,11 +224,11 @@ bool handleFileRead(AsyncWebServerRequest* request, String path){ | |||
|   DEBUG_PRINTLN("FileRead: " + path); | ||||
|   if(path.endsWith("/")) path += "index.htm"; | ||||
|   String contentType = getContentType(request, path); | ||||
|   String pathWithGz = path + ".gz"; | ||||
|   /*String pathWithGz = path + ".gz";
 | ||||
|   if(SPIFFS.exists(pathWithGz)){ | ||||
|     request->send(SPIFFS, pathWithGz, contentType); | ||||
|     return true; | ||||
|   } | ||||
|   }*/ | ||||
|   if(SPIFFS.exists(path)) { | ||||
|     request->send(SPIFFS, path, contentType); | ||||
|     return true; | ||||
|  |  | |||
|  | @ -85,6 +85,14 @@ void WLED::loop() | |||
|     handleHue(); | ||||
|     handleBlynk(); | ||||
| 
 | ||||
|     if (presetToApply) { | ||||
|       StaticJsonDocument<1024> temp; | ||||
|       errorFlag = !readObjectFromFileUsingId("/presets.json", presetToApply, &temp); | ||||
|       serializeJson(temp, Serial); | ||||
|       deserializeState(temp.as<JsonObject>()); | ||||
|       presetToApply = 0; | ||||
|     } | ||||
| 
 | ||||
|     yield(); | ||||
|     if (!offMode) | ||||
|       strip.service(); | ||||
|  |  | |||
|  | @ -34,9 +34,9 @@ | |||
|   #define WLED_ENABLE_WEBSOCKETS | ||||
| #endif | ||||
| 
 | ||||
| #define WLED_DISABLE_FILESYSTEM        // SPIFFS is not used by any WLED feature yet
 | ||||
| //#define WLED_ENABLE_FS_SERVING   // Enable sending html file from SPIFFS before serving progmem version
 | ||||
| //#define WLED_ENABLE_FS_EDITOR    // enable /edit page for editing SPIFFS content. Will also be disabled with OTA lock
 | ||||
| //#define WLED_DISABLE_FILESYSTEM        // SPIFFS is not used by any WLED feature yet
 | ||||
| #define WLED_ENABLE_FS_SERVING   // Enable sending html file from SPIFFS before serving progmem version
 | ||||
| #define WLED_ENABLE_FS_EDITOR    // enable /edit page for editing SPIFFS content. Will also be disabled with OTA lock
 | ||||
| 
 | ||||
| // to toggle usb serial debug (un)comment the following line
 | ||||
| //#define WLED_DEBUG
 | ||||
|  | @ -167,6 +167,8 @@ WLED_GLOBAL char otaPass[33] _INIT(DEFAULT_OTA_PASS); | |||
| // Hardware CONFIG (only changeble HERE, not at runtime)
 | ||||
| // LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
 | ||||
| 
 | ||||
| WLED_GLOBAL byte presetToApply _INIT(0);  | ||||
| 
 | ||||
| WLED_GLOBAL byte auxDefaultState _INIT(0);                         // 0: input 1: high 2: low
 | ||||
| WLED_GLOBAL byte auxTriggeredState _INIT(0);                       // 0: input 1: high 2: low
 | ||||
| WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org");   // NTP server to use
 | ||||
|  |  | |||
|  | @ -621,6 +621,12 @@ void savedToPresets() | |||
| 
 | ||||
| bool applyPreset(byte index, bool loadBri) | ||||
| { | ||||
|   StaticJsonDocument<1024> temp; | ||||
|   errorFlag = !readObjectFromFileUsingId("/presets.json", index, &temp); | ||||
|   serializeJson(temp, Serial); | ||||
|   deserializeState(temp.as<JsonObject>()); | ||||
|   //presetToApply = index;
 | ||||
|   return true; | ||||
|   if (index == 255 || index == 0) | ||||
|   { | ||||
|     loadSettingsFromEEPROM(false);//load boot defaults
 | ||||
|  | @ -668,6 +674,12 @@ bool applyPreset(byte index, bool loadBri) | |||
| 
 | ||||
| void savePreset(byte index, bool persist) | ||||
| { | ||||
|   StaticJsonDocument<1024> doc; | ||||
|   serializeState(doc.to<JsonObject>()); | ||||
|   doc["p"]=50; | ||||
|   serializeJson(doc, Serial); | ||||
|   writeObjectToFileUsingId("/presets.json", index, &doc); | ||||
|   return; | ||||
|   if (index > 16) return; | ||||
|   if (index < 1) {saveSettingsToEEPROM();return;} | ||||
|   uint16_t i = 380 + index*20;//min400
 | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Aircoookie
						Aircoookie