Go Down

Topic: explication de code (Read 1 time) previous topic - next topic

kira

Aug 13, 2012, 04:08 pm Last Edit: Aug 13, 2012, 07:36 pm by kira Reason: 1
J'ai une requete assez chiante, donc si ça ne se bouscule pas pour me répondre je comprendrais  :smiley-mr-green:

Alors voila un code ( qui soit dit en passant fonctionne très bien) dont pas mal de subtilités m'échappent :
Code: [Select]
#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<br>");
         }
         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 :
-
Code: [Select]
   char request[10];
   int i = 0;
   boolean current_line_is_blank = true;
   request[9] = '\0';

-
Code: [Select]
char c = client.read();
       if (i < 9) {
         request[i] = c;
         i++;

-
Code: [Select]
if (c == '\n' && current_line_is_blank)
-
Code: [Select]
for (int x = 0; x < 6; x++) {
           client.print(x);
           client.print(" = ");
           client.print(5000 * (analogRead(x) / 1024.0));
           client.print(" mV<br>");

-
Code: [Select]
if (strncmp("GET /off", request, 8) == 0)
-
Code: [Select]
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 ! :smiley-sweat: :smiley-sweat:

SesechXP

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 :
Code: [Select]
for (int x = 0; x < 6; x++) {
    client.print(x);
    client.print(" = ");
    client.print(5000 * (analogRead(x) / 1024.0));
    client.print(" mV<br>");

Jean-François

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

MacBook intel core 2 duo  os X snow Leopard 10.6
 eMac PPc G4  os X Leopard 10.5
powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

kira

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

skywodd

Bonjour,


J'ai une requete assez chiante, donc si ça ne se bouscule pas pour me répondre je comprendrais  :smiley-mr-green:

Bon et bien c'est parti :smiley-mr-green:


-
Code: [Select]
    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)


-
Code: [Select]
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.


-
Code: [Select]
if (c == '\n' && current_line_is_blank)


-
Code: [Select]
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.


-
Code: [Select]
for (int x = 0; x < 6; x++) {
            client.print(x);
            client.print(" = ");
            client.print(5000 * (analogRead(x) / 1024.0));
            client.print(" mV<br>");


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


-
Code: [Select]
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.
Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

kira

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  :smiley-mr-green: :smiley-mr-green: :smiley-mr-green:
Juste une idée hein !

kira

En lisant attentivement toutes ces explications, je ne comprend pas une chose, où la variable request prend la valeur "GET /off" :/
Quote
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

kira

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)

Gromain59

Salut,

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


ici:

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


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

Gromain
"pour résoudre un gros problème, il est souvent plus facile de le diviser en petits problèmes élémentaires..."

projet domotique xPLDuino
IRC: freenode #xplduino

kira

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

SesechXP

A cette ligne :
Code: [Select]
char c = client.read();
On vient lire ce qui arrive sur la liaison Ethernet.

Gromain59

Quote

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
"pour résoudre un gros problème, il est souvent plus facile de le diviser en petits problèmes élémentaires..."

projet domotique xPLDuino
IRC: freenode #xplduino

kira

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é  :smiley-mr-green:

kira

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

Gromain59

#14
Aug 14, 2012, 05:44 pm Last Edit: Aug 14, 2012, 09:08 pm by Gromain59 Reason: 1
Quote
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
"pour résoudre un gros problème, il est souvent plus facile de le diviser en petits problèmes élémentaires..."

projet domotique xPLDuino
IRC: freenode #xplduino

Go Up