[RESOLU]Problème de récupération des données d'un fichier .ini Arduino carte SD

Bonjour,

Lors du démarrage de mon Arduino UNO, je dois récupérer des informations sur un fichier .ini et les exploiter chacune, elles ne doivent pas être dépendantes des autres.
J’en suis actuellement à l’étape de récupération et j’ai un problème. L’image du problème est jointe.

Je vous mets aussi mon code en pièce jointe, en espérant que vous pourrez m’aider et m’éclairer sur le problème.

Voici le contenu du fichier config.ini :

[NOM MACHINE]
A01
[AdresseIP]
10.138.0.1
[USER]
TOTO

Merci.

pb1.PNG

Fichier_ini.ino (615 Bytes)

Essaye sur cette base :

#include <SD.h>
File fichier;

char nommachine = "";
const int TAILLE_BUFFER = 6;
char inputString [TAILLE_BUFFER];
char inputChar;
int stringIndex = 0; // String stringIndexing int;

void setup()
{
  Serial.begin(115200);
  if (!SD.begin(4)) {
    Serial.println("Erreur à l'init!");
    return;
  }
  Serial.println("init Ok.");
  fichier = SD.open("config.ini");
}


void loop()
{
  inputChar = fichier.read(); // Gets one byte from serial buffer
  if (inputChar != EOF) // define breaking char here (\n isnt working for some reason, i will follow this up later)
  {
    inputString[stringIndex] = inputChar; // Store it
    stringIndex++; // Increment where to write next
  }
  else
  {
    Serial.println(inputString);
    delay (1000);
    stringIndex = 0; // clear the value for the next cycle
  }
}

en réglant la vitesse de la console sur 115200 bauds.

Merci pour ton code, il fonctionne très bien.

Au niveau code, j’ai donc :

#include <SD.h>

File fichier;

char nommachine = "";
const int TAILLE_BUFFER = 80;
char inputString [TAILLE_BUFFER];
char inputChar;
int stringIndex = 0; // String stringIndexing int;

void setup()
{
  Serial.begin(115200);
  if (!SD.begin(4)) {
    Serial.println("Erreur à l'init!");
    return;
  }
  Serial.println("init Ok.");
  fichier = SD.open("config.txt");
}


void loop()
{
  inputChar = fichier.read(); // Gets one byte from serial buffer
  if (inputChar != EOF) // define breaking char here (\n isnt working for some reason, i will follow this up later)
  {
    inputString[stringIndex] = inputChar; // Store it
    stringIndex++; // Increment where to write next
  }
  else
  {
    Serial.println(inputString);
    delay (1000);
    stringIndex = 0; // clear the value for the next cycle
  }
}

Et le moniteur m’affiche :
[NOM MACHINE]
A01
[Adresse IP]
10.138.0.1
[USER]
TOTO
[PW]
TOTOTTE

C’est ce que je voulais.

Maintenant, j’aimerais stocker dans des variables seulement les informations utiles, donc oublier les informations entre crochets. Existe t-il un moyen de savoir sur quelle ligne on se trouve dans le fichier lorsqu’on le lit ?

Merci.

Salut, tu peux utiliser la librairie Textfinder comme si dessous pour récupérer tes adresses directement dans une chaine de caractères puis utilisé la fonction Parse byte pour récupérer leurs valeurs :slight_smile:

#include <Ethernet.h>
#include <TextFinder.h>
#include <dht11.h>

byte mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; //adresse mac de votre carte
byte ip[] = {0, 0, 0, 0}; //adresse IP
byte dnServer[] = {0, 0, 0, 0}; //adresse IP
byte mask[]= {0, 0, 0, 0}; //mask
byte gw[]= {0, 0, 0, 0}; //gateway
EthernetServer serveur(80); // déclare l'objet serveur au port d'écoute 80


File conf;

//fonction qui découpe la chaîne de caractères pour la mettre en byte
void parseBytes(const char* str, char sep, byte* bytes, int maxBytes, int base) {
      for (int i = 0; i < maxBytes; i++) {
        bytes[i] = strtoul(str, NULL, base);  // Convert byte
        str = strchr(str, sep);               // Find next separator
        if (str == NULL || *str == '\0') {
            break;                            // No more separators, exit
        }
        str++;                                // Point to next character after separator
      }
}



    
void setup() {

 Serial.begin(9600);
  pinMode(10, OUTPUT);
  digitalWrite(10,HIGH);
  int temp;//
  char buff[50];  //chaine de caractère pour récupérer les valeurs dans le fichier


  if (!SD.begin(4)) { // Gère les erreurs
    //Serial.println("Erreur de carte SD !");
    for(;;);
    }
    
    conf=SD.open("config.xml", FILE_READ);
    TextFinder finder(conf);
    conf.seek(0);

    //Analyse reseau\\
    conf.seek(0);
    temp=finder.getString("<ip>","</ip>",buff,50);
    parseBytes(buff, '.', ip, 4, 10);
    //
    temp=finder.getString("<dns>","</dns>",buff,50);
    parseBytes(buff, '.',dnServer, 4, 10);
    //
    temp=finder.getString("<gw>","</gw>",buff,50);
    parseBytes(buff, '.',gw, 4, 10);
    //
    temp=finder.getString("<mask>","</mask>",buff,50);
    parseBytes(buff, '.',mask, 4, 10);
    //
    temp=finder.getString("<mac>","</mac>",buff,50);
    parseBytes(buff, ':',mac, 6, 16);
    Ethernet.begin(mac,ip,dnServer,gw,mask);
    Serial.println(Ethernet.localIP());

      Serial.println("configuration réseaux");
      Serial.println("adresse IP:");
      Serial.println(ip[0]);Serial.println(ip[1]);Serial.println(ip[2]);Serial.println(ip[3]);
      Serial.println("adresse dns:");
      Serial.println(dnServer[0]);Serial.println(dnServer[1]);Serial.println(dnServer[2]);Serial.println(dnServer[3]);
      Serial.println("adresse GW:");
      Serial.println(gw[0]);Serial.println(gw[1]);Serial.println(gw[2]);Serial.println(gw[3]);
      Serial.println("adresse Mask:");
      Serial.println(mask[0]);Serial.println(mask[1]);Serial.println(mask[2]);Serial.println(mask[3]);
      Serial.println("adresse MAC:");
      Serial.println(mac[0],HEX);Serial.println(mac[1],HEX);Serial.println(mac[2],HEX);Serial.println(mac[3],HEX);Serial.println(mac[4],HEX);Serial.println(mac[5],HEX);
    }
     
 }

Si tu ne comprends pas certaine chose sur n’hésite pas à poser des questions :wink:

Si elles sont toujours comme ça, c'est à dire une sur deux est à retenir, tu mets un compteur que tu incrémentes à chaque passage dans la loop et tu testes sa valeur :

  • 1 : nom de la machine
  • 3 : adresse IP
  • 5 : user
  • 7 : password

Désolé Scroum mais je ne comprends pas le rapport de ton programme avec mon problème. Moi j'essaie de récupérer des informations présentes sur certaines lignes de mon fichier présent sur la carte SD.

lesept: Si elles sont toujours comme ça, c'est à dire une sur deux est à retenir, tu mets un compteur que tu incrémentes à chaque passage dans la loop et tu testes sa valeur :

  • 1 : nom de la machine
  • 3 : adresse IP
  • 5 : user
  • 7 : password

Le nom des machines varie de 2 à 10 caractères, donc comment faire une boucle fiable permettant de récupérer ce nom ? Quand je teste la valeur du compteur, j'ai une boucle "for" qui s'exécute de x à y mais comment définir les valeurs x et y ? J'avais pensé à une boucle qui récupère autant de caractères qu'elle peut et dès qu'elle rencontre un crochet ouvrant ([), elle se stoppe et concatène tous les caractères qu'elle a trouvé dans l'ordre. Est-ce viable ?

Herouis:
Désolé Scroum mais je ne comprends pas le rapport de ton programme avec mon problème. Moi j’essaie de récupérer des informations présentes sur certaines lignes de mon fichier présent sur la carte SD.

Je te fais une ligne de démonstration

File Fichier;
 Fichier=SD.open("config.txt", FILE_READ);
    TextFinder finder(conf); //ici tu passes le fichier a textFinder
    conf.seek(0); // Permet de revenir au début du fichier simple sécurité

   temp=finder.getString("<ip>","</ip>",buff,50);

Scroum:
Je te fais une ligne de démonstration

File Fichier;

Fichier=SD.open(“config.txt”, FILE_READ);
    TextFinder finder(conf); //ici tu passes le fichier a textFinder
    conf.seek(0); // Permet de revenir au début du fichier simple sécurité

temp=finder.getString("","",buff,50);

A quoi sert ta dernière ligne de code ?

Herouis: Désolé Scroum mais je ne comprends pas le rapport de ton programme avec mon problème. Moi j'essaie de récupérer des informations présentes sur certaines lignes de mon fichier présent sur la carte SD.

Je te fais une ligne de démonstration

File Fichier;
 Fichier=SD.open("config.txt", FILE_READ);
    TextFinder finder(conf); //ici tu passes le fichier a textFinder
    conf.seek(0); // Permet de revenir au début du fichier simple sécurité

    temp=finder.getString("[NOM MACHINE]","[",buff,50); // La tu vas pouvoir récupérer la chaine de caractère 
                                                                                   // situé entre [NOM MACHINE] et [ dans buff qui a 
                                                                                   //pour taille maxi 50 caractères.
                                                                                   //temp reçois 0 ou 1 si la chaine de caractères a été 
                                                                                  // trouvé

Tu peux aussi ajouté un ';' après A01 comme pour t'arrêter pour simplifier la lecture.

Herouis: Le nom des machines varie de 2 à 10 caractères, donc comment faire une boucle fiable permettant de récupérer ce nom ? Quand je teste la valeur du compteur, j'ai une boucle "for" qui s'exécute de x à y mais comment définir les valeurs x et y ? J'avais pensé à une boucle qui récupère autant de caractères qu'elle peut et dès qu'elle rencontre un crochet ouvrant ([), elle se stoppe et concatène tous les caractères qu'elle a trouvé dans l'ordre. Est-ce viable ?

Soit j'ai mal compris, soit tu te compliques la vie :)

Le code que j'ai fourni (copié sur Internet et arrangé) te donne une nouvelle ligne à chaque fois que la loop est exécutée. Tu ne veux conserver que les lignes impaires (la première étant à 0) donc tu comptes les lignes. Et tu mets dans un string le tableau de char qui est récupéré, quelle que soit sa longueur.

si tu veux chercher des caractères, regarde les exemples sur les strings.

Scroum: Je te fais une ligne de démonstration

File Fichier;
 Fichier=SD.open("config.txt", FILE_READ);
    TextFinder finder(conf); //ici tu passes le fichier a textFinder
    conf.seek(0); // Permet de revenir au début du fichier simple sécurité

    temp=finder.getString("[NOM MACHINE]","[",buff,50); // La tu vas pouvoir récupérer la chaine de caractère                                                                                   // situé entre [NOM MACHINE] et [ dans buff qui a                                                                                   //pour taille maxi 50 caractères.                                                                                   //temp reçois 0 ou 1 si la chaine de caractères a été                                                                                   // trouvé



Tu peux aussi ajouté un ';' après A01 comme pour t'arrêter pour simplifier la lecture.

J'ai compris, quelle est la bibliothèque permettant d'utiliser TextFinder ?

lesept: Soit j'ai mal compris, soit tu te compliques la vie :)

Le code que j'ai fourni (copié sur Internet et arrangé) te donne une nouvelle ligne à chaque fois que la loop est exécutée. Tu ne veux conserver que les lignes impaires (la première étant à 0) donc tu comptes les lignes. Et tu mets dans un string le tableau de char qui est récupéré, quelle que soit sa longueur.

si tu veux chercher des caractères, regarde les exemples sur les strings.

En réalité, je crois que je me complique la vie et que je ne comprends pas :roll_eyes:

Je pense que je n'ai pas tout à fait compris le programme que tu m'as envoyé.

pour telecharcher la librairie si tu veux essayer https://playground.arduino.cc/Code/TextFinder

Scroum: pour telecharcher la librairie si tu veux essayer https://playground.arduino.cc/Code/TextFinder

Merci beaucoup. Dans ton code d'exemple, certaines variables sortent d'où ?

J'ai changé de format pour le fichier config.txt, j'ai trouvé que cela serai plus simple si il était sous ce format : A01:10.138.0.1:TOTO:TOTOTTE

J'ai donc dans l'ordre le nom de la machine, une adresse ip aléatoire pour le moment, un utilisateur et le mot de passe.

Je veux donc récupérer dans une variable différente pour chaque chaine les informations.

Je pense donc qu'il y aurait des moyens plus simples et moins gourmant en mémoire. Cependant je ne sais toujours pas comment m'y prendre. Merci.

Tu cherches en gros à connaitre les positions d’un caractère de séparation ‘:’ dans une chaîne de caractères. La fonction strtok est faite pour toi.

Dans ton code actuel, tu peux ajouter après le Serial.println une recherche de ces caractères :

#include <SD.h>

File fichier;

char nommachine = "";
const int TAILLE_BUFFER = 80;
char inputString [TAILLE_BUFFER];
char inputChar;
int stringIndex = 0; // String stringIndexing int;

void setup()
{
  Serial.begin(115200);
  if (!SD.begin(4)) {
    Serial.println("Erreur à l'init!");
    return;
  }
  Serial.println("init Ok.");
  fichier = SD.open("config.txt");
}


void loop()
{
  inputChar = fichier.read(); // Gets one byte from serial buffer
  if (inputChar != EOF) // define breaking char here (\n isnt working for some reason, i will follow this up later)
  {
    inputString[stringIndex] = inputChar; // Store it
    stringIndex++; // Increment where to write next
  }
  else
  {
    Serial.println(inputString);
    RechercheCarac(inputString); // <----
    delay (1000);
    stringIndex = 0; // clear the value for the next cycle
  }
}

void RechercheCarac (char inputString) {
  char * pch;
  pch = strtok (inputString,":");
  while (pch != NULL)
  {
    Serial.println ("%s\n",pch);
    pch = strtok (NULL, ":");
  }
}

Ce n’est qu’une idée, tu peux tester. Je ne sais pas si le passage du tableau en argument va fonctionner. Si ça coince, tu peux déplacer le contenu de la fonction à la place où elle est appelée…

Oui en gros je cherche a connaitre la position des “:” pour pouvoir récupérer le texte avant et après.
J’ai essayé ton programme mais une erreur que je ne comprends pas s’affiche, saurais-tu me dire à quoi elle correspond ?
Merci

pb2.PNG

Remplace la ligne par :

Serial.println (pch);

Je ne sais pas ce que ça donnera, je ne suis pas très fort avec les pointeurs... mais ça devrait compiler

Le résultat est en pièce jointe.

Cela m’affiche des caractères bizarres mais aussi ceux que je désirent.
Comment intégrer chaque partie (A01, adresse IP, etc …) dans une variable ?

J’aimerais pouvoir mettre A01 dans la variable nom_machine par exemple.

Est-ce possible ?

pb3.PNG

j’ai essayé ceci :

#include <SD.h>

File fichier;

char inputChar;
const int TAILLE = 80;
char tabsd[TAILLE];
int evolutif = 0;
char nom_machine = "";

void setup() 
{
  Serial.begin(115200);
  if (!SD.begin(4)) {
    Serial.println("Erreur à l'init!");
    return;
  }
  Serial.println("init Ok.");
  fichier = SD.open("config.txt");


}

void loop() 
{
  inputChar = fichier .read();

  if(inputChar != ':' && inputChar != EOF)
  {
    Serial.print("EOF : ");
    Serial.println(inputChar);
    tabsd[evolutif] = inputChar;
    Serial.print("tableau : ");
    Serial.println(tabsd[evolutif]);
  }
  else if(inputChar == ':')
  {
    for(int i = 0; i < evolutif; i++)
    {
      nom_machine = nom_machine + tabsd[i];
    }
    Serial.print("Resultat : ");
    Serial.println(nom_machine);
  }

  evolutif++;
  delay(1000);
}

Cela marche à peut près comme je le souhaite seulement lorsque je veux afficher le tableau, ben il ne m’affiche rien.
Vous voyez le problème ? Moi je ne le trouve pas.
[EDIT] J’ai trouvé le problème, j’ai remplacé ma variable char par une String.
Maintenant j’ai besoin de récupérer mes 3 autres informations dans des variable, une idée de comment faire ?