Go Down

Topic: Shield Ethernet2: récupérer les requètes dans un string [Résolu] (Read 147 times) previous topic - next topic

naute

Bonjour  :) ,

j'envoie à l'Arduino UNO, par l'intermédiaire d'un shield Ethernet 2, une requête depuis mon navigateur. Pour traiter cette requête, il me faut l'analyser, et donc la charger dans un objet String. Mon problème est que je reçois bien la requête, elle s'affiche comme il faut dans la console, mais la chaine que je construit à priori en même temps que je l'affiche, reste vide. Comme le code est simple et qu'il compile bien, je ne vois pas ce qui se passe.

Voici la portion de code en cause
Code: [Select]

      if (client.available()) carLu = client.read();
      while (client.available() && carLu != 10)  //Tant qu'il reste au moins 1 octet à lire sur la première ligne
      {  //(On ne lit que la première ligne car c'est elle qui contient la requète)
        reception = reception + carLu;  //Construction de la chaine contenant la requète: PROBLEME
        Serial.print(carLu);  //On affiche le caractère lu sur la console OK
        carLu = client.read();  //puis on passe au caractère suivant  OK     
      }
      Serial.print("\nLa chaine 'reception' est: ");
      Serial.println(reception);  //LA CHAINE EST VIDE

à ce stade, la première ligne de la requête est parfaitement affichée dans la console mais la chaine 'reception' est vide


et le contexte plus général
Code: [Select]

/*
   CONTEXTE:
   Arduino UNO rev3
   Shield Ethernet 2
      SPI Ethernet: SS = 10
      SPI SD: SS = 4
   Carte micro SDHC 8Gio
   IDE 1.6.8

   OBJECTIF:
   Lire le contenu du fichier "page.htm" depuis la carte micro SD pour l'afficher dans la console,
   puis l'envoyer par le réseau Ethernet au navigateur pour afficher la page codée.
*/

#include <SPI.h>
#include <Ethernet2.h>
#include <SdFat.h>
SdFat SD;  //Force la compatibilité de SdFat avec SD

//CONSTANTES
byte mac[] = {0x90, 0xA2, 0xDA, 0x10, 0x4F, 0x25};  //Adresse MAC du shield Ethernet (non critique)
const int carteSD = 4; //Broche de commande par défaut pour le shield Ethernet Arduino

//VARIABLES
String reception = "";  //Chaine reçue par le serveur (première ligne uniquement <=> requète)
char carLu;

//INSTANCIATIONS
EthernetServer serveurHTTP(80); //Instanciation d'un serveur sur le port 80 (port HTTP par défaut)

//INITIALISATIONS
void setup()
{
  Serial.begin(115200); //Penser à paramétrer le terminal série avec la même valeur
  //Initialisation de la connexion Ethernet
  Ethernet.begin(mac);//Initialisation du serveur
  delay(1000);  //Délais d'initialisation du Shield Ethernet 2
  if (Ethernet.localIP() != NULL)  //Petite vérification avant démarrage du serveur
  {
    Serial.print("Serveur a l'adresse '");
    Serial.print(Ethernet.localIP());
    Serial.println("' OK!");
  }
  else
  {
    Serial.println("Un probleme empeche l'initialisation du serveur: Demarrage du serveur abandonne!");
    return;
  }
}

void loop()
{
  EthernetClient client = serveurHTTP.available();  //Instanciation d'un client
  if (client) //Si le client existe
  {
    Serial.println("DEMANDE DE CONNEXION");
    reception = "";
    if (client.connected())  //Si le client est connecté
    {
      Serial.println("Le client est connecte");
      if (client.available()) carLu = client.read();
      while (client.available() && carLu != 10)  //Tant qu'il reste au moins 1 octet à lire sur la première ligne
      {  //(On ne lit que la première ligne car c'est elle qui contient la requète)
        reception = reception + carLu;  //Construction de la chaine contenant la requète
        Serial.print(carLu);  //On affiche le caractère lu sur la console
        carLu = client.read();  //puis on passe au caractère suivant       
      }
      Serial.print("\nLa chaine 'reception' est: ");
      Serial.println(reception);
    }
  }
}


Je me demande s'il ne pourrait pas y avoir un problème avec une des librairies que j'utilise, mais c'est peu vraisemblable: je ne dois pas être le seul à utiliser ces librairies et des objets 'String' dans un même code.
Je dois faire une erreur quelque-part mais je n'arrive pas à mettre la main dessus.

Si quelqu'un a une idée, je suis preneur!

D'avance, merci  :) ,

naute

kamill

Bonjour,

Est ce que tu ne lirais pas un seul caractère dans le while(), ce qui fait que pour lire la chaine complète tu entres plusieurs fois dans la loop() et tu réinitialise la chaine avec reception = "";
Vire reception = ""; pour essayer.

naute

Bonjour et merci de te préoccuper de ma santé mentale :smiley-mr-green: .

Pareil (mais pas pire).

Le code décortique bien la réception caractère par caractère puisqu'il affiche la requête dans la console. C'est la construction de la chaine qui ne se fait pas, et pourtant, la syntaxe est bonne puisqu'elle fonctionne dans d'autres sketchs.

kamill

C'est hallucinant! Je n'ai jamais eu de problème avec les String.
Essaie de faire un Serial.println(reception) à la place de Serial.print(carlu)

schrist

Salut.

Ton texte "La chaine 'reception' est: " s'affiche-ti-il correctement ?

Si, dans ta section variables, tu remplaces
String reception ="";
par
String reception;
Cela change-t-il quelque chose ?

Bon courage!

naute

Bonjour,
Essaie de faire un Serial.println(reception) à la place de Serial.print(carlu)
Déjà fait (dernière ligne du code), et ça m'affiche une chaine vide.

Je m'aperçois d'ailleurs que mon code n'est pas fini, il manque les lignes suivantes:
Code: [Select]

delay(1); //La transmission est rapide mais pas instantanée. 1 ms suffit largement
client.stop();  //Fermeture de la connexion

Mais bon!  :-[  "C'est un exemple" aurait dit Coluche.

Quote from: schrist
Ton texte "La chaine 'reception' est: " s'affiche-ti-il correctement ?
Oui, heureusement, sinon je ne pourrais rien faire!
Quote from: schrist
Si, dans ta section variables, tu remplaces
String reception ="";
par
String reception;
Cela change-t-il quelque chose ?
Non, le fait d'initialiser une variable n'en fait pas une constante  :) .

Je dois dire à ma plus grande honte que le code que je fournis comme exemple fonctionne. je viens de le tester à tout hasard. Ce n'est qu'une partie de mon code que j'avais mis comme exemple. Il se trouve que la partie qui l'empêche de fonctionner n'y est pas. La voici:
Code: [Select]

  //Initialisation de la carte SD
  Serial.println("Initialisation de la carte SD");
  if (SD.begin(carteSD))  //Si la fonction d'initialisation renvoi TRUE,
  {
    Serial.println("Initialisation OK!");
  }
  else   //sinon on quitte le SETUP
  {
    Serial.println("Initialisation impossible:\n\tAbandon du setup!");
    return;
  }

Cette partie concerne l'initialisation du lecteur de carte SD du shield Ethernet 2 et se place dans le setup. Si je l'enlève, le string se remplit mais je n'accède pas à ma carte SD, et dans le cas contraire, j'accède à ma carte mais j'ai un string vide. Des deux cotés mon mal est infini aurait dit Le Cid.

kamill

Bonjour,Déjà fait (dernière ligne du code), et ça m'affiche une chaine vide.
Je ne parles pas de l'afficher à la fin, mais de l'afficher à chaque réception d'un caractère à la place de carlu pour voir quand elle est réinitialisée, car je reste persuadé que le plus probable est que la chaine est réinitialisée.

naute

OK!!! Autant pour moi, je n'avais pas compris.

Donc je fais ce que tu me dis et là, ça fonctionne: le string se remplit avec la chaine représentant la requête. Mais ce qui est étonnant, c'est que maintenant, ça fonctionne aussi quand j'enlève la ligne que tu m'as suggérée. Pour reprendre tes propres écrits, c'est hallucinant. Je n'ai rien changé???

Et ce n'est pas tout: si je reprends mon code original et non pas l'exemple que j'ai envoyé, le résultat à la console est incompréhensible pour la seconde requête (demande d'envoi du fichier css pour la mise en forme du code html demandé par la première requête). Je précise que je n'ai pas encore traité les différentes requête car, jusqu'à présent, le string restait vide. Cela n'empêche pas de constater que la seconde requête est mal stockée, et que par conséquent, je ne peux pas traiter les requêtes pour envoyer les fichiers demandés.

Je mets le code en pièce jointe pour raccourcir le message (trop long).

et voilà ce que la console affiche
Code: [Select]

Initialisation de la carte SD
Initialisation OK!
Initialisation de la connexion ethernet
Serveur a l'adresse '192.168.1.18' OK!'
DEMANDE DE CONNEXION
Le client est connecte
G
GE
GET
GET
GET /
GET /
GET / H
GET / HT
GET / HTT
GET / HTTP
GET / HTTP/
GET / HTTP/1
GET / HTTP/1.
GET / HTTP/1.1
GET / HTTP/1.1


La chaine 'reception' est: GET / HTTP/1.1

La chaine est une requete valide (commence par GET)
<!DOCTYPE html>
<html>
<head>
<title>Test d'affichage du fichier "page.htm" sur carte SD du shield Ethernet 2 Arduino</title>
<link rel="stylesheet" href="exemple_css.css" />
</head>
<body>
<center>
<div>
<h3>Test d'affichage du fichier "page.htm"</h3>
<p>Le fichier codant pour cette page se trouve sur une carte microSD de 8Go insérée dans son support sur un shield Ethernet 2 connecté à une carte Arduino UNO v3.</p>
</div>
</center>
</body>
</html>DEMANDE DE CONNEXION
Le client est connecte
G
GE
GET
GET
GET /
GET /e
GET /ex
GET /exe
GET /exem
GET /exemp
GET /exempl
GET /exemple
GET /exemple_
GET /exemple_c
GET /exemple_cs
GET /exemple_css
GET /exemple_css.
GET /exemple_css.c
GET /exemple_css.cs
GET /exemple_css.css
GET /exemple_css.css
GET /exemple_css.css H
GET /exemple_css.css HT
GET /exemple_css.css HTT
GET /exemple_css.css HTTP
GET /exemple_css.css HTTP/
GET /exemple_css.css HTTP/1

1
1


La chaine 'reception' est: 1

La chaine n'est pas une requete car elle ne commence pas par GET
DEMANDE DE CONNEXION
Le client est connecte
G
GE
GET
GET
GET /
GET /e
GET /ex
GET /exe
GET /exem
GET /exemp
GET /exempl
GET /exemple
GET /exemple_
GET /exemple_c
GET /exemple_cs
GET /exemple_css
GET /exemple_css.
GET /exemple_css.c
GET /exemple_css.cs
GET /exemple_css.css
GET /exemple_css.css
GET /exemple_css.css H

T
TP
TP/
TP/1
TP/1.
TP/1.1
TP/1.1


La chaine 'reception' est: TP/1.1

La chaine n'est pas une requete car elle ne commence pas par GET
DEMANDE DE CONNEXION
Le client est connecte
G
GE
GET
GET
GET /
GET /e
GET /ex
GET /exe
GET /exem
GET /exemp
GET /exempl
GET /exemple
GET /exemple_
GET /exemple_c
GET /exemple_cs
GET /exemple_css
GET /exemple_css.
GET /exemple_css.c
GET /exemple_css.cs
GET /exemple_css.css
GET /exemple_css.css
GET /exemple_css.css H

T
TP
TP/
TP/1
TP/1.
TP/1.1
TP/1.1


La chaine 'reception' est: TP/1.1

La chaine n'est pas une requete car elle ne commence pas par GET
DEMANDE DE CONNEXION
Le client est connecte
G
GE
GET
GET
GET /
GET /e
GET /ex
GET /exe
GET /exem
GET /exemp
GET /exempl
GET /exemple
GET /exemple_
GET /exemple_c
GET /exemple_cs
GET /exemple_css
GET /exemple_css.
GET /exemple_css.c
GET /exemple_css.cs
GET /exemple_css.css
GET /exemple_css.css
GET /exemple_css.css H

T
TP
TP/
TP/1
TP/1.
TP/1.1
TP/1.1


La chaine 'reception' est: TP/1.1

La chaine n'est pas une requete car elle ne commence pas par GET
DEMANDE DE CONNEXION
Le client est connecte
G
GE
GET
GET
GET /
GET /e
GET /ex
GET /exe
GET /exem
GET /exemp
GET /exempl
GET /exemple
GET /exemple_
GET /exemple_c
GET /exemple_cs
GET /exemple_css
GET /exemple_css.
GET /exemple_css.c
GET /exemple_css.cs
GET /exemple_css.css
GET /exemple_css.css
GET /exemple_css.css H

T
TP
TP/
TP/1
TP/1.
TP/1.1
TP/1.1


La chaine 'reception' est: TP/1.1

La chaine n'est pas une requete car elle ne commence pas par GET
DEMANDE DE CONNEXION
Le client est connecte
G
GE
GET
GET
GET /
GET /e
GET /ex
GET /exe
GET /exem
GET /exemp
GET /exempl
GET /exemple
GET /exemple_
GET /exemple_c
GET /exemple_cs
GET /exemple_css
GET /exemple_css.
GET /exemple_css.c
GET /exemple_css.cs
GET /exemple_css.css
GET /exemple_css.css
GET /exemple_css.css H

T
TP
TP/
TP/1
TP/1.
TP/1.1
TP/1.1


La chaine 'reception' est: TP/1.1

La chaine n'est pas une requete car elle ne commence pas par GET



La première requête est correctement stockée dans le string 'reception' mais pas la requête suivante, et lors des répétitions de la seconde requête (dues au fait que, comme la requête n'est pas valide, je n'envoie pas d'accusé de réception), la première des requêtes est stockée différemment des trois autres.

Cherchez l'erreur :o  . Y-a quequ'chose qui m'échappe   :smiley-mr-green:.

Merci de toute manière pour l'aide apportée  :)  .

kamill

Oui, là il y a vraiment de quoi en perdre son latin

naute

Je crois que j'ai trouvé le problème.

En épluchant les messages du compilateur, une des lignes indiquait une mémoire faible (80% de la RAM utilisée) avec possibilité d'instabilités.
J'ai donc revu mes messages à la baisse et les ai installés en mémoire flash avec la macro F(message). Je suis redescendu à 52% d'utilisation de la RAM, et, apparemment, ça fonctionne.
Ce qui me rassure, c'est que c'était normal de ne pas trouver d'erreur, vu qu'il n'y en avait pas, d'où le coté 'hallucinant' :smiley-yell: .
Ce qui m'inquiète, c'est la faible marge de manœuvre dont je dispose pour mon programme. Les librairies sont gourmandes. Il est vrai que, dans la version finale, toute la partie 'message', utile au débogage, sera supprimée, mais quand même.

Je pense que je peux marquer ce post comme résolu, mais si quelqu'un veut laisser un commentaire, il est le bienvenu.

Merci pour votre aide, à bientôt :)

PS @kamill
J'ai eu l'avis de ton message au moment de poster le mien. Il y avait effectivement de quoi en perdre son latin. Tu ne pouvais pas trouver car tu ne disposais pas des messages du compilateur. Merci à toi.

naute

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy