Les Bases d'un Serveur Web sur ESP-01 en commande AT

Partie 4: répondre à une requête

On a donc une requête de type HTTP GET qui vient d'arriver sur notre ESP-01, il nous faut répondre sans tarder sinon la connexion expire.

si vous êtes un peu lent, vous pouvez configurer le time out avec la commande [color=blue]AT+CIPSTO[/color] qui est bien sûr documentée


Vous passez un temps en secondes, jusqu'à 7200 secondes (deux heures !).

la valeur par défaut de votre firmware est interrogeable par la commande [color=blue]AT+CIPSTO?[/color] qui me répond

[color=purple]AT+CIPSTO?

+CIPSTO:180

OK
[/color]

je vois donc que j'ai 180 secondes (soit 3 minutes) pour envoyer une réponse par défaut.

Si vous mettez 0 il n'y aura pas de timeout, ce n'est pas recommandé, le mieux c'est de ne pas y toucher, 3 minutes devraient suffire au commun des mortels.

La question qui se pose donc maintenant c'est comment répondre et que répondre ?

On a eu une requête en HTTP qui est un protocole de la couche application. Il peut fonctionner sur n'importe quelle connexion fiable, dans les faits on utilise le protocole TCP comme couche de transport. Dans le protocole HTTP, une méthode est une commande qui spécifie un type d'action que le serveur doit effectuer. En général l'action concerne une ressource identifiée par une URL qui suit le nom de la méthode. Vous vous souvenez de la requête que nous a envoyé notre ESP-01 listée plus haut:

[color=purple][color=red]+IPD,0,408:[/color][color=green]GET[/color] [color=blue]/[/color] HTTP/1.1[/color]

La méthode est GET et la resource demandée est / (c'est à dire la racine du site web, la page de garde). Il existe de nombreuses méthodes, les plus courantes étant GET, HEAD et POST

Pour se convaincre que tout cela fonctionne, entrez dans Chrome l'URL suivante

http://192.168.1.28:80[color=blue]/arduino[/color]

si vous regardez maintenant dans la console série vous voyez que l'ESP-01 a reçu une requête

[color=purple]0,CONNECT

[color=red]+IPD,0,415:[/color][color=green]GET[/color] [color=blue]/arduino[/color] HTTP/1.1
Host: 192.168.1.28
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,fr;q=0.8,en;q=0.6,en-US;q=0.4

[/color]

Vous êtes rodé, on reconnait donc qu'on a reçu une requête TCP puisque l'on a +IPD, que le numéro de connexion réseau sur l'ESP-01 est 0, que la requête comporte 415 caractères et que la méthode est GET et que la resource demandée est /arduino

wow, ça marche !

Bon, merci pour l'entracte, mais ça ne nous dit toujours pas comment on répond et ce que l'on doit répondre.

Pour savoir ce que l'on doit répondre, il faut lire la specification du protocole HTTP... c'est long et pénible et ça évolue sans cesse - par exemple en février 2014, la spécification de HTTP 1.1 a été re-publiée et éclatée en plusieurs RFC et corrigée pour toutes ses imprécisions, RFC 7230 à RFC 7237)

Le protocole HTTP 1.0, décrit dans la RFC 1945, prévoit l'utilisation d'en-têtes spécifiés dans la RFC 822. La gestion de la connexion est simple: le client établit la connexion, envoie une requête, le serveur répond et ferme immédiatement la connexion pour signifier la fin de transmission.

Voilà à quoi ça ressemble:

Une requête HTTP présente le format suivant :

Ligne de commande (Commande, URL, Version de protocole)
En-tête de la requête
[Ligne vide]
Corps de la requête

Les réponses HTTP présentent le format suivant :

Ligne de statut (Version, Code-réponse, Texte-réponse)
En-tête de la réponse
[Ligne vide]
Corps de la réponse

donc il suffit de savoir qu'une réponse HTTP c'est "en gros" juste de renvoyer des données en vrac et terminer la connexion. Si vous organisez un peu le "vrac" alors vous pourrez avoir des jolies pages HTML mais sinon le navigateur web va essayer de comprendre ce que vous renvoyez et l'afficher.

Bon mais comment répondre à une requête

par une ou plusieurs commandes AT pardi !

Donc comme précisé par la spec HTPP, on va balancer des octets sur la ligne. il nous faut donc une commande qui envoie un certain nombre d'octets. Cette commande c'est [color=blue]AT+CIPSEND[/color]

On voit que l'on a besoin de 2 choses pour exécuter correctement cette commande, d'une part le numéro de la connexion (vous vous souvenez, c'est le chiffre qui était juste après le [color=red]+IPD,[/color] et le nombre d'octets que l'on veut transmettre

Une fois cette commande envoyée votre ESP-01 n'interprète plus ce qu'il reçoit comme des commandes AT, mais récupère le tout comme octets à transférer, jusqu'à ce qu'il ait reçu le nombre d'octets spécifiés.

Bien sûr on n'est pas complètement coincé si on change d'avis: La doc dit que si vous voulez sortir de ce mode sans tout taper, vous envoyez la séquence magique "+++" dans un paquet unique (et attendre 1 seconde avant de passer à la commande AT suivante)

Enfin et c'est important la doc dit que le nombre d'octets dans un "paquet" doit être inférieur à 2048 (2 kilo-octets) et qu'il faut 20ms entre l'envoi de deux paquets.

OK, c'est bien beau tout cela mais je fais quoi alors ?

On va aller au plus simple. on va ignorer la Ligne de statut et les en-tête de la réponse et juste balancer du texte.

Donc on se prépare

  • ATTENTION: si vous avez fait l'essai des +++ pensez à remettre la console avec la fin de ligne sous forme de CR+NL car sinon vos commandes AT ne sont pas prises en compte.

  • on tape dans le navigateur web

[color=blue]http://192.168.1.28:80[/color]

On vérifie que l'on reçoit bien la requête dans la console Série et on note le numéro de connexion

[color=purple]0,CONNECT

+IPD,[color=red][b]0[/b][/color],408:GET / HTTP/1.1
Host: 192.168.1.28
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,fr;q=0.8,en;q=0.6,en-US;q=0.4

[/color]

On note le 0 et on tape donc avant le timeout dans la console Série que l'on veut envoyer une réponse de 13 octets. Pourquoi 13? parce que je vais envoyer le texte "HELLO WORLD" suivi de CR et de NL qui sont rajoutés par la console série et que si vous comptez ça fait 11 octets pour le texte et 2 octets rajoutés (CR et NL) = 13

[color=blue]AT+CIPSEND=[color=red][b]0[/b][/color],13[/color]

la réponse:

[color=purple]AT+CIPSEND=0,13


OK
> [/color]

On voit le prompt d'attente > et on tape notre message

[color=blue]HELLO WORLD[/color]

on valide, comme ça fait 13 octets, l'ESP vous dit qu'il a tout reçu

[color=purple]Recv 13 bytes

SEND OK[/color]

il ne reste plus qu'à clore la connexion pour dire au navigateur que la conversation HTTP est terminée. Pour cela on envoie simplement une commande AT supplémentaire

[color=blue]AT+CIPCLOSE=0[/color] (le 0 c'est le numéro de connexion, le même que vous avez utilisé dans la commande CIPSEND )

et là, pour le plus grand bonheur des petits et grands, devant nos yeux ébahis, le navigateur web affiche...

ça fonctionne donc !!!