Communication Web Get -> Arduino

Salut Salut,
je viens finalement demander votre aide, car je me suis servis de plein de codes sur ce forum et d'autre site pour créer le code que j'ai aujourd"hui. Mais J'ai un soucis et ça fais 2 jours que je suis bloqué dessus!
Le principe de mon application:
Avec mon arduino mega, et shieldwifi, je possède un LCD. Grace à une page web du style: http://192.168.1.90/scene1/1/0 par exemple, ça active une action dans l'arduino (exemple afficher un message).

Ca marche nickel lors du premier envoie!
Mais pour les suivantes ça ne fonctionne pas! Il faut que je relance l'arduino!

Je vous joins mon code, puis les valeurs des variables! J'ai l'impression que mon histoire de slash se décale! Mais je ne vois pas ou! Help me please ami arduinoyein!

// mise en place des fichier externe
#include <SPI.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiServer.h>
#include "LiquidCrystal.h"
#include <string.h>

// Info pour connection au routeur
char ssid[] = "SFR_C0E8";     //  your network SSID (name) 
char pass[] = "llaxwelliativ6estura";  // your network password
int status = WL_IDLE_STATUS;     // the Wifi radio's status
WiFiServer server(80); // Port 80 is http.

// Infos sur les costantes (entrées et sorties)
LiquidCrystal lcd(6,5,28,26,24,22);

//-- Definition des variables. Commands and parameters (sent by browser) --
char cmd[30];    // Nothing magical about 15, increase these if you need longer commands/parameters
char param1[30];
char param2[30];
char ALIM[30];

// definition des entrées ou sortie. Et valeurs si c'est le cas.
void SetupES() {
  pinMode(2,OUTPUT); digitalWrite(2,LOW);  // I use this pin as GND for the LED.
  pinMode(53,OUTPUT); // Sample output, unable to use built-in LED at pin 13 because Ethernet Shield uses pins 10,11,12,13.
}

void messagedebut() {
  lcd.setCursor(2,0);
  lcd.print("Bienvenue au");
  lcd.setCursor(5,1);
  lcd.print("Theatre");
  lcd.setCursor(0,0);
}

void setup() {
  lcd.begin(16,2);
  messagedebut();
  WiFi.begin(ssid, pass);
  server.begin();
  Serial.begin(9600);
  SetupES();
}

#define bufferMax 128
int bufferSize;
char buffer[bufferMax];

void loop() // Sa verifie les nouvelles donnée
{
  WiFiClient client = server.available();
  if (client)
  {
    WaitForRequest(client);
    ParseReceivedRequest();
    PerformRequestedCommands();
    client.stop();
  }
}

void WaitForRequest(WiFiClient client) // Est ce que le client bouge quelque chose?
{
  bufferSize = 0;
  while (client.connected()) {
    if (client.available()) {
      char c = client.read();
      if (c == '\n')
        break;
      else
        if (bufferSize < bufferMax)
          buffer[bufferSize++] = c;
        else
          break;
    }
  }
  
  PrintNumber("bufferSize", bufferSize);
}

void ParseReceivedRequest() // C'est bon j'ai un mouvement! je récupere les données.
{ 
  //Received buffer contains "GET /cmd/param1/param2 HTTP/1.1".  Break it up.
  char* slash1;
  char* slash2;
  char* slash3;
  char* space2;
  
  slash1 = strstr(buffer, "/") + 1; // Look for first slash
  slash2 = strstr(slash1, "/") + 1; // second slash
  slash3 = strstr(slash2, "/") + 1; // third slash
  space2 = strstr(slash2, " ") + 1; // space after second slash (in case there is no third slash)
  
  if (slash3 > space2) slash3=slash2;

  PrintString("slash1",slash1);
  PrintString("slash2",slash2);
  PrintString("slash3",slash3);
  PrintString("space2",space2);
  
  // strncpy does not automatically add terminating zero, but strncat does! So start with blank string and concatenate.
  cmd[0] = 0;
  strncat(cmd, slash1, slash2-slash1-1);
  
  PrintString("cmd",cmd);

}

void PerformRequestedCommands()
{
  if ( strcmp(cmd,"welcome") == 0 ) Bienvenue();
  if ( strcmp(cmd,"noir") == 0 ) Noir();
  if ( strcmp(cmd,"scene1") == 0 ) Scene1();
  if ( strcmp(cmd,"scene2") == 0 ) Scene2();
  if ( strcmp(cmd,"scene3") == 0 ) Scene3();
  if ( strcmp(cmd,"scene4") == 0 ) Scene4();
  if ( strcmp(cmd,"scene5") == 0 ) Scene5();
  if ( strcmp(cmd,"scene6") == 0 ) Scene6();
  
}

void Bienvenue()  // Modifie la valeur d'une PIN sur la carte arduino
{}

void Noir()  // Modifie la valeur d'une PIN sur la carte arduino
{}

void Scene1()  // Modifie la valeur d'une PIN sur la carte arduino
{

}

void Scene2()   // Lit la valeur d'une des PIN sur la page web
{

}

void Scene3()  // Modifie la valeur d'une PIN sur la carte arduino
{
 lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Scene 3 en cours");
}

void Scene4()  // Modifie la valeur d'une PIN sur la carte arduino
{
 lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Scene 4 en cours");
}

void Scene5()  // Modifie la valeur d'une PIN sur la carte arduino
{}

void Scene6()  // Modifie la valeur d'une PIN sur la carte arduino
{}

void PrintString(char* label, char* str)
{
  Serial.print(label);
  Serial.print("=");
  Serial.println(str);
}

void PrintNumber(char* label, int number)
{
  Serial.print(label);
  Serial.print("=");
  Serial.println(number, DEC);

Le premier passage:

bufferSize=25
slash1=scene3/7/0 HTTP/1.1

slash2=7/0 HTTP/1.1

slash3=0 HTTP/1.1

space2=HTTP/1.1

cmd=scene3

Le deuxième passage:

bufferSize=19
slash1=1.1

slash2=
slash3=
space2=
cmd=1.1

Le troisième passage:

bufferSize=128
slash1=5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.29.13 (KHTML, like Gecko) Version/6.0.4 Safari/536.29W
slash2=536.29.13 (KHTML, like Gecko) Version/6.0.4 Safari/536.29W
slash3=536.29.13 (KHTML, like Gecko) Version/6.0.4 Safari/536.29W
space2=(KHTML, like Gecko) Version/6.0.4 Safari/536.29W
cmd=5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit

Le cinquième passage:

bufferSize=3
slash1=5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.29.13 (KHTML, like Gecko) Version/6.0.4 Safari/536.29W
slash2=536.29.13 (KHTML, like Gecko) Version/6.0.4 Safari/536.29W
slash3=536.29.13 (KHTML, like Gecko) Version/6.0.4 Safari/536.29W
space2=(KHTML, like Gecko) Version/6.0.4 Safari/536.29W
cmd=5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit

Le sixième passage:

bufferSize=72
slash1=html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
36.29.13 (KHTML, like Gecko) Version/6.0.4 Safari/536.29W
slash2=xhtml+xml,application/xml;q=0.9,/;q=0.8
36.29.13 (KHTML, like Gecko) Version/6.0.4 Safari/536.29W
slash3=xml;q=0.9,/;q=0.8
36.29.13 (KHTML, like Gecko) Version/6.0.4 Safari/536.29W
space2=(KHTML, like Gecko) Version/6.0.4 Safari/536.29W
cmd=html,application

Bref je comprend pas pourquoi ça part en vrille comme ça!
Merci de votre éclaircissement :slight_smile:

bonjour,
inspire toi du tuto [Arduino] Panneaux d’affichage (rudimentaire) par wifi | Skyduino - Le DIY à la française
mais tu confonds client et server.
client => se connecte à un serveur distant par un GET
server => recoit des ordres, les traite et agit

Bonjour,

Tu te compliques la vie :wink:

Fait un algo dans ce genre :

  • Lit une ligne (mise en buffer tant que != '\n', dés que tu reçoit \n tu met un \0 à la place dans le buffer)
  • si ligne[0] == '\0' ou ligne[0] == '\r' -> ligne vide = fin de la requête HTTP
  • sinon si 1er ligne -> boucle de traitement
    -- 1er ligne = false
  • sinon si nième ligne -> ne rien faire

La boucle de traitement :

char method[8], ressource[64];
sscanf(buffer, "%7[^ ] %63[^ ]", method, ressource);
// method -> GET
// ressource -> /scene1/1/0

Bonjour,

Merci pour vos réponses, je viens de modifier la partie traitement, qui est vraiment plus simple que ce que j'avais c'est claire. Parcontre pour l'algo, j'ai beau comparer avec le liens que tu m'as envoyé infobarquee, pour moi c'est le même :~

Ce que je comprend pas c'est qu'il fonctionne à la perfection lors du premier. Puis plusieurs série ou cela ne fonctionne pas. Puis ca remarche une fois puis ca ne remarche pas plusieurs fois.... etc (toute les 10 fois en fait)
Vous pensez vraiment que ça viens de l'algol, et non de la fonction client.read() qui aurait un soucis?
(J'ai essayer de travailler un algo sur ton exemple skywodd mais je galère encore plus a recevoir de l'info pour le moment...)

Message reçu par l'action method et cmd (ou ressource dans ton code skywodd)

Arriver sur la page http://192.168.1.90/scene3/7/0 :
Method: GET
Ressource: /scene3/7/0
// Donc celui ci c'est bon ça fonctionne

Actualisation 1:
Method: Host:
Ressource:192.168.1.90 P/1.1

Actualisation 2:
Method: User-Ag
Ressource :ent:

Actualisation 3:
Method: 13 r-Ag
Ressource: ent:

Actualisation 4:
Method: Accept:
Ressource: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8

Actualisation 5:
Method: Accept-
Ressource: Language:

Actualisation 6:
Method: Accept-
Ressource: Encoding:

Actualisation 7:
Method: Connect
Ressource: ion:

Actualisation 8:
Method: onnect
Ressource: ion:

Actualisation 9:
Method: GET
Ressource: /scene3/7/0

Actualisation 10:
Method: Host:
Ressource: 192.168.1.90 P/1.1

Actualisation 11:
Method: flate
Ressource: html+xml,application/xml;q=0.9,/;q=0

Actualisation 12:
Method: User-Ag
Ressource: ent:

Actualisation 13:
Method: 13 r-Ag
Ressource: ent:

Actualisation 14:
Method: Accept:
Ressource: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8

Actualisation 15:
Method: Accept-
Ressource: Language:

Actualisation 16:
Method: Accept-
Ressource: Encoding:

Actualisation 17:
Method: Connect
Ressource: ion:

Actualisation 18:
Method:onnect
Ressource: ion:

Ton problème vient du fait que tu ne gères pas correctement le protocole HTTP :wink:

Voici un exemple de requête + réponse en HTTP :

GET / HTTP/1.1
Host: perdu.com
User-Agent: Links (2.7; Linux 3.5.0-17-generic x86_64; GNU C 4.7.1; dump)
Accept: */*
Accept-Language: en,*;q=0.1
Accept-Encoding: gzip,deflate,bzip2,lzma,lzma2
Accept-Charset: us-ascii,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-13,ISO-8859-14,ISO-8859-15,ISO-8859-16,windows-1250,windows-1251,windows-1252,windows-1256,windows-1257,cp437,cp737,cp850,cp852,cp866,x-cp866-u,x-mac,x-mac-ce,x-kam-cs,koi8-r,koi8-u,koi8-ru,TCVN-5712,VISCII,utf-8
Connection: keep-alive

HTTP/1.1 200 OK
Date: Thu, 16 May 2013 10:44:07 GMT
Server: Apache
Last-Modified: Tue, 02 Mar 2010 18:52:21 GMT
ETag: "cc-480d5dd98a340"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 163
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/html

..........5....0.Dw...H.....L.l..Cc.H%).S..'!....:...L..:B
:3.S.pU.0....4....#.O....\...-*KdmzE...m........."...v...R..0...$\..j.....ny
2...0.4.B...>....|....-....

Comme tu peut le voir il y a trois parties :

  • l'entête (ligne finissant par \r\n)
  • la séparation (juste \r\n)
  • le corps (n'importe quoi)

L'entête est lui même composé de deux parties :

  • la commande HTTP (1er ligne)
  • les headers (n lignes suivantes avant la ligne vide)

Dans ton cas la 1er ligne déclenche ton système, normale c'est la commande HTTP, mais le reste bug car tu ne laisse pas de côté les lignes d'headers qui suivent.
D’où mon algo qui différencie la 1er ligne des n lignes suivante :wink:

Genial, je comprend maintenant le principe, Il garde en fait en mémoire tout ce qui suit la première ligne, dont je n'ai pas besoin :slight_smile: Et il ne les charge qu'au fur et à mesure de mes actualisations.
J'ai essayé de faire ton algorithme qui me parait totalement logique maintenant, mais j'étais bloqué sur identifier les lignes 1 des autres (ligne[0] il ne le comprend pas, doit y avoir une bibliothèque que je n'ai pas encore trouvé).

Bref, j'ai voulu directement effacer le buffer dés qu'il reçois le premier \n mais il ne comprend pas non plus: buffer = ""; Pour moi ça devrai pourtant remettre le buffer à zéro, et donc repartir de nouveau!

Et je me suis dit, finalement si je met le client.stop() à cette emplacement, il arrêterai de charger le reste. Mais en fait non!

Donc j'ai bien compris, je continue mes recherches surtout aujourd'hui, mais je pense que je vais devoir étudier les librairies string pour trouver ces infos. Ou celle de Wifi pour trouver comment stopper cette mise en buffer!

Si vous avez des astuces n'hésiter pas je suis preneur :slight_smile:

A tout a l'heure!

Je pense surtout que tu devrais regarder le principe des tableaux de char et des boucles en C :wink:
Si tu comptes sur la classe String pour tout faire tu va avoir des surprises (et pas dans le bon sens).

Tu auras besoin de readBytesUntil() pour lire une ligne finissant par \n :wink:

Yehhha ca marche :slight_smile:
J'ai réussis à trouver une bonne page web sur le forum:

Et à partir de là j'ai modifier le code, et d'ailleurs j'ai pu voir comme ça la fameuse solution que tu m'avais proposé pour terminé la ligne!

Voici mon code utilisable:

#include <SPI.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiServer.h>
#include "LiquidCrystal.h"

// Mise en place du réseau
char ssid[] = "SFR_C0E8";     //  Mon nom de réseau 
char pass[] = "llaxwelliativ6estura";  // Le mot de passe
int status = WL_IDLE_STATUS;     // the Wifi radio's status
WiFiServer server(80); // Port 80 is http.


// Infos sur les constantes (entrées et sorties)
LiquidCrystal lcd(6,5,28,26,24,22);

String HTTP_req;          // Le stockage des données HTTP
boolean LED_status = 0;   // LED allumé par default (allumé quand pret.

void SetupES() {
    pinMode(2, OUTPUT);       // La LED statut
}

void messagedebut() { // message de bienvenue
  lcd.setCursor(2,0);
  lcd.print("Bienvenue au");
  lcd.setCursor(5,1);
  lcd.print("Theatre");
  lcd.setCursor(0,0);
}

void setup()    // Installation
{
    lcd.begin(16,2);
    messagedebut();
    WiFi.begin(ssid, pass);  // initialisation du réseau
    server.begin();           // On commence l'acceuil sur notre page web.
    Serial.begin(9600);       // pour la communication
    SetupES();
}

void loop()
{
    WiFiClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                HTTP_req += c;  // save the HTTP request 1 char at a time
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    ProcessAction(client);
                    Serial.print(HTTP_req);
                    HTTP_req = "";    // finished with request, empty string
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

// On action suivant ce qu'on recoit
void ProcessAction(WiFiClient cl)
{
    if (HTTP_req.indexOf("scene1") > -1) {  // est ce qu'il y a marqué ?scene1 
            LED_status = 1;
            Scene3();
    }
    
        if (HTTP_req.indexOf("scene2") > -1) {  // est ce qu'il y a marqué ?scene2
            LED_status = 0;
            Scene4();
    }
    
// POur la fameuse LED installé si on veux l'allumer ou l'éteindre.
    if (LED_status) {    // switch LED on
        digitalWrite(2, LOW);;
    }
    else {              // switch LED off
        digitalWrite(2, HIGH);
    }
}

void Scene3()  // Modifie la valeur d'une PIN sur la carte arduino
{
 lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Scene 3 en cours");
}

void Scene4()  // Modifie la valeur d'une PIN sur la carte arduino
{
 lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Scene 4 en cours...");
}

Encore merci pour les infos, je n'aurais pas autant creuser, mais le principal c'est que ça marche :smiley:

Bon il y a toujours une String dans ton code mais qu'importe tu as compris le principe :wink: