Difference between revisions of "Wi-Fi-ESP32-E-Paper"

From
Jump to: navigation, search
(Code Wi-Fi & ESP32 & E-Paper)
(Code Wi-Fi & ESP32 & E-Paper)
Line 557: Line 557:
 
   server.handleClient();
 
   server.handleClient();
 
}
 
}
 +
</pre>
 +
 +
<pre>
 +
✅ Mode AP + STA simultané
 +
 +
✅ STA avec SSID/mot de passe par défaut, surchargeables via la page de config
 +
 +
✅ AP fixe : SSID XIAO_Config / mot de passe 12345678
 +
 +
✅ Page de configuration Wi‑Fi stylée (/)
 +
 +
✅ Page de statut (/status) : IP STA, IP AP, RSSI, mode, uptime
 +
 +
✅ Bouton Reboot (/reboot)
 +
 +
✅ Bouton Reset Wi‑Fi (/resetwifi) qui efface Preferences + reboot
 +
 +
✅ Résumé sur le moniteur série au reset Wi‑Fi
 
</pre>
 
</pre>

Revision as of 18:54, 19 December 2025

Code Wi-Fi & ESP32 & E-Paper

Wi-Fi-ESP32-E-Paper

#include <WiFi.h>
#include <WebServer.h>
#include <Preferences.h>

Preferences prefs;
WebServer server(80);

String ssid, pass;

const char* configPage = R"rawliteral(
<!DOCTYPE html>
<html>
  <body>
    <h2>Configuration WiFi</h2>
    <form action="/save" method="POST">
      SSID: <input type="text" name="ssid"><br>
      Password: <input type="text" name="pass"><br>
      <input type="submit" value="Save">
    </form>
  </body>
</html>
)rawliteral";

void handleRoot() {
  server.send(200, "text/html", configPage);
}

void handleSave() {
  if (server.hasArg("ssid") && server.hasArg("pass")) {
    ssid = server.arg("ssid");
    pass = server.arg("pass");
    prefs.begin("wifi", false);
    prefs.putString("ssid", ssid);
    prefs.putString("pass", pass);
    prefs.end();
    server.send(200, "text/html", "Paramètres sauvegardés. Redémarrage...");
    delay(2000);
    ESP.restart();
  }
}

bool connectToWiFi() {
  prefs.begin("wifi", true);
  ssid = prefs.getString("ssid", "");
  pass = prefs.getString("pass", "");
  prefs.end();

  if (ssid == "") return false;

  WiFi.begin(ssid.c_str(), pass.c_str());
  Serial.print("Connexion à "); Serial.println(ssid);

  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - start < 10000) {
    delay(500);
    Serial.print(".");
  }
  return WiFi.status() == WL_CONNECTED;
}

void startAP() {
  WiFi.softAP("XIAO_Config", "12345678");
  Serial.println("AP démarré. IP: " + WiFi.softAPIP().toString());
  server.on("/", handleRoot);
  server.on("/save", HTTP_POST, handleSave);
  server.begin();
}

void setup() {
  Serial.begin(115200);

  if (!connectToWiFi()) {
    Serial.println("Échec connexion. Passage en mode AP.");
    startAP();
  } else {
    Serial.println("Connecté au WiFi. IP: " + WiFi.localIP().toString());
    // Ici vous pouvez lancer un serveur web normal ou autre logique
  }
}

void loop() {
  server.handleClient();
}
## ⚙️ Fonctionnement
- **Premier démarrage** : pas de SSID enregistré → le module crée un AP `XIAO_Config`.  
- **Page web** : accessible via l’IP du point d’accès (souvent `192.168.4.1`).  
- **Sauvegarde** : SSID et mot de passe sont stockés dans `Preferences`.  
- **Redémarrage** : le module tente de se connecter au Wi Fi enregistré.  
- **Fallback** : si la connexion échoue, retour en mode AP pour reconfigurer.
- **Mode AP (point d’accès)** au démarrage → permet de configurer les paramètres Wi Fi via une page web.  
- **Sauvegarde des paramètres** (SSID, mot de passe, etc.) dans la mémoire non volatile (Preferences).  
- **Redémarrage automatique en mode station** → le XIAO se connecte au réseau configuré.  
- **Fallback** : si la connexion échoue, il revient en mode AP pour reconfigurer.

Code Modifié

#include <WiFi.h>
#include <WebServer.h>
#include <Preferences.h>

Preferences prefs;
WebServer server(80);

// ---- CONFIG WIFI DOMESTIQUE PAR DÉFAUT ----
const char* DEFAULT_STA_SSID = "TonSSID";
const char* DEFAULT_STA_PASS = "TonMotDePasse";

// ---- CONFIG AP ----
const char* AP_SSID = "XIAO_Config";
const char* AP_PASS = "12345678";

String ssid, pass;

// ---- PAGE HTML DE CONFIG WIFI ----
const char* configPage = R"rawliteral(
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Configuration WiFi</title>
<style>
  body {
    font-family: Arial, sans-serif;
    background: linear-gradient(135deg, #4c8bf5, #6dd5fa);
    height: 100vh;
    margin: 0;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .card {
    background: white;
    padding: 25px;
    border-radius: 15px;
    width: 320px;
    box-shadow: 0 8px 20px rgba(0,0,0,0.2);
    text-align: center;
  }

  h2 {
    margin-top: 0;
    color: #333;
  }

  input[type="text"], input[type="password"] {
    width: 90%;
    padding: 10px;
    margin: 10px 0;
    border-radius: 8px;
    border: 1px solid #aaa;
    font-size: 16px;
  }

  input[type="submit"] {
    background: #4c8bf5;
    color: white;
    border: none;
    padding: 12px 20px;
    border-radius: 8px;
    font-size: 16px;
    cursor: pointer;
    width: 100%;
    margin-top: 10px;
  }

  input[type="submit"]:hover {
    background: #3a6fd8;
  }

  .links {
    margin-top: 15px;
    font-size: 14px;
  }

  .links a {
    color: #4c8bf5;
    text-decoration: none;
  }

  .links a:hover {
    text-decoration: underline;
  }
</style>
</head>
<body>
  <div class="card">
    <h2>Configuration WiFi</h2>
    <form action="/save" method="POST">
      <input type="text" name="ssid" placeholder="Nom du réseau (SSID)" required>
      <input type="password" name="pass" placeholder="Mot de passe" required>
      <input type="submit" value="Enregistrer">
    </form>
    <div class="links">
      <a href="/status">Voir le statut</a>
    </div>
  </div>
</body>
</html>
)rawliteral";

// ---- HANDLERS HTTP ----

void handleRoot() {
  server.send(200, "text/html", configPage);
}

void handleSave() {
  if (server.hasArg("ssid") && server.hasArg("pass")) {
    prefs.begin("wifi", false);
    prefs.putString("ssid", server.arg("ssid"));
    prefs.putString("pass", server.arg("pass"));
    prefs.end();

    String page = R"rawliteral(
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Paramètres enregistrés</title>
<style>
  body {
    font-family: Arial, sans-serif;
    background: linear-gradient(135deg, #4c8bf5, #6dd5fa);
    height: 100vh;
    margin: 0;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .card {
    background: white;
    padding: 25px;
    border-radius: 15px;
    width: 320px;
    box-shadow: 0 8px 20px rgba(0,0,0,0.2);
    text-align: center;
  }
  h2 { margin-top: 0; color: #333; }
</style>
</head>
<body>
  <div class="card">
    <h2>Paramètres sauvegardés</h2>
    <p>L'appareil va redémarrer<br>et tenter de se connecter au nouveau réseau.</p>
  </div>
</body>
</html>
)rawliteral";

    server.send(200, "text/html", page);
    delay(1500);
    ESP.restart();
  } else {
    server.send(400, "text/plain", "SSID ou mot de passe manquant");
  }
}

void handleStatus() {
  String mode = "";
  wifi_mode_t currentMode = WiFi.getMode();

  if (currentMode == WIFI_STA) mode = "Station (STA)";
  else if (currentMode == WIFI_AP) mode = "Point d'accès (AP)";
  else if (currentMode == WIFI_AP_STA) mode = "AP + Station (AP_STA)";
  else mode = "Inconnu";

  String page = R"rawliteral(
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Statut WiFi</title>
<style>
  body {
    font-family: Arial, sans-serif;
    background: linear-gradient(135deg, #6dd5fa, #4c8bf5);
    height: 100vh;
    margin: 0;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .card {
    background: white;
    padding: 25px;
    border-radius: 15px;
    width: 350px;
    box-shadow: 0 8px 20px rgba(0,0,0,0.2);
    text-align: center;
  }

  h2 {
    margin-top: 0;
    color: #333;
  }

  .info {
    text-align: left;
    margin-top: 15px;
    font-size: 16px;
  }

  .info div {
    margin-bottom: 8px;
  }

  .btn {
    margin-top: 15px;
    display: inline-block;
    padding: 10px 20px;
    background: #4c8bf5;
    color: white;
    border-radius: 8px;
    text-decoration: none;
    font-size: 14px;
  }

  .btn:hover {
    background: #3a6fd8;
  }

  .btn-danger {
    background: #f56d6d;
  }

  .btn-danger:hover {
    background: #d84a4a;
  }
</style>
</head>
<body>
  <div class="card">
    <h2>Statut WiFi</h2>
    <div class="info">
)rawliteral";

  page += "<div><b>Mode :</b> " + mode + "</div>";
  page += "<div><b>IP (STA) :</b> " + WiFi.localIP().toString() + "</div>";
  page += "<div><b>IP (AP) :</b> " + WiFi.softAPIP().toString() + "</div>";

  if (WiFi.status() == WL_CONNECTED) {
    page += "<div><b>RSSI :</b> " + String(WiFi.RSSI()) + " dBm</div>";
  } else {
    page += "<div><b>RSSI :</b> Non connecté</div>";
  }

  unsigned long ms = millis();
  unsigned long sec = ms / 1000;
  unsigned long min = sec / 60;
  unsigned long hr  = min / 60;

  page += "<div><b>Uptime :</b> " + String(hr) + "h " + String(min % 60) + "m " + String(sec % 60) + "s</div>";

  page += R"rawliteral(
    </div>
    <a class="btn" href="/">Config WiFi</a>
    <a class="btn" href="/reboot">Redémarrer</a>
    <a class="btn btn-danger" href="/resetwifi">Reset Wi‑Fi</a>
  </div>
</body>
</html>
)rawliteral";

  server.send(200, "text/html", page);
}

void handleReboot() {
  String page = R"rawliteral(
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Redémarrage</title>
<style>
  body {
    font-family: Arial, sans-serif;
    background: linear-gradient(135deg, #4c8bf5, #6dd5fa);
    height: 100vh;
    margin: 0;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .card {
    background: white;
    padding: 25px;
    border-radius: 15px;
    width: 320px;
    box-shadow: 0 8px 20px rgba(0,0,0,0.2);
    text-align: center;
  }

  h2 {
    margin-top: 0;
    color: #333;
  }
</style>
</head>
<body>
  <div class="card">
    <h2>Redémarrage en cours…</h2>
    <p>L'appareil va redémarrer dans quelques secondes.</p>
  </div>
</body>
</html>
)rawliteral";

  server.send(200, "text/html", page);
  delay(1500);
  ESP.restart();
}

void handleResetWiFi() {
  // Effacer les identifiants WiFi stockés
  prefs.begin("wifi", false);
  prefs.clear();
  prefs.end();

  String page = R"rawliteral(
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Reset WiFi</title>
<style>
  body {
    font-family: Arial, sans-serif;
    background: linear-gradient(135deg, #f56d6d, #fa9a6d);
    height: 100vh;
    margin: 0;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .card {
    background: white;
    padding: 25px;
    border-radius: 15px;
    width: 320px;
    box-shadow: 0 8px 20px rgba(0,0,0,0.2);
    text-align: center;
  }

  h2 {
    margin-top: 0;
    color: #333;
  }
</style>
</head>
<body>
  <div class="card">
    <h2>Réinitialisation WiFi…</h2>
    <p>Les paramètres WiFi ont été effacés.<br>Redémarrage en cours…</p>
  </div>
</body>
</html>
)rawliteral";

  server.send(200, "text/html", page);

  // Résumé sur le moniteur série
  Serial.println("\n===== RESET WIFI =====");
  Serial.println("IP STA : " + WiFi.localIP().toString());
  Serial.println("IP AP  : " + WiFi.softAPIP().toString());
  Serial.println("AP SSID : " + String(AP_SSID));
  Serial.println("AP PASS : " + String(AP_PASS));

  if (WiFi.status() == WL_CONNECTED)
    Serial.println("RSSI : " + String(WiFi.RSSI()) + " dBm");
  else
    Serial.println("RSSI : Non connecté");

  Serial.println("=======================\n");

  delay(1500);
  ESP.restart();
}

// ---- LOGIQUE WIFI ----

bool connectToWiFi() {
  // Charger les valeurs enregistrées (ou défaut)
  prefs.begin("wifi", true);
  ssid = prefs.getString("ssid", DEFAULT_STA_SSID);
  pass = prefs.getString("pass", DEFAULT_STA_PASS);
  prefs.end();

  Serial.print("Connexion à "); Serial.println(ssid);

  WiFi.begin(ssid.c_str(), pass.c_str());

  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - start < 10000) {
    delay(500);
    Serial.print(".");
  }

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\n[WiFi] Connecté en STA");
    Serial.println("IP STA : " + WiFi.localIP().toString());
    Serial.println("RSSI   : " + String(WiFi.RSSI()) + " dBm");
    return true;
  } else {
    Serial.println("\n[WiFi] Échec connexion STA");
    return false;
  }
}

// ---- SETUP / LOOP ----

void setup() {
  Serial.begin(115200);
  delay(500);
  Serial.println("\n==== DÉMARRAGE XIAO ESP32C3 ====");

  // Mode AP + STA
  WiFi.mode(WIFI_AP_STA);

  // Lancer AP
  WiFi.softAP(AP_SSID, AP_PASS);
  Serial.println("[WiFi] AP actif");
  Serial.println("  SSID : " + String(AP_SSID));
  Serial.println("  PASS : " + String(AP_PASS));
  Serial.println("  IP AP: " + WiFi.softAPIP().toString());

  // Tenter connexion STA
  connectToWiFi();

  // Routes HTTP
  server.on("/", handleRoot);
  server.on("/save", HTTP_POST, handleSave);
  server.on("/status", handleStatus);
  server.on("/reboot", handleReboot);
  server.on("/resetwifi", handleResetWiFi);

  server.begin();
  Serial.println("[HTTP] Serveur web démarré");
}

void loop() {
  server.handleClient();
}
✅ Mode AP + STA simultané

✅ STA avec SSID/mot de passe par défaut, surchargeables via la page de config

✅ AP fixe : SSID XIAO_Config / mot de passe 12345678

✅ Page de configuration Wi‑Fi stylée (/)

✅ Page de statut (/status) : IP STA, IP AP, RSSI, mode, uptime

✅ Bouton Reboot (/reboot)

✅ Bouton Reset Wi‑Fi (/resetwifi) qui efface Preferences + reboot

✅ Résumé sur le moniteur série au reset Wi‑Fi