{"id":395,"date":"2020-05-10T16:40:09","date_gmt":"2020-05-10T16:40:09","guid":{"rendered":"https:\/\/marcjuneau.ca\/?p=395"},"modified":"2020-05-10T16:40:09","modified_gmt":"2020-05-10T16:40:09","slug":"serveur-esp32-et-e-s","status":"publish","type":"post","link":"https:\/\/marcjuneau.ca\/?p=395","title":{"rendered":"Serveur ESP32 et E\/S"},"content":{"rendered":"<p>Dans cet article, nous allons ajouter des fonctionnalit\u00e9s \u00e0 notre ESP32. Ce dernier va maintenant afficher l&rsquo;\u00e9tat d&rsquo;une LED, d&rsquo;un bouton et d&rsquo;un potentiom\u00e8tre en plus de permettre de changer l&rsquo;\u00e9tat de la LED.<\/p>\n<p><!--more--><\/p>\n<p>Assurez-vous de lire l&rsquo;article <a href=\"https:\/\/marcjuneau.ca\/?p=379\">Serveur Web sur le ESP32<\/a> avant de d\u00e9buter cette partie.<\/p>\n<p><strong>Attention : le ESP32 n&rsquo;est pas tol\u00e9rant au 5V sur les E\/S. Utilisez le 3.3V pour comme alimentation pour vos circuits.<\/strong><\/p>\n<h4>1 &#8211; Lecture des entr\u00e9es<\/h4>\n<p>La lecture d&rsquo;une broche num\u00e9rique s&rsquo;effectue via la fonction <em>digitalRead<\/em>. Sur le montage, le bouton sera sur la broche 23 donc il sera possible d&rsquo;afficher l&rsquo;\u00e9tat du bouton avec un simple test.<\/p>\n<pre>if(digitalRead(23))\n\u00a0 client.print(\"off\");\nelse\n  client.print(\"on\");<\/pre>\n<p>La lecture du potentiom\u00e8tre utilise la fonction <em>analogRead<\/em>. Sur le montage, le potentiom\u00e8tre sera reli\u00e9 \u00e0 la broche 34 (ADC1:6). L&rsquo;affichage de la valeur du potentiom\u00e8tre sera affich\u00e9e directement.<\/p>\n<pre>client.print(analogRead(34));<\/pre>\n<h4>2 &#8211; \u00c9criture des sorties<\/h4>\n<p>Pour modifier l&rsquo;\u00e9tat de la LED, nous allons utiliser la fonction <em>digitalWrite<\/em>. La LED sera connect\u00e9e sur la broche 15 avec une r\u00e9sistance de 1kohms en s\u00e9rie. La cathode de la LED sera reli\u00e9e au GND.<\/p>\n<p>Pour recevoir la commande d&rsquo;\u00e9tat \u00e0 partir du navigateur, nous allons ajouter un bouton dans notre code html. Le bouton provoquera une requ\u00eate html vers \u00a0un URL qui contiendra l&rsquo;adresse IP du ESP32, ainsi que l&rsquo;\u00e9tat d\u00e9sir\u00e9e du LED.<\/p>\n<p>Ajout du bouton dans le code HTML.<\/p>\n<pre>if (led1State)<br \/>  client.println(\"&lt;p&gt;&lt;a href=\\\"\/LED1\/off\\\"&gt;&lt;button&gt;ON&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\");<br \/>else<br \/>  client.println(\"&lt;p&gt;&lt;a href=\\\"\/LED1\/on\\\"&gt;&lt;button&gt;OFF&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\");<\/pre>\n<p>Dans le code pr\u00e9c\u00e9dent, \u00a0on ajoute un bouton dans la page html qui affiche l&rsquo;\u00e9tat actuel du bouton, et qui appel \u00a0le URL avec le IP plus le text \/LED1\/X o\u00f9 X est le nouvel \u00e9tat d\u00e9sir\u00e9.<\/p>\n<p>Pour r\u00e9cup\u00e9rer l&rsquo;information dans le URL, il faudra dans un premier temps conserver la requete html re\u00e7ue, puis analyser celle-ci pour voir si l&rsquo;on y retrouve la commande GET avec un des deux href configurer dans le bouton.<\/p>\n<pre> \/\/ ajout de la r\u00e9cup\u00e9ration de la requ\u00eate http compl\u00e8te<br \/>char rxData = client.read(); <br \/>rxHttpRequest+=rxData;<br \/>\/\/ Ajout de l'analyse de la requ\u00eate, lorsque qu'elle est re\u00e7ue au complet<br \/>if (rxHttpRequest.indexOf(\"GET \/LED1\/on\") &gt;= 0) <br \/>{<br \/>  \u00a0 digitalWrite(15,1); \/\/ gestion de la sortie<br \/>\u00a0\u00a0  led1State=1; \/\/ gestion de la variable d'\u00e9tat pour modifier le bouton<br \/>}<br \/>if (rxHttpRequest.indexOf(\"GET \/LED1\/off\") &gt;= 0) <br \/>{<br \/>\u00a0 digitalWrite(15,0); \/\/ gestion de la sortie<br \/>\u00a0\u00a0 led1State=0; \/\/ gestion de la variable d'\u00e9tat pour modifier le bouton<br \/>}<\/pre>\n<p>Il faudra aussi activer la LED en sortie dans la fonction setup avec la fonction pinMode.<\/p>\n<pre>pinmode(15,OUTPUT);<\/pre>\n<p>Finalement, lorsque l&rsquo;on ferme la connexion avec le client, il faut vider la requ\u00eate http. Voici donc le code complet pour le moment.\u00a0<\/p>\n<pre>#include &lt;Arduino.h&gt;<br \/>#include &lt;WiFi.h&gt;<br \/>\/\/ Informations sur le r\u00e9seau Wi-Fi<br \/>\/\/ Vous devez remplacer les informations pas celles de votre r\u00e9seau<br \/>const char* ssid = \"devRouteur\";<br \/>const char* password = \"#1234#fafa\";<br \/>\/\/ Cr\u00e9er un serveur sur le port 80<br \/>WiFiServer serveur(80);<br \/>\/\/ Cr\u00e9er une string pour conserver la requ\u00eate http<br \/>String rxHttpRequest = \"\";<br \/>\/\/Variable pour conserver l'\u00e9tat du LED<br \/>boolean led1State = 0;<br \/><br \/>void setup() <br \/>{<br \/> \u00a0\/\/ Nous allons utiliser la console pour afficher des informations<br \/>  Serial.begin(9600);<br \/>  \/\/D\u00e9but de la connexion au r\u00e9seau<br \/>  Serial.print(\"Connection au r\u00e9seau \");<br \/>  Serial.println(ssid);<br \/>  WiFi.disconnect();<br \/>  WiFi.begin(ssid, password);<br \/><br \/>  \/\/ Tant que le status n'est pas connect\u00e9, attendre...<br \/>  while (WiFi.status() != WL_CONNECTED) <br \/>  {<br \/>    delay(500);<br \/>\u00a0 \u00a0 Serial.print(\".\");<br \/>\u00a0 }<br \/>\u00a0 \/\/ Une fois connect\u00e9, on affiche l'adresse IP du ESP32<br \/>\u00a0 Serial.println(\"\");<br \/>\u00a0 Serial.println(\"Connect\u00e9 au Wi-fi\");<br \/>\u00a0 Serial.println(\"Adresse IP = \");<br \/>\u00a0 Serial.println(WiFi.localIP());<br \/>\u00a0 serveur.begin();<br \/>\u00a0 pinMode(15,OUTPUT);<br \/>}<\/pre>\n<pre>void loop() <br \/>{<br \/>  \/\/ Regarde s'il y a un client sur le serveur<br \/>\u00a0 WiFiClient client = serveur.available();<br \/>\u00a0 if(client)<br \/>\u00a0 {<br \/>\u00a0   Serial.println(\"Nouveau Client.\");<br \/>\u00a0 \u00a0 \/\/ rester dans la boucle tant que le client est connect\u00e9<br \/>\u00a0 \u00a0 while (client.connected()) <br \/>\u00a0 \u00a0 { <br \/>\u00a0 \u00a0  \u00a0if (client.available()) \/\/ V\u00e9rifie si le client a envoy\u00e9 des donn\u00e9es<br \/>\u00a0 \u00a0  \u00a0{<br \/>\u00a0 \u00a0 \u00a0\u00a0\u00a0 char rxData = client.read();<br \/>\u00a0 \u00a0 \u00a0 \u00a0 rxHttpRequest+=rxData; <br \/>\u00a0\u00a0   \u00a0 \u00a0Serial.write(rxData); <br \/>\u00a0 \u00a0  \u00a0 \u00a0if (rxData == '\\n') \/\/ si c'.est la fin de la commande re\u00e7ue<br \/>\u00a0 \u00a0  \u00a0 \u00a0{<br \/>          \/\/analyse de la commande re\u00e7ue<br \/>          if (rxHttpRequest.indexOf(\"GET \/LED1\/on\") &gt;= 0)<br \/>          {<br \/>            digitalWrite(15,1); \/\/ gestion de la sortie<br \/>            led1State=1; \/\/ gestion de la variable d'\u00e9tat pour modifier le bouton<br \/>          }<br \/>          if (rxHttpRequest.indexOf(\"GET \/LED1\/off\") &gt;= 0)<br \/>          {<br \/>            digitalWrite(15,0); \/\/ gestion de la sortie<br \/>            led1State=0; \/\/ gestion de la variable d'\u00e9tat pour modifier le bouton<br \/>          }<br \/>          Serial.println(\"\");<br \/>          Serial.println(\"Charge page HTML\");<br \/>          client.println(\"HTTP\/1.1 200 OK\"); \/\/send new page<br \/>          client.println(\"Content-Type: text\/html\");<br \/>          client.println();<br \/>          client.println(\"&lt;html&gt;\");<br \/>          client.println(\"&lt;body&gt;\");<br \/>          client.print(\"&lt;p&gt;Bouton=\");<br \/>          if(digitalRead(23))<br \/>            client.print(\"off\");<br \/>          else <br \/>            client.print(\"on\");<br \/>          client.println(\"&lt;\/p&gt;\");<br \/>          client.print(\"&lt;p&gt;Potentiometre=\");<br \/>          client.print(analogRead(34));<br \/>          client.println(\"&lt;\/p&gt;\");<br \/>          if (led1State)<br \/>            client.println(\"&lt;p&gt;&lt;a href=\\\"\/LED1\/off\\\"&gt; &lt;button&gt;ON&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\");<br \/>          else<br \/>            client.println(\"&lt;p&gt;&lt;a href=\\\"\/LED1\/on\\\"&gt;&lt;button&gt;OFF&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\");<br \/><br \/>          client.println(\"&lt;\/body&gt;\");<br \/>          client.println(\"&lt;\/html&gt;\");<br \/>          client.stop();<br \/>          rxHttpRequest = \"\";<br \/>        }<br \/>      }<br \/>    }<br \/>  }<br \/>}<\/pre>\n<p>Voici le r\u00e9sulta que vous devriez obtenir au navigateur.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-405\" src=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2020\/05\/nav1.png\" alt=\"\" width=\"627\" height=\"242\" srcset=\"https:\/\/marcjuneau.ca\/wp-content\/uploads\/2020\/05\/nav1.png 627w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2020\/05\/nav1-300x116.png 300w, https:\/\/marcjuneau.ca\/wp-content\/uploads\/2020\/05\/nav1-465x179.png 465w\" sizes=\"auto, (max-width: 627px) 100vw, 627px\" \/><\/p>\n<p>Si le montage est compl\u00e9t\u00e9, vous devriez obtenir la lecture du bouton et du potentiom\u00e8tre, en plus de pouvoir contr\u00f4ler la LED.<\/p>\n<p>Notez que vous devez rafra\u00eechir le navigateur afin de voir les changements pour le bouton et le potentiom\u00e8tre. Vous pouvez ajouter la commande suivante dans l&rsquo;ent\u00eate html afin de provoquer le rafra\u00eechissement automatique aux 2s.<\/p>\n<pre>&lt;meta http-equiv=\"refresh\" content=\"2\"&gt;<\/pre>\n<p>Aussi, nous pourrions am\u00e9liorer l\u2019esth\u00e9tique de notre page en utilisant les styles CSS. Le code suivant permet d&rsquo;ajouter un style pour le bouton et le texte en g\u00e9n\u00e9ral.<\/p>\n<pre> &lt;style&gt;<br \/>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;} <br \/>.button1 { background-color: #d1c819; border:2px solid #d1c819;color: white; width: 100px;border-radius: 12px;padding-top: 10px;padding-bottom: 10px;<br \/>transition-duration: 0.1s; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}<br \/>.button1:hover { background-color: white; color:black ;border: 2px solid #d1c819;}<br \/>.buttonoff {background-color: #27282e;border:2px solid #27282e;}<br \/>.buttonoff:hover { background-color: white; color:black ;border: 2px solid #27282e;}<br \/>&lt;\/style&gt;<\/pre>\n<p>Pour appliquer le style \u00e0 notre site, il suffit ajouter ce code \u00e0 notre ent\u00eate html et de modifier l&rsquo;appel du bouton comme suit :<\/p>\n<pre>if (led1State)<br \/>  client.println(\"&lt;p&gt;&lt;a href=\\\"\/LED1\/off\\\"&gt;&lt;button class=\\\"button1\\\"&gt;ON&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\");<br \/>else<br \/>  client.println(\"&lt;p&gt;&lt;a href=\\\"\/LED1\/on\\\"&gt;&lt;button class=\\\"button1 buttonoff\\\"&gt;OFF&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\");<\/pre>\n<p>Pour simplifier l&rsquo;ajout de code html dans l&rsquo;ent\u00eate, il est possible d&rsquo;utiliser un tableau de caract\u00e8res constant et de d\u00e9finir son contenu comme litt\u00e9ral. \u00c7a \u00e9vite d&rsquo;avoir \u00e0 mettre les \\ partout devant les \u00a0\u00bb ou \u00e0 la fin des lignes.<\/p>\n<p>Voici le code complet avec le style. Notez que le site \u00e0 un titre et m\u00eame un icone.<\/p>\n<pre>#include &lt;Arduino.h&gt;<br \/>#include &lt;WiFi.h&gt;<br \/>\/\/ Informations sur le r\u00e9seau Wi-Fi<br \/>\/\/ Vous devez remplacer les informations pas celles de votre r\u00e9seau<br \/>const char* ssid = \"devRouteur\";<br \/>const char* password = \"#1234#fafa\";<br \/>\/\/ code html de l'ent\u00eate\u00a0<br \/>const char pageHeadHtml[] = R\"(<br \/>HTTP\/1.1 200 OK<br \/>Content-Type: text\/html<br \/>Connection: close<br \/><br \/>&lt;!DOCTYPE html&gt;<br \/>&lt;html&gt; <br \/>&lt;meta http-equiv=\"refresh\" content=\"2\"&gt; <br \/>&lt;head&gt;&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;<br \/>&lt;title&gt;ESP32 Serveur&lt;\/title&gt;<br \/>&lt;link rel=\"icon\" href=\"https:\/\/www.iconsdb.com\/icons\/download\/red\/online-16.png\"&gt; <br \/>&lt;style&gt;<br \/>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;} <br \/>.button1 { background-color: #d1c819; border:2px solid #d1c819;color: white; width: 100px;border-radius: 12px;padding-top: 10px;padding-bottom: 10px;<br \/>transition-duration: 0.1s; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}<br \/>.button1:hover { background-color: white; color:black ;border: 2px solid #d1c819;}<br \/>.buttonoff {background-color: #27282e;border:2px solid #27282e;}<br \/>.buttonoff:hover { background-color: white; color:black ;border: 2px solid #27282e;}<br \/>&lt;\/style&gt;<br \/>&lt;\/head&gt; <br \/>&lt;body&gt;&lt;h1&gt; Serveur ESP32 &lt;\/h1&gt; <br \/>)\";<br \/>\/\/ Cr\u00e9er un serveur sur le port 80<br \/>WiFiServer serveur(80);<br \/>\/\/ Cr\u00e9er une string pour conserver la requ\u00eate http<br \/>String rxHttpRequest = \"\";<br \/>\/\/Variable pour conserver l'\u00e9tat du LED<br \/>boolean led1State = 0;<\/pre>\n<pre>void setup() <br \/>{<br \/> \/\/ Nous allons utiliser la console pour afficher des informations<br \/> Serial.begin(9600);<br \/> \/\/D\u00e9but de la connexion au r\u00e9seau<br \/> Serial.print(\"Connection au r\u00e9seau \");<br \/> Serial.println(ssid);<br \/> WiFi.disconnect();<br \/> WiFi.begin(ssid, password);<br \/> \/\/ Tant que le status n'est pas connect\u00e9, attendre...<br \/> while (WiFi.status() != WL_CONNECTED) <br \/> {<br \/>  delay(500);<br \/>  Serial.print(\".\");<br \/>  }<br \/> \/\/ Une fois connect\u00e9, on affiche l'adresse IP du ESP32<br \/> Serial.println(\"\");<br \/> Serial.println(\"Connect\u00e9 au Wi-fi\");<br \/> Serial.println(\"Adresse IP = \");<br \/> Serial.println(WiFi.localIP());<br \/> serveur.begin();<br \/> pinMode(15,OUTPUT);<br \/>}<\/pre>\n<pre>void loop() <br \/>{<br \/> \/\/ Regarde s'il y a un client sur le serveur<br \/> WiFiClient client = serveur.available();<br \/> if(client)<br \/> {<br \/>  Serial.println(\"Nouveau Client.\");<br \/>  \/\/ rester dans la boucle tant que le client est connect\u00e9<br \/>  while (client.connected()) <br \/>  { <br \/>   if (client.available()) \/\/ V\u00e9rifie si le client a envoy\u00e9 des donn\u00e9es<br \/>   {<br \/>     char rxData = client.read();<br \/>     rxHttpRequest+=rxData; <br \/>     Serial.write(rxData); <br \/>     if (rxData == '\\n') \/\/ si c'.est la fin de la commande re\u00e7ue<br \/>     {<br \/>       \/\/analyse de la commande re\u00e7ue<br \/>       if (rxHttpRequest.indexOf(\"GET \/LED1\/on\") &gt;= 0)<br \/>       {<br \/>        digitalWrite(15,1); \/\/ gestion de la sortie<br \/>        led1State=1; \/\/ gestion de la variable d'\u00e9tat pour modifier le bouton<br \/>       }<br \/>       if (rxHttpRequest.indexOf(\"GET \/LED1\/off\") &gt;= 0)<br \/>       {<br \/>        digitalWrite(15,0); \/\/ gestion de la sortie<br \/>        led1State=0; \/\/ gestion de la variable d'\u00e9tat pour modifier le bouton<br \/>       }<br \/>       client.print(pageHeadHtml);<br \/>       client.print(\"&lt;p&gt;Bouton=\");<br \/>       if(digitalRead(23))<br \/>        client.print(\"off\");<br \/>       else <br \/>        client.print(\"on\");<br \/>       client.println(\"&lt;\/p&gt;\");<br \/>       client.print(\"&lt;p&gt;Potentiometre=\");<br \/>       client.print(analogRead(34));<br \/>       client.println(\"&lt;\/p&gt;\");<br \/>       if (led1State)<br \/>         client.println(\"&lt;p&gt;&lt;a href=\\\"\/LED1\/off\\\"&gt;&lt;button class=\\\"button1\\\"&gt;ON&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\");<br \/>       else<br \/>        client.println(\"&lt;p&gt;&lt;a href=\\\"\/LED1\/on\\\"&gt;&lt;button class=\\\"button1 buttonoff\\\"&gt;OFF&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\");<br \/><br \/>       client.println(\"&lt;\/body&gt;\");<br \/>       client.println(\"&lt;\/html&gt;\");<br \/><br \/>       client.stop();<br \/>       rxHttpRequest = \"\";<br \/>    }<br \/>   }<br \/>  }<br \/> }<br \/>}<\/pre>\n\n","protected":false},"excerpt":{"rendered":"<p>Dans cet article, nous allons ajouter des fonctionnalit\u00e9s \u00e0 notre ESP32. Ce dernier va maintenant afficher l&rsquo;\u00e9tat d&rsquo;une LED, d&rsquo;un bouton et d&rsquo;un potentiom\u00e8tre en plus de permettre de changer l&rsquo;\u00e9tat de la LED.<span class=\"more-link\"><a href=\"https:\/\/marcjuneau.ca\/?p=395\">Continue Reading<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":396,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,22],"tags":[25,23,26,24],"class_list":["entry","author-mjuneau","has-more-link","post-395","post","type-post","status-publish","format-standard","has-post-thumbnail","category-esp32_cat","category-esp32-projets","tag-css","tag-esp32","tag-html","tag-web-server"],"_links":{"self":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/395","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=395"}],"version-history":[{"count":14,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/395\/revisions"}],"predecessor-version":[{"id":412,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/posts\/395\/revisions\/412"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=\/wp\/v2\/media\/396"}],"wp:attachment":[{"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=395"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=395"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/marcjuneau.ca\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=395"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}