I am creating a project where I want to do auto update by downloading update data from the server (FIRMWARE and SPIFFS update), I did it and it works, but I have a little problem because the device configuration (wifi password, ssid etc.) is saved on the SPIFFS partition.
But as you can guess, updating SPIFFS with a .bin image will remove the file from the configuration. I came up with the idea to load the configuration into RAM before updating SPIFFS and then overwrite the already updated configuration file with the data previously loaded into RAM after the update.
But the problem is with the solution that after restarting the board, the configuration file has the update data, not the RAM overwritten. But when the board is booted 5-10 times, the actual configuration data read from RAM suddenly appears in the configuration file. It is a bit problematic and it shouldn't be a solution that should be included in the software, because it may not always be loaded on all board.
Does anyone know how effectively you can overwrite the update data before restarting the board?
I will add that I use the default memory partitioning layout:
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x140000,
app1, app, ota_1, 0x150000,0x140000,
spiffs, data, spiffs, 0x290000,0x170000,
This is code:
void makeUpdate(String host, String bin, int command = 0)
{
WiFiClientSecure client;
client.setCACert(github_cert);
long contentLength = 0;
bool isValidContentType = false;
Serial.println("Connecting to: " + String(host));
if (client.connect(host.c_str(), PORT)){
Serial.println("Fetching Bin: " + String(bin));
client.print(String("GET ") + bin + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Cache-Control: no-cache\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0){
if (millis() - timeout > 5000){
Serial.println("Client Timeout !");
client.stop();
return;
}
}
while (client.available()){
String line = client.readStringUntil('\n');
line.trim();
if (!line.length()) break;
if (line.startsWith("HTTP/1.1")){
if (line.indexOf("200") < 0){
Serial.println("Got a non 200 status code from server. Exiting OTA Update.");
break;
}
}
if (line.startsWith("Content-Length: ")){
contentLength = atol((this->getHeaderValue(line, "Content-Length: ")).c_str());
Serial.println("Got " + String(contentLength) + " bytes from server");
}
if (line.startsWith("Content-Type: ")){
String contentType = this->getHeaderValue(line, "Content-Type: ");
Serial.println("Got " + contentType + " payload.");
if (contentType == "application/octet-stream") isValidContentType = true;
}
}
}
else Serial.println("Connection to " + String(host) + " failed. Please check your setup");
Serial.println("contentLength : " + String(contentLength) + ", isValidContentType : " + String(isValidContentType));
String configFileSave = "";
if (contentLength && isValidContentType){
//*************** This is read config file **************************
if (command == U_SPIFFS){
Serial.printf("Reading config file: %s\r\n", CONFIG_FILE);
File file = SPIFFS.open(CONFIG_FILE);
if (!file || file.isDirectory()){
Serial.println("======Failed to open config file======");
return;
}
configFileSave = file.readString();
file.close();
Serial.println("--Configuration file reading complete--");
}
//*************** This is read config file **************************
bool canBegin = Update.begin(contentLength, command, LED_BUILTIN, HIGH);
if (canBegin){
Serial.println("Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience!");
size_t written = Update.writeStream(client);
if (written == contentLength) Serial.println("Written : " + String(written) + " successfully");
else Serial.println("Written only : " + String(written) + "/" + String(contentLength) + ". Retry?");
if (Update.end()){
Serial.println("OTA done!");
if (Update.isFinished()){
//*************** This is write config file **************************
if (command == U_SPIFFS){
Serial.printf("Writing config file: %s\r\n", CONFIG_FILE);
File file = SPIFFS.open(CONFIG_FILE, FILE_WRITE);
if (!file || file.isDirectory()){
Serial.println("======Failed to open config file======");
return;
}
if (!file.println(configFileSave)){
Serial.println("======Failed to write data to config file======");
return;
}
file.close();
Serial.println("--Completed writing data to the configuration file");
File f = SPIFFS.open(CONFIG_FILE, FILE_READ);
if (!f || f.isDirectory()){
Serial.println("======Failed to open config file======");
return;
}
String configFile = f.readString();
Serial.print("===Config File: ");
Serial.println(configFile);
f.close();
}
//*************** This is write config file **************************
Serial.println("Update successfully completed. Rebooting.");
// ESP.restart();
}
else Serial.println("Update not finished? Something went wrong!");
}
else Serial.println("Error Occurred. Error #: " + String(Update.getError()));
}
else{
Serial.println("Not enough space to begin OTA");
client.flush();
}
}
else{
Serial.println("There was no content in the response");
client.flush();
}
}