fbpixel
Étiquettes : ,

Dans un appareils connectés au WiFi comme un ESP8266, les paramètres WiFi sont souvent codés en dur ce qui rend impossible leur modification. Nous allons voir comment modifier les paramètres lorsque le wifi est perdu sans avoir à charger un nouveau code.

Principe d’enregistrement des paramètres WiFi sur un ESP8266

Nous allons rajouter dans le code un test pour se connecter au WiFi avec des paramètres enregistrés en EEPROM. Si l’ESP n’arrive pas à se connecter, il active un serveur sur un réseau en point d’accès (mode AP). Vous pouvez alors vous connecté au réseau de l’ESP (AC-ESP8266)

esp8266-apmode-result Modifier les paramètres WiFi d'un ESP8266 sans téléversement

Dès que votre appareil est connecté au réseau de l’ESP, vous pouvez vous connecter à l’adresse par défaut,192.168.4.1 pour atteindre le formulaire des paramètres WiFi.

wifi-credentials-config-mode Modifier les paramètres WiFi d'un ESP8266 sans téléversement
wifi-credentials-webserver Modifier les paramètres WiFi d'un ESP8266 sans téléversement

Une fois les paramètres envoyés alors l’ESP enregistre les paramètres pour la prochaine connexion puis il redémarre et se connecte au réseau.

wifi-credentials-connected Modifier les paramètres WiFi d'un ESP8266 sans téléversement

Code pour ajouter une page de connexion

Les librairies utilisées pour cette fonctionnalité sont les suivantes :

  • WiFi.h pour la gestion du Wifi et mode AP
  • Webserver pour créer une interface web
  • EEPROM pour gérer l’enregistrement en mémoire.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>

Dans un premier temps, nous vérifions si les paramètres Wifi sont en mémoire.

  // Read eeprom for ssid and password
  EEPROM.begin(512); //Initializing EEPROM
  Serial.println("Reading EEPROM ssid");
  //for (int i = 0 ; i < 96 ; i++) EEPROM.write(i, 0); // reset EEPROM if needed
  //EEPROM.commit();
  String esid;
  for (int i = 0; i < 32; ++i){
    esid += char(EEPROM.read(i));
  }
  Serial.print("SSID: ");
  Serial.println(esid);
  Serial.println("Reading EEPROM pass");

  String epass = "";
  for (int i = 32; i < 96; ++i){
    epass += char(EEPROM.read(i));
  }
  Serial.print("PASS: ");
  Serial.println(epass);

N.B.: Lors de vos tests, il est possible d’effacer la mémoire EEPROM

Nous pouvons ensuite tester la connexion au Wifi

bool testWifi(void){
  int tentative = 0;
  Serial.println("Waiting for WiFi to connect");
  while ( tentative < 20 ) {
    if (WiFi.status() == WL_CONNECTED){
      return true;
    }
    delay(500);
    Serial.print("*");
    tentative++;
  }
  Serial.println("");
  Serial.println("Connection timed out, opening AP or Hotspot");
  return false;
}

Si l’ESP se connecte au WiFi, on exécute le code normalement, si la connexion échoue, on rentre en mode AP et on affiche une page de connexion

// test wifi connection
  WiFi.begin(esid.c_str(), epass.c_str());  
  if (testWifi()){
    Serial.print(F(" connected to Wifi! IP address : http://")); Serial.println(WiFi.localIP()); // Print the IP address
    serveClient();
    
  }else{
    setupAP();// Setup accesspoint or HotSpot
    createWebServer();

    Serial.println();
    Serial.println("Waiting.");
    int dispcount=0;
    while ((WiFi.status() != WL_CONNECTED)){
      Serial.print(".");
      if (dispcount>50){
        dispcount=0;
        Serial.println();
      }
      delay(100);
      webserver.handleClient();
      dispcount++;
    }
  
  }

La fonction setupAP initialise l’ESP8266 en point d’accès et scanne les réseaux existant

void setupAP(void){
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  int n = WiFi.scanNetworks();
  Serial.println("scan completed");
  if (n == 0){
    Serial.println("No WiFi Networks found");
  }else{
    Serial.print(n);
    Serial.println(" Networks found");
    for (int i = 0; i < n; ++i){
      // Print SSID and RSSI for each network found
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
      delay(10);
    }
  }
  Serial.println("");
  netlist = "<ol>";
  for (int i = 0; i < n; ++i){
    // Print SSID and RSSI for each network found
    netlist += "<li>";
    netlist += WiFi.SSID(i);
    netlist += " (";
    netlist += WiFi.RSSI(i);

    netlist += ")";
    netlist += (WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*";
    netlist += "</li>";
  }
  netlist += "</ol>";
  delay(100);
  //WiFi.softAPConfig(local_IP, gateway, subnet) // force IP address
  WiFi.softAP("AC-ESP", "");
  Serial.print("Turning the HotSpot On. SoftAP IP: "); Serial.println(WiFi.softAPIP());
  //Serial.println("Initializing_Wifi_accesspoint");
  //launchWeb();
  //Serial.println("over");
}

La fonction createWebServer va créer un formulaire accessible à l’adresse de l’ESP (192.168.4.1) dans lequel vous pourrez entrer les paramètres Wifi. On redémarre l’ESP une fois les paramètres enregistrés.

void createWebServer(){
    webserver.on("/", []() {

      IPAddress ip = WiFi.softAPIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
      content = "<!DOCTYPE HTML>\r\n<html>ESP8266 WiFi Parameters Setup ";
      content += "<form action=\"/scan\" method=\"POST\"><input type=\"submit\" value=\"scan\"></form>";
      content += ipStr;
      content += "<p>";
      content += netlist;
      content += "</p><form method='get' action='setting'><label>SSID: </label><input name='ssid' length=32><input name='pass' length=64><input type='submit'></form>";
      content += "</html>";
      webserver.send(200, "text/html", content);
    });
    webserver.on("/scan", []() {
      //setupAP();
      IPAddress ip = WiFi.softAPIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);

      content = "<!DOCTYPE HTML>\r\n<html>go back";
      webserver.send(200, "text/html", content);
    });

    webserver.on("/setting", []() {
      String qsid = webserver.arg("ssid");
      String qpass = webserver.arg("pass");
      if (qsid.length() > 0 && qpass.length() > 0) {
        Serial.println("clearing eeprom");
        for (int i = 0; i < 96; ++i) {
          EEPROM.write(i, 0);
        }
        Serial.println(qsid);
        Serial.println("");
        Serial.println(qpass);
        Serial.println("");

        Serial.println("writing eeprom ssid:");
        for (int i = 0; i < qsid.length(); ++i)
        {
          EEPROM.write(i, qsid[i]);
          Serial.print("Wrote: ");
          Serial.println(qsid[i]);
        }
        Serial.println("writing eeprom pass:");
        for (int i = 0; i < qpass.length(); ++i)
        {
          EEPROM.write(32 + i, qpass[i]);
          Serial.print("Wrote: ");
          Serial.println(qpass[i]);
        }
        EEPROM.commit();

        content = "{\"Success\":\"saved to eeprom... reset to boot into new wifi\"}";
        statusCode = 200;
        ESP.reset();
      } else {
        content = "{\"Error\":\"404 not found\"}";
        statusCode = 404;
        Serial.println("Sending 404");
      }
      webserver.sendHeader("Access-Control-Allow-Origin", "*");
      webserver.send(statusCode, "application/json", content);

    });

    webserver.begin();
}

Voici le code complet pour la modification de paramètres Wifi sur ESP8266

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

//Variables
int i = 0;
int statusCode;

String netlist;
String content;


//Function Declaration
bool testWifi(void);
void launchWeb(void);
void setupAP(void);

//--------Establishing Local server at port 80 whenever required
ESP8266WebServer webserver(80);

void setup()
{
  // initialization
  Serial.begin(115200); //Initializing if(DEBUG)Serial Monitor
  WiFi.disconnect(); //Disconnecting previously connected WiFi
  delay(10);

  // Read eeprom for ssid and password
  EEPROM.begin(512); //Initializing EEPROM
  Serial.println("Reading EEPROM ssid");
  //for (int i = 0 ; i < EEPROM.length() ; i++) EEPROM.write(i, 0); // reset EEPROM if needed
  //EEPROM.commit();
  String esid;
  for (int i = 0; i < 32; ++i)
  {
    esid += char(EEPROM.read(i));
  }
  Serial.print("SSID: ");
  Serial.println(esid);
  Serial.println("Reading EEPROM pass");

  String epass = "";
  for (int i = 32; i < 96; ++i)
  {
    epass += char(EEPROM.read(i));
  }
  Serial.print("PASS: ");
  Serial.println(epass);

  // test wifi connection
  WiFi.begin(esid.c_str(), epass.c_str());  
  if (testWifi()){
    Serial.print(F(" connected to Wifi! IP address : http://")); Serial.println(WiFi.localIP()); // Print the IP address
    serveClient();
    
  }else{
    setupAP();// Setup accesspoint or HotSpot
    createWebServer();

    Serial.println();
    Serial.println("Waiting.");
    int dispcount=0;
    while ((WiFi.status() != WL_CONNECTED)){
      Serial.print(".");
      if (dispcount>50){
        dispcount=0;
        Serial.println();
      }
      delay(100);
      webserver.handleClient();
      dispcount++;
    }
  
  }
}

void loop() {
  if ((WiFi.status() == WL_CONNECTED)){
    webserver.handleClient();
  }else{
  }
}


bool testWifi(void){
  int tentative = 0;
  Serial.println("Waiting for WiFi to connect");
  while ( tentative < 20 ) {
    if (WiFi.status() == WL_CONNECTED){
      return true;
    }
    delay(500);
    Serial.print("*");
    tentative++;
  }
  Serial.println("");
  Serial.println("Connection timed out, opening AP or Hotspot");
  return false;
}


void setupAP(void){
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  int n = WiFi.scanNetworks();
  Serial.println("scan completed");
  if (n == 0){
    Serial.println("No WiFi Networks found");
  }else{
    Serial.print(n);
    Serial.println(" Networks found");
    for (int i = 0; i < n; ++i){
      // Print SSID and RSSI for each network found
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
      delay(10);
    }
  }
  Serial.println("");
  netlist = "<ol>";
  for (int i = 0; i < n; ++i){
    // Print SSID and RSSI for each network found
    netlist += "<li>";
    netlist += WiFi.SSID(i);
    netlist += " (";
    netlist += WiFi.RSSI(i);

    netlist += ")";
    netlist += (WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*";
    netlist += "</li>";
  }
  netlist += "</ol>";
  delay(100);
  //WiFi.softAPConfig(local_IP, gateway, subnet) // force IP address
  WiFi.softAP("ESP-MYSTERIAU", "");
  Serial.print("Turning the HotSpot On. SoftAP IP: "); Serial.println(WiFi.softAPIP());
  //Serial.println("Initializing_Wifi_accesspoint");
  //launchWeb();
  //Serial.println("over");
}

void createWebServer(){
    webserver.on("/", []() {

      IPAddress ip = WiFi.softAPIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
      content = "<!DOCTYPE HTML>\r\n<html>ESP8266 WiFi Parameters Setup ";
      content += "<form action=\"/scan\" method=\"POST\"><input type=\"submit\" value=\"scan\"></form>";
      content += ipStr;
      content += "<p>";
      content += netlist;
      content += "</p><form method='get' action='setting'><label>SSID: </label><input name='ssid' length=32><input name='pass' length=64><input type='submit'></form>";
      content += "</html>";
      webserver.send(200, "text/html", content);
    });
    webserver.on("/scan", []() {
      //setupAP();
      IPAddress ip = WiFi.softAPIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);

      content = "<!DOCTYPE HTML>\r\n<html>go back";
      webserver.send(200, "text/html", content);
    });

    webserver.on("/setting", []() {
      String qsid = webserver.arg("ssid");
      String qpass = webserver.arg("pass");
      if (qsid.length() > 0 && qpass.length() > 0) {
        Serial.println("clearing eeprom");
        for (int i = 0; i < 96; ++i) {
          EEPROM.write(i, 0);
        }
        Serial.println(qsid);
        Serial.println("");
        Serial.println(qpass);
        Serial.println("");

        Serial.println("writing eeprom ssid:");
        for (int i = 0; i < qsid.length(); ++i)
        {
          EEPROM.write(i, qsid[i]);
          Serial.print("Wrote: ");
          Serial.println(qsid[i]);
        }
        Serial.println("writing eeprom pass:");
        for (int i = 0; i < qpass.length(); ++i)
        {
          EEPROM.write(32 + i, qpass[i]);
          Serial.print("Wrote: ");
          Serial.println(qpass[i]);
        }
        EEPROM.commit();

        content = "{\"Success\":\"saved to eeprom... reset to boot into new wifi\"}";
        statusCode = 200;
        ESP.reset();
      } else {
        content = "{\"Error\":\"404 not found\"}";
        statusCode = 404;
        Serial.println("Sending 404");
      }
      webserver.sendHeader("Access-Control-Allow-Origin", "*");
      webserver.send(statusCode, "application/json", content);

    });

    webserver.begin();
}

void serveClient(){
    webserver.on("/", []() {

      IPAddress ip = WiFi.localIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
      content = "<!DOCTYPE HTML>\r\n<html><p>ESP8266 Connected to Wifi : <b>";
      content += ipStr;
      content += "</b></p>";
      content += "</html>";
      webserver.send(200, "text/html", content);
    });

    webserver.begin();
}

Utilisation de la librairie WiFiManager

Des librairies existent pour faciliter la connexion automatique à un réseau et enregistrer les paramètres Wifi

N.B.: Actuellement je n’ai pas réussi à utiliser WiFiManager correctement. D’autres librairies existent également. N’hésitez pas à nous faire un retour si ça fonctionne pour vous.

Sources