ESP32 | OTA更新| spiffs中的配置文件
我正在创建一个项目,我想通过从服务器下载更新数据来进行自动更新(固件和Spiffs Update),我做到了,它有效,但是我有一些问题,因为设备配置(WiFi密码,SSID等) )保存在Spiffs分区中。
但是,您可以猜到,使用.bin映像更新spiffs将从配置中删除文件。我想出了在更新Spiffs之前将配置加载到RAM中的想法,然后在更新后使用先前已加载到RAM的数据覆盖已更新的配置文件。
但是问题在于解决方案是在重新启动板后,配置文件具有更新数据,而不是RAM覆盖。但是,当板启动5-10次时,从RAM读取的实际配置数据突然出现在配置文件中。 这有点有问题,它不应是软件中应包含的解决方案,因为它可能并不总是在所有板上加载。
有人知道您在重新启动板之前可以有效地覆盖更新数据吗?
我会补充说,我使用默认的内存分区布局:
# 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,
是代码:
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();
}
}
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();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我在搜索遇到的类似问题时遇到了这个问题。对我来说,问题是在开始更新之前,我没有在启用SPIFSS图像。
spiffs.end();
在启动OTA更新之前,然后spiffs.begin();
一旦OTA更新完成。在我的情况下,用户正在从Spiffs提供的HTML页面启动更新,因此需要在实际启动更新之前加载这些更新,因此将其添加到相关的HTML页面的末尾。
I came across this whilst searching a similar issue I was having. For me the problem was that I was not un-mounting the SPIFSS image before commencing the update.
SPIFFS.end();
before starting the OTA update, and thenSPIFFS.begin();
once the OTA update is complete.In my case a user was initiating the update from html pages served from SPIFFS, so needed to allow time for these to load before actually starting the update, so added this to the end of the relevant html page.