Prob. ESP32 en webserver (affichage page HTML+ config vers l'ESP32)

Bonjour @ ts,J'ai un soucis avec un ESP32 utilisé en webserver pour afficher une image du fichier HTML.
Je vais essayer d'être clair dans mes explications.
Tout d'abord, je me sert de VisualStudioCode avec Platformio pour le configuré. Je n'ai rien inventé car je suis parti d'une vidéo en français (avec un léger accent canadien :grinning:) bien expliquée.
Le but final sera d'adapter son programme à un projet que je voudrai faire, en y allant étape par étape.
Sans aucune modification de sa configuration, tout fonctionne correctement. Les problèmes commencent quand je veux modifier la page html pour y insérer une image avec une de ces lignes là (le problème est le même dans les 2 cas):

<div class="w3-card w3-black w3-padding-small w3-center">
 <img src="teamMonkey.png" alt="D.A Monkey Reignacais"  />
 </div>
ou
<div class="w3-card w3-black w3-padding-small w3-center">
 <img src="images/logo_amr33.jpg" alt="D.A Monkey Reignacais" />
 </div>

Une fois modifiée la page html et enregistrée, si j'ouvre l'index.html du projet j'ai bien l'image qui s'affiche. Par contre une fois tout enregistré sur l'ESP32, lorsque je me connecte dessus (avec mon pC ou le smartphone) je ne l'ai plus. J'ai juste marqué le "alt". Si je fais "inspecter" sur la page, lorsque je pointe la souris sur le nom de l'image ça marque: impossible de charger l'image.

Dans le setup du programme il y a une partie qui affiche les différents fichiers enregistrés sur la carte (index.html, script.js, w3.css, logo_amr33.jpg, teamMonkey.png).

Voilà en gros mon problème. Je me doute qu'il doit vous manquer des infos pour pouvoir m'aider, mais n'hésitez pas , je vous donnerai d'autres infos dont vous auriez besoin pour essayer de résoudre mon problème.

D'avance merci pour votre aide.

Salut.
Tout dépend du serveur utilisé (WebServer, AsyncWebServer, etc.).
Avec AsyncWebServer et une image stockée dans SPIFFS, le code pourrait ressembler à ceci :

  server.on("/teamMonkey.png", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/teamMonkey.png", "image/png");
  });

Bonjour et merci pour ta réponse.
Effectivement je suis en "AsyncWebServer" et effectivement je n'avais pas mis cette commande. Ça fonctionne mieux...:yum:
Heureusement qu'il y a des personnes comme toi qui permettent de faire avancer les choses pour des mecs comme moi...

Bon choix, et bonne continuation.

Merci,
Si j'ai choisi de le faire avec "AsyncWebServer" c'est surtout grâce à des vidéos que j'ai vu sur YouTube et surtout en français :smile:.
Si j'arrive à finaliser mon projet je viendrai sans doute le mettre sur le site. Mais faut pas être pressé car comme je ne suis pas un expert, j'y passe pas mal de temps...

Bonsoir @ tous,
Après avoir , grâce à la réponse de "hbachetti", avancé dans la mise en page du fichier HTML je me permet de revenir vers vous pour deux questions au niveau programmation entre la page Web et l'ESP32.
Tout d'abord je voudrai créer un bouton impulsionnel. Je m'explique: lorsque je clique sur le bouton je voudrai que l'état d'une variable (je l'appellerai "depart") de l'ESP passe à "HIGH" et lorsqu'on relâche elle revienne à "LOW". Pour l'instant je n'ai trouvé que pour passer de LOW (valeur initiale) à HIGH après clic mais pas la suite (revenir à LOW) sauf en mettant un "delay" dans le "main" ce que je voudrai éviter.
Ma deuxième question: comment depuis l'esp32 je pourrai afficher une variable "decompte", (valeur de 60 à 0 par exemple) en sachant que cette valeur change dans le void loop du main.cpp et quelle sert pour commander deux afficheur 7 segments. Cette partie de configuration fonctionne déjà, je voudrai également l'envoyer sur la page Web.
j'espère avoir été claire dans ma requête et n'hésitez pas à m'envoyer un MP si vous voulez plus de précision.
Merci par avance pour vos réponses.. :wink:

Pour la première question, il faut utiliser les événements mouseDown() et mouseUp() de javascript :

<!DOCTYPE html>
<html>
<body>

<p>"onmousedown" & "onmouseup" events</p>

<button type="button" id="btn1" onmousedown="btn1MouseDown()" onmouseup="btn1MouseUp()">Click me!</button>

<script>
function btn1MouseDown() {
  const Http = new XMLHttpRequest();
  const url='btn1Pressed';
  Http.open("GET", url);
  Http.send();
}

function btn1MouseUp() {
  const Http = new XMLHttpRequest();
  const url='btn1Released';
  Http.open("GET", url);
  Http.send();
}
</script>
</body>
</html>

L'ESP32 devra traiter les requêtes btn1Pressed et btn1Released.

Deuxième question : simplement intégrer la variable dans la page WEB. Mais cela dépend totalement de la manière d'afficher la page WEB.

Si le fichier HTML est construit à l'aide d'une String, y ajouter la valeur de la variable entre balises P par exemple.

Si le fichier HTML est stocké dans SPIFFS, il faudra utiliser une template.
https://techtutorialsx.com/2018/07/23/esp32-arduino-http-server-template-processing-with-multiple-placeholders/

Il est possible de rafraîchir la page automatiquement en ajoutant ceci entre les balises HEAD :
<meta http-equiv="refresh" content="5">

Bonjour et merci pour ta réponse.
Effectivement mes fichiers sont dans le SPIFFS (index.html, script.js, w3.css et des images). Si j'ai bien compris: je crée mon bouton comme tu l'as écrit dans le fichier index.html puis je met les 2 function "btn1MouseDown" et "btn1MouseUp" dans le script.js et enfin dans le main.cpp je crée 2 requêtes "btn1Pressed" et "btn1Realeased" qui me donneront à ma variable "depart" mon état HIGH ou LOW... Génial.... :+1:
Pour la 2ème question, comme j'ai marqué plus haut tout est stocké dans le SPIFFS, du coup, je vais étudier le lien que tu as mis. Mais ça va être plus long avant d'avoir tout décodé, mon anglais n'étant pas extraordinaire... :smile: Et aussi de mettre en place mon bouton...
Je reviendrai vers toi si besoin.
En tout cas MERCI pour ton aide

Une petite recherche autour des templates AsyncWebServer n'est pas la mer à boire. Sincèrement cela en vaut vraiment la peine. Une fois cette notion acquise il est difficile de s'en passer.
Une petite aide en français que j'ai écrit il y a déjà quelque temps (paragraphe 6.3. Utiliser une template) :

1 Like

Bonjour et merci pour toutes ces infos. Pour l'instant j'ai pas mal de taff dans d'autres domaines, mais dès que je peux je m'y mettrai mais il va falloir que je sois vraiment concentré et attentif pour bien comprendre .

Bonjour @ tous,

Bon bin je progresse et j'ai compris le principe de "mouseDown" et "mouseUp". J'ai réussi à l'intégrer dans le brouillon que je me sers pour mon projet et ça fonctionne.
Maintenant reste à comprendre les templades. J'ai commencé à regarder ton liens et il va falloir que j'assimile tout ça pour l'adapter à mes besoins.
Encore merci pour ton aide (hbachetti)... :+1:

Slt,
J'ai pu enfin regarder et essayer de comprendre comment les "templates" fonctionnent. Je pense avoir compris, par contre je n'ai pas réussi à) l'intégrer à mon projet. Du coup j'ai essayer de faire un truc à partir de ce que j'avais et ça arrive à faire ce que je voulais même si ce n'est pas dans la simplicité et logique normale.
Du coup j'ai pas mal avancé sur mon projet.
Encore merci d'avoir passé du temps à répondre à mes questions...

OK, bonne suite.

Merci,
Je pense que je vais bientôt revenir mais je sais pas si je continue sur ce sujet ou si j'en crée un autre :thinking:

Si les questions tournent autour de ESP32 en WebServer, autant continuer ici.

Dommage. Je t'ai peut-être mal orienté.
Un autre exemple peut-être ?

Sur cette page l'auteur donne un exemple avec :
une page HTML stockée dans le SPIFFS avec un placeholder : %GPIO_STATE%

<!DOCTYPE html>
<html>

<head>
  <title>ESP32 WEB SERVER</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css"
    integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <link rel="stylesheet" type="text/css" href="style.css">
</head>

<body>
  <h2>ESP32 WEB SERVER</h2>
  <div class="content">
    <div class="card-grid">
      <div class="card">
        <p><i class="fas fa-lightbulb fa-2x" style="color:#c81919;"></i>     <strong>GPIO2</strong></p>
        <p>GPIO state: <strong> %GPIO_STATE%</strong></p>
        <p>
          <a href="/led2on"><button class="button">ON</button></a>
          <a href="/led2off"><button class="button button2">OFF</button></a>
        </p>
      </div>
    </div>
  </div>
</body>
</html>

On voit bien le placeholder : %GPIO_STATE%
Pour ce qui est du CSS, ignore, tout simplement. Seul le HTML a besoin d'être vraiment compris. On peut résumer sans CSS :

<!DOCTYPE html>
<html>
<head>
  <title>ESP32 WEB SERVER</title>
</head>
<body>
  <h2>ESP32 WEB SERVER</h2>
        <p>GPIO state: <strong> %GPIO_STATE%</strong></p>
        <p>
          <a href="/led2on"><button>ON</button></a>
          <a href="/led2off"><button>OFF</button></a>
        </p>
</body>
</html>

Le code de la fonction processor :

String processor(const String& var){
  Serial.println(var);
  if(var == "GPIO_STATE"){
    if(digitalRead(ledPin)){
      ledState = "ON";
    }
    else{
      ledState = "OFF";
    }
    Serial.print(ledState);
    return ledState;
  }
  return String();
}

On voit que si %GPIO_STATE% est rencontré dans le code HTML, la fonction va remplacer par ON ou OFF.

Le code qui associe l'URL à la fonction qui va la traiter :

  server.on("/led2on", HTTP_GET, [](AsyncWebServerRequest *request){
    digitalWrite(ledPin, HIGH);    
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });
  
  // Route to set GPIO to LOW
  server.on("/led2off", HTTP_GET, [](AsyncWebServerRequest *request){
    digitalWrite(ledPin, LOW);    
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

On voit bien que le code HTML est stocké dans SPIFFS, que le fichier s'appelle /index.html, et que la fonction processor() va faire le boulot de substitution.

Merci pour ton aide, vraiment sympa... :+1: :+1:

Pour le css, je sais en général je ne m'y attarde pas. Le principe de ton exemple, ça je l'ai bien compris.

En fait pour mon projet il faut que je le multiplie par 3. Je m'explique:

J'ai 3 variables n, m et v3.
m va être 10, 20, 30, 40, 50 et 60
n va aller de "valeur m choisie" à 0 toutes les secondes (décompte)
v3 va être une valeur de vitesse entre 0 et 99.
Ces 3 valeurs je l'ai obtient dans le void "loop"

Dans l'index.html il y a à trois endroits différents où il y a :

div class="w3-center
p class="w3-xlarge w3-text-win8-emerald">Temps avant Départ =span id="valeurDepart" 0 span
p
div

div
h3 class="w3-xlarge" span id="valeurDecompte">0 span Sec. avant Départ h3
div

div
h3 class="w3-xxlarge">Vitesse = span id="valeurVitesse" 0 span Km/h h3

Au départ je pensais mettre valeurDepart, valeurDecompte et valeurVitesse dans des %.....% et après écrire un String Processor, mais ça ne fonctionne pas.

Pour la configuration , je le fais avec Visual Studio Code et platformio.
Il y a un dossier avec l'index.html, un script.js et un css et il y a le main.cpp dans le scr.

Pour l'instant, j'ai créé 3 "setInterval(fonction getdata(1, 2 et3)) dans le scrip.js qui récupèrent les infos n, m et v3 du main.cpp et les envoie dans l'index. Ça n'est sans doute pas la meilleur solution, mais ça a l'air de fonctionner...

Je t'ai expliqué tout ça mais ne te sent pas obligé de te prendre la tête et trouver une solution plus simple.
Quoi que, ça pourrait me faire progresser... :laughing: :laughing: :laughing:

Pour continuer dans mes soucis, pourquoi s’arrêter en si bon chemin... :laughing:

Dans mon index.html j'ai créé 2 onglets qui apparaissent en cliquant sur deux boutons (le 2ème faisant disparaitre le 1er et vice-versa.
J'ai rien inventé, je suis parti de cet exemple de w3school:

how to create tabs with CSS and JavaScript.

Ce que j'aimerai c'est qu'en cliquant sur ces boutons j'indique à une variable du main.cpp quel bouton a été cliquer. Si on reste sur l'exemple ce serait envoyer "london", "paris", "tokio".
Peut-on jouer sur les boutons et mettre 2 commandes
onclick="openCity(event, 'London') + "envoyer la ville dans le main.cpp"
ou faut-il faire quelque chose dans le script?

Merci par avance pour vos réponses...

Tu dois écrire
p class="w3-xlarge w3-text-win8-emerald">Temps avant Départ =span id="valeurDepart" %VALEUR_DEPART% span
Donc %VALEUR_DEPART% représente la valeur. Idem pour les deux autres :

h3 class="w3-xlarge" span id="valeurDecompte">%VALEUR_DECOMPTE% span Sec. avant Départ h3
h3 class="w3-xxlarge">Vitesse = span id="valeurVitesse" %VALEUR_VITESSE% span Km/h h3

Dans le String processor :

String processor(const String& var){
  Serial.println(var);      // permet de voir passer le placeholder
  if(var == "VALEUR_DEPART"){
    return n;
  }
  if(var == "VALEUR_DECOMPTE"){
    return m;
  }
  if(var == "VALEUR_VITESSE"){
    return h3;
  }
  return String();
}

n, m, v3 étant des variables du code C.
Si tu n'as pas oublié d'ajouter Processor en argument de ton handler (server.on()), il n'y a pas de raison que cela ne fonctionne pas.

Dans la fonction qui traite le click il faut probablement ajouter :

  let xmlhttp = new XMLHttpRequest();
  xmlhttp.open("GET", "/url?city="+cityName, true);
  xmlhttp.send();

/url étant une URL à traiter à l'aide d'un handler dans le code C, qui recevra l'argument city avec comme valeur cityName.