diff --git a/README.md b/README.md index 53aedd2..d857adf 100644 --- a/README.md +++ b/README.md @@ -82,3 +82,8 @@ Configuration of the Transceiver is done with the ELECHOUSE_CC1101 library which +pio pkg exec -p tool-esptoolpy -- esptool.py --port COM9 read_flash 0x3F0000 0x10000 coredump.bin + + + +esp-coredump info_corefile --core coredump.bin --core-format=raw --gdb C:\Users\oem\.platformio\packages\toolchain-xtensa-esp32\bin\xtensa-esp32-elf-gdb.exe .pio\build\esp32dev\firmware.elf > coredump_report.txt \ No newline at end of file diff --git a/minify.py b/minify.py index a5c581c..bff2956 100644 --- a/minify.py +++ b/minify.py @@ -133,12 +133,12 @@ def minify_svg(text: str) -> str: MINIFIERS = { - # ".html": minify_html, - # ".htm": minify_html, - # ".css": minify_css, + ".html": minify_html, + ".htm": minify_html, + ".css": minify_css, # ".js": minify_js, # ".json": minify_json, - # ".svg": minify_svg, + ".svg": minify_svg, # ".xml": minify_svg, # same approach works for generic XML } diff --git a/platformio.ini b/platformio.ini index 6bf731f..52fcb65 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,9 +11,11 @@ [platformio] default_envs = esp32dev + + [env:esp32dev] platform = espressif32 -board = esp32-c3-devkitm-1 +board = esp32dev framework = arduino lib_deps = bblanchon/ArduinoJson@^7.2.2 @@ -23,7 +25,11 @@ lib_deps = extra_scripts = pre:minify.py board_build.partitions = min_spiffs.csv board_build.filesystem = littlefs - +build_flags = + -DCONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=1 + -DCONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=1 + -DCONFIG_ESP_COREDUMP_CHECKSUM_CRC32=1 + [env:esp32devdbg] build_type = debug platform = espressif32 @@ -36,4 +42,17 @@ lib_deps = knolleary/PubSubClient@^2.8 extra_scripts = pre:minify.py board_build.partitions = min_spiffs.csv +board_build.filesystem = littlefs + +[env:esp32c3dev] +platform = espressif32 +board = esp32-c3-devkitm-1 +framework = arduino +lib_deps = + bblanchon/ArduinoJson@^7.2.2 + links2004/WebSockets@^2.7.3 + lsatan/SmartRC-CC1101-Driver-Lib@^2.5.7 + knolleary/PubSubClient@^2.8 +extra_scripts = pre:minify.py +board_build.partitions = min_spiffs.csv board_build.filesystem = littlefs \ No newline at end of file diff --git a/src/ConfigFile.cpp b/src/ConfigFile.cpp index e515bed..43fcbb7 100644 --- a/src/ConfigFile.cpp +++ b/src/ConfigFile.cpp @@ -22,10 +22,15 @@ bool ConfigFile::begin(const char* filename, bool readOnly) { this->_opened = true; return true; } +bool ConfigFile::beginRAM(String *buf) { + _ramBuf = buf; + _opened = true; + return true; +} void ConfigFile::end() { if(this->isOpen()) { - if(!this->readOnly) this->file.flush(); - this->file.close(); + if(_ramBuf) { _ramBuf = nullptr; } + else { if(!this->readOnly) this->file.flush(); this->file.close(); } } this->_opened = false; } @@ -187,10 +192,16 @@ bool ConfigFile::readVarString(char *buff, size_t len) { bool ConfigFile::writeString(const char *val, size_t len, const char tok) { if(!this->isOpen()) return false; int slen = strlen(val); + if(_ramBuf) { + if(slen > 0) _ramBuf->concat(val); + while(slen < (int)len - 1) { _ramBuf->concat(' '); slen++; } + if(tok != CFG_TOK_NONE) _ramBuf->concat(tok); + return true; + } if(slen > 0) if(this->file.write((uint8_t *)val, slen) != slen) return false; // Now we need to pad the end of the string so that it is of a fixed length. - while(slen < len - 1) { + while(slen < (int)len - 1) { this->file.write(' '); slen++; } @@ -202,6 +213,13 @@ bool ConfigFile::writeString(const char *val, size_t len, const char tok) { bool ConfigFile::writeVarString(const char *val, const char tok) { if(!this->isOpen()) return false; int slen = strlen(val); + if(_ramBuf) { + _ramBuf->concat((char)CFG_TOK_QUOTE); + if(slen > 0) _ramBuf->concat(val); + _ramBuf->concat((char)CFG_TOK_QUOTE); + if(tok != CFG_TOK_NONE) _ramBuf->concat(tok); + return true; + } this->writeChar(CFG_TOK_QUOTE); if(slen > 0) if(this->file.write((uint8_t *)val, slen) != slen) return false; this->writeChar(CFG_TOK_QUOTE); @@ -210,6 +228,7 @@ bool ConfigFile::writeVarString(const char *val, const char tok) { } bool ConfigFile::writeChar(const char val) { if(!this->isOpen()) return false; + if(_ramBuf) { _ramBuf->concat(val); return true; } if(this->file.write(static_cast(val)) == 1) return true; return false; } diff --git a/src/ConfigFile.h b/src/ConfigFile.h index 5ad9281..011e7a9 100644 --- a/src/ConfigFile.h +++ b/src/ConfigFile.h @@ -31,12 +31,14 @@ struct config_header_t { class ConfigFile { protected: File file; + String *_ramBuf = nullptr; bool readOnly = false; bool begin(const char *filename, bool readOnly = false); uint32_t startRecPos = 0; bool _opened = false; public: config_header_t header; + bool beginRAM(String *buf); void end(); bool isOpen(); bool seekRecordByIndex(uint16_t ndx); diff --git a/src/Somfy.cpp b/src/Somfy.cpp index bffebd2..0b5eff1 100644 --- a/src/Somfy.cpp +++ b/src/Somfy.cpp @@ -633,8 +633,10 @@ void SomfyShadeController::commit() { void SomfyShadeController::writeBackup() { if(git.lockFS) return; esp_task_wdt_reset(); // Make sure we don't reset inadvertently. + this->backupData = ""; + this->backupData.reserve(16384); ShadeConfigFile file; - file.begin("/controller.backup", false); + file.beginRAM(&this->backupData); file.backup(this); file.end(); } @@ -2888,6 +2890,7 @@ void SomfyShade::moveToMyPosition() { } void SomfyShade::sendCommand(somfy_commands cmd) { this->sendCommand(cmd, this->repeats); } void SomfyShade::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSize) { + Serial.print("Send command start\n"); // This sendCommand function will always be called externally. sendCommand at the remote level // is expected to be called internally when the motor needs commanded. if(this->bitLength == 0) this->bitLength = somfy.transceiver.config.type; @@ -2930,9 +2933,13 @@ void SomfyShade::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSiz else if(cmd == somfy_commands::My) { if(this->isToggle() || this->shadeType == shade_types::drycontact) SomfyRemote::sendCommand(cmd, repeat); - else if(this->shadeType == shade_types::drycontact2) return; + else if(this->shadeType == shade_types::drycontact2){ + Serial.print("Send command start 1\n"); + return; + } else if(this->isIdle()) { - this->moveToMyPosition(); + this->moveToMyPosition(); + Serial.print("Send command end 2\n"); return; } else { @@ -2951,6 +2958,7 @@ void SomfyShade::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSiz else { SomfyRemote::sendCommand(cmd, repeat, stepSize); } + Serial.print("Send command end\n"); } void SomfyGroup::sendCommand(somfy_commands cmd) { this->sendCommand(cmd, this->repeats); } void SomfyGroup::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSize) { diff --git a/src/Somfy.h b/src/Somfy.h index bc5c99b..7f99703 100644 --- a/src/Somfy.h +++ b/src/Somfy.h @@ -578,6 +578,7 @@ class SomfyShadeController { void processWaitingFrame(); void commit(); void writeBackup(); + String backupData; bool loadShadesFile(const char *filename); #ifdef USE_NVS bool loadLegacy(); diff --git a/src/SomfyController.ino b/src/SomfyController.ino index 464d179..a76c7e2 100644 --- a/src/SomfyController.ino +++ b/src/SomfyController.ino @@ -9,6 +9,7 @@ #include "Somfy.h" #include "MQTT.h" #include "GitOTA.h" +#include "esp_core_dump.h" ConfigSettings settings; Web webServer; @@ -20,11 +21,61 @@ MQTTClass mqtt; GitUpdater git; uint32_t oldheap = 0; -void setup() { + +void inline checkCoreDumpPartition() { + esp_core_dump_init(); + esp_core_dump_summary_t *summary = + static_cast(malloc(sizeof(esp_core_dump_summary_t))); + if (summary) { + esp_err_t err = esp_core_dump_get_summary(summary); + if (err == ESP_OK) { + log_i("Getting core dump summary ok."); + + } else { + log_e("Getting core dump summary not ok. Error: %d", (int)err); + log_e("Probably no coredump present yet."); + log_e("esp_core_dump_image_check() = %d", esp_core_dump_image_check()); + } + free(summary); + } +} + +void listDir(const char *dirname, uint8_t levels) { + Serial.printf("Listing: %s\n", dirname); + File root = LittleFS.open(dirname); + if (!root || !root.isDirectory()) { + Serial.println("Failed to open directory"); + return; + } + File file = root.openNextFile(); + while (file) { + if (file.isDirectory()) { + Serial.printf(" DIR : %s\n", file.name()); + if (levels) listDir(file.path(), levels - 1); + } else { + Serial.printf(" FILE: %-30s %d bytes\n", file.name(), file.size()); + } + file = root.openNextFile(); + } +} + +void setup() { Serial.begin(115200); Serial.println(); Serial.println("Startup/Boot...."); Serial.println("Mounting File System..."); + checkCoreDumpPartition(); + + if (LittleFS.begin()) { + Serial.printf("\nTotal: %d bytes\n", LittleFS.totalBytes()); + Serial.printf("Used: %d bytes\n", LittleFS.usedBytes()); + Serial.printf("Free: %d bytes\n", LittleFS.totalBytes() - LittleFS.usedBytes()); + Serial.println(); + listDir("/", 3); +} else { + Serial.println("LittleFS mount failed!"); +} + if(LittleFS.begin()) Serial.println("File system mounted successfully"); else Serial.println("Error mounting file system"); settings.begin(); diff --git a/src/Web.cpp b/src/Web.cpp index b4f481d..832b153 100644 --- a/src/Web.cpp +++ b/src/Web.cpp @@ -858,14 +858,11 @@ void Web::handleBackup(WebServer &server, bool attach) { } Serial.println("Saving current shade information"); somfy.writeBackup(); - File file = LittleFS.open("/controller.backup", "r"); - if (!file) { - Serial.println("Error opening shades.cfg"); - server.send(500, _encoding_text, "shades.cfg"); + if(somfy.backupData.length() == 0) { + server.send(500, _encoding_text, "backup failed"); return; } - server.streamFile(file, _encoding_text); - file.close(); + server.send(200, _encoding_text, somfy.backupData); } void Web::handleSetPositions(WebServer &server) { webServer.sendCORSHeaders(server);