diff --git a/platformio.ini b/platformio.ini index 492799df..fbb630b8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,7 +16,7 @@ extra_configs = # ------------------------------------------------------------------------------ # Travis CI binaries (comment this out when building for single board) -default_envs = d1_mini, esp01, esp01_1m_ota, esp32dev +;default_envs = d1_mini, esp01, esp01_1m_ota, esp32dev # Release binaries ; default_envs = nodemcuv2, esp01, esp01_1m_ota, esp01_1m_full, esp32dev, custom_WS2801, custom_APA102, custom_LEDPIN_16, custom_LEDPIN_4, custom32_LEDPIN_16 @@ -27,11 +27,11 @@ default_envs = d1_mini, esp01, esp01_1m_ota, esp32dev ; 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 @@ -245,7 +245,7 @@ build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_HUESYNC -D WLED_USE_ board = d1_mini platform = ${common.platform_latest} board_build.ldscript = ${common.ldscript_4m1m} -build_flags = ${common.build_flags_esp8266} -D WLED_USE_ANALOG_LEDS -D SHOJO_PCB -D WLED_ENABLE_5CH_LEDS +build_flags = ${common.build_flags_esp8266} -D WLED_USE_ANALOG_LEDS -D WLED_USE_SHOJO_PCB -D WLED_ENABLE_5CH_LEDS # ------------------------------------------------------------------------------ # DEVELOPMENT BOARDS diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index faee293a..8a3f9544 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -14,6 +14,8 @@ //#define WLED_USE_ANALOG_LEDS //Uncomment for using "dumb" PWM controlled LEDs (see pins below, default R: gpio5, G: 12, B: 15, W: 13) //#define WLED_USE_H801 //H801 controller. Please uncomment #define WLED_USE_ANALOG_LEDS as well //#define WLED_USE_5CH_LEDS //5 Channel H801 for cold and warm white +//#define WLED_USE_BWLT11 +//#define WLED_USE_SHOJO_PCB #ifndef BTNPIN #define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended) @@ -62,7 +64,7 @@ #define GPIN 4 //G pin for analog LED strip #define BPIN 14 //B pin for analog LED strip #define WPIN 5 //W pin for analog LED strip - #elif defined(SHOJO_PCB) + #elif defined(WLED_USE_SHOJO_PCB) //PWM pins - to use with Shojo PCB (https://www.bastelbunker.de/esp-rgbww-wifi-led-controller-vbs-edition/) #define RPIN 14 //R pin for analog LED strip #define GPIN 4 //G pin for analog LED strip diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 2d8401bc..78a74b03 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -45,7 +45,13 @@ void handleDMX(); void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet); //file.cpp +bool find(const char* target, File f); bool handleFileRead(AsyncWebServerRequest*, String path); +bool writeObjectToFileUsing(const char* file, const char* key, JsonObject content, File input, bool doClose); +bool writeObjectToFile(const char* file, const char* key, JsonObject content, File input, bool doClose); +bool appendObjectToFile(const char* file, const char* key, JsonObject& content, File input, bool doClose); +bool readObjectFromFileUsingId(const char* file, uint16_t id, JsonDocument* dest); +bool readObjectFromFile(const char* file, const char* key, JsonDocument* dest); //hue.cpp void handleHue(); diff --git a/wled00/file.cpp b/wled00/file.cpp index eb0dcb93..4a2cf278 100644 --- a/wled00/file.cpp +++ b/wled00/file.cpp @@ -13,6 +13,163 @@ #include "SPIFFSEditor.h" #endif +#ifndef WLED_DISABLE_FILESYSTEM + +bool find(const char *target, File f) { + size_t targetLen = strlen(target); + size_t index = 0; + int c; + + while(f.position() < f.size() -1) { + c = f.read(); + if(c != target[index]) + index = 0; // reset index if any char does not match + + if(c == target[index]) { + if(++index >= targetLen) { // return true if all chars in the target match + return true; + } + } + } + return false; +} + +bool writeObjectToFileUsingId(const char* file, uint16_t id, JsonObject content, File input, bool doClose = true) +{ + char objKey[10]; + sprintf(objKey, "\"%ld\":", id); + writeObjectToFile(file, objKey, content, input, doClose); +} + +bool writeObjectToFile(const char* file, const char* key, JsonObject content, File input, bool doClose = true) +{ + uint32_t pos = 0; + File f = (input) ? input : SPIFFS.open(file, "r+"); + if (!f) f = SPIFFS.open(file,"w"); + if (!f) return false; + //f.setTimeout(1); + f.seek(0, SeekSet); + + if (!find(key, f)) //key does not exist in file + { + return appendObjectToFile(file, key, content, f, true); + } + + //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, true); + } + f.close(); +} + +bool appendObjectToFile(const char* file, const char* key, JsonObject& content, File input, bool doClose = true) +{ + uint32_t pos = 0; + File f = (input) ? input : SPIFFS.open(file, "r+"); + if (!f) f = SPIFFS.open(file,"w"); + if (!f) return false; + f.setTimeout(1); + if (f.size() < 3) f.print("{}"); + + //if there is enough empty space in file, insert there instead of appending + uint32_t contentLen = measureJson(content); + uint32_t spaces = 0, spaceI = 0, spacesMax = 0, spaceMaxI = 0; + f.seek(1, SeekSet); + for (uint32_t i = 1; i < f.size(); i++) + { + if (f.read() == ' ') { + if (!spaces) spaceI = i; spaces++; + } else { + if (spaces > spacesMax) { spacesMax = spaces; spaceMaxI = spaceI;} + spaces = 0; + if (spacesMax >= contentLen) { + f.seek(spaceMaxI, SeekSet); + serializeJson(content, f); + return true; + } + } + } + + //check if last character in file is '}' (typical) + uint32_t lastByte = f.size() -1; + f.seek(1, SeekEnd); + if (f.read() == '}') pos = lastByte; + + if (pos == 0) //not found + { + while (find("}",f)) //find last closing bracket in JSON if not last char + { + pos = f.position(); + } + } + + if (pos) + { + 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('}'); + if (doClose) 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 (f.find(key)) //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 +195,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; diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 40ce6f60..5421d79c 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -81,6 +81,14 @@ void WLED::loop() handleHue(); handleBlynk(); + if (presetToApply) { + StaticJsonDocument<1024> temp; + errorFlag = !readObjectFromFileUsingId("/presets.json", presetToApply, &temp); + serializeJson(temp, Serial); + deserializeState(temp.as()); + presetToApply = 0; + } + yield(); if (!offMode) strip.service(); diff --git a/wled00/wled.h b/wled00/wled.h index c791f4ee..4aa8da78 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -29,9 +29,9 @@ #define WLED_ENABLE_ADALIGHT // saves 500b only //#define WLED_ENABLE_DMX // uses 3.5kb (use LEDPIN other than 2) -#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 @@ -158,6 +158,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 diff --git a/wled00/wled_eeprom.cpp b/wled00/wled_eeprom.cpp index 807d3a44..fc00c2c9 100644 --- a/wled00/wled_eeprom.cpp +++ b/wled00/wled_eeprom.cpp @@ -594,7 +594,7 @@ void savedToPresets() savedPresets &= ~(0x01 << (index-1)); } } - if (EEPROM.read(700) == 2) { + if (EEPROM.read(700) == 2 || EEPROM.read(700) == 3) { savedPresets |= 0x01 << 15; } else { @@ -604,6 +604,12 @@ void savedToPresets() bool applyPreset(byte index, bool loadBri) { + StaticJsonDocument<1024> temp; + errorFlag = !readObjectFromFileUsingId("/presets.json", index, &temp); + serializeJson(temp, Serial); + deserializeState(temp.as()); + //presetToApply = index; + return true; if (index == 255 || index == 0) { loadSettingsFromEEPROM(false);//load boot defaults