Serveur sur Esp8266 qui "plante"

Bonjour à tous,
j’ai ce petit serveur sur une carte Wemos D1 minipro montée avec un capteur qui m’envoie des données sur une page web.
Tout fonctionne, sauf que le serveur “plante” régulièrement en affichant “nouveau client” sur la console série…
Surtout lorsque je connecte ou déconnecte un nouveau client.
Je ne comprends pas pourquoi…
Aurais-je oublié une instruction qui permettrai d’arrêter la boucle dans l’attente d’un client ?
Si vous pouviez jetter un oeil sur mon code et me dire ce qui cloche, je vous en serai reconnaissant.
Merci.

Question + : est-il possible de connecter plusieurs “clients” simultanément sur ce type de serveur ?

#include <ESP8266WiFi.h>
#include "Adafruit_Si7021.h"
Adafruit_Si7021 sensor = Adafruit_Si7021();

const char* ssid = "Livebox 4 ABC";
const char* password = "Ton_MDP";
 
int ledPin = D5;
WiFiServer server(80);
 
void setup() {
  Serial.begin(9600);
  delay(10);

// wait for serial port to open
  while (!Serial) {
    delay(10);
  }
//_____Demarrage du capteur Si7021_______
  Serial.println("Si7021 test!");
  
  if (!sensor.begin()) {
    Serial.println("Did not find Si7021 sensor!");
    while (true);
  }
//888888888888888888888888888888888888888

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
 
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecté à : ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connecté");
 
  // Start the server
  server.begin();
  Serial.println("Serveur démarré");
 
  // Print the IP address
  Serial.print("Utilisez ce lien : ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

} 
void loop() 
{
  // Check si un client ets connecté
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
 
  // Attends que le client envoie des données
  Serial.println("nouveau client");
  while(!client.available()){
    delay(100);
  }
 
  // Lis la première ligne de la requête
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();
 
  // Match the request
 
  int value = LOW;
  if (request.indexOf("/LED=ON") != -1) {
    digitalWrite(ledPin, HIGH);
    value = HIGH;
  }
  if (request.indexOf("/LED=OFF") != -1){
    digitalWrite(ledPin, LOW);
    value = LOW;
  }

//_____Affiche les relevés du capteur Si7021 dans le moniteur série__________
{
  Serial.print("Humidite:    "); Serial.print(sensor.readHumidity(),1);
  Serial.print("\tTemperature: "); Serial.println(sensor.readTemperature(),1);
  //delay(500);
}
//888888888888888888888888888888888888888888888888888888888
 
// Retourne la réponse
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println("Connection: close");  // termine la connexion après la bonne fin de cette réponse
//  client.println("Refresh: 15");  // mise à jour toutes les 15 sec
  client.println(""); //  do not forget this one
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");

client.println("

<font color=GREEN");
  client.println("<font size=7></b>Le taux d'humidit&eacute; est de : ");
  client.print(sensor.readHumidity(),0);
  client.print(" %</font color=0>");

 client.println("
");
  client.println("

<font color=BLUE");
  client.println("<font size=7></b>La temp&eacute;rature est de : ");
 client.print(sensor.readTemperature(),1);
  client.print(" &deg;C</font color=0>");
 
  client.println("


");
  client.print("<font size=7>La LED est maintenant : ");
 
  if(value == HIGH) {
    client.print("<font color=GREEN>Allum&eacute;e</font color=0> ☺");  
  } else {
    client.print("<font color=RED>&Eacute;teinte</font color=0> ☹");
  }
  client.println("

<B><font size=8>");
  client.println("Cliquez <a href=\"/LED=ON\">ICI</a> pour allumer la LED

");
  client.println("Cliquez <a href=\"/LED=OFF\">ICI</a> pour &eacute;teindre la LED
");
  //client.println("Cliquez <a href=\"/LED=OFF\"><button style=width:100px style=height:50px>ICI</button></a> pour &eacute;teindre la LED
");
  client.println("

");
    
  client.println("</B><center><font size=5>&copy; Richard ROUSSINET");
  client.println("</html>");
 
  delay(10);
  Serial.println("Client déconnecté");
  Serial.println("");
}

Un petit

delay(1);
client.stop(); // termine la connexion

après avoir balancé la page ne serait sans doute pas superflu.

Il me semble que vous avez deux ou trois posts ouverts sur ce theme - ce n’est pas une bonne pratique. Gardez tout dans le même fil de discussion.

Il me semble Notamment que je vous avais donné deux liens sur des tutos (et comment rafraîchir la page). Si vous aviez lu les tutos et étudier le code vous ne poseriez sans doute pas cette question

Bonjour J-M-L
merci d'avoir répondu à ma question et de me faire la leçon :wink:

Je n'ai ouvert qu'un seul autre post à ce jour, mais comme le sujet était différent,
j'ai cru bon en ouvrir un nouveau avec un titre différent...
Ais-je mal fait ?

En tous cas, merci pour vos conseils,
c'est vrai, j'avoue ne pas avoir lu vos tutos en entier, mais quoi qu'il en soit
la solution de rajouter
delay(1);
client.stop();

en fin de code,
n'empêche pas le serveur de s'arrêter.
Parfois il supporte plusieurs requêtes sans problèmes,
parfois il s'arrête dès le début.

Est-ce que j'aurai mal placé l'instruction client.stop ?
Ou est-ce une erreur dans la boucle de lecture des données du capteur ?

Je vais lire des tutos pour essayer de comprendre...

Je vais aussi chercher du coté de la connexion WiFi, mais pourtant le module reste bien connecté à mon routeur...

Problème résolu :slight_smile:

Il suffisait de remplacer "While" par "if(!client.available())

Le code ci-dessus fonctionne sans s'arrêter :slight_smile:

Bonjour,
je me permets de poster sur ce sujet car j’ai le même problème. (si c’est interdit dites le et je m’abstiendrai à l’avenir.
Voilà ma question : j’ai exactement les memes plantages avec (presque) le meme programme basique sur un nodemcu lolin V3 chinois.
je me bagarre depuis 2 jours à ajouter (puis enlever des delay() pour le laisser respirer, rien n’y fait plantage toutes les X rafraichissements de page.
et là je viens de tester sur “Bing” de Microsoft et ca marche, alors que j’utilisais Chrome et que ca plantait toutes les 5 ou 10 clics.
Est-ce que c’est un défaut connu de Chrome ?
Quel navigateur conseillez vous sous windows et sous android pour les pages générées par esp8266 ?
merci de votre aide
pour info mon prog

////////////////////////////////////////////////////////////////
// Programme simple de webserver
////////////////////////////////////////////////////////////////
#include <ESP8266WiFi.h> 

const char* ssid = "maFreebox";
const char* password = "monPass";
int ledPin = 13;
 int value = LOW;
byte heureMonte=0;
// ATTENTION GPIO13 correspond à la PIN 07
WiFiServer server(80);

void setup() {
  Serial.begin(9600);// je l'ai supprimé pour tester si c'est lui qui rame mais non donc je l'ai remis
  delay(10);
  
   pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
 
  // 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://");
  Serial.println(WiFi.localIP());
} 
void loop() {
  // Controle de la connection client
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
 
  // Attente de l'envoi de quelque chose du client
  Serial.println("new client");
 while(!client.available()){
 // if(!client.available()){

    delay(1);
  }
 
  // Première ligne de la requête
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();
 
  // Lecture-préparation réponse de la requête
 // int value = LOW; //je l'ai déplacé dans les déclarations en tete
  if (request.indexOf("/LED=ON") != -1)  {
    digitalWrite(ledPin, HIGH);
    value = HIGH;
  }
  else if (request.indexOf("/LED=OFF") != -1)  {
    digitalWrite(ledPin, LOW);
    value = LOW;
  }
  else if (request.indexOf("/heureMonte=+") != -1)  {
    heureMonte +=1; if (heureMonte==24){ heureMonte=0;}
   Serial.println("augmenter heureMonte");
  }
 delay(5);//ajouté par moi puis supprime
  // Réponse à la requête
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); 
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head>");
  client.println("</head>");
  client.println("<body>");
  client.println("<div style=\"text-align:center\">");
  client.println("<h1>TEST WIFI SERVEUR</h1>

");
  client.print("Led pin is now: ");
  if(value == HIGH) {
    client.print("On");
  } else if (value==LOW)
  {
    client.print("Off");
  }
  client.println("

");
  client.println("<a href=\"/LED=ON\"\"><button style=\"height: 50px; width: 100px\"> ON </button></a>");
  client.println("<a href=\"/LED=OFF\"\"><button style=\"height: 50px; width: 100px\"> OFF </button></a>
");
  client.println("

");
  client.print("heureMonte = ");  
  client.println(heureMonte);
  client.println("

");
  client.println("<a href=\"/heureMonte=+\"\"><button style=\"height: 50px; width: 100px\"> heureMonte+1 </button></a>
");

  client.println("</body>");
  client.println("</html>");
 
  delay(1);
  client.stop(); // termine la connexion
  Serial.println("Client disconnected");
  Serial.println("");
 
}

les delay() ne changent rien à l'affaire, votre ESP ne respire pas. c'est pas de la magie noire...

N'utilsez pas client.flush();, ça sert à émettre tout ce qui a déjà été posté sur le client, pas à vider le buffer en entrée (cf le code source)

pour vider le buffer reçu (sinon le client reste actif) faites un while (client.available()) client.read();

merci beaucoup J-M-L,
effectivement j'ai fait des test pendant 10 minutes et aucun plantage.

par contre sous Chrome j'ai quitté l'ordi 1 heure et au retour c'est complètement planté (ca fait 2 heures que la page est en actualisation et rien ne bouge)...
Que faire ?
d'autre part pourquoi sous Bing ca marchait alors que sous chrome ça plantait ? (je n'ai pas essayé la pause d'une heure sur Bing donc je ne sais pas si ça se serait bloqué aussi !

modification de message

sous "Bing" j'ai laissé toute la nuit l'esp branché et ce matin ca fonctionne, alors qu'hier sous Chrome il s'était planté au bout de moins d'une heure...
pourquoi ? et que me conseillez vous sous Windows (l'ordi) et Android (mon portable à la maison) pour afficher la page de façon fiable sans plantage ?
Merci

J’utilise pas Windows / suis sur Mac et Linux

Avez vous viré tous les delay() ?

Postez le nouveau code et comment vous testez

Bonjour,
merci J-M-L
les delay() je les ai remis à 1
j'ai fait la modif que vous aviez suggérée

N'utilsez pas client.flush();, ça sert à émettre tout ce qui a déjà été posté sur le client, pas à vider le buffer en entrée (cf le code source) 

pour vider le buffer reçu (sinon le client reste actif) faites un
Code: [Select]
while (client.available()) client.read();

pour tester j'ai mon nodeMCU branché sur l'USB de mon ordi, aucune pin utilisée le nodemcu est nu.
le Serial à 9600 bauds

⸮EO⸮v@MM⸮4C(R⸮

Connecting to (*****ma box)
...
WiFi connected
Server started
Use this URL to connect: http://192.168.0.210
new client
GET / HTTP/1.1
Client disconnected

new client
GET /heureMonte=+ HTTP/1.1
augmenter heureMonte
Client disconnected

new client
GET /heureMonte=+ HTTP/1.1
augmenter heureMonte
Client disconnected

etc... quand ca ne plante pas

et ensuite g'agit sur les 3 boutons répétitivement, puis je fais une pause, je reviens... etc...
Mais surtout les nouvelles de ce matin c'est que sous "bing", avec vos modif ça marche...
pourquoi pas sur chrome ?
NB : je n'ai pas gardé le débug de quand ca a planté sous chrome, je le relance et je regarderai pour vous le poster

oups et voici mon nouveau code

////////////////////////////////////////////////////////////////
// Programme simple de webserver
////////////////////////////////////////////////////////////////
#include <ESP8266WiFi.h> 

const char* ssid = "ma freebox";
const char* password = "mon pass";
int ledPin = 13;
 int value = LOW;
byte heureMonte=0;
// ATTENTION GPIO13 correspond à la PIN 07
WiFiServer server(80);

void setup() {
  Serial.begin(9600);// je l'ai supprimé pour tester si c'est lui qui rame mais non donc je l'ai remis
  delay(10);
  
   pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
 
  // 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://");
  Serial.println(WiFi.localIP());
} 
void loop() {
  // Controle de la connection client
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
 
  // Attente de l'envoi de quelque chose du client
  Serial.println("new client");
 while(!client.available()){
 // if(!client.available()){

    delay(1);
  }
 
  // Première ligne de la requête
  String request = client.readStringUntil('\r');
  Serial.println(request);
 while (client.available()) client.read();
 // client.flush();
 
  // Lecture-préparation réponse de la requête
 // int value = LOW; //je l'ai déplacé dans les déclarations en tete
  if (request.indexOf("/LED=ON") != -1)  {
    digitalWrite(ledPin, HIGH);
    value = HIGH;
  }
  else if (request.indexOf("/LED=OFF") != -1)  {
    digitalWrite(ledPin, LOW);
    value = LOW;
  }
  else if (request.indexOf("/heureMonte=+") != -1)  {
    heureMonte +=1; if (heureMonte==24){ heureMonte=0;}
   Serial.println("augmenter heureMonte");
  }
 delay(5);//ajouté par moi puis supprime
  // Réponse à la requête
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); 
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head>");
  client.println("</head>");
  client.println("<body>");
  client.println("<div style=\"text-align:center\">");
  client.println("<h1>TEST WIFI SERVEUR</h1>

");
  client.print("Led pin is now: ");
  if(value == HIGH) {
    client.print("On");
  } else if (value==LOW)
  {
    client.print("Off");
  }
  client.println("

");
  client.println("<a href=\"/LED=ON\"\"><button style=\"height: 50px; width: 100px\"> ON </button></a>");
  client.println("<a href=\"/LED=OFF\"\"><button style=\"height: 50px; width: 100px\"> OFF </button></a>
");
  client.println("

");
  client.print("heureMonte = ");  
  client.println(heureMonte);
  client.println("

");
  client.println("<a href=\"/heureMonte=+\"\"><button style=\"height: 50px; width: 100px\"> heureMonte+1 </button></a>
");

  client.println("</body>");
  client.println("</html>");
 
  delay(1);
  client.stop(); // termine la connexion
  Serial.println("Client disconnected");
  Serial.println("");
 
}

debug plantage (chrome) après 1 heure de repos
j’appuie sur le bouton heureMontee+1
pas de réponse
debug

new client
GET /favicon.ico HTTP/1.1
Client disconnected

new client

Bonjour,

De ce que je comprends de votre dernière séquence debug :

  • le navigateur vous demande une "favicon". (Cherchez sur Internet pour savoir ce que c'est),
  • vous lui envoyez votre page, ce qui n'est pas ce qu'il attend et vous déconnectez,
  • il se reconnecte (?) sans rien vous renvoyer (?) et vous restez en attente dans le

String request = client.readStringUntil('\r');

Vérifiez en mettant des "traces" (Serial.println("quelquechose qui vous parle"):wink: pour comprendre ce qui se passe. Vous verrez où et quand le programme se bloque.

J'ai été aussi bien embêté par la "favicon". Désormais, je réponds aux demandes de "favicon" par une favicon vide :

"HTTP/1.1 200 OK\r\n"
 "Content-Type: image/x-icon\r\n"
 "Content-Length: 0\r\n\r\n";

Cela calme Internet Explorer et Chrome sur W, Firefox sur W et Linux, Chrome sur Android... Pour le Mac, je n'ai pas essayé, faute de Mac...

Bonne bidouille,

MicroQuettas

PS : 1 petit truc : il semble que les navigateurs HTML acceptent les ' (apostrophes) à la place des " (guillemets). C'est plus sympa et plus lisible de taper ' que "...

Certains navigateurs en effet envoient 2 GET pour une requête: une pour le contenu et une pour la favicon
il faut traiter cela correctement et surtout vous assurer que vous terminez bien chaque requête client. Si les clients ne sont pas fermés correctement, alors vous aurez une fuite mémoire et au bout d'un moment ça va planter. (c'est pour cela que c'est bien de vider toute la requête jusqu'à ce que available() dise 0)

Bonjour,
merci J-M-L et microquettas
j’ai appliqué (enfin je pense avoir appliqué) vos idées, c’est toujours pareil même plantage sur Chrome même débug. donc je ne le reposte pas

citation J-M-L : Si les clients ne sont pas fermés correctement, alors vous aurez une fuite mémoire et au bout d'un moment ça va planter. (c'est pour cela que c'est bien de vider toute la requête jusqu'à ce que available() dise 0)

est-ce que c’est bien ce que j’ai fait en mettant while (client.available()) client.read();// suggestion J-M-L au lieu de //client.flush();
voici mon code à jour :

////////////////////////////////////////////////////////////////
// Programme simple de webserver
////////////////////////////////////////////////////////////////
#include <ESP8266WiFi.h> 

const char* ssid = "ma freebox";
const char* password = "mon pass";
int ledPin = 13;
 int value = LOW;
byte heureMonte=0;
// ATTENTION GPIO13 correspond à la PIN 07
WiFiServer server(80);

void setup() {
  Serial.begin(9600);// je l'ai supprimé pour tester si c'est lui qui rame mais non donc je l'ai remis
  delay(10);
  
   pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
 
  // 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://");
  Serial.println(WiFi.localIP());
} 
void loop() {
  // Controle de la connection client
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
 
  // Attente de l'envoi de quelque chose du client
  Serial.println("new client");
 while(!client.available()){
 // if(!client.available()){

    delay(1);
  }
 
  // Première ligne de la requête
  String request = client.readStringUntil('\r');
  Serial.println(request);
 while (client.available()) client.read();// suggestion J-M-L au lieu de //client.flush();
 
  // Lecture-préparation réponse de la requête
 // int value = LOW; //je l'ai déplacé dans les déclarations en tete
 if (request.indexOf("/LED=ON") != -1)  {
    digitalWrite(ledPin, HIGH);
    value = HIGH;
  }
  else if (request.indexOf("/LED=OFF") != -1)  {
    digitalWrite(ledPin, LOW);
    value = LOW;
  }
  else if (request.indexOf("/heureMonte=+") != -1)  {
    heureMonte +=1; if (heureMonte==24){ heureMonte=0;}
   Serial.println("augmenter heureMonte");
  }
 //delay(5);//ajouté par moi puis supprime
  // Réponse à la requête
       // ajout microquettas****************************************
       if (request.indexOf("/favicon.ico")!= -1){
         client.println("HTTP/1.1 200 OK\r\n");
         client.println("Content-Type: image/x-icon\r\n");
         client.println("Content-Length: 0\r\n\r\n");
        }//fin d'ajout microquettas
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); 
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head>");
  client.println("</head>");
  client.println("<body>");
  client.println("<div style=\"text-align:center\">");
  client.println("<h1>TEST WIFI SERVEUR</h1>

");
  client.print("Led pin is now: ");
  if(value == HIGH) {
    client.print("On");
  } else if (value==LOW)
  {
    client.print("Off");
  }
  client.println("

");
  client.println("<a href=\"/LED=ON\"\"><button style=\"height: 50px; width: 100px\"> ON </button></a>");
  client.println("<a href=\"/LED=OFF\"\"><button style=\"height: 50px; width: 100px\"> OFF </button></a>
");
  client.println("

");
  client.print("heureMonte = ");  
  client.println(heureMonte);
  client.println("

");
  client.println("<a href=\"/heureMonte=+\"\"><button style=\"height: 50px; width: 100px\"> heureMonte+1 </button></a>
");

  client.println("</body>");
  client.println("</html>");
 
  delay(1);
  client.stop(); // termine la connexion
  Serial.println("Client déconnecté");
  Serial.println("");
 
}

bonsoir,
ce que je ne comprend pas, c'est que sur Egde (microsoft) ca marche sans problème, et que sur Chrome sur l'ordi ca plante. je viens de tester avec mon smartphone android, apparemment ca fonctionne aussi.
a titre pédagogique, je voudrais bien que vous me disiez si mon code est bon et après je pense qu'on pourra cloturer ce sujet
merci encore à J-M-L et à Microquettas, j'ai bien entendu fait une distribution de "karmas"

C’est pas bon si vous recevez une requête de favicon vous balancez une réponse http mal formée (en Fait vous balancez 2 réponses dans la même transaction)

merci J-M-L
déjà je viens enfin de comprendre pourquoi ca plante sur Chrome et pas sur Edge.
je viens (après une modif que j’ai mal faite) de tester les 2.
Chrome demande le favicon et Edge ne le demande pas
je viens de modifier l’erreur que vous aviez détectée
est-ce que comme ca c’est bon s’il vous plait ?
NB : ca plante toujours sur Chrome, notamment quand je reviens cliquer sur un bouton après un temps de repos

////////////////////////////////////////////////////////////////
// Programme simple de webserver
////////////////////////////////////////////////////////////////
#include <ESP8266WiFi.h> 

const char* ssid = "ma freebox";
const char* password = "mon pass";
int ledPin = 13;
 int value = LOW;
byte heureMonte=0;
// ATTENTION GPIO13 correspond à la PIN 07
WiFiServer server(80);

void setup() {
  Serial.begin(9600);// je l'ai supprimé pour tester si c'est lui qui rame mais non donc je l'ai remis
  delay(10);
  
   pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
 
  // 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://");
  Serial.println(WiFi.localIP());
} 
void loop() {
  // Controle de la connection client
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
 
  // Attente de l'envoi de quelque chose du client
  Serial.println("new client");
 while(!client.available()){
 // if(!client.available()){

    delay(1);
  }
 
  // Première ligne de la requête
  String request = client.readStringUntil('\r');
  Serial.println(request);
 while (client.available()) client.read();// suggestion J-M-L au lieu de //client.flush();
 
  // Lecture-préparation réponse de la requête
 // int value = LOW; //je l'ai déplacé dans les déclarations en tete
 if (request.indexOf("/LED=ON") != -1)  {
    digitalWrite(ledPin, HIGH);
    value = HIGH;
  }
  else if (request.indexOf("/LED=OFF") != -1)  {
    digitalWrite(ledPin, LOW);
    value = LOW;
  }
  else if (request.indexOf("/heureMonte=+") != -1)  {
    heureMonte +=1; if (heureMonte==24){ heureMonte=0;}
   Serial.println("augmenter heureMonte");
  }
 //delay(5);//ajouté par moi puis supprime
  // Réponse à la requête
       // ajout microquettas****************************************
       if (request.indexOf("/favicon.ico")!= -1){
         client.println("HTTP/1.1 200 OK\r\n");
         client.println("Content-Type: image/x-icon\r\n");
         client.println("Content-Length: 0\r\n\r\n");
        }//fin d'ajout microquettas
        else {
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); 
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head>");
  client.println("</head>");
  client.println("<body>");
  client.println("<div style=\"text-align:center\">");
  client.println("<h1>TEST WIFI SERVEUR</h1>

");
  client.print("Led pin is now: ");
  
  if(value == HIGH) {
    client.print("On");
  } else if (value==LOW)
  {
    client.print("Off");
  }
  client.println("

");
  client.println("<a href=\"/LED=ON\"\"><button style=\"height: 50px; width: 100px\"> ON </button></a>");
  client.println("<a href=\"/LED=OFF\"\"><button style=\"height: 50px; width: 100px\"> OFF </button></a>
");
  client.println("

");
  client.print("heureMonte = ");  
  client.println(heureMonte);
  client.println("

");
  client.println("<a href=\"/heureMonte=+\"\"><button style=\"height: 50px; width: 100px\"> heureMonte+1 </button></a>
");
       } // fin du else lié au favicon ou non
  client.println("</body>");
  client.println("</html>");
 
  delay(1);
  client.stop(); // termine la connexion
  Serial.println("Client déconnecté");
  Serial.println("");
 
}

Bonsoir,

Vous avez encore 3 petits problèmes avec ce code :

  • le contenu que je vous ai passé pour la page favicon vide comporte les fins de lignes. Il faut donc les envoyer avec un "print" et pas un "println" qui rajoute une deuxième fin de ligne. Le navigateur reçoit alors des lignes vides, qui ont une signification bien particulière, et il ne sait plus de quoi il retourne ;

  • la } de fin du else du if favicon est mal placée. Elle doit être juste avant le "delay(1)",

  • plus subtil, la page favicon vide et votre page gèrent de manière différente la déconnexion client :

  • La page favicon contient la longueur du contenu, ce qui permet au client (le navigateur) de savoir quand il a tout reçu. Il (le client) se déconnecte du serveur quand il a tout reçu,

  • pour votre page, pas d'information de taille de contenu. C'est le serveur qui indique au client que tout a été envoyé en le déconnectant côté serveur. En d'autres termes, c'est le serveur qui déconnecte le client quand il a tout envoyé.

Les deux façons de faire sont licites, mais, dans votre code où les deux pages se rejoignent sur la déconnexion côté serveur, vous risquez de faire une demande de déconnexion pour un client déjà déconnecté !
Déconnecter côté serveur quand tout est terminé est une sage précaution dans tous les cas. Il faut simplement rajouter un test avant la demande de déconnexion :

if (client.connected())
  {  /* Le client est encore connecté */
  client.close();  /* On peut le virer sans crainte */
  }

[/li]

Toujours par rapport à la demande de déconnexion, je me demande si un "yield()" (qui rend la main au "système" pour qu'il gère ses tâches, les transmissions entre autres) ne serait pas plus approprié qu'un "delay(1)". A essayer, de toutes façon un delay() rend également la main.

Dernier point, sans doute le plus important. Même si votre code arrive à fonctionner, il manque de robustesse. Il n'est pas normal qu'au moindre problème avec un client, il reste bloqué dans l'attente de quelque chose qui ne viendra pas (le "readStringUntil"). C'est normal à votre stade, mais avant de poursuivre, regardez les tutos (J-M-L entre autres) et les exemples des bibliothèques qui proposent des codes, certes plus volumineux, mais plus robustes.

Bonne bidouille,

MicroQuettas

Bonjour,
Merci beaucoup Microquettas et merci beaucoup J-M-L.

maintenant ça fonctionne sans bug même sous Chrome qui demande une favicon. :slight_smile:

Grace à vous 2 j’ai beaucoup appris en quelques jours et c’est le but entre autres
Microquettas, j’ai fait les modifs que vous m’aviez suggérées
remplacer mes println par des print là où le retour à la ligne était déjà dans la phrase…
déplacer mon accolade fermante du else qui était effectivement mal placée

ajouter la condition

 if (client.connected())
  {  /* Le client est encore connecté */
  client.close();  /* On peut le virer sans crainte */
  }
sauf que j'ai remplacé "client.close" par "client.stop" car close n'était pas dans la bibli (messe d'erreur)

j’ai remplacé le delay(1) par un yield();

Au passage merci à J-M-L qui m’avait dit d’enlever TOUS mes delay() mais j’en avais oublié un…

j’ai lu sur le net "Un delay de plus de 20us peut mener à des pertes de connexion."

Ca bugait encore, j’ai rajouté un yield() avant la réponse à la requête et depuis ça roule…

vous me parliez des tutos qu’il faut que je lise, je suis d’accord et je le fais déjà : je suis même en train d’essayer de retranscrire le tuto de J-M-L sur le shield ethernet pour moi pour l’adapter à l’esp8266 mais j’avoue que je n’y comprend rien.
en règle générale les tutos s’adressent aux utilisateurs ayant déjà une connaissance de base et je m’arrache la tête sur chaque ligne… alors ma technique est de prendre des exemples existant et de le modifier, souvent ça marche (et là je ne viens pas vous embêter) et parfois ça plante, comme aujourd’hui.
Dans d’espoir que ça puisse aider un autre débutant, je poste mon code modifié (je l’ai relativement documenté)

////////////////////////////////////////////////////////////////
// Programme simple de webserver
////////////////////////////////////////////////////////////////
#include <ESP8266WiFi.h> 

const char* ssid = "ma freebox";
const char* password = "mon pass";
int ledPin = 13;
 int value = LOW;
byte heureMonte=0;
// ATTENTION GPIO13 correspond à la PIN 07
WiFiServer server(80);

void setup() {
  Serial.begin(9600);// je l'ai supprimé pour tester si c'est lui qui rame mais non donc je l'ai remis
  delay(10);
  
   pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
 
  // 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://");
  Serial.println(WiFi.localIP());
} 
void loop() {
  // Controle de la connection client
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
 
  // Attente de l'envoi de quelque chose du client
  Serial.println("new client");
 while(!client.available()){
    //delay(1); supprimé "Un delay de plus de 20us peut mener à des pertes de connexion."
  }
 
  // Première ligne de la requête
  String request = client.readStringUntil('\r');
  Serial.println(request);
 while (client.available()) client.read();// suggestion J-M-L au lieu de //client.flush();
 
  // Lecture-préparation réponse de la requête
 // int value = LOW; //je l'ai déplacé dans les déclarations en tete
 if (request.indexOf("/LED=ON") != -1)  {
    digitalWrite(ledPin, HIGH);
    value = HIGH;
  }
  else if (request.indexOf("/LED=OFF") != -1)  {
    digitalWrite(ledPin, LOW);
    value = LOW;
  }
  else if (request.indexOf("/heureMonte=+") != -1)  {
    heureMonte +=1; if (heureMonte==24){ heureMonte=0;}
   Serial.println("augmenter heureMonte");
  }
  yield();
 //delay(5);//ajouté par moi puis supprime
  // Réponse à la requête
       // ajout microquettas****************************************
       if (request.indexOf("/favicon.ico")!= -1){
         client.print("HTTP/1.1 200 OK\r\n");
         client.print("Content-Type: image/x-icon\r\n");
         client.print("Content-Length: 0\r\n\r\n");
        }//fin d'ajout microquettas
        else {
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); 
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head>");
  client.println("</head>");
  client.println("<body>");
  client.println("<div style=\"text-align:center\">");
  client.println("<h1>TEST WIFI SERVEUR</h1>

");
  client.print("Led pin is now: ");
  
  if(value == HIGH) {
    client.print("On");
  } 
  else if (value==LOW)
  {
    client.print("Off");
  }
  client.println("

");
  client.println("<a href=\"/LED=ON\"\"><button style=\"height: 50px; width: 100px\"> ON </button></a>");
  client.println("<a href=\"/LED=OFF\"\"><button style=\"height: 50px; width: 100px\"> OFF </button></a>
");
  client.println("

");
  client.print("heureMonte = ");  
  client.println(heureMonte);
  client.println("

");
  client.println("<a href=\"/heureMonte=+\"\"><button style=\"height: 50px; width: 100px\"> heureMonte+1 </button></a>
");
     // deplacé 2 lignes plus bas   } // fin du else lié au favicon ou non
  client.println("</body>");
  client.println("</html>");
       } // fin du else lié au favicon ou non
  yield();//delay(1);
  if (client.connected())
  {  /* Le client est encore connecté */
 // client.close();  /* On peut le virer sans crainte */ DEBUG 'class WiFiClient' has no member named 'close'
  client.stop(); // termine la connexion
  Serial.println("Client déconnecté par client.stop");
  }
  //Serial.println("Client déconnecté");
  Serial.println("");
 
}
1 Like

Bonjour

esp8266... WiFi... delay()... yield()..... delayMicroseconds() ??

Pour une information actualisée voir la doc de référence
https://arduino-esp8266.readthedocs.io/en/2.5.2/reference.html#timing-and-delays

-> A proscrire : les delayMicroseconds() supérieurs à 20000 , soit 20ms.... pas les delay(20) parce que le compilateur (dans le cas particulier des ESP8266) sait maintenant profiter des delay() pour rendre la main à la pile WiFi !!
N.B : Il ne le fait pas pour la fonction delayMicroseconds()

Auparavant il fallait éviter , en ESP8266 avec WiFi, tout autant les delay() que les delayMicroseconds()

1 Like