mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-03-30 08:52:11 +02:00
backup with RAM
This commit is contained in:
parent
9113e58ec4
commit
2509030c49
9 changed files with 121 additions and 19 deletions
|
|
@ -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
|
||||||
|
|
@ -133,12 +133,12 @@ def minify_svg(text: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
MINIFIERS = {
|
MINIFIERS = {
|
||||||
# ".html": minify_html,
|
".html": minify_html,
|
||||||
# ".htm": minify_html,
|
".htm": minify_html,
|
||||||
# ".css": minify_css,
|
".css": minify_css,
|
||||||
# ".js": minify_js,
|
# ".js": minify_js,
|
||||||
# ".json": minify_json,
|
# ".json": minify_json,
|
||||||
# ".svg": minify_svg,
|
".svg": minify_svg,
|
||||||
# ".xml": minify_svg, # same approach works for generic XML
|
# ".xml": minify_svg, # same approach works for generic XML
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,11 @@
|
||||||
[platformio]
|
[platformio]
|
||||||
default_envs = esp32dev
|
default_envs = esp32dev
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[env:esp32dev]
|
[env:esp32dev]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
board = esp32-c3-devkitm-1
|
board = esp32dev
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
bblanchon/ArduinoJson@^7.2.2
|
bblanchon/ArduinoJson@^7.2.2
|
||||||
|
|
@ -23,7 +25,11 @@ lib_deps =
|
||||||
extra_scripts = pre:minify.py
|
extra_scripts = pre:minify.py
|
||||||
board_build.partitions = min_spiffs.csv
|
board_build.partitions = min_spiffs.csv
|
||||||
board_build.filesystem = littlefs
|
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]
|
[env:esp32devdbg]
|
||||||
build_type = debug
|
build_type = debug
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
|
|
@ -36,4 +42,17 @@ lib_deps =
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
extra_scripts = pre:minify.py
|
extra_scripts = pre:minify.py
|
||||||
board_build.partitions = min_spiffs.csv
|
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
|
board_build.filesystem = littlefs
|
||||||
|
|
@ -22,10 +22,15 @@ bool ConfigFile::begin(const char* filename, bool readOnly) {
|
||||||
this->_opened = true;
|
this->_opened = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool ConfigFile::beginRAM(String *buf) {
|
||||||
|
_ramBuf = buf;
|
||||||
|
_opened = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
void ConfigFile::end() {
|
void ConfigFile::end() {
|
||||||
if(this->isOpen()) {
|
if(this->isOpen()) {
|
||||||
if(!this->readOnly) this->file.flush();
|
if(_ramBuf) { _ramBuf = nullptr; }
|
||||||
this->file.close();
|
else { if(!this->readOnly) this->file.flush(); this->file.close(); }
|
||||||
}
|
}
|
||||||
this->_opened = false;
|
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) {
|
bool ConfigFile::writeString(const char *val, size_t len, const char tok) {
|
||||||
if(!this->isOpen()) return false;
|
if(!this->isOpen()) return false;
|
||||||
int slen = strlen(val);
|
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(slen > 0)
|
||||||
if(this->file.write((uint8_t *)val, slen) != slen) return false;
|
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.
|
// 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(' ');
|
this->file.write(' ');
|
||||||
slen++;
|
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) {
|
bool ConfigFile::writeVarString(const char *val, const char tok) {
|
||||||
if(!this->isOpen()) return false;
|
if(!this->isOpen()) return false;
|
||||||
int slen = strlen(val);
|
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);
|
this->writeChar(CFG_TOK_QUOTE);
|
||||||
if(slen > 0) if(this->file.write((uint8_t *)val, slen) != slen) return false;
|
if(slen > 0) if(this->file.write((uint8_t *)val, slen) != slen) return false;
|
||||||
this->writeChar(CFG_TOK_QUOTE);
|
this->writeChar(CFG_TOK_QUOTE);
|
||||||
|
|
@ -210,6 +228,7 @@ bool ConfigFile::writeVarString(const char *val, const char tok) {
|
||||||
}
|
}
|
||||||
bool ConfigFile::writeChar(const char val) {
|
bool ConfigFile::writeChar(const char val) {
|
||||||
if(!this->isOpen()) return false;
|
if(!this->isOpen()) return false;
|
||||||
|
if(_ramBuf) { _ramBuf->concat(val); return true; }
|
||||||
if(this->file.write(static_cast<uint8_t>(val)) == 1) return true;
|
if(this->file.write(static_cast<uint8_t>(val)) == 1) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,14 @@ struct config_header_t {
|
||||||
class ConfigFile {
|
class ConfigFile {
|
||||||
protected:
|
protected:
|
||||||
File file;
|
File file;
|
||||||
|
String *_ramBuf = nullptr;
|
||||||
bool readOnly = false;
|
bool readOnly = false;
|
||||||
bool begin(const char *filename, bool readOnly = false);
|
bool begin(const char *filename, bool readOnly = false);
|
||||||
uint32_t startRecPos = 0;
|
uint32_t startRecPos = 0;
|
||||||
bool _opened = false;
|
bool _opened = false;
|
||||||
public:
|
public:
|
||||||
config_header_t header;
|
config_header_t header;
|
||||||
|
bool beginRAM(String *buf);
|
||||||
void end();
|
void end();
|
||||||
bool isOpen();
|
bool isOpen();
|
||||||
bool seekRecordByIndex(uint16_t ndx);
|
bool seekRecordByIndex(uint16_t ndx);
|
||||||
|
|
|
||||||
|
|
@ -633,8 +633,10 @@ void SomfyShadeController::commit() {
|
||||||
void SomfyShadeController::writeBackup() {
|
void SomfyShadeController::writeBackup() {
|
||||||
if(git.lockFS) return;
|
if(git.lockFS) return;
|
||||||
esp_task_wdt_reset(); // Make sure we don't reset inadvertently.
|
esp_task_wdt_reset(); // Make sure we don't reset inadvertently.
|
||||||
|
this->backupData = "";
|
||||||
|
this->backupData.reserve(16384);
|
||||||
ShadeConfigFile file;
|
ShadeConfigFile file;
|
||||||
file.begin("/controller.backup", false);
|
file.beginRAM(&this->backupData);
|
||||||
file.backup(this);
|
file.backup(this);
|
||||||
file.end();
|
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) { this->sendCommand(cmd, this->repeats); }
|
||||||
void SomfyShade::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSize) {
|
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
|
// This sendCommand function will always be called externally. sendCommand at the remote level
|
||||||
// is expected to be called internally when the motor needs commanded.
|
// is expected to be called internally when the motor needs commanded.
|
||||||
if(this->bitLength == 0) this->bitLength = somfy.transceiver.config.type;
|
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) {
|
else if(cmd == somfy_commands::My) {
|
||||||
if(this->isToggle() || this->shadeType == shade_types::drycontact)
|
if(this->isToggle() || this->shadeType == shade_types::drycontact)
|
||||||
SomfyRemote::sendCommand(cmd, repeat);
|
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()) {
|
else if(this->isIdle()) {
|
||||||
this->moveToMyPosition();
|
this->moveToMyPosition();
|
||||||
|
Serial.print("Send command end 2\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -2951,6 +2958,7 @@ void SomfyShade::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSiz
|
||||||
else {
|
else {
|
||||||
SomfyRemote::sendCommand(cmd, repeat, stepSize);
|
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) { this->sendCommand(cmd, this->repeats); }
|
||||||
void SomfyGroup::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSize) {
|
void SomfyGroup::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSize) {
|
||||||
|
|
|
||||||
|
|
@ -578,6 +578,7 @@ class SomfyShadeController {
|
||||||
void processWaitingFrame();
|
void processWaitingFrame();
|
||||||
void commit();
|
void commit();
|
||||||
void writeBackup();
|
void writeBackup();
|
||||||
|
String backupData;
|
||||||
bool loadShadesFile(const char *filename);
|
bool loadShadesFile(const char *filename);
|
||||||
#ifdef USE_NVS
|
#ifdef USE_NVS
|
||||||
bool loadLegacy();
|
bool loadLegacy();
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include "Somfy.h"
|
#include "Somfy.h"
|
||||||
#include "MQTT.h"
|
#include "MQTT.h"
|
||||||
#include "GitOTA.h"
|
#include "GitOTA.h"
|
||||||
|
#include "esp_core_dump.h"
|
||||||
|
|
||||||
ConfigSettings settings;
|
ConfigSettings settings;
|
||||||
Web webServer;
|
Web webServer;
|
||||||
|
|
@ -20,11 +21,61 @@ MQTTClass mqtt;
|
||||||
GitUpdater git;
|
GitUpdater git;
|
||||||
|
|
||||||
uint32_t oldheap = 0;
|
uint32_t oldheap = 0;
|
||||||
void setup() {
|
|
||||||
|
void inline checkCoreDumpPartition() {
|
||||||
|
esp_core_dump_init();
|
||||||
|
esp_core_dump_summary_t *summary =
|
||||||
|
static_cast<esp_core_dump_summary_t *>(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.begin(115200);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
Serial.println("Startup/Boot....");
|
Serial.println("Startup/Boot....");
|
||||||
Serial.println("Mounting File System...");
|
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");
|
if(LittleFS.begin()) Serial.println("File system mounted successfully");
|
||||||
else Serial.println("Error mounting file system");
|
else Serial.println("Error mounting file system");
|
||||||
settings.begin();
|
settings.begin();
|
||||||
|
|
|
||||||
|
|
@ -858,14 +858,11 @@ void Web::handleBackup(WebServer &server, bool attach) {
|
||||||
}
|
}
|
||||||
Serial.println("Saving current shade information");
|
Serial.println("Saving current shade information");
|
||||||
somfy.writeBackup();
|
somfy.writeBackup();
|
||||||
File file = LittleFS.open("/controller.backup", "r");
|
if(somfy.backupData.length() == 0) {
|
||||||
if (!file) {
|
server.send(500, _encoding_text, "backup failed");
|
||||||
Serial.println("Error opening shades.cfg");
|
|
||||||
server.send(500, _encoding_text, "shades.cfg");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
server.streamFile(file, _encoding_text);
|
server.send(200, _encoding_text, somfy.backupData);
|
||||||
file.close();
|
|
||||||
}
|
}
|
||||||
void Web::handleSetPositions(WebServer &server) {
|
void Web::handleSetPositions(WebServer &server) {
|
||||||
webServer.sendCORSHeaders(server);
|
webServer.sendCORSHeaders(server);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue