ESP8266 EEPROM or FLASH Error: Succesfully connecting to Wifi with false credentials

ESP8266 EEPROM or FLASH Error: Succesfully connecting to Wifi with false credentials

我正在构建一个基于 ESP8266 的小型传感器。为了设置 wifi,我托管了一个小型网络服务器,用户可以在其中输入凭据。

在设置例程中,我加载了凭据并尝试连接到 wifi。如果连接失败,esp 会创建一个 AP,用户可以输入新的凭据。

我有一些奇怪的行为。因为当我删除凭据时,esp 仍然成功连接到 wifi。但是 'serial.print()' 不显示任何凭据。

可能是EEPROM或FLASH的问题我不知道。我可以在多个 ESP 上重现此行为。

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>

ESP8266WebServer server(80);

const char *soft_ap_ssid = "Connect Sensor to MCU";
const char *soft_ap_password = "MySensor";

char ssid[32] = "";
char password[32] = "";

bool wifi_status;

void setup()
{
    Serial.begin(115200);
    Serial.println();
    delay(10);

    load_credentials();
    wifi_status = setup_wifi(5);

    if (!wifi_status)
    {
        setup_soft_ap();
        setup_server();
    }
}

void loop()
{
    if (!wifi_status)
    {
        server.handleClient();
    }
    else
    {
        Serial.println("Doing Sensor stuff");
        delay(2000);
        // Remove exsting credentials
        for( int i = 0; i < sizeof(ssid);  i++ ){
            ssid[i] = (char)0;
            password[i] = (char)0;
        }
        save_credentials();
    }
}

/*
############## Gernerische Code ########### TODO LIB
*/
bool setup_wifi(int timeout)
{
    int timeout_ctr = 0;
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password); //Connect to the WiFi network

    while ((WiFi.status() != WL_CONNECTED) && (timeout_ctr < timeout))
    {
        delay(500);
        Serial.println("...");
        timeout_ctr++;
    }

    if (WiFi.status())
    {
        Serial.print("IP address: ");
        Serial.println(WiFi.localIP()); //Print the local IP
    }
    else
    {
        Serial.println("Connection to MCU failed, setting up AP.");
    }

    return (WiFi.status() == WL_CONNECTED);
}

void setup_soft_ap()
{
    Serial.println();
    Serial.println("Creating WiFi AP...");

    WiFi.softAP(soft_ap_ssid, soft_ap_password);
    Serial.print("AP \"");
    Serial.print(soft_ap_ssid);
    Serial.println("\" is online.");
    Serial.print("IP address: ");
    Serial.println(WiFi.softAPIP());
    Serial.println();
}

void setup_server()
{
    server.on("/", handle_root);         //Associate the landingpage function to the path
    server.on("/submit", handle_submit); //Associate the handler function to the path
    server.begin();                     //Start the server
    Serial.println("Server listening");
}

void handle_root()
{
    const char *landingpage = "<html><head> <title>ESP8266 Demo</title> <style></style></head><body> <h1>Sensor einrichten</h1> <p> Eingabe der Wifi Daten </p><form action='/submit' method='post'> <input type='text' name='ssid' placeholder='Wifi SSID'> <input type='text' name='pw' placeholder='Wifi Password'> <input type='submit' value='Submit'> </form></body></html>";
    server.send(200, "text/html", landingpage);
}

void handle_submit()
{
    if (server.args() > 0)
    {
        Serial.println("POST:");
        Serial.println(server.arg("ssid"));
        Serial.println(server.arg("pw"));

        server.arg("ssid").toCharArray(ssid, sizeof(ssid) - 1);
        server.arg("pw").toCharArray(password, sizeof(password) - 1);

        Serial.println("credentials:");
        Serial.println(ssid);
        Serial.println(password);
        save_credentials();
    }
    server.sendHeader("Location", String("/"), true);
    server.send(302, "text/plain", "");
}

void load_credentials()
{
    EEPROM.begin(512);
    EEPROM.get(0, ssid);
    EEPROM.get(0 + sizeof(ssid), password);
    char ok[2 + 1];
    EEPROM.get(0 + sizeof(ssid) + sizeof(password), ok);
    EEPROM.end();
    if (String(ok) != String("OK"))
    {
        ssid[0] = 0;
        password[0] = 0;
    }
    Serial.println("Recovered credentials:");
    Serial.println(ssid);
    Serial.println(password);
}

/** Store WLAN credentials to EEPROM */
void save_credentials()
{
    EEPROM.begin(512);
    EEPROM.put(0, ssid);
    EEPROM.put(0 + sizeof(ssid), password);
    char ok[2 + 1] = "OK";
    EEPROM.put(0 + sizeof(ssid) + sizeof(password), ok);
    EEPROM.commit();
    EEPROM.end();
}

默认情况下,ESP8266 Arduino SDK 将其 wifi 配置保存在闪存中。

这里是documented但是没叫清楚

您需要调用 Wifi.persistent() 让 ESP 不保存凭据。在我看到的很多 ESP Arduino 核心文章中,这似乎并没有被明确指出。

试试这个:

Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.persistent(false);
WiFi.begin(ssid, password); //Connect to the WiFi network

while ((WiFi.status() != WL_CONNECTED) && (timeout_ctr < timeout))

在更新代码以告诉 SDK 停止保存它们之前,您可能想要写入一组错误的凭据以闪存,否则我认为它会继续使用最后保存的一组。另一种方法是擦除 ESP 上存储凭据的闪存扇区,这需要更多工作。

有一些关于 WiFi.persistent() here - which appears to be incorrect 的文档 - 我相信这个调用按照我描述的方式运行(传递 false 根本不存储凭据)。

如果您的项目要经常重启(比如经常进入和退出深度睡眠),我肯定会使用 WiFi.persistent(false) 来避免闪光灯磨损。