Remplacement de caractères accentués

Bonjour,

Je récupère une chaine de caractère via un GET http (réponse en ISO-8859-1) et je souhaite l'afficher sur un écran LCD.

Cette chaîne de caractère pouvant contenir des caractères accentués, je cherche à les remplacer par des caractères non accentués en utilisant string.replace avant d'afficher sur mon écran.

Cela ne fonctionne pas.

Ci-dessous mon code (expurger de toute la partie extraction / LCD):

1 - En fin de Setup je remplace des accents dans une chaine de caractère accentuée, cela fonctionne.
2 - Dans le loop j'essaye de faire la meme chose sur les caractères que je récupère de ma réponse http.
Cela fonctionne quand j'essaye de substituer un "D" par un "x"
Cela ne fonctionne plus quand j'essaye de substituer un "é" par un "e"

Je ne comprends pas quelle différence il y a entre mes 2 tests, mais j'imagine que j'ai un problème d'encodage quelque part.

Auriez vous une piste s'il vous plait ?

Merci !

void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(9600);

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    Ethernet.begin(mac, ip);
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    // Make a HTTP request:
      client.println("GET /index.php?api_lang=fr&localidad=48949&affiliate_id=4d2q7ug3fmoa&v=2 HTTP/1.1");
    client.println("Host: api.tameteo.com");
    client.println("Connection: close");
    client.println();
  } 
  else {
    // kf you didn't get a connection to the server:
    Serial.println("connection failed");
  }
  char *tests = "bébébébébé";
  String test(tests);
  Serial.println(test);
  test.replace("é","e");
  Serial.println(test);
}

void loop()
{
  // if there are incoming bytes available 
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    String str(c);
    str.replace("é","e");
    str.replace("D","x");
    Serial.print(str);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    // do nothing forevermore:
    while(true);
  }
}

bonjour,
pourquoi ne pas faire l'inverse?
faire le get sur un fichier php qui lui va traiter avec str_replace?

lorsque tu recois un caractère avec accent, c'est un code et non la lettre accentuée, donc normal que ca ne fonctionne pas.
http://www.codeshttp.com/iso88591.htm

è è

Bonjour,

Ce sont des datas météo que je récupère d'un flux RSS.

Mettre en place un serveur web intermédiaire pour faire le traitement de substitution, nettoyer les datas dont je n'ai pas besoin, ... effectivement pourquoi pas, mais si j'avais pu m'en passer ...

Concernant la piste du caractère accentué codé : si cela étais le cas, j'imagine que mes lignes :

  if (client.available()) {
    char c = client.read();
    String str(c);
    str.replace("é","e");
    str.replace("D","x");
    Serial.print(str);
  }

m'afficheraient alors chaque caractère du code et non pas directement le car. accentué.

or :
devient :

Dans tous les cas, merci pour ces pistes.

si tu faisais un serial.print des caractères recus afin de voir :wink:

La gestion des caractères accentués est différente suivant le codage utilisé (UTF8, UTF16, ISO....)
Normalement dans l'entête de l'HTML que tu reçois il y a le type d'encodage utilisé par la page.
Exemple la page du forum Arduino

	<head>
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
	  	<meta charset="utf-8" />

Il faut tenir compte de cette information pour transcoder les caractères.

Bonjour

wget http://api.tameteo.com/index.php?api_lang=fr&localidad=48949&affiliate_id=4d2q7ug3fmoa&v=2

  • J'ai bien des accents et non des codes. Ce que j'ai affiché dans le post précédent est ce que j'ai

    si je mets
    Serial.print(c)
    après
    char c = client.read();

  • comme je le disais dans mon premier post,

<?xml version="1.0" encoding="ISO-8859-1" ?>

Donc oui j'ai bien conscience que je dois avoir un pb d'encodage, mais je ne vois pas comment m'en sortir ...

hyperbenax:
Bonjour

wget http://api.tameteo.com/index.php?api_lang=fr&localidad=48949&affiliate_id=4d2q7ug3fmoa&v=2

  • J'ai bien des accents et non des codes. Ce que j'ai affiché dans le post précédent est ce que j'ai

    si je mets
    Serial.print(c)
    après
    char c = client.read();

  • comme je le disais dans mon premier post,

<?xml version="1.0" encoding="ISO-8859-1" ?>

Donc oui j'ai bien conscience que je dois avoir un pb d'encodage, mais je ne vois pas comment m'en sortir ...

c'est pas le xml dans le navigateur qui nous intéresse, mais ce que recois le nono :wink:
tu fais prendre toute la page sans changer quoi que ce soit et regardes ce sui se passe avec les accents comment ils arrivent.
sachant que chaque caractère a un code propre, il suffit après de remplacer par le bon code.

Le problème c'est que l'IDE encode les caractères accentués en UTF-8 si je ne me trompe pas.
Pour résoudre ton problème, dans ton programme, il faut mettre le code ASCII dans le test et non pas le caractère directement comme ça tu ne sera pas tributaire de l'encodage utilisé par la chaîne Arduino.

  if (client.available()) {
    char c = client.read();
    switch (c){
         case 232:                                   // caractère è
               c='e; break;
         case 233:                                   // caractère é
               c='e; break;
    } 
    Serial.print(c);
}

J'ai utilisé le code ACSII étendu dans mon exemple. Adapte en fonction de ce que ton soft reçoit comme codes.

je pensais plutot à de l'ASCII, mais je peux me tromper aussi

L'IDE fait sa cuisine avec les chaines que l'on met dans le programme.
Si on compile le code suivant:

char chaine[]={"J'ai placé une chaine avec des àéè accents"};

void setup(void){
  Serial.begin(9600);
  Serial.println(chaine);
}

void loop(void){
}

On retrouve à la fin du .hex qui est chargé les constantes.

Pour la compréhension, j'ai mis au-dessus du "binaire" les caractères codés en mettant à chaque fois un underscore suivi du caractère. On voit que tous les caractères accentués sont codés sur 2 octets. Le premier étant C3.

         _J_'_a_i_ _p_l_a_c_é_ _u_n_e_  
:100772004A27616920706C6163C3A920756E652088
         _c_h_a_i_n_e_ _a_v_e_c_ _d_e_s_
:10078200636861696E6520617665632064657320C4
         ___à___é___è_ _a_c_c_e_n_t_s
:10079200C3A0C3A9C3A820616363656E747300001C

autant pour moi, confondu la compilation et la lecture des chaines recues :wink:

Pas de problème.
En plus, à ma connaissance, c'est écrit nulle part. C'est en cherchant pourquoi j'avais des caractères bizarres à la console que j'ai trouvé ça.

fdufnews:
C'est en cherchant pourquoi j'avais des caractères bizarres à la console que j'ai trouvé ça.

Je me garderais bien de contre-dire mais j'ai une interrogation :
Si j'utilise une interface USB/TTL et un terminal comme screen (sous Linux) les accents sont bien représentés.
La version améliorée de l'IDE proposée par Majenko, qui a ré-écrit le terminal, ne présente pas non plus de pb avec les accents.
Vu comme celà j'aurais tendance à penser que le pb des accents n'est pas dans le code hex mais dans le terminal de L'IDE. Je n'ai pas pu contrôler la véracité de l'info mais j'ai lu que l'IDE utilisait unicode et non pas UTF-8.

J'ai repris le même programme
Voir en pièce jointe la recopie d'écran
J'utilise minicom comme terminal.
Je fais un reset une première fois pour afficher en texte.
Je modifie la configuration de minicom pour faire afficher la chaîne reçue en hexadécimal et je fais un second reset qui affiche en hexa. On retrouve bien les C3 xx

D'après ce que j'ai pu investiguer sur le sujet :

Oui le code compilé (et donc la RAM à l'exécution) stocke les caractères accentués en UTF-8.
Donc un "é" occupe physiquement 2 octets, dont le premier est C3.
Je pense que cela provient du compilo et non de l'IDE (pour s'en assurer il suffit d'ouvrir le source avec un éditeur de fichier hexadécimal)

Oui dans l'IDE standard Arduino, le terminal série "de base" interprète les caractères supérieurs à 127 selon la norme UNICODE.

Il faut donc transcoder les caractères >127 en fonction de ce qu'attend le media en sortie.

Perso je me suis fait une petite librairie pour contourner simplement tous ces problèmes (mais limitées aux caractères spéciaux usuels).

http://forum.arduino.cc/index.php?topic=218373.msg1732549#msg1732549

Elle contient des fonctions de transcodification de chaînes de caractères.
Par exemple utilisable ici :

  • une fonction pour supprimer tous les accents (pour affichage LCD)
  • une fonction pour convertir en UNICODE (pour affichage terminal série)

Et peu importe le format de la source de donnée : un &eacute ou un C3A9 (ou l'équivalent ASCII ou UNICODE) sera pris comme un é.

bricoleau:
D'après ce que j'ai pu investiguer sur le sujet :

Oui le code compilé (et donc la RAM à l'exécution) stocke les caractères accentués en UTF-8.
Donc un "é" occupe physiquement 2 octets, dont le premier est C3.
Je pense que cela provient du compilo et non de l'IDE (pour s'en assurer il suffit d'ouvrir le source avec un éditeur de fichier hexadécimal)

bonjour
petit test avec l'exemple ASCIItable modifié pour aller jusqu'à 255
et avec ça dans le setup

Serial.println("ASCII Table ~ Character Map éèàù");

testé avec 4 prog termianaux serie
cette ligne part dans les choux à l'affichage en ce qui concerne les caracteres accentués
alors que les caracteres accentués s'affichent corcectement dans la boucle (33-255)
le code asciitable modifié "avé l'assen" :grin:

/*
  ASCII table
 
 Prints out byte values in all possible formats:  
 * as raw binary values
 * as ASCII-encoded decimal, hex, octal, and binary values
 
 For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII
 
 The circuit:  No external hardware needed.
 
 created 2006
 by Nicholas Zambetti 
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.

 <http://www.zambetti.com> 
 
 */
void setup() { 
 //Initialize serial and wait for port to open:
  Serial.begin(9600); 
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  
  // prints title with ending line break 
  Serial.println("ASCII Table ~ Character Map éèàù"); // ajout de caractere avé l'assen :D
} 

// first visible ASCIIcharacter '!' is number 33:
int thisByte = 33; 
// you can also write ASCII characters in single quotes.
// for example. '!' is the same as 33, so you could also use this:
//int thisByte = '!';  

void loop() { 
  // prints value unaltered, i.e. the raw binary version of the 
  // byte. The serial monitor interprets all bytes as 
  // ASCII, so 33, the first number,  will show up as '!' 
  Serial.write(thisByte);    

  Serial.print(", dec: "); 
  // prints value as string as an ASCII-encoded decimal (base 10).
  // Decimal is the  default format for Serial.print() and Serial.println(),
  // so no modifier is needed:
  Serial.print(thisByte);      
  // But you can declare the modifier for decimal if you want to.
  //this also works if you uncomment it:

  // Serial.print(thisByte, DEC);  


  Serial.print(", hex: "); 
  // prints value as string in hexadecimal (base 16):
  Serial.print(thisByte, HEX);     

  Serial.print(", oct: "); 
  // prints value as string in octal (base 8);
  Serial.print(thisByte, OCT);     

  Serial.print(", bin: "); 
  // prints value as string in binary (base 2) 
  // also prints ending line break:
  Serial.println(thisByte, BIN);   

  // if printed last visible character '~' or 255, stop: 
  if(thisByte == 255) {     // you could also use if (thisByte == '~') {
    // This loop loops forever and does nothing
    while(true) { 
      continue; 
    } 
  } 
  // go on to the next character
  thisByte++;  
}

Question : est-ce que Windows gère l'UTF-8 de base sans être obligé de faire des réglages ?

Question subsidiaire : quelles versions gèrent ou gèrent pas de Xp à 8.1 ?

68tjs:
Question : est-ce que Windows gère l'UTF-8 de base sans être obligé de faire des réglages ?

Question subsidiaire : quelles versions gèrent ou gèrent pas de Xp à 8.1 ?

Bonjour 68tjs
Ce n'est vraiment pas mon "truc" , mais de memoire je crois que l'encodage de base des "windows" est l'UTF16 depuis le support NTFS.

sans aucune autre garantie :grin:

bricoleau:
D'après ce que j'ai pu investiguer sur le sujet :

Oui le code compilé (et donc la RAM à l'exécution) stocke les caractères accentués en UTF-8.
Donc un "é" occupe physiquement 2 octets, dont le premier est C3.
Je pense que cela provient du compilo et non de l'IDE (pour s'en assurer il suffit d'ouvrir le source avec un éditeur de fichier hexadécimal)

Les caractères sont encodés avec le C3 dans le .ino

68tjs:
Question : est-ce que Windows gère l'UTF-8 de base sans être obligé de faire des réglages ?

Question subsidiaire : quelles versions gèrent ou gèrent pas de Xp à 8.1 ?

Je crois que les versions récentes de Windows gère l'UNICODE et l'UTF-8 est compatible UNICODE d'après Wikipedia