Wi-Fi-ESP32-E-Paper

From
Jump to: navigation, search

Code Wi-Fi & ESP32 & E-Paper[edit]

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é

CONFIGURATION-WI-FI.PNG STATUS-WI-FI.PNG OUTPUT SERIAL-Wi-Fi.PNG


#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

Code Wi-Fi & ESP32 & E-Paper 3 onglets[edit]

#include <WiFi.h>
#include <WebServer.h>
#include <Preferences.h>
#include "TimeDisplayEPaper.h"   // ✅ Ajout pour l’e-paper

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() {
  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);

  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() {
  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 ====");

  WiFi.mode(WIFI_AP_STA);

  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());

  connectToWiFi();

  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é");

  initEPaper();   // ✅ Ajout
}

void loop() {
  server.handleClient();
  updateEPaperTime();  // ✅ Ajout
}
// Onglet TimeDisplayEPaper.h
#pragma once
#include <time.h>
#include <TFT_eSPI.h>
#include <SPI.h>
#include <WiFi.h>

#ifdef EPAPER_ENABLE
EPaper epaper = EPaper();  // Pins définis dans User_Setup.h
#endif

// ⚙️ Paramètres NTP
const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 3600;       // +1h (Suisse en hiver)
const int   daylightOffset_sec = 3600;  // +1h (DST été)

// Variables pour éviter scintillement
int lastMinute = -1;

// --- Initialisation de l’e-paper ---
void initEPaper() {
#ifdef EPAPER_ENABLE
  epaper.begin();
  epaper.setRotation(1);
  epaper.fillScreen(TFT_WHITE);
  epaper.setTextColor(TFT_BLACK, TFT_WHITE);
  epaper.update();
  epaper.sleep();
#endif

  // Initialisation NTP
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
}

// --- Fonction pour dessiner un pictogramme Wi-Fi ---
void drawWiFiIcon(int x, int y, int rssi) {
  int bars = 0;
  if (rssi > -50) bars = 4;
  else if (rssi > -60) bars = 3;
  else if (rssi > -70) bars = 2;
  else if (rssi > -80) bars = 1;
  else bars = 0;

  int barWidth = 6;
  int spacing = 3;
  for (int i = 0; i < 4; i++) {
    int barHeight = (i+1) * 6;
    int bx = x + i * (barWidth + spacing);
    int by = y + (24 - barHeight);
    if (i < bars) {
      epaper.fillRect(bx, by, barWidth, barHeight, TFT_BLACK);
    } else {
      epaper.drawRect(bx, by, barWidth, barHeight, TFT_BLACK);
    }
  }
}

// --- Mise à jour de l’affichage ---
void updateEPaperTime() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Erreur récupération heure NTP");
    return;
  }

  if (timeinfo.tm_min != lastMinute) {
    lastMinute = timeinfo.tm_min;

#ifdef EPAPER_ENABLE
    epaper.fillScreen(TFT_WHITE);

    // --- Affichage DATE ---
    epaper.setTextDatum(TC_DATUM);
    epaper.drawString(
      String(timeinfo.tm_mday) + "/" + 
      String(timeinfo.tm_mon+1) + "/" + 
      String(timeinfo.tm_year+1900),
      epaper.width()/2, 30, 4
    );

    // --- Affichage HEURE ---
    char buffer[6];
    sprintf(buffer, "%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min);
    epaper.setTextDatum(MC_DATUM);
    epaper.drawString(buffer, epaper.width()/2, epaper.height()/2, 7);

    // --- Encadré infos réseau ---
    int boxX = 5;
    int boxY = epaper.height() - 70;
    int boxW = epaper.width() - 10;
    int boxH = 60;

    epaper.fillRect(boxX, boxY, boxW, boxH, TFT_LIGHTGREY);
    epaper.drawRect(boxX, boxY, boxW, boxH, TFT_BLACK);

    epaper.setTextColor(TFT_BLACK, TFT_LIGHTGREY);
    epaper.setTextDatum(TL_DATUM);
    epaper.drawString("IP STA: " + WiFi.localIP().toString(), boxX + 10, boxY + 12, 2);

    // --- Pictogramme Wi-Fi centré ---
    int iconX = boxX + (boxW/2) - 15;
    int iconY = boxY + 5;
    drawWiFiIcon(iconX, iconY, WiFi.RSSI());

    // --- RSSI sous l’icône ---
    epaper.setTextDatum(TC_DATUM);
    epaper.drawString("RSSI: " + String(WiFi.RSSI()) + " dBm", boxX + boxW/2, boxY + 40, 2);

    epaper.update();
#endif

    // --- Sortie série ---
    Serial.printf("Heure actuelle : %02d:%02d:%02d\n", 
                  timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
    Serial.println("IP STA : " + WiFi.localIP().toString());
    Serial.println("RSSI   : " + String(WiFi.RSSI()) + " dBm");
  }
}
// onglet driver.h
// driver.h file 
#define BOARD_SCREEN_COMBO 505 // 1.54 inch monochrome ePaper Screen (SSD1681)
#define USE_XIAO_EPAPER_BREAKOUT_BOARD