Client et serveur web


Le protocole HTTP (HyperText Transfer Protocol)

C'est un protocole de communication client-serveur développé pour le World Wide Web.

Le but du protocole HTTP est de permettre un transfert de fichiers (essentiellement au format HTML) localisés grâce à une chaîne de caractères appelée URL entre un client (navigateur) et un serveur Web

Un serveur web est un logiciel capable de répondre à des requêtes HTTP, c'est à dire de renvoyer des données comme une page HTML en réponse à des demandes écrites en HTTP (exemple : une requête GET)


Communication entre client et serveur

  • Le serveur écoute le port. Il attend la connexion d'un client.
  • Tant qu'aucun client ne se présente, on reste bloqué (accept)
  • Le client envoie une requête.
  • Le serveur traite la requête puis envoie la réponse.




Serveur web, code HTML et MicroPython pour afficher une variable sur une page web



Affiche le résultat de la conversion analogique numérique de la tension présente sur la broche 34


Raccorder un potentiomètre sur la broche 34 (ADC1_CH6, repère A3  Shield base Grove).

Connecter l'ESP32 et le smartphone au point à un point d'accès Wifi (voir chapitre Configuration Wifi)


Le code HTML est directement intégré au code Micropython.

La variable à afficher, ici pot, est directement intégrée au code HTML.


Pour éviter de rafraîchir manuellement la page, ajouter le code HTML suivant dans l'en-tête (head)  :  <meta http-equiv="refresh" content="1">

Le client enverra automatiquement toutes les secondes une requête GET pour rafraîchira la page.



from machine import ADC, Pin
can = ADC(Pin(34))               # crée un objet ADC sur la broche 34
can.atten(ADC.ATTN_11DB)         # étendue totale : 3.3V
ADC.width(ADC.WIDTH_12BIT)       # résolution du convertisseur à 12bits


def web_page():
    pot = can.read()
    print("CAN =", pot)
    html = """
    <!DOCTYPE html>
    <html>
        <head>
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>ESP32 Serveur Web</title>
            <style>
                p { font-size: 36px; }
            </style>
        </head>
        <body>
            <h1>CAN potentiometre = </h1>
            <p><span>""" + str(pot) + """</span></p>
        </body>
    </html>
    """
    return html

socketServeur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socketServeur.bind(('', 80))
socketServeur.listen(5)


while True:
    try:
        if gc.mem_free() < 102000:
            gc.collect()

        print("Attente d'une connexion client")
        connexionClient, adresse = socketServeur.accept()
        connexionClient.settimeout(4.0)
        print("Connecté avec le client", adresse)

        print("Attente requete du client")
        requete = connexionClient.recv(1024)     #requête du client
        requete = str(requete)
        print("Requete du client = ", requete)
        connexionClient.settimeout(None)

        print("Envoi reponse du serveur : code HTML a afficher")
        connexionClient.send('HTTP/1.1 200 OK\n')
        connexionClient.send('Content-Type: text/html\n')
        connexionClient.send("Connection: close\n\n")
        reponse = web_page()
        connexionClient.sendall(reponse)
        connexionClient.close()  
        print("Connexion avec le client fermee")
       
    except:
        connexionClient.close()  
        print("Connexion avec le client fermee, le programme a declenché une erreur")




Serveur web, code HTML et MicroPython pour écrire une variable depuis une page Web, pilotage d'une LED



Commande une LED raccordée sur la broche 25 depuis deux liens hypertexte.


Raccorder une LED sur la broche 25 (repère D3  Shield base Grove).

Connecter l'ESP32 et le smartphone au point à un point d'accès Wifi (voir chapitre Configuration Wifi)


Le code HTML est directement intégré au code Micropython.


Le client envoie au serveur certains paramètres GET par le biais de l’URL demandée. Ces paramètres sont ajoutées à l’URL avec le signe « ? » et ils indiquent au serveur quelles ressources sont demandées.  Le nom et sa valeur sont toujours séparées avec le symbole « = ». La syntaxe retenue est la suivante : ?nom1=valeur1

Les paramètres étant transmis par l’URL, il est conseillé d'utiliser les paramètres GET seulement pour des applications qui ne posent pas de problème de sécurité.


Ce qui donne dans l'exemple suivant :  

    • /?led=on  ou /?led=off dans la requête du client ; 
    • En décodant la requête, le serveur saura s'il faut allumer ou non la LED grâce aux paramètres ;
    • Le serveur donnera comme réponse au client le code HTML contenu dans la fonction web_page() ;



from machine import Pin

led_1 = Pin(25, Pin.OUT)  # broche 25 en sortie (repère D3 shield base)

def web_page():

    html = """
    <!DOCTYPE html>
    <html>
        <head 
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>ESP32 Serveur Web</title>
            <style>
                p { font-size: 36px; }
            </style>
        </head>
        <body>
            <h1>Commande LED</h1>
            <p><a href="/?led=on">Allumer LED</a></p>
            <P><a href="/?led=off">Eteindre LED</a></p>
        </body>
    </html>
    """
    return html

socketServeur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socketServeur.bind(('', 80))
socketServeur.listen(5)

while True:
    try:    
        if gc.mem_free() < 102000:
            gc.collect()
            
        print("Attente connexion d'un client")
        connexionClient, adresse = socketServeur.accept()
        connexionClient.settimeout(4.0)
        print("Connecté avec le client", adresse)

        print("Attente requete du client")
        requete = connexionClient.recv(1024)     #requête du client
        requete = str(requete)
        print("Requete du client = ", requete)
        connexionClient.settimeout(None)
        
        #analyse de la requête, recherche de led=on ou led=off
        if "GET /?led=on" in requete:
            print("LED ON")
            led_1.value(1)
        if "GET /?led=off" in requete:
            print("LED OFF")
            led_1.value(0)
            
        print("Envoi reponse du serveur : code HTML a afficher")
        connexionClient.send('HTTP/1.1 200 OK\n')
        connexionClient.send('Content-Type: text/html\n')
        connexionClient.send("Connection: close\n\n")
        reponse = web_page()
        connexionClient.sendall(reponse)
        connexionClient.close()  
        print("Connexion avec le client fermee")
        
    except:
        connexionClient.close()  
        print("Connexion avec le client fermee, le programme a declenché une erreur")
   




Serveur web, code HTML pour afficher des boutons On OFF sur une page web


Le code MicroPython est identique au code avec liens hypertextes ci-dessus.



HTML


<html>
       <head>
               <title>ESP</title>
               <meta name="viewport" content="width=device-width, initial-scale=1">
               <style>
                       html
                       {
                               font-family: Helvetica;
                               margin: 0px auto;
                               text-align: center;
                       }
                       h1
                       {
                               color: #0F3376;
                               padding: 2vh;
                       }
                       p
                       {
                               font-size: 24px;
                       }
                       .button
                       {
                               background-color: #4CAF50;   /* Vert */
                               border: none;
                               border-radius: 6px;   /* Angle arrondi */
                               color: white;
                               padding: 15px 32px;
                               text-align: center;
                               text-decoration: none;
                               font-size: 30px;
                       }
                       .button2
                       {
                               background-color: #f44336; /* Rouge */
                       }
               </style>
       </head>
       <body>
               <h1>ESP Serveur Web</h1>
               <p><a href="/?led=on"><button class="button">ON</button></a></p>
               <p><a href="/?led=off"><button class="button button2">OFF</button></a></p>
       </body>
</html>




Code sur https://www.w3schools.com





Serveur web, code HTML et MicroPython pour afficher un potentiomètre sur une page web


Ce code permet d'afficher un potentiomètre sur le navigateur et de transmettre sa valeur courante par requête.


Le client envoie au serveur des  paramètres GET.

Dans l'exemple suivant :  

    • Le client envoie  /?pot1_valeur=121 par exemple. 121 étant la valeur courante du potentiomètre.
    • Le serveur décode la requête pour isoler la valeur courante : 121
    • Le serveur donnera comme réponse au client le code HTML contenu dans la fonction web_page() ;




def web_page():
    html = """
    <!DOCTYPE html>
    <html>
        <head>
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>ESP32 Serveur Web</title>
            <style>
                p { font-size: 36px; }
                .slidecontainer {width: 100%;}
                .slider {
                    -webkit-appearance: none;
                    width: 80%;
                    height: 25px;
                    background: #ffd800;    /*couleur glisssière jaune*/
                    outline: none;
                }
                .slider::-webkit-slider-thumb {
                    -webkit-appearance: none;
                    appearance: none;
                    width: 35px;
                    height: 35px;
                    background: #FF0000; /*couleur curseur rouge*/
                    cursor: pointer;
                }
            </style>
        </head>
        
        <body>
            <h1>Potentiometre 1</h1>
            <p><input type="range" onchange="fct_envoi()" min="0" max="255" value="127" class="slider" id="id_pot1" ></p>
            <p>Valeur : <span id="id_affichage_pot1_valeur"></span></p>
            
            <script>    // Java script
            function fct_envoi() {
                var pot1 = document.getElementById("id_pot1");
                var pot1_valeur = pot1.value;
                document.getElementById("id_affichage_pot1_valeur").innerHTML = pot1_valeur
                
                var objet_XHR = new XMLHttpRequest();
                objet_XHR.open("GET", "/pot1?valeur="+pot1_valeur, true);
                objet_XHR.send();
            }
            </script>
        </body>
    </html>
    """
    return html

socketServeur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socketServeur.bind(('', 80))
socketServeur.listen(5)

while True:
    try:
        if gc.mem_free() < 102000:
            gc.collect()

        print("Attente connexion d'un client")
        connexionClient, adresse = socketServeur.accept()
        connexionClient.settimeout(4.0)
        print("Connecté avec le client", adresse)

        print("Attente requete du client")
        requete = connexionClient.recv(1024)     #requête du client
        requete = str(requete)
        print("Requete du client = ", requete)
        connexionClient.settimeout(None)

        #analyse de la requête, recherche de pot1?valeur=
        if "GET /pot1?valeur=" in requete:
            indice_debut = requete.find("=")+1
            indice_fin = requete.find("HTTP")-1
            pot1_valeur = int(requete[indice_debut:indice_fin])
            print("pot1_valeur = ", pot1_valeur)
           
        print("Envoi reponse du serveur : code HTML a afficher")
        connexionClient.send('HTTP/1.1 200 OK\n')
        connexionClient.send('Content-Type: text/html\n')
        connexionClient.send("Connection: close\n\n")
        reponse = web_page()
        connexionClient.sendall(reponse)
        connexionClient.close()
        print("Connexion avec le client fermee")

    except:
        connexionClient.close()
        print("Connexion avec le client fermee, le programme a declenché une erreur")
        






Code sur https://www.w3schools.com




























Créé avec HelpNDoc Personal Edition: Outil de création d'aide complet