ESP32 | OTA 更新 | SPIFFS 中的配置文件

问题描述 投票:0回答:1

我正在创建一个项目,我想通过从服务器下载更新数据(固件和 SPIFFS 更新)来进行自动更新,我做到了并且它有效,但我有一个小问题,因为设备配置(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();
    }
}
configuration esp32 auto-update ota spiffs
1个回答
0
投票

我在搜索我遇到的类似问题时遇到了这个。对我来说,问题是我在开始更新之前没有卸载 SPIFSS 映像。

开始 OTA 更新之前

SPIFFS.end();
,OTA 更新完成后
SPIFFS.begin();

在我的例子中,用户从 SPIFFS 提供的 html 页面启动更新,因此需要在实际开始更新之前留出时间加载这些页面,因此将其添加到相关 html 页面的末尾。

<script>
$(document).ready(function() {
    $.post('/url-to-start-update', {}, function(response) {
        // Ignore the response
    });
});
</script>
© www.soinside.com 2019 - 2024. All rights reserved.