explication de code

J’ai une requete assez chiante, donc si ça ne se bouscule pas pour me répondre je comprendrais :grin:

Alors voila un code ( qui soit dit en passant fonctionne très bien) dont pas mal de subtilités m’échappent :

#include <SPI.h>
#include <Ethernet.h>
#define LED 7

byte mac[] = {  0x92, 0xA2, 0xDA, 0x0D, 0x20, 0x63 };
byte ip[] = { 192, 168, 1, 177 };
char link[30], LEDStatus[4];

Server server(80);

void setup() {
  pinMode(7, OUTPUT);
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop() {
  Client client = server.available();
  if (client) {
    char request[10];
    int i = 0;
    boolean current_line_is_blank = true;
    request[9] = '\0';
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (i < 9) {
          request[i] = c;
          i++;
        }
        if (c == '\n' && current_line_is_blank) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          
          client.println("<html><head><title>LampeChambre</title></head><body>");
          client.println("<h1>LampeIphoneChambre</h1>");
          client.println("<table>");
          client.print("<tr><td>Analog inputs:</td><td><b>");
          for (int x = 0; x < 6; x++) {
            client.print(x);
            client.print(" = ");
            client.print(5000 * (analogRead(x) / 1024.0));
            client.print(" mV
");
          }
          client.println("</b></td></tr><tr><td>uptime:</td> <td><b>");
          client.print(millis() / 1000.0);
          client.println(" seconds</b></td></tr>");
          if (strncmp("GET /off", request, 8) == 0) {
            digitalWrite(7, LOW);
            sprintf(LEDStatus, "OFF");
            sprintf(link, "<a href=\"/on\">Allumer</a>");
          }
          else {
            sprintf(LEDStatus, "ON");
            digitalWrite(7, HIGH);
            sprintf(link, "<a href=\"/off\">Eteindre</a>");
          }
          client.print("<tr><td>Lampe:</td> <td><b>");
          client.print(LEDStatus);
          client.println("</b></td></tr><tr><td colspan=\"2\" align=\"center\">");
          client.println(link);
          client.println("</td></tr></table></body></html>");
          break;
        }
        if (c == '\n') {
          current_line_is_blank = true;
        } else if (c != '\r') {
          current_line_is_blank = false;
        }
      }
    }
    delay(1);
    client.stop();
  }
}

j’aimerais qu’on m’explique ce que veulent dire les lignes suivantes en fait :

   char request[10];
    int i = 0;
    boolean current_line_is_blank = true;
    request[9] = '\0';
char c = client.read();
        if (i < 9) {
          request[i] = c;
          i++;

-if (c == '\n' && current_line_is_blank)

for (int x = 0; x < 6; x++) {
            client.print(x);
            client.print(" = ");
            client.print(5000 * (analogRead(x) / 1024.0));
            client.print(" mV
");

-if (strncmp("GET /off", request, 8) == 0)

if (c == '\n') {
          current_line_is_blank = true;
        } else if (c != '\r') {
          current_line_is_blank = false;

ca fait de gros bouts de code que je ne connais pas tout de meme ! :sweat_smile: :sweat_smile:

Salut,

Il y a pas mal de choses qui servent à générer une page HTML compréhensible par un navigateur.

Ce morceau là lit les 6 entrées analogiques de l’Arduino, fait un petit calcul et affiche les valeurs sur la page web :

for (int x = 0; x < 6; x++) {
    client.print(x);
    client.print(" = ");
    client.print(5000 * (analogRead(x) / 1024.0));
    client.print(" mV
");

Est ce que tu peux éditer ton message et mettre le code entre les balises "code" et pas "quote" XD

Merci SesechXP, pour m'avoir éclairé sur le premier bout de code et désolé Jean-François, c'est réparé ! :)

Bonjour,

kira:
J’ai une requete assez chiante, donc si ça ne se bouscule pas pour me répondre je comprendrais :grin:

Bon et bien c’est parti :grin:

kira:

    char request[10];

int i = 0;
    boolean current_line_is_blank = true;
    request[9] = ‘\0’;

  1. Déclare un tableau de 10 char
  2. Déclare une variable i de type int, initialisé à la valeur 0
  3. Déclare une variable current_line_is_blank de type boolean, initialisé à la valeur true (vrai)
  4. Clôture la chaine de caractéres ASCIIZ que représente le tableau “request”
    (En C un chaine de caractéres est un tableau de char se terminant par ‘\0’ = valeur 0)

kira:

char c = client.read();

if (i < 9) {
          request[i] = c;
          i++;

  1. Lit un octet depuis l’ethernet et le stock dans la variable “c” de type char
  2. Si i est strictement inférieur à 9 alors :
  3. l’octet en question est stocké dans la chaine de caractéres que représente le tableau “request” à l’index i
  4. Incrémentation de i (i = i + 1)
    → Cette portion de code a pour but de stocker 9 octets lu depuis l’ethernet dans la chaine de caractére.

kira:
-if (c == '\n' && current_line_is_blank)

kira:

if (c == '\n') {

current_line_is_blank = true;
        } else if (c != ‘\r’) {
          current_line_is_blank = false;

En protocole HTTP un entête de requête se termine par \n\r, ces deux morceaux de code ont pour but de détecter la fin d’entête.

kira:

for (int x = 0; x < 6; x++) {

client.print(x);
            client.print(" = “);
            client.print(5000 * (analogRead(x) / 1024.0));
            client.print(” mV
");

Affiche 6 lignes (en html) correspondant au 6 entrées analogiques (valeur calculé en millivolts).

kira:
-if (strncmp("GET /off", request, 8) == 0)

strcmp = “string compare” → comparaison de deux chaines de caractéres.
Si la requête recu dans la variable “request” est égale à “GET /off” le code exécute le contenu du if.

super simpa la réponse aussi détaillée ! :) J'ai pas encore compris tout le code mais au moins j'ai les mots clefs pour chercher !

Et skywodd, je pense que tu devrais faire un tuto sur ton blog (si tu es bien le même skywodd que le skywood qui fait des tuto video :p ), qui expliquerait comment se servir de feuilles de styles qu'on aurait stocké dans une microSD insérée dans l'eternet shield ! C'est pas que j'en ai besoin hein, mais ça manque au blog :grin: :grin: :grin: Juste une idée hein !

En lisant attentivement toutes ces explications, je ne comprend pas une chose, où la variable request prend la valeur "GET /off" :/

Si la requête recu dans la variable "request" est égale à "GET /off" le code exécute le contenu du if.

C'est pas ultra simple tout ca :p

Ou sinon, n'y aurait il pas un moyen plus simple de controler l'etat de mes pin avec du code html, avec une case à coché dans, qui quand elle est cochée renvoi une valeur à l'arduino.. Je ne comprend pas bien ce code en fait, il me parait alambiqué ( j'ai surement tord hein, mais c'est l'effet que ça me donne)

Salut,

En lisant attentivement toutes ces explications, je ne comprend pas une chose, où la variable request prend la valeur “GET /off” :

ici:

        if (i < 9) {
          request[i] = c;
          i++;
        }

c’est à dire lorsque tu décharges le buffer de l’ENC28J60 octet par octet.

Gromain

Oui ça j'avais à peu près compris, mais les octets, ou prennent ils leurs valeurs ? Et au fait simpa ton site Gromain :)

A cette ligne :

char c = client.read();

On vient lire ce qui arrive sur la liaison Ethernet.

Oui ça j’avais à peu près compris, mais les octets, ou prennent ils leurs valeurs ?

Le contrôleur Ethernet ENC28J60 ou Wiznet (selon le shield) reçoit des paquets TCP/UDP en provenance du réseau.
Il fait un premier tri pour n’accepter dans son buffer Rx que les paquets qui t’intéresse.
Ton code interroge le contrôleur via le bus SPI pour savoir s’il a reçu des données. Si c’est le cas, il récupère octet par octet le paquet, toujours via le bus.
Dans le cas d’un Wiznet, l’arduino ne reçoit que la partie data du paquet. Pour l’ENC28J60, c’est le paquet complet qui est récupéré (en-tête+data). A ton code (ou la lib) d’extraire les datas.

Avec un logiciel comme Wireshark tu peux écouter le réseau local et voir passer toutes les données. Chaque paquet aura une en-tête qui précise les ports et adresses mac et IP de la source et de la destination.

Gromain

Hum d'accord mais qu'es-ce qui fait qu'on retrouve "GET / OFF" dans les data ? :/ je comprend vite mais il faut m'expliquer longtemps.. désolé :grin:

enfait, je voudrais arriver à gérer une autre entrée avec un autre lien par exemple.. L'idéal serait mêmede pouvoir entrer une valeur dans la page généré, valeur qui déterminerais l'Etat d'un pin PWM.. pour par exemple diriger ma lampe avec un servo.. :p

qu'est-ce qui fait qu'on retrouve "GET / OFF" dans les data ?

En simplifiant: "GET / OFF" fait partie d'une requête HTTP, envoyée par le client au serveur (ici l'arduino). Cette requête HTTP (couche applicative) est encapsulée dans un paquet TCP/IP (couche transport, géré par le wiznet), contenant une en-tête (IP, mac, port...). Donc du point de vue réseau, "GET /OFF" fait partie des datas.

Pour arriver à tes fins, je te conseille de t'intéresser aux grandes lignes de la pile TCP/IP et au protocole HTTP (cf wikipedia par ex). En supposant que le HTML ne te pose pas de problème ;)

Gromain

kira:
super simpa la réponse aussi détaillée ! :slight_smile:
J’ai pas encore compris tout le code mais au moins j’ai les mots clefs pour chercher !

Dit ce qui va pas et on explique :wink:

kira:
Et skywodd, je pense que tu devrais faire un tuto sur ton blog (si tu es bien le même skywodd que le skywodd qui fait des tuto video :stuck_out_tongue: ), qui expliquerait comment se servir de feuilles de styles qu’on aurait stocké dans une microSD insérée dans l’eternet shield !

Faut un code arduino qui fasse office de serveur HTTP et une page web en langage HTML avec la balise :

<link rel="stylesheet" href="lenomdufichiercss.css">

Si tu veut pas te casser la tête avec la gestion des requêtes HTTP :
http://code.google.com/p/webduino/

kira:
Hum d’accord mais qu’es-ce qui fait qu’on retrouve “GET / OFF” dans les data ? :confused:
je comprend vite mais il faut m’expliquer longtemps… désolé :grin:

GET c’est la commande HTTP, va faire un tour sur wikipedia pour comprendre la structure d’une requête HTTP :wink:
Tu n’as pas compris comment marche le protocole HTTP à mon avis, une fois que tu auras compris tout seras plus clair.

En effet, je n'ai jamais eu à m’intéresser au protocole TCP/IP ni au HTTP, mais j'ai l'impression que ca deviens plus que nécessaire, je potasse ça, et reviens vous importuner avec mes question quand je ne comprendrais pas :p Merci à vous, Gromain et Skywodd !

Après avoir lu ça : http://www.siteduzero.com/tutoriel-3-35613-les-requetes-http.html , je comprend en effet bien mieux le code. Mais je ne fais qu'entrevoir une solution pour piloter une autre entrée. C'est pas d'une simplicité enfantine tout ça :p Il faut que je digère ça :p Et donc selon toi, Skywodd, si je met une css dans une micro sd, je n'ai rien à faire de particulier pour y avoir accès ? juste à écrire le chemin ?

kira:
Et donc selon toi, Skywodd, si je met une css dans une micro sd, je n’ai rien à faire de particulier pour y avoir accès ? juste à écrire le chemin ?

Il faut que :

  • tu fasse un morceau de code pour gérer GET /lenomdetonfichier.css, qui prenne le fichier sur la sd et l’envoi par ethernet (suivant la structure d’une réponse HTTP)
  • tu modifie le html de la page pour inclure la balise link

A mon avis tu devrais regarder les bases avant de regarder la gestion de fichier css/js/… :wink:
Le CSS c’est pour faire jolie, mais si tu n’as rien à rendre jolie ça ne sert à rien :wink:

Je suis bien d'accord, mais après avoir lu la page que le HTTP, je ne sais plus vers quoi me tourner.