Comment maintenir un ESP8266 en ligne et reconnecter au wifi en cas de bug

Bonjour,

Je galère depuis des jours pour ajouter à mon code un test comme par exemple un ping qui permettrait au module ESP-01 (esp8266) de se reconnecter en cas de bug. A priori c'est courant et je n'arrive pas à trouver de quoi cela provient. Ce n'est pas l'alimentation, ni la distance par rapport à la box wifi (ca le fait à proximité de la box aussi)
Au bout d'une journée je n'arrive plus à le commander via un lien sur internet, il répond par un timeout.
J'ai vu que certains testent avec un ping et en cas de non réponse relance le wifi ou reboot le module.
J'ai essayé mais je n'y arrive pas.

Je publie mon code actuel dans un prochain message.

Pourriez vous m'aider ?
Merci

Voici mon code actuel :

#include <ESP8266WiFi.h>
 
const char* ssid = "xxxxxxxxxxx"; // fill in here your router or wifi SSID
const char* password = "xxxxxxxxxxx"; // fill in here your router or wifi password
 #define RELAY 0 // relay connected to  GPIO0
WiFiServer server(80);
 
void setup() 
{
  Serial.begin(57600); // must be same baudrate with the Serial Monitor
 
  pinMode(RELAY,OUTPUT);
  digitalWrite(RELAY, HIGH);
 
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".$");
  }
  Serial.println("");
  Serial.println("WiFi connected");
 
  // Start the server
  server.begin();
  Serial.println("Server started");
 
  // Print the IP address
  Serial.print("Use this URL to connect: ");
  Serial.print("http://xxxxxxxxxxxxx:PORT/");
  Serial.print(WiFi.localIP());
  Serial.println("/");
 
}
void loop() 
{
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) 
  {
    
    return;
  }
 
  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available())
  {
    delay(1);
  }

  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();
 
  // Match the request
  int value = LOW;
  if (request.indexOf("/RELAY=ON") != -1)  
  {
    Serial.println("RELAY=ON");
    digitalWrite(RELAY,LOW);
    value = LOW;
  }
  if (request.indexOf("/RELAY=OFF") != -1)  
  {
    Serial.println("RELAY=OFF");
    digitalWrite(RELAY,HIGH);
    value = HIGH;
  }
  
  // Return the response
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  this is a must
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head><title>ESP8266 RELAY Control</title></head>");
  client.print("Relay is now: ");
 
  if(value == HIGH) 
  {
    client.print("OFF");
  } 
  else 
  {
    client.print("ON");
  }
  client.println("<br><br>");
  client.println("Turn <a href=\"/RELAY=OFF\">OFF</a> RELAY<br>");
  client.println("Turn <a href=\"/RELAY=ON\">ON</a> RELAY<br>");
    client.println("</html>");
 
  delay(1);
  Serial.println("Client disonnected");
  Serial.println("");
}

C'est à dire qu'as tu essayé et quel résultat as tu obtenu?

As tu essayé ce genre de librairie?
Ou as tu essayé de simplement utilise HTTPClient.h?

Tout est (bien) expliqué ici :

Désolé mais je débute en arduino donc je n'ai pas un gros niveau.

Pour moi la librairie c'est celle indiquée en haut mais j'avoue que je comprends pas à quoi ca sert dans la mesure ou le système execute le code indiqué et je ne vois pas à quoi servirait une autre librairie. Il va falloir que je reprenne les bases... je vais lire pour comprendre l'intérêt de ces librairie. Merci.
J'ai essayé des lignes de codes que j'ai mis dans la boucle ou le système attendait une action du client en me disant qu'à ce stade il faudrait un test pour vérifier que la connexion était toujours là. mais je n'ai eu comme résultat que le moniteur serie affichait "reconnexion wifi" sans arrêt... et beaucoup de lignes de codes ou lors de la compilation il y avait un problème que je n'arrivais pas à corriger car ne comprenant pas l'origine de ce qui n'allait pas...

Merci lesept pour ce lien. Je vais le lire avec attention. J'ai commencé par la 1ere proposition en ajoutant les 2 lignes de codes suivants :

 WiFi.setAutoReconnect(true);
  WiFi.persistent(true);

Je vais brancher le ESP01 et le laisser jusque demain soir pour voir si cela change quelque chose ou pas ?

Merci en attendant je vais lire le lien que tu m'as donné.

Voila j'ai pu compiler et injecter le nouveau code dans l'ESP01.
J'ai testé sur le PC dans le moniteur série et tout fonctionnait normalement.
Ensuite j'ai fait un test (je ne sais pas ce que ca vaut ?) en arrêtant le wifi sur la box, la connexion a donc bien été interrompue, le module s'affichait "hors ligne". Puis j'ai remis la connexion wifi et au bout de 30 secondes le ESP s'est bien reconnecté. A voir si cela va fonctionner lorsqu'il y aura un bug. Je vous tiens informé, je le lancerai demain soir ;). Merci à tous en attendant.

Ok Terwal j’ai vu la librairie. Je vais l’installer sur mon pc pour regarder et faire des tests de Ping pour voir comment ça marche. Merci.

Il n'y a pas à être désolé on est tous passé par là :slight_smile:

Oui tu n'a pas tord, cette librairie permet de gérer la communication via le WIFI, mais je ne sais pas si elle gère le ping(trame ICMP).

Ok, mais cela ne dis pas ce que tu fais exactement, ni le code que tu as employé.
Là on peut juste te dire si l'idée est correcte ou non, en soit l'idée n'est pas mauvaise.

Salut la compagnie,

Merci Terwal c’est plus clair désormais.

Ce soir le module était toujours en ligne donc c’est plutôt bon signe. A voir si ces 2 commandes ajoutées au code vont corriger ce problème de déconnection ?
Je vais laisser le module 2 jours sans le toucher pour voir s’il fonctionnera toujours. Si c’est le cas je pense que ce sera gagné. Dans tous les cas je vais m’intéresser à tout ce que vous m’avez transmis ça m’intéresse.
Donc à suivre dans 2 jours le résultat… je croise les doigts :wink:

Bon et bien l’espoir était de courte durée car ce matin ça ne marchait plus…
Il va donc falloir que j’essaye autre chose.
Je vais le laisser connecter sur le pc dans le moniteur série pour essayer de voir où il bug…

Salut.
Pour ce genre de problème j'utilise les WiFiEventHandler, comme sur ce projet :
level-control.ino

Il te faut 3 fonctions importantes :
onStationConnected
onStationDisconnected
onStationGotIP

Ensuite, instancier les handlers :

WiFiEventHandler stationConnectedHandler;
WiFiEventHandler stationDisconnectedHandler;
WiFiEventHandler stationGotIpHandler;

Ensuite, les initialiser dans Setup() :

  stationConnectedHandler = WiFi.onStationModeConnected(onStationConnected);
  stationDisconnectedHandler = WiFi.onStationModeDisconnected(onStationDisconnected);
  stationGotIpHandler = WiFi.onStationModeGotIP(onStationGotIP);

Dans la fonction onStationGotIP() j'incrémente une variable connections, qui est affichée sur la page HTML, ainsi que le RSSI (qualité du signal), et la date du dernier boot.
Actuellement :

Boot 31/12/2023 06:27

Connections 11

RSSI -86 dBm

Le dernier boot a eu lieu le 31/12, probablement à cause d'une coupure de courant.
11 connections à ce jour.
RSSI = -86dBm ce qui n'est pas trop mal.

S'il s'agit d'un bug qui plante l'ESP au point qu'il ne redémarre pas, il faut avant tout corriger ce bug.

Ici un exemple plus simple, pour ESP8266 ou ESP32 :
basic-web-server.ino
Tu peux essayer de charger cet exemple dans ton ESP et voir ce qui se passe. Un afficheur OLED est utilisé mais s'il est absent, ce n'est pas un problème, la page HTML reste utilisable.

Fais nous un compte rendu des données affichées, surtout RSSI.

Merci pour ton message je garde sous le coude.

Je vais déjà essayer la proposition plus simple de hbachetti que je remercie aussi.

Merci en tout cas pour votre aide.

Je vous tiens au courant.

Les données affichées sur le moniteur série est le suivant :
image

J'ai fait deux tests on / off que l'on voit. Sinon rien de spécial.

Et voici la page du serveur :

image

Bon, on peut écarter la qualité du signal, excellente.
Laisse tourner quelques jours ...

Héllo,

Après 1 jour aucune reconnexion.

J'ai voulu le mettre en place en configuration réelle et le laisser plusieurs jours mais le programme d'origine n'enclenchait pas le relais de mise en marche.
J'ai donc revu le code en déclarant le relais sur la sortie 0 GPIO0 et en enclenchant le contact lorsque la led est allumée avec ``````digitalWrite(RELAY,LOW);```` et High sur la position OFF.

Tout à l'air de marcher à merveille. Demain je mets le nouvel ESP01 en place dans mon poulailler pour essai en réel sur plusieurs jours. Je vous tiens au courant.

Voici le nouveau code modifié pour celui qui en aurait besoin à l'avenir :wink:

#ifdef ESP32
#include <WiFi.h>
#include <WebServer.h>
#else
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#endif
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

const char *ssid = "**********";
const char *password = "**********";

const char* ntpServer = "pool.ntp.org";
time_t  bootTime;
char timeBuffer[80];
unsigned connections;

#define OLED_RESET     -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define RELAY 0 // relay connected to  GPIO0

#ifdef ESP32
WebServer server(80);
//#define LED         LED_BUILTIN
//#define LED_CMD     LOW
#define LED         23
#define LED_CMD     HIGH
#else
ESP8266WebServer server(80);
#define LED         LED_BUILTIN
#define LED_CMD     LOW
#endif

void handleRoot() {
  int ledState = digitalRead(LED);
  String state = ledState == LED_CMD ? "ON" : "OFF";
  String message = "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}";
  message += ".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;";
  message += "text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}";
  message += ".button2 {background-color: #555555;}</style></head>";
#ifdef ESP32
  message += "<body><h1>ESP32 Web Server</h1>";
#else
  message += "<body><h1>ESP8266 Web Server</h1>";
#endif
  message += "<p>LED - State " + state + "</p>";
  if (ledState == LED_CMD) {
    message += "<p><a href=\"/off\"><button class=\"button button2\">OFF</button></a></p>";
  } else {
    message += "<p><a href=\"/on\"><button class=\"button\">ON</button></a></p>";
  }
  message += "<p>Boot : " + String(timeBuffer) + "</p>";
  message += "<p>WIFI Connections : " + String(connections) + "</p>";
  message += "<p>MAC : " + WiFi.BSSIDstr() + "</p>";
  message += "<p>RSSI : " + String(WiFi.RSSI()) + " dBm</p>";
  message += "</body></html>";
  server.send(200, "text/html", message);
}

void handleNotFound() {
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}

#ifdef ESP32
void onStationConnected(WiFiEvent_t event, WiFiEventInfo_t info) {
  Serial.println("Connected to AP successfully!");
}

void onStationDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
  digitalWrite(LED, LED_CMD);
  Serial.println("Disconnected from WiFi access point");
  Serial.print("WiFi lost connection. Reason: ");
  Serial.println(info.disconnected.reason);
  Serial.printf("Trying to reconnect to %s\n", ssid);
  WiFi.reconnect();
}
void onStationGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
  digitalWrite(LED, !LED_CMD);
  Serial.printf("WiFi connected to %s\n", ssid);
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  connections++;
}
#else
void onStationConnected(const WiFiEventStationModeConnected& evt) {
  Serial.println("Connected to AP successfully!");
}

void onStationDisconnected(const WiFiEventStationModeDisconnected& evt) {
  Serial.print("Station disconnected: ");
  digitalWrite(LED, LED_CMD);
  Serial.println("Disconnected from WiFi access point");
  Serial.print("WiFi lost connection. Reason: ");
  Serial.println(evt.reason);
  Serial.printf("Trying to reconnect to %s\n", ssid);
  WiFi.reconnect();
}

void onStationGotIP(const WiFiEventStationModeGotIP& evt) {
  digitalWrite(LED, !LED_CMD);
  Serial.printf("WiFi connected to %s\n", ssid);
  Serial.print("IP address: "); Serial.println(WiFi.localIP());
  connections++;
}
WiFiEventHandler stationConnectedHandler;
WiFiEventHandler stationDisconnectedHandler;
WiFiEventHandler stationGotIpHandler;
#endif

void setup() {
  Serial.begin(115200);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LED_CMD);
  pinMode(RELAY,OUTPUT);
  digitalWrite(RELAY, HIGH);
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
  }
#ifdef ESP32
  WiFi.onEvent(onStationConnected, SYSTEM_EVENT_STA_CONNECTED);
  WiFi.onEvent(onStationDisconnected, SYSTEM_EVENT_STA_DISCONNECTED);
  WiFi.onEvent(onStationGotIP, SYSTEM_EVENT_STA_GOT_IP);
#else
  stationConnectedHandler = WiFi.onStationModeConnected(onStationConnected);
  stationDisconnectedHandler = WiFi.onStationModeDisconnected(onStationDisconnected);
  stationGotIpHandler = WiFi.onStationModeGotIP(onStationGotIP);
#endif
  configTzTime("CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00", ntpServer);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  WiFi.begin(ssid, password);
  Serial.println("");
  Serial.print("Connecting to ");
  Serial.println(ssid);

  server.on("/", handleRoot);

  server.on("/inline", []() {
    server.send(200, "text/plain", "This works as well");
  });

  server.on("/on", []() {
    Serial.println("ON");
    digitalWrite(LED, LED_CMD);
    digitalWrite(RELAY,LOW);
    handleRoot();
  });

  server.on("/off", []() {
    Serial.println("OFF");
    digitalWrite(LED, !LED_CMD);
    digitalWrite(RELAY,HIGH);
    handleRoot();
  });

  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  static unsigned long lastTime;
  server.handleClient();
  if (millis() - lastTime >= 1000) {
    if (bootTime < 1000) {
      bootTime = time( NULL );
      struct tm *pTime = localtime(&bootTime);
      strftime(timeBuffer, 80, "%d/%m/%Y %H:%M", pTime);
      Serial.println(timeBuffer);
    }
    display.clearDisplay();
    display.setTextSize(1);      // Normal 1:1 pixel scale
    display.setTextColor(SSD1306_WHITE); // Draw white text
    display.setCursor(0, 0);
    display.print("WIFI ") ; display.print(WiFi.isConnected() ? "CONNECTED" : "DISCONNECTED");
    display.print(" ("); display.print(connections); display.print(")");
    display.setCursor(0, 20);
    display.print("Boot "); display.print(timeBuffer);
    display.setCursor(0, 32);
    display.print("MAC ") ; display.print(WiFi.BSSIDstr());
    display.setCursor(0, 44);
    display.print("IP "); display.print(WiFi.localIP());
    display.setCursor(0, 56);
    display.print("RSSI "); display.print(WiFi.RSSI()); display.print(" dBm");
    display.display();
    lastTime = millis();
  }
}

Après vérification, la fonction setAutoReconnect() ne fait pas grand chose, à part affecter une valeur true ou false à une variable statique _autoReconnect.
Ce n'est pas étonnant que cela ne donne rien.
Mystère ...

Ok je comprend…
Effectivement ça ne risquait pas de marcher.
Pour l’instant avec le nouveau programme tout est ok.
J’ai enfermé mes poules à distance ce soir et l’appareil a bien fonctionné. Il était connecté depuis ce matin.
En parallèle j’en teste un autre que je vais laisser 2 jours sans le toucher pour voir si tout fonctionne bien.
Ensuite si tout est ok, les 2 esp fonctionneront en parallèle avec 2 alimentations distinctes pour commander le même bouton d’ouverture ou fermeture du poulaillier.
Ainsi, si un esp connaît un problème il y aura le 2e en secours.
Je partirai en vacances plus tranquille en me disant que mes cocottes sont plus en sécurité surtout lorsque l’on est en voyage à l’étranger… je les surveille en caméra ip et ouverture / fermeture à distance. Distribution d’eau automatique avec un programmateur arrosage de jardin… bref le poulaillier 2.0… :joy:

1 Like